mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-23 13:45:40 +00:00
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. Backports commit f69d277ece43c42c7ab0144c2ff05ba740f6706b from qemu
This commit is contained in:
parent
551ef0a9f7
commit
b8c93597b4
|
@ -1827,6 +1827,18 @@ static const TCGTargetOpDef aarch64_op_defs[] = {
|
|||
{ -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)
|
||||
{
|
||||
tcg_regset_set32(s->tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
|
||||
|
@ -1849,8 +1861,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_TMP);
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_REG_X18); /* platform register */
|
||||
|
||||
tcg_add_target_add_op_defs(s, aarch64_op_defs);
|
||||
}
|
||||
|
||||
/* Saving pairs: (X19, X20) .. (X27, X28), (X29(fp), X30(lr)). */
|
||||
|
|
|
@ -2017,6 +2017,18 @@ static const TCGTargetOpDef arm_op_defs[] = {
|
|||
{ -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)
|
||||
{
|
||||
/* Only probe for the platform and capabilities if we havn't already
|
||||
|
@ -2047,8 +2059,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_TMP);
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC);
|
||||
|
||||
tcg_add_target_add_op_defs(s, arm_op_defs);
|
||||
}
|
||||
|
||||
static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
|
||||
|
|
|
@ -2431,6 +2431,18 @@ static const TCGTargetOpDef x86_op_defs[] = {
|
|||
{ -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[] = {
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
TCG_REG_RBP,
|
||||
|
@ -2592,6 +2604,4 @@ static void tcg_target_init(TCGContext *s)
|
|||
|
||||
tcg_regset_clear(s->reserved_regs);
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
|
||||
|
||||
tcg_add_target_add_op_defs(s, x86_op_defs);
|
||||
}
|
||||
|
|
|
@ -2276,6 +2276,18 @@ static const TCGTargetOpDef mips_op_defs[] = {
|
|||
{ -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[] = {
|
||||
TCG_REG_S0, /* used for the global env (TCG_AREG0) */
|
||||
TCG_REG_S1,
|
||||
|
@ -2578,8 +2590,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_SP); /* stack pointer */
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP); /* global pointer */
|
||||
|
||||
tcg_add_target_add_op_defs(s, mips_op_defs);
|
||||
}
|
||||
|
||||
void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
|
||||
|
|
|
@ -2625,6 +2625,18 @@ static const TCGTargetOpDef ppc_op_defs[] = {
|
|||
{ -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)
|
||||
{
|
||||
unsigned long hwcap = qemu_getauxval(AT_HWCAP);
|
||||
|
@ -2661,8 +2673,6 @@ static void tcg_target_init(TCGContext *s)
|
|||
if (USE_REG_RA) {
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return addr */
|
||||
}
|
||||
|
||||
tcg_add_target_add_op_defs(s, ppc_op_defs);
|
||||
}
|
||||
|
||||
#ifdef __ELF__
|
||||
|
|
|
@ -2350,6 +2350,18 @@ static void query_s390_facilities(void)
|
|||
}
|
||||
}
|
||||
|
||||
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 tcg_target_init(TCGContext *s)
|
||||
{
|
||||
query_s390_facilities();
|
||||
|
@ -2375,8 +2387,6 @@ static void tcg_target_init(TCGContext *s)
|
|||
/* 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_CALL_STACK);
|
||||
|
||||
tcg_add_target_add_op_defs(s, s390_op_defs);
|
||||
}
|
||||
|
||||
#define FRAME_SIZE ((int)(TCG_TARGET_CALL_STACK_OFFSET \
|
||||
|
|
|
@ -1585,6 +1585,18 @@ static const TCGTargetOpDef sparc_op_defs[] = {
|
|||
{ -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)
|
||||
{
|
||||
/* Only probe for the platform and capabilities if we havn't already
|
||||
|
@ -1624,8 +1636,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_T1); /* for internal use */
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_REG_T2); /* for internal use */
|
||||
|
||||
tcg_add_target_add_op_defs(s, sparc_op_defs);
|
||||
}
|
||||
|
||||
#if SPARC64
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
/* Forward declarations for functions declared in tcg-target.inc.c and
|
||||
used here. */
|
||||
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 patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
intptr_t value, intptr_t addend);
|
||||
|
@ -306,6 +307,8 @@ static const TCGHelperInfo all_helpers[] = {
|
|||
#include "exec/helper-tcg.h"
|
||||
};
|
||||
|
||||
static void process_op_defs(TCGContext *s);
|
||||
|
||||
void tcg_context_init(TCGContext *s)
|
||||
{
|
||||
int op, total_args, n, i;
|
||||
|
@ -352,6 +355,7 @@ void tcg_context_init(TCGContext *s)
|
|||
}
|
||||
|
||||
tcg_target_init(s);
|
||||
process_op_defs(s);
|
||||
|
||||
/* Reverse the order of the saved registers, assuming they're all at
|
||||
the start of tcg_target_reg_alloc_order. */
|
||||
|
@ -1265,29 +1269,33 @@ static void sort_constraints(TCGOpDef *def, int start, int n)
|
|||
}
|
||||
}
|
||||
|
||||
void tcg_add_target_add_op_defs(TCGContext *s, const TCGTargetOpDef *tdefs)
|
||||
static void process_op_defs(TCGContext *s)
|
||||
{
|
||||
TCGOpcode op;
|
||||
TCGOpDef *def;
|
||||
const char *ct_str;
|
||||
int i, nb_args;
|
||||
|
||||
for(;;) {
|
||||
if (tdefs->op == (TCGOpcode)-1)
|
||||
break;
|
||||
op = tdefs->op;
|
||||
tcg_debug_assert((unsigned)op < NB_OPS);
|
||||
def = &s->tcg_op_defs[op];
|
||||
#if defined(CONFIG_DEBUG_TCG)
|
||||
/* Duplicate entry in op definitions? */
|
||||
tcg_debug_assert(!def->used);
|
||||
def->used = 1;
|
||||
#endif
|
||||
for (op = 0; op < NB_OPS; op++) {
|
||||
TCGOpDef *def = &s->tcg_op_defs[op];
|
||||
const TCGTargetOpDef *tdefs;
|
||||
int i, nb_args, ok;
|
||||
|
||||
if (def->flags & TCG_OPF_NOT_PRESENT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nb_args = def->nb_iargs + def->nb_oargs;
|
||||
for(i = 0; i < nb_args; i++) {
|
||||
ct_str = tdefs->args_ct_str[i];
|
||||
/* Incomplete TCGTargetOpDef entry? */
|
||||
if (nb_args == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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_regset_clear(def->args_ct[i].u.regs);
|
||||
def->args_ct[i].ct = 0;
|
||||
if (ct_str[0] >= '0' && ct_str[0] <= '9') {
|
||||
|
@ -1316,11 +1324,9 @@ void tcg_add_target_add_op_defs(TCGContext *s, const TCGTargetOpDef *tdefs)
|
|||
ct_str++;
|
||||
break;
|
||||
default:
|
||||
if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
|
||||
fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
|
||||
ct_str, i, def->name);
|
||||
exit(1);
|
||||
}
|
||||
ok = target_parse_constraint(&def->args_ct[i], &ct_str);
|
||||
/* Typo in TCGTargetOpDef constraint. */
|
||||
tcg_debug_assert(ok == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1332,42 +1338,7 @@ void tcg_add_target_add_op_defs(TCGContext *s, const TCGTargetOpDef *tdefs)
|
|||
/* sort the constraints (XXX: this is just an heuristic) */
|
||||
sort_constraints(def, 0, def->nb_oargs);
|
||||
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_org_max; op++) {
|
||||
const TCGOpDef *def = &s->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)
|
||||
|
|
|
@ -1026,8 +1026,6 @@ do {\
|
|||
abort();\
|
||||
} while (0)
|
||||
|
||||
void tcg_add_target_add_op_defs(TCGContext *s, const TCGTargetOpDef *tdefs);
|
||||
|
||||
#if UINTPTR_MAX == UINT32_MAX
|
||||
#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))
|
||||
|
|
Loading…
Reference in a new issue