mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-09 04:38:03 +02:00
nouveau/mme: Fix add64 of immediates on Fermi
Fixes: 162269f049 ("nouveau/mme: Add Fermi builder")
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30703>
This commit is contained in:
parent
f2655b10c7
commit
381be88473
3 changed files with 130 additions and 18 deletions
|
|
@ -698,28 +698,35 @@ mme_to_fermi_alu_op(enum mme_alu_op op)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
mme_fermi_alu_to(struct mme_builder *b,
|
||||
struct mme_value dst,
|
||||
enum mme_alu_op op,
|
||||
struct mme_value x,
|
||||
struct mme_value y)
|
||||
static bool
|
||||
is_imm18_nonzero(struct mme_value x)
|
||||
{
|
||||
return x.type == MME_VALUE_TYPE_IMM && x.imm != 0 && is_int18(x.imm);
|
||||
}
|
||||
|
||||
static void
|
||||
mme_fermi_build_alu(struct mme_builder *b,
|
||||
struct mme_value dst,
|
||||
enum mme_alu_op op,
|
||||
struct mme_value x,
|
||||
struct mme_value y,
|
||||
bool need_carry)
|
||||
{
|
||||
struct mme_fermi_builder *fb = &b->fermi;
|
||||
|
||||
switch (op) {
|
||||
case MME_ALU_OP_ADD:
|
||||
if (x.type == MME_VALUE_TYPE_IMM && x.imm != 0 && is_int18(x.imm)) {
|
||||
if (is_imm18_nonzero(x) && !need_carry) {
|
||||
mme_fermi_add_imm18(fb, dst, y, x.imm);
|
||||
return;
|
||||
}
|
||||
if (y.type == MME_VALUE_TYPE_IMM && y.imm != 0 && is_int18(y.imm)) {
|
||||
if (is_imm18_nonzero(y) && !need_carry) {
|
||||
mme_fermi_add_imm18(fb, dst, x, y.imm);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case MME_ALU_OP_SUB:
|
||||
if (y.type == MME_VALUE_TYPE_IMM && is_int18(-y.imm)) {
|
||||
if (y.type == MME_VALUE_TYPE_IMM && is_int18(-y.imm) && !need_carry) {
|
||||
mme_fermi_add_imm18(fb, dst, x, -y.imm);
|
||||
return;
|
||||
}
|
||||
|
|
@ -762,6 +769,30 @@ mme_fermi_alu_to(struct mme_builder *b,
|
|||
mme_free_reg_if_tmp(b, y, y_reg);
|
||||
}
|
||||
|
||||
void
|
||||
mme_fermi_alu_to(struct mme_builder *b,
|
||||
struct mme_value dst,
|
||||
enum mme_alu_op op,
|
||||
struct mme_value x,
|
||||
struct mme_value y)
|
||||
{
|
||||
mme_fermi_build_alu(b, dst, op, x, y, false);
|
||||
}
|
||||
|
||||
void
|
||||
mme_fermi_alu64_to(struct mme_builder *b,
|
||||
struct mme_value64 dst,
|
||||
enum mme_alu_op op_lo,
|
||||
enum mme_alu_op op_hi,
|
||||
struct mme_value64 x,
|
||||
struct mme_value64 y)
|
||||
{
|
||||
assert(dst.lo.type == MME_VALUE_TYPE_REG);
|
||||
assert(dst.hi.type == MME_VALUE_TYPE_REG);
|
||||
|
||||
mme_fermi_build_alu(b, dst.lo, op_lo, x.lo, y.lo, true);
|
||||
mme_fermi_build_alu(b, dst.hi, op_hi, x.hi, y.hi, true);
|
||||
}
|
||||
|
||||
void mme_fermi_state_arr_to(struct mme_builder *b,
|
||||
struct mme_value dst,
|
||||
|
|
|
|||
|
|
@ -90,20 +90,13 @@ mme_fermi_alu_to(struct mme_builder *b,
|
|||
struct mme_value x,
|
||||
struct mme_value y);
|
||||
|
||||
static inline void
|
||||
void
|
||||
mme_fermi_alu64_to(struct mme_builder *b,
|
||||
struct mme_value64 dst,
|
||||
enum mme_alu_op op_lo,
|
||||
enum mme_alu_op op_hi,
|
||||
struct mme_value64 x,
|
||||
struct mme_value64 y)
|
||||
{
|
||||
assert(dst.lo.type == MME_VALUE_TYPE_REG);
|
||||
assert(dst.hi.type == MME_VALUE_TYPE_REG);
|
||||
|
||||
mme_fermi_alu_to(b, dst.lo, op_lo, x.lo, y.lo);
|
||||
mme_fermi_alu_to(b, dst.hi, op_hi, x.hi, y.hi);
|
||||
}
|
||||
struct mme_value64 y);
|
||||
|
||||
void
|
||||
mme_fermi_bfe_to(struct mme_builder *b, struct mme_value dst,
|
||||
|
|
|
|||
|
|
@ -291,6 +291,94 @@ TEST_F(mme_fermi_sim_test, addc)
|
|||
test_macro(&b, macro, params);
|
||||
}
|
||||
|
||||
TEST_F(mme_fermi_sim_test, add_imm_carry)
|
||||
{
|
||||
mme_builder b;
|
||||
mme_builder_init(&b, devinfo);
|
||||
|
||||
mme_value max = mme_load(&b);
|
||||
|
||||
mme_value add_res = mme_alloc_reg(&b);
|
||||
mme_value add_imm_res = mme_alloc_reg(&b);
|
||||
mme_value carry = mme_alloc_reg(&b);
|
||||
|
||||
/* Dummy add clears the carry register */
|
||||
mme_fermi_asm(&b, i) {
|
||||
i.op = MME_FERMI_OP_ALU_REG;
|
||||
i.assign_op = MME_FERMI_ASSIGN_OP_MOVE;
|
||||
i.dst = mme_fermi_value_as_reg(add_res);
|
||||
i.src[0] = MME_FERMI_REG_ZERO;
|
||||
i.src[1] = MME_FERMI_REG_ZERO;
|
||||
i.alu_op = MME_FERMI_ALU_OP_ADD;
|
||||
}
|
||||
|
||||
/* ADD_IMM should not touch carry */
|
||||
mme_fermi_asm(&b, i) {
|
||||
i.op = MME_FERMI_OP_ADD_IMM;
|
||||
i.assign_op = MME_FERMI_ASSIGN_OP_MOVE;
|
||||
i.dst = mme_fermi_value_as_reg(add_imm_res);
|
||||
i.src[0] = mme_fermi_value_as_reg(max);
|
||||
i.imm = 1;
|
||||
}
|
||||
|
||||
/* Grab the carry */
|
||||
mme_fermi_asm(&b, i) {
|
||||
i.op = MME_FERMI_OP_ALU_REG;
|
||||
i.assign_op = MME_FERMI_ASSIGN_OP_MOVE;
|
||||
i.dst = mme_fermi_value_as_reg(carry);
|
||||
i.src[0] = MME_FERMI_REG_ZERO;
|
||||
i.src[1] = MME_FERMI_REG_ZERO;
|
||||
i.alu_op = MME_FERMI_ALU_OP_ADDC;
|
||||
}
|
||||
|
||||
/* Store everything after all that ALU so none of the stores mess up the
|
||||
* carry behind our back.
|
||||
*/
|
||||
mme_store_imm_addr(&b, data_addr + 0, add_res, false);
|
||||
mme_store_imm_addr(&b, data_addr + 4, add_imm_res, false);
|
||||
mme_store_imm_addr(&b, data_addr + 8, carry, false);
|
||||
|
||||
/* Set carry to 1 */
|
||||
mme_fermi_asm(&b, i) {
|
||||
i.op = MME_FERMI_OP_ALU_REG;
|
||||
i.assign_op = MME_FERMI_ASSIGN_OP_MOVE;
|
||||
i.dst = mme_fermi_value_as_reg(add_res);
|
||||
i.src[0] = mme_fermi_value_as_reg(max);
|
||||
i.src[1] = mme_fermi_value_as_reg(max);
|
||||
i.alu_op = MME_FERMI_ALU_OP_ADD;
|
||||
}
|
||||
|
||||
/* ADD_IMM should not touch carry */
|
||||
mme_fermi_asm(&b, i) {
|
||||
i.op = MME_FERMI_OP_ADD_IMM;
|
||||
i.assign_op = MME_FERMI_ASSIGN_OP_MOVE;
|
||||
i.dst = mme_fermi_value_as_reg(add_imm_res);
|
||||
i.src[0] = MME_FERMI_REG_ZERO;
|
||||
i.imm = 1;
|
||||
}
|
||||
|
||||
/* Grab the carry */
|
||||
mme_fermi_asm(&b, i) {
|
||||
i.op = MME_FERMI_OP_ALU_REG;
|
||||
i.assign_op = MME_FERMI_ASSIGN_OP_MOVE;
|
||||
i.dst = mme_fermi_value_as_reg(carry);
|
||||
i.src[0] = MME_FERMI_REG_ZERO;
|
||||
i.src[1] = MME_FERMI_REG_ZERO;
|
||||
i.alu_op = MME_FERMI_ALU_OP_ADDC;
|
||||
}
|
||||
|
||||
mme_store_imm_addr(&b, data_addr + 12, add_res, true);
|
||||
mme_store_imm_addr(&b, data_addr + 16, add_imm_res, true);
|
||||
mme_store_imm_addr(&b, data_addr + 20, carry, true);
|
||||
|
||||
auto macro = mme_builder_finish_vec(&b);
|
||||
|
||||
std::vector<uint32_t> params;
|
||||
params.push_back(UINT32_MAX);
|
||||
|
||||
test_macro(&b, macro, params);
|
||||
}
|
||||
|
||||
TEST_F(mme_fermi_sim_test, sub)
|
||||
{
|
||||
mme_builder b;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue