diff options
Diffstat (limited to 'tcg/tcg.c')
| -rw-r--r-- | tcg/tcg.c | 173 |
1 files changed, 79 insertions, 94 deletions
diff --git a/tcg/tcg.c b/tcg/tcg.c index aabf94f365..cb898f1636 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -62,6 +62,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); @@ -95,7 +96,8 @@ static void tcg_register_jit_int(void *buf, size_t size, __attribute__((unused)); /* Forward declarations for functions declared and used in tcg-target.inc.c. */ -static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str); +static const char *target_parse_constraint(TCGArgConstraint *ct, + const char *ct_str, TCGType type); static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, intptr_t arg2); static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg); @@ -319,6 +321,7 @@ static const TCGHelperInfo all_helpers[] = { }; 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) { @@ -362,6 +365,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. */ @@ -1221,59 +1225,68 @@ 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; - 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 = &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 = &tcg_op_defs[op]; + const TCGTargetOpDef *tdefs; + TCGType type; + int i, nb_args; + + 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); + + type = (def->flags & TCG_OPF_64BIT ? TCG_TYPE_I64 : TCG_TYPE_I32); + 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') { - int oarg; - oarg = ct_str[0] - '0'; - tcg_debug_assert(oarg < def->nb_oargs); - tcg_debug_assert(def->args_ct[oarg].ct & TCG_CT_REG); - /* TCG_CT_ALIAS is for the output arguments. The input - argument is tagged with TCG_CT_IALIAS. */ - def->args_ct[i] = def->args_ct[oarg]; - def->args_ct[oarg].ct = TCG_CT_ALIAS; - def->args_ct[oarg].alias_index = i; - def->args_ct[i].ct |= TCG_CT_IALIAS; - def->args_ct[i].alias_index = oarg; - } else { - for(;;) { - if (*ct_str == '\0') - break; - switch(*ct_str) { - case 'i': - def->args_ct[i].ct |= TCG_CT_CONST; - 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); - } + while (*ct_str != '\0') { + switch(*ct_str) { + case '0' ... '9': + { + int oarg = *ct_str - '0'; + tcg_debug_assert(ct_str == tdefs->args_ct_str[i]); + tcg_debug_assert(oarg < def->nb_oargs); + tcg_debug_assert(def->args_ct[oarg].ct & TCG_CT_REG); + /* TCG_CT_ALIAS is for the output arguments. + The input is tagged with TCG_CT_IALIAS. */ + def->args_ct[i] = def->args_ct[oarg]; + def->args_ct[oarg].ct |= TCG_CT_ALIAS; + def->args_ct[oarg].alias_index = i; + def->args_ct[i].ct |= TCG_CT_IALIAS; + def->args_ct[i].alias_index = oarg; } + ct_str++; + break; + case '&': + def->args_ct[i].ct |= TCG_CT_NEWREG; + ct_str++; + break; + case 'i': + def->args_ct[i].ct |= TCG_CT_CONST; + ct_str++; + break; + default: + ct_str = target_parse_constraint(&def->args_ct[i], + ct_str, type); + /* Typo in TCGTargetOpDef constraint. */ + tcg_debug_assert(ct_str != NULL); } } } @@ -1284,42 +1297,7 @@ void tcg_add_target_add_op_defs(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_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) @@ -2208,7 +2186,8 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOpDef *def, TCGOpcode opc, const TCGArg *args, TCGLifeData arg_life) { - TCGRegSet allocated_regs; + TCGRegSet i_allocated_regs; + TCGRegSet o_allocated_regs; int i, k, nb_iargs, nb_oargs; TCGReg reg; TCGArg arg; @@ -2225,8 +2204,10 @@ static void tcg_reg_alloc_op(TCGContext *s, args + nb_oargs + nb_iargs, sizeof(TCGArg) * def->nb_cargs); + tcg_regset_set(i_allocated_regs, s->reserved_regs); + tcg_regset_set(o_allocated_regs, s->reserved_regs); + /* satisfy input constraints */ - tcg_regset_set(allocated_regs, s->reserved_regs); for(k = 0; k < nb_iargs; k++) { i = def->sorted_args[nb_oargs + k]; arg = args[i]; @@ -2241,7 +2222,7 @@ static void tcg_reg_alloc_op(TCGContext *s, goto iarg_end; } - temp_load(s, ts, arg_ct->u.regs, allocated_regs); + temp_load(s, ts, arg_ct->u.regs, i_allocated_regs); if (arg_ct->ct & TCG_CT_IALIAS) { if (ts->fixed_reg) { @@ -2275,13 +2256,13 @@ static void tcg_reg_alloc_op(TCGContext *s, allocate_in_reg: /* allocate a new register matching the constraint and move the temporary register into it */ - reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs, + reg = tcg_reg_alloc(s, arg_ct->u.regs, i_allocated_regs, ts->indirect_base); tcg_out_mov(s, ts->type, reg, ts->reg); } new_args[i] = reg; const_args[i] = 0; - tcg_regset_set_reg(allocated_regs, reg); + tcg_regset_set_reg(i_allocated_regs, reg); iarg_end: ; } @@ -2293,31 +2274,35 @@ static void tcg_reg_alloc_op(TCGContext *s, } if (def->flags & TCG_OPF_BB_END) { - tcg_reg_alloc_bb_end(s, allocated_regs); + tcg_reg_alloc_bb_end(s, i_allocated_regs); } else { if (def->flags & TCG_OPF_CALL_CLOBBER) { /* XXX: permit generic clobber register list ? */ for (i = 0; i < TCG_TARGET_NB_REGS; i++) { if (tcg_regset_test_reg(tcg_target_call_clobber_regs, i)) { - tcg_reg_free(s, i, allocated_regs); + tcg_reg_free(s, i, i_allocated_regs); } } } if (def->flags & TCG_OPF_SIDE_EFFECTS) { /* sync globals if the op has side effects and might trigger an exception. */ - sync_globals(s, allocated_regs); + sync_globals(s, i_allocated_regs); } /* satisfy the output constraints */ - tcg_regset_set(allocated_regs, s->reserved_regs); for(k = 0; k < nb_oargs; k++) { i = def->sorted_args[k]; arg = args[i]; arg_ct = &def->args_ct[i]; ts = &s->temps[arg]; - if (arg_ct->ct & TCG_CT_ALIAS) { + if ((arg_ct->ct & TCG_CT_ALIAS) + && !const_args[arg_ct->alias_index]) { reg = new_args[arg_ct->alias_index]; + } else if (arg_ct->ct & TCG_CT_NEWREG) { + reg = tcg_reg_alloc(s, arg_ct->u.regs, + i_allocated_regs | o_allocated_regs, + ts->indirect_base); } else { /* if fixed register, we try to use it */ reg = ts->reg; @@ -2325,10 +2310,10 @@ static void tcg_reg_alloc_op(TCGContext *s, tcg_regset_test_reg(arg_ct->u.regs, reg)) { goto oarg_end; } - reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs, + reg = tcg_reg_alloc(s, arg_ct->u.regs, o_allocated_regs, ts->indirect_base); } - tcg_regset_set_reg(allocated_regs, reg); + tcg_regset_set_reg(o_allocated_regs, reg); /* if a fixed register is used, then a move will be done afterwards */ if (!ts->fixed_reg) { if (ts->val_type == TEMP_VAL_REG) { @@ -2357,7 +2342,7 @@ static void tcg_reg_alloc_op(TCGContext *s, tcg_out_mov(s, ts->type, ts->reg, reg); } if (NEED_SYNC_ARG(i)) { - temp_sync(s, ts, allocated_regs, IS_DEAD_ARG(i)); + temp_sync(s, ts, o_allocated_regs, IS_DEAD_ARG(i)); } else if (IS_DEAD_ARG(i)) { temp_dead(s, ts); } |