@@ -862,6 +862,8 @@ static int tcg_out_pool_finalize(TCGContext *s)
#define C_N1_O1_I4(O1, O2, I1, I2, I3, I4) C_PFX6(c_n1_o1_i4_, O1, O2, I1, I2, I3, I4),
typedef enum {
+ C_NotReached = -3,
+ C_Dynamic = -2,
C_NotImplemented = -1,
#include "tcg-target-con-set.h"
} TCGConstraintSetIndex;
@@ -955,6 +957,11 @@ static const TCGConstraintSet constraint_sets[] = {
#define C_O2_I4(O1, O2, I1, I2, I3, I4) C_PFX6(c_o2_i4_, O1, O2, I1, I2, I3, I4)
#define C_N1_O1_I4(O1, O2, I1, I2, I3, I4) C_PFX6(c_n1_o1_i4_, O1, O2, I1, I2, I3, I4)
+typedef struct TCGOutOp {
+ TCGConstraintSetIndex static_constraint;
+ TCGConstraintSetIndex (*dynamic_constraint)(TCGType type, unsigned flags);
+} TCGOutOp;
+
#include "tcg-target.c.inc"
#ifndef CONFIG_TCG_INTERPRETER
@@ -964,6 +971,14 @@ QEMU_BUILD_BUG_ON((int)(offsetof(CPUNegativeOffsetState, tlb.f[0]) -
< MIN_TLB_MASK_TABLE_OFS);
#endif
+static const TCGOutOp outop_notreached = {
+ .static_constraint = C_NotReached,
+};
+
+static const TCGOutOp * const all_outop[NB_OPS] = {
+ [0 ... NB_OPS - 1] = &outop_notreached,
+};
+
/*
* 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
@@ -2410,8 +2425,32 @@ bool tcg_op_supported(TCGOpcode op, TCGType type, unsigned flags)
return has_type && TCG_TARGET_HAS_cmpsel_vec;
default:
- tcg_debug_assert(op > INDEX_op_last_generic && op < NB_OPS);
+ if (op < INDEX_op_last_generic) {
+ const TCGOutOp *outop;
+ TCGConstraintSetIndex con_set;
+
+ if (!has_type) {
+ return false;
+ }
+
+ outop = all_outop[op];
+ tcg_debug_assert(outop != NULL);
+
+ con_set = outop->static_constraint;
+ if (con_set == C_Dynamic) {
+ con_set = outop->dynamic_constraint(type, flags);
+ }
+ if (con_set >= 0) {
+ return true;
+ }
+ tcg_debug_assert(con_set == C_NotImplemented);
+ return false;
+ }
+ tcg_debug_assert(op < NB_OPS);
return true;
+
+ case INDEX_op_last_generic:
+ g_assert_not_reached();
}
}
@@ -3331,18 +3370,25 @@ static void process_constraint_sets(TCGContext *s)
static const TCGArgConstraint *opcode_args_ct(const TCGOp *op)
{
- const TCGOpDef *def = &tcg_op_defs[op->opc];
+ TCGOpcode opc = op->opc;
+ TCGType type = TCGOP_TYPE(op);
+ unsigned flags = TCGOP_FLAGS(op);
+ const TCGOpDef *def = &tcg_op_defs[opc];
+ const TCGOutOp *outop = all_outop[opc];
TCGConstraintSetIndex con_set;
-#ifdef CONFIG_DEBUG_TCG
- assert(tcg_op_supported(op->opc, TCGOP_TYPE(op), TCGOP_FLAGS(op)));
-#endif
-
if (def->flags & TCG_OPF_NOT_PRESENT) {
return empty_cts;
}
- con_set = tcg_target_op_def(op->opc, TCGOP_TYPE(op), TCGOP_FLAGS(op));
+ if (outop) {
+ con_set = outop->static_constraint;
+ if (con_set == C_Dynamic) {
+ con_set = outop->dynamic_constraint(type, flags);
+ }
+ } else {
+ con_set = tcg_target_op_def(opc, type, flags);
+ }
tcg_debug_assert(con_set >= 0 && con_set < ARRAY_SIZE(constraint_sets));
/* The constraint arguments must match TCGOpcode arguments. */
Add infrastructure for more consolidated output of opcodes. The base structure allows for constraints to be either static or dynamic, and for the existence of those constraints to replace TCG_TARGET_HAS_* and the bulk of tcg_op_supported. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- tcg/tcg.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 7 deletions(-)