diff options
Diffstat (limited to 'tcg/i386/tcg-target.c')
-rw-r--r-- | tcg/i386/tcg-target.c | 169 |
1 files changed, 113 insertions, 56 deletions
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index fafd900c5a..43a51a1c54 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -116,17 +116,7 @@ static inline int tcg_target_get_call_iarg_regs_count(int flags) return 6; } - flags &= TCG_CALL_TYPE_MASK; - switch(flags) { - case TCG_CALL_TYPE_STD: - return 0; - case TCG_CALL_TYPE_REGPARM_1: - case TCG_CALL_TYPE_REGPARM_2: - case TCG_CALL_TYPE_REGPARM: - return flags - TCG_CALL_TYPE_REGPARM_1 + 1; - default: - tcg_abort(); - } + return 0; } /* parse target specific constraints */ @@ -188,6 +178,9 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) tcg_regset_set32(ct->u.regs, 0, 0xffff); tcg_regset_reset_reg(ct->u.regs, TCG_REG_RSI); tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDI); +#ifdef CONFIG_TCG_PASS_AREG0 + tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDX); +#endif } else { tcg_regset_set32(ct->u.regs, 0, 0xff); tcg_regset_reset_reg(ct->u.regs, TCG_REG_EAX); @@ -967,6 +960,27 @@ static void tcg_out_jmp(TCGContext *s, tcg_target_long dest) #include "../../softmmu_defs.h" +#ifdef CONFIG_TCG_PASS_AREG0 +/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, + int mmu_idx) */ +static const void *qemu_ld_helpers[4] = { + helper_ldb_mmu, + helper_ldw_mmu, + helper_ldl_mmu, + helper_ldq_mmu, +}; + +/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr, + uintxx_t val, int mmu_idx) */ +static const void *qemu_st_helpers[4] = { + helper_stb_mmu, + helper_stw_mmu, + helper_stl_mmu, + helper_stq_mmu, +}; +#else +/* legacy helper signature: __ld_mmu(target_ulong addr, int + mmu_idx) */ static void *qemu_ld_helpers[4] = { __ldb_mmu, __ldw_mmu, @@ -974,12 +988,15 @@ static void *qemu_ld_helpers[4] = { __ldq_mmu, }; +/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val, + int mmu_idx) */ static void *qemu_st_helpers[4] = { __stb_mmu, __stw_mmu, __stl_mmu, __stq_mmu, }; +#endif /* Perform the TLB load and compare. @@ -1148,7 +1165,12 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int data_reg, data_reg2 = 0; int addrlo_idx; #if defined(CONFIG_SOFTMMU) - int mem_index, s_bits, arg_idx; + int mem_index, s_bits; +#if TCG_TARGET_REG_BITS == 64 + int arg_idx; +#else + int stack_adjust; +#endif uint8_t *label_ptr[3]; #endif @@ -1184,16 +1206,48 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, } /* XXX: move that code at the end of the TB */ +#if TCG_TARGET_REG_BITS == 32 + tcg_out_pushi(s, mem_index); + stack_adjust = 4; + if (TARGET_LONG_BITS == 64) { + tcg_out_push(s, args[addrlo_idx + 1]); + stack_adjust += 4; + } + tcg_out_push(s, args[addrlo_idx]); + stack_adjust += 4; +#ifdef CONFIG_TCG_PASS_AREG0 + tcg_out_push(s, TCG_AREG0); + stack_adjust += 4; +#endif +#else /* The first argument is already loaded with addrlo. */ arg_idx = 1; - if (TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 64) { - tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx++], - args[addrlo_idx + 1]); - } tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx], mem_index); +#ifdef CONFIG_TCG_PASS_AREG0 + /* XXX/FIXME: suboptimal */ + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3], + tcg_target_call_iarg_regs[2]); + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2], + tcg_target_call_iarg_regs[1]); + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1], + tcg_target_call_iarg_regs[0]); + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], + TCG_AREG0); +#endif +#endif + tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]); +#if TCG_TARGET_REG_BITS == 32 + if (stack_adjust == (TCG_TARGET_REG_BITS / 8)) { + /* Pop and discard. This is 2 bytes smaller than the add. */ + tcg_out_pop(s, TCG_REG_ECX); + } else if (stack_adjust != 0) { + tcg_out_addi(s, TCG_REG_CALL_STACK, stack_adjust); + } +#endif + switch(opc) { case 0 | 4: tcg_out_ext8s(s, data_reg, TCG_REG_EAX, P_REXW); @@ -1359,45 +1413,42 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, } /* XXX: move that code at the end of the TB */ - if (TCG_TARGET_REG_BITS == 64) { - tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32), - TCG_REG_RSI, data_reg); - tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index); - stack_adjust = 0; - } else if (TARGET_LONG_BITS == 32) { - tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, data_reg); - if (opc == 3) { - tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_ECX, data_reg2); - tcg_out_pushi(s, mem_index); - stack_adjust = 4; - } else { - tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index); - stack_adjust = 0; - } - } else { - if (opc == 3) { - tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, args[addrlo_idx + 1]); - tcg_out_pushi(s, mem_index); - tcg_out_push(s, data_reg2); - tcg_out_push(s, data_reg); - stack_adjust = 12; - } else { - tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, args[addrlo_idx + 1]); - switch(opc) { - case 0: - tcg_out_ext8u(s, TCG_REG_ECX, data_reg); - break; - case 1: - tcg_out_ext16u(s, TCG_REG_ECX, data_reg); - break; - case 2: - tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_ECX, data_reg); - break; - } - tcg_out_pushi(s, mem_index); - stack_adjust = 4; - } +#if TCG_TARGET_REG_BITS == 32 + tcg_out_pushi(s, mem_index); + stack_adjust = 4; + if (opc == 3) { + tcg_out_push(s, data_reg2); + stack_adjust += 4; } + tcg_out_push(s, data_reg); + stack_adjust += 4; + if (TARGET_LONG_BITS == 64) { + tcg_out_push(s, args[addrlo_idx + 1]); + stack_adjust += 4; + } + tcg_out_push(s, args[addrlo_idx]); + stack_adjust += 4; +#ifdef CONFIG_TCG_PASS_AREG0 + tcg_out_push(s, TCG_AREG0); + stack_adjust += 4; +#endif +#else + tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32), + TCG_REG_RSI, data_reg); + tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index); + stack_adjust = 0; +#ifdef CONFIG_TCG_PASS_AREG0 + /* XXX/FIXME: suboptimal */ + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3], + tcg_target_call_iarg_regs[2]); + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2], + tcg_target_call_iarg_regs[1]); + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1], + tcg_target_call_iarg_regs[0]); + tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], + TCG_AREG0); +#endif +#endif tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]); @@ -1962,9 +2013,15 @@ static void tcg_target_qemu_prologue(TCGContext *s) tcg_out_push(s, tcg_target_callee_save_regs[i]); } - tcg_out_addi(s, TCG_REG_ESP, -stack_addend); - +#if TCG_TARGET_REG_BITS == 32 + tcg_out_ld(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP, + (ARRAY_SIZE(tcg_target_callee_save_regs) + 1) * 4); + tcg_out_ld(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[1], TCG_REG_ESP, + (ARRAY_SIZE(tcg_target_callee_save_regs) + 2) * 4); +#else tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]); +#endif + tcg_out_addi(s, TCG_REG_ESP, -stack_addend); /* jmp *tb. */ tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, tcg_target_call_iarg_regs[1]); |