tcg: Convert add to TCGOutOpBinary

Drop all backend support for an immediate as the first operand.
This should never happen in any case, as we swap commutative
operands to place immediates as the second operand.

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2025-01-06 09:00:07 -08:00
parent b5701261da
commit 662cdbcf00
12 changed files with 302 additions and 195 deletions

View file

@ -978,6 +978,14 @@ typedef struct TCGOutOp {
TCGConstraintSetIndex (*dynamic_constraint)(TCGType type, unsigned flags);
} TCGOutOp;
typedef struct TCGOutOpBinary {
TCGOutOp base;
void (*out_rrr)(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, TCGReg a2);
void (*out_rri)(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, tcg_target_long a2);
} TCGOutOpBinary;
#include "tcg-target.c.inc"
#ifndef CONFIG_TCG_INTERPRETER
@ -987,10 +995,21 @@ QEMU_BUILD_BUG_ON((int)(offsetof(CPUNegativeOffsetState, tlb.f[0]) -
< MIN_TLB_MASK_TABLE_OFS);
#endif
/*
* Register V as the TCGOutOp for O.
* This verifies that V is of type T, otherwise give a nice compiler error.
* This prevents trivial mistakes within each arch/tcg-target.c.inc.
*/
#define OUTOP(O, T, V) [O] = _Generic(V, T: &V.base)
/* Register allocation descriptions for every TCGOpcode. */
static const TCGOutOp * const all_outop[NB_OPS] = {
OUTOP(INDEX_op_add_i32, TCGOutOpBinary, outop_add),
OUTOP(INDEX_op_add_i64, TCGOutOpBinary, outop_add),
};
#undef OUTOP
/*
* All TCG threads except the parent (i.e. the one that called tcg_context_init
* and registered the target's TCG globals) must register with this function
@ -5414,6 +5433,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
}
/* emit instruction */
TCGType type = TCGOP_TYPE(op);
switch (op->opc) {
case INDEX_op_ext_i32_i64:
tcg_out_exts_i32_i64(s, new_args[0], new_args[1]);
@ -5424,12 +5444,29 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
case INDEX_op_extrl_i64_i32:
tcg_out_extrl_i64_i32(s, new_args[0], new_args[1]);
break;
case INDEX_op_add_i32:
case INDEX_op_add_i64:
{
const TCGOutOpBinary *out =
container_of(all_outop[op->opc], TCGOutOpBinary, base);
/* Constants should never appear in the first source operand. */
tcg_debug_assert(!const_args[1]);
if (const_args[2]) {
out->out_rri(s, type, new_args[0], new_args[1], new_args[2]);
} else {
out->out_rrr(s, type, new_args[0], new_args[1], new_args[2]);
}
}
break;
default:
if (def->flags & TCG_OPF_VECTOR) {
tcg_out_vec_op(s, op->opc, TCGOP_TYPE(op) - TCG_TYPE_V64,
tcg_out_vec_op(s, op->opc, type - TCG_TYPE_V64,
TCGOP_VECE(op), new_args, const_args);
} else {
tcg_out_op(s, op->opc, TCGOP_TYPE(op), new_args, const_args);
tcg_out_op(s, op->opc, type, new_args, const_args);
}
break;
}