mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 15:23:53 -06:00
tcg: Add all_outop[]
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. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
cf5c9f697f
commit
5500bd9e2e
1 changed files with 68 additions and 8 deletions
76
tcg/tcg.c
76
tcg/tcg.c
|
@ -861,6 +861,7 @@ 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_Dynamic = -2,
|
||||
C_NotImplemented = -1,
|
||||
#include "tcg-target-con-set.h"
|
||||
} TCGConstraintSetIndex;
|
||||
|
@ -954,6 +955,29 @@ 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)
|
||||
|
||||
/*
|
||||
* TCGOutOp is the base class for a set of structures that describe how
|
||||
* to generate code for a given TCGOpcode.
|
||||
*
|
||||
* @static_constraint:
|
||||
* C_NotImplemented: The TCGOpcode is not supported by the backend.
|
||||
* C_Dynamic: Use @dynamic_constraint to select a constraint set
|
||||
* based on any of @type, @flags, or host isa.
|
||||
* Otherwise: The register allocation constrains for the TCGOpcode.
|
||||
*
|
||||
* Subclasses of TCGOutOp will define a set of output routines that may
|
||||
* be used. Such routines will often be selected by the set of registers
|
||||
* and constants that come out of register allocation. The set of
|
||||
* routines that are provided will guide the set of constraints that are
|
||||
* legal. In particular, assume that tcg_optimize() has done its job in
|
||||
* swapping commutative operands and folding operations for which all
|
||||
* operands are constant.
|
||||
*/
|
||||
typedef struct TCGOutOp {
|
||||
TCGConstraintSetIndex static_constraint;
|
||||
TCGConstraintSetIndex (*dynamic_constraint)(TCGType type, unsigned flags);
|
||||
} TCGOutOp;
|
||||
|
||||
#include "tcg-target.c.inc"
|
||||
|
||||
#ifndef CONFIG_TCG_INTERPRETER
|
||||
|
@ -963,6 +987,10 @@ QEMU_BUILD_BUG_ON((int)(offsetof(CPUNegativeOffsetState, tlb.f[0]) -
|
|||
< MIN_TLB_MASK_TABLE_OFS);
|
||||
#endif
|
||||
|
||||
/* Register allocation descriptions for every TCGOpcode. */
|
||||
static const TCGOutOp * const all_outop[NB_OPS] = {
|
||||
};
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
@ -2416,8 +2444,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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3335,19 +3387,27 @@ static void process_constraint_sets(void)
|
|||
|
||||
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));
|
||||
tcg_debug_assert(con_set >= 0 && con_set < ARRAY_SIZE(constraint_sets));
|
||||
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);
|
||||
tcg_debug_assert(con_set < ARRAY_SIZE(constraint_sets));
|
||||
|
||||
/* The constraint arguments must match TCGOpcode arguments. */
|
||||
tcg_debug_assert(constraint_sets[con_set].nb_oargs == def->nb_oargs);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue