tcg: Transition flat op_defs array to a target callback

This will allow the target to tailor the constraints to the
auto-detected ISA extensions.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Richard Henderson <rth@twiddle.net>
master
Richard Henderson 2016-11-18 09:31:40 +01:00
parent 82790a8709
commit f69d277ece
11 changed files with 136 additions and 77 deletions

View File

@ -1812,6 +1812,18 @@ static const TCGTargetOpDef aarch64_op_defs[] = {
{ -1 }, { -1 },
}; };
static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
{
int i, n = ARRAY_SIZE(aarch64_op_defs);
for (i = 0; i < n; ++i) {
if (aarch64_op_defs[i].op == op) {
return &aarch64_op_defs[i];
}
}
return NULL;
}
static void tcg_target_init(TCGContext *s) static void tcg_target_init(TCGContext *s)
{ {
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff); tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
@ -1834,8 +1846,6 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_set_reg(s->reserved_regs, TCG_REG_FP); tcg_regset_set_reg(s->reserved_regs, TCG_REG_FP);
tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP); tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP);
tcg_regset_set_reg(s->reserved_regs, TCG_REG_X18); /* platform register */ tcg_regset_set_reg(s->reserved_regs, TCG_REG_X18); /* platform register */
tcg_add_target_add_op_defs(aarch64_op_defs);
} }
/* Saving pairs: (X19, X20) .. (X27, X28), (X29(fp), X30(lr)). */ /* Saving pairs: (X19, X20) .. (X27, X28), (X29(fp), X30(lr)). */

View File

@ -2008,6 +2008,18 @@ static const TCGTargetOpDef arm_op_defs[] = {
{ -1 }, { -1 },
}; };
static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
{
int i, n = ARRAY_SIZE(arm_op_defs);
for (i = 0; i < n; ++i) {
if (arm_op_defs[i].op == op) {
return &arm_op_defs[i];
}
}
return NULL;
}
static void tcg_target_init(TCGContext *s) static void tcg_target_init(TCGContext *s)
{ {
/* Only probe for the platform and capabilities if we havn't already /* Only probe for the platform and capabilities if we havn't already
@ -2038,8 +2050,6 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK); tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP); tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP);
tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC); tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC);
tcg_add_target_add_op_defs(arm_op_defs);
} }
static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,

View File

@ -2330,6 +2330,18 @@ static const TCGTargetOpDef x86_op_defs[] = {
{ -1 }, { -1 },
}; };
static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
{
int i, n = ARRAY_SIZE(x86_op_defs);
for (i = 0; i < n; ++i) {
if (x86_op_defs[i].op == op) {
return &x86_op_defs[i];
}
}
return NULL;
}
static int tcg_target_callee_save_regs[] = { static int tcg_target_callee_save_regs[] = {
#if TCG_TARGET_REG_BITS == 64 #if TCG_TARGET_REG_BITS == 64
TCG_REG_RBP, TCG_REG_RBP,
@ -2471,8 +2483,6 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_clear(s->reserved_regs); tcg_regset_clear(s->reserved_regs);
tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK); tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
tcg_add_target_add_op_defs(x86_op_defs);
} }
typedef struct { typedef struct {

View File

@ -2352,6 +2352,18 @@ static const TCGTargetOpDef ia64_op_defs[] = {
{ -1 }, { -1 },
}; };
static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
{
int i, n = ARRAY_SIZE(ia64_op_defs);
for (i = 0; i < n; ++i) {
if (ia64_op_defs[i].op == op) {
return &ia64_op_defs[i];
}
}
return NULL;
}
/* Generate global QEMU prologue and epilogue code */ /* Generate global QEMU prologue and epilogue code */
static void tcg_target_qemu_prologue(TCGContext *s) static void tcg_target_qemu_prologue(TCGContext *s)
{ {
@ -2471,6 +2483,4 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R5); tcg_regset_set_reg(s->reserved_regs, TCG_REG_R5);
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R6); tcg_regset_set_reg(s->reserved_regs, TCG_REG_R6);
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R7); tcg_regset_set_reg(s->reserved_regs, TCG_REG_R7);
tcg_add_target_add_op_defs(ia64_op_defs);
} }

View File

@ -2262,6 +2262,18 @@ static const TCGTargetOpDef mips_op_defs[] = {
{ -1 }, { -1 },
}; };
static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
{
int i, n = ARRAY_SIZE(mips_op_defs);
for (i = 0; i < n; ++i) {
if (mips_op_defs[i].op == op) {
return &mips_op_defs[i];
}
}
return NULL;
}
static int tcg_target_callee_save_regs[] = { static int tcg_target_callee_save_regs[] = {
TCG_REG_S0, /* used for the global env (TCG_AREG0) */ TCG_REG_S0, /* used for the global env (TCG_AREG0) */
TCG_REG_S1, TCG_REG_S1,
@ -2563,8 +2575,6 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */ tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */ tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP); /* global pointer */ tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP); /* global pointer */
tcg_add_target_add_op_defs(mips_op_defs);
} }
void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr) void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)

View File

@ -2634,6 +2634,18 @@ static const TCGTargetOpDef ppc_op_defs[] = {
{ -1 }, { -1 },
}; };
static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
{
int i, n = ARRAY_SIZE(ppc_op_defs);
for (i = 0; i < n; ++i) {
if (ppc_op_defs[i].op == op) {
return &ppc_op_defs[i];
}
}
return NULL;
}
static void tcg_target_init(TCGContext *s) static void tcg_target_init(TCGContext *s)
{ {
unsigned long hwcap = qemu_getauxval(AT_HWCAP); unsigned long hwcap = qemu_getauxval(AT_HWCAP);
@ -2670,8 +2682,6 @@ static void tcg_target_init(TCGContext *s)
if (USE_REG_RA) { if (USE_REG_RA) {
tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return addr */ tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return addr */
} }
tcg_add_target_add_op_defs(ppc_op_defs);
} }
#ifdef __ELF__ #ifdef __ELF__

View File

@ -2326,6 +2326,18 @@ static const TCGTargetOpDef s390_op_defs[] = {
{ -1 }, { -1 },
}; };
static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
{
int i, n = ARRAY_SIZE(s390_op_defs);
for (i = 0; i < n; ++i) {
if (s390_op_defs[i].op == op) {
return &s390_op_defs[i];
}
}
return NULL;
}
static void query_s390_facilities(void) static void query_s390_facilities(void)
{ {
unsigned long hwcap = qemu_getauxval(AT_HWCAP); unsigned long hwcap = qemu_getauxval(AT_HWCAP);
@ -2368,8 +2380,6 @@ static void tcg_target_init(TCGContext *s)
/* XXX many insns can't be used with R0, so we better avoid it for now */ /* XXX many insns can't be used with R0, so we better avoid it for now */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0); tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0);
tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK); tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
tcg_add_target_add_op_defs(s390_op_defs);
} }
#define FRAME_SIZE ((int)(TCG_TARGET_CALL_STACK_OFFSET \ #define FRAME_SIZE ((int)(TCG_TARGET_CALL_STACK_OFFSET \

View File

@ -1583,6 +1583,18 @@ static const TCGTargetOpDef sparc_op_defs[] = {
{ -1 }, { -1 },
}; };
static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
{
int i, n = ARRAY_SIZE(sparc_op_defs);
for (i = 0; i < n; ++i) {
if (sparc_op_defs[i].op == op) {
return &sparc_op_defs[i];
}
}
return NULL;
}
static void tcg_target_init(TCGContext *s) static void tcg_target_init(TCGContext *s)
{ {
/* Only probe for the platform and capabilities if we havn't already /* Only probe for the platform and capabilities if we havn't already
@ -1622,8 +1634,6 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_set_reg(s->reserved_regs, TCG_REG_O6); /* stack pointer */ tcg_regset_set_reg(s->reserved_regs, TCG_REG_O6); /* stack pointer */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_T1); /* for internal use */ tcg_regset_set_reg(s->reserved_regs, TCG_REG_T1); /* for internal use */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_T2); /* for internal use */ tcg_regset_set_reg(s->reserved_regs, TCG_REG_T2); /* for internal use */
tcg_add_target_add_op_defs(sparc_op_defs);
} }
#if SPARC64 #if SPARC64

View File

@ -62,6 +62,7 @@
/* Forward declarations for functions declared in tcg-target.inc.c and /* Forward declarations for functions declared in tcg-target.inc.c and
used here. */ used here. */
static void tcg_target_init(TCGContext *s); static void tcg_target_init(TCGContext *s);
static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode);
static void tcg_target_qemu_prologue(TCGContext *s); static void tcg_target_qemu_prologue(TCGContext *s);
static void patch_reloc(tcg_insn_unit *code_ptr, int type, static void patch_reloc(tcg_insn_unit *code_ptr, int type,
intptr_t value, intptr_t addend); intptr_t value, intptr_t addend);
@ -319,6 +320,7 @@ static const TCGHelperInfo all_helpers[] = {
}; };
static int indirect_reg_alloc_order[ARRAY_SIZE(tcg_target_reg_alloc_order)]; static int indirect_reg_alloc_order[ARRAY_SIZE(tcg_target_reg_alloc_order)];
static void process_op_defs(TCGContext *s);
void tcg_context_init(TCGContext *s) void tcg_context_init(TCGContext *s)
{ {
@ -362,6 +364,7 @@ void tcg_context_init(TCGContext *s)
} }
tcg_target_init(s); tcg_target_init(s);
process_op_defs(s);
/* Reverse the order of the saved registers, assuming they're all at /* Reverse the order of the saved registers, assuming they're all at
the start of tcg_target_reg_alloc_order. */ the start of tcg_target_reg_alloc_order. */
@ -1221,29 +1224,33 @@ static void sort_constraints(TCGOpDef *def, int start, int n)
} }
} }
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs) static void process_op_defs(TCGContext *s)
{ {
TCGOpcode op; TCGOpcode op;
TCGOpDef *def;
const char *ct_str;
int i, nb_args;
for(;;) { for (op = 0; op < NB_OPS; op++) {
if (tdefs->op == (TCGOpcode)-1) TCGOpDef *def = &tcg_op_defs[op];
break; const TCGTargetOpDef *tdefs;
op = tdefs->op; int i, nb_args, ok;
tcg_debug_assert((unsigned)op < NB_OPS);
def = &tcg_op_defs[op]; if (def->flags & TCG_OPF_NOT_PRESENT) {
#if defined(CONFIG_DEBUG_TCG) continue;
/* Duplicate entry in op definitions? */ }
tcg_debug_assert(!def->used);
def->used = 1;
#endif
nb_args = def->nb_iargs + def->nb_oargs; nb_args = def->nb_iargs + def->nb_oargs;
for(i = 0; i < nb_args; i++) { if (nb_args == 0) {
ct_str = tdefs->args_ct_str[i]; continue;
/* Incomplete TCGTargetOpDef entry? */ }
tdefs = tcg_target_op_def(op);
/* Missing TCGTargetOpDef entry. */
tcg_debug_assert(tdefs != NULL);
for (i = 0; i < nb_args; i++) {
const char *ct_str = tdefs->args_ct_str[i];
/* Incomplete TCGTargetOpDef entry. */
tcg_debug_assert(ct_str != NULL); tcg_debug_assert(ct_str != NULL);
tcg_regset_clear(def->args_ct[i].u.regs); tcg_regset_clear(def->args_ct[i].u.regs);
def->args_ct[i].ct = 0; def->args_ct[i].ct = 0;
if (ct_str[0] >= '0' && ct_str[0] <= '9') { if (ct_str[0] >= '0' && ct_str[0] <= '9') {
@ -1272,11 +1279,9 @@ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
ct_str++; ct_str++;
break; break;
default: default:
if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) { ok = target_parse_constraint(&def->args_ct[i], &ct_str);
fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n", /* Typo in TCGTargetOpDef constraint. */
ct_str, i, def->name); tcg_debug_assert(ok == 0);
exit(1);
}
} }
} }
} }
@ -1288,42 +1293,7 @@ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
/* sort the constraints (XXX: this is just an heuristic) */ /* sort the constraints (XXX: this is just an heuristic) */
sort_constraints(def, 0, def->nb_oargs); sort_constraints(def, 0, def->nb_oargs);
sort_constraints(def, def->nb_oargs, def->nb_iargs); sort_constraints(def, def->nb_oargs, def->nb_iargs);
#if 0
{
int i;
printf("%s: sorted=", def->name);
for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
printf(" %d", def->sorted_args[i]);
printf("\n");
} }
#endif
tdefs++;
}
#if defined(CONFIG_DEBUG_TCG)
i = 0;
for (op = 0; op < tcg_op_defs_max; op++) {
const TCGOpDef *def = &tcg_op_defs[op];
if (def->flags & TCG_OPF_NOT_PRESENT) {
/* Wrong entry in op definitions? */
if (def->used) {
fprintf(stderr, "Invalid op definition for %s\n", def->name);
i = 1;
}
} else {
/* Missing entry in op definitions? */
if (!def->used) {
fprintf(stderr, "Missing op definition for %s\n", def->name);
i = 1;
}
}
}
if (i == 1) {
tcg_abort();
}
#endif
} }
void tcg_op_remove(TCGContext *s, TCGOp *op) void tcg_op_remove(TCGContext *s, TCGOp *op)

View File

@ -906,8 +906,6 @@ do {\
abort();\ abort();\
} while (0) } while (0)
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs);
#if UINTPTR_MAX == UINT32_MAX #if UINTPTR_MAX == UINT32_MAX
#define TCGV_NAT_TO_PTR(n) MAKE_TCGV_PTR(GET_TCGV_I32(n)) #define TCGV_NAT_TO_PTR(n) MAKE_TCGV_PTR(GET_TCGV_I32(n))
#define TCGV_PTR_TO_NAT(n) MAKE_TCGV_I32(GET_TCGV_PTR(n)) #define TCGV_PTR_TO_NAT(n) MAKE_TCGV_I32(GET_TCGV_PTR(n))

View File

@ -259,6 +259,18 @@ static const TCGTargetOpDef tcg_target_op_defs[] = {
{ -1 }, { -1 },
}; };
static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
{
int i, n = ARRAY_SIZE(tcg_target_op_defs);
for (i = 0; i < n; ++i) {
if (tcg_target_op_defs[i].op == op) {
return &tcg_target_op_defs[i];
}
}
return NULL;
}
static const int tcg_target_reg_alloc_order[] = { static const int tcg_target_reg_alloc_order[] = {
TCG_REG_R0, TCG_REG_R0,
TCG_REG_R1, TCG_REG_R1,
@ -875,7 +887,6 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_clear(s->reserved_regs); tcg_regset_clear(s->reserved_regs);
tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK); tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
tcg_add_target_add_op_defs(tcg_target_op_defs);
/* We use negative offsets from "sp" so that we can distinguish /* We use negative offsets from "sp" so that we can distinguish
stores that might pretend to be call arguments. */ stores that might pretend to be call arguments. */