提交 b18212c6 编写于 作者: S Stefan Weil 提交者: Aurelien Jarno

tcg/i386: Add shortcuts for registers used in L constraint

While 64 bit hosts use the first three registers which are also used
as function input parameters, 32 bit hosts use TCG_REG_EAX and
TCG_REG_EDX which are not used in parameter passing.

After defining new register macros for the registers used in L
constraint, the patch replaces most occurrences of
tcg_target_call_iarg_regs[0], tcg_target_call_iarg_regs[1] and
tcg_target_call_iarg_regs[2] by those new macros.

tcg_target_call_iarg_regs remains unchanged when it is used for input
arguments (only with 64 bit hosts) before tcg_out_calli.

A comment related to those registers was fixed, too.
Signed-off-by: NStefan Weil <sw@weilnetz.de>
[aurel32: build fix on i386, small optimization for i386 in the prologue]
Signed-off-by: NAurelien Jarno <aurelien@aurel32.net>
上级 1b7621ad
...@@ -88,6 +88,18 @@ static const int tcg_target_call_oarg_regs[] = { ...@@ -88,6 +88,18 @@ static const int tcg_target_call_oarg_regs[] = {
#endif #endif
}; };
/* Registers used with L constraint, which are the first argument
registers on x86_64, and two random call clobbered registers on
i386. */
#if TCG_TARGET_REG_BITS == 64
# define TCG_REG_L0 tcg_target_call_iarg_regs[0]
# define TCG_REG_L1 tcg_target_call_iarg_regs[1]
# define TCG_REG_L2 tcg_target_call_iarg_regs[2]
#else
# define TCG_REG_L0 TCG_REG_EAX
# define TCG_REG_L1 TCG_REG_EDX
#endif
static uint8_t *tb_ret_addr; static uint8_t *tb_ret_addr;
static void patch_reloc(uint8_t *code_ptr, int type, static void patch_reloc(uint8_t *code_ptr, int type,
...@@ -179,16 +191,16 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) ...@@ -179,16 +191,16 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
/* qemu_ld/st address constraint */ /* qemu_ld/st address constraint */
case 'L': case 'L':
ct->ct |= TCG_CT_REG; ct->ct |= TCG_CT_REG;
if (TCG_TARGET_REG_BITS == 64) { #if TCG_TARGET_REG_BITS == 64
tcg_regset_set32(ct->u.regs, 0, 0xffff); tcg_regset_set32(ct->u.regs, 0, 0xffff);
tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[0]); tcg_regset_reset_reg(ct->u.regs, TCG_REG_L0);
tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[1]); tcg_regset_reset_reg(ct->u.regs, TCG_REG_L1);
tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[2]); tcg_regset_reset_reg(ct->u.regs, TCG_REG_L2);
} else { #else
tcg_regset_set32(ct->u.regs, 0, 0xff); tcg_regset_set32(ct->u.regs, 0, 0xff);
tcg_regset_reset_reg(ct->u.regs, TCG_REG_EAX); tcg_regset_reset_reg(ct->u.regs, TCG_REG_L0);
tcg_regset_reset_reg(ct->u.regs, TCG_REG_EDX); tcg_regset_reset_reg(ct->u.regs, TCG_REG_L1);
} #endif
break; break;
case 'e': case 'e':
...@@ -1029,8 +1041,8 @@ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx, ...@@ -1029,8 +1041,8 @@ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
uint8_t **label_ptr, int which) uint8_t **label_ptr, int which)
{ {
const int addrlo = args[addrlo_idx]; const int addrlo = args[addrlo_idx];
const int r0 = tcg_target_call_iarg_regs[0]; const int r0 = TCG_REG_L0;
const int r1 = tcg_target_call_iarg_regs[1]; const int r1 = TCG_REG_L1;
TCGType type = TCG_TYPE_I32; TCGType type = TCG_TYPE_I32;
int rexw = 0; int rexw = 0;
...@@ -1192,8 +1204,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, ...@@ -1192,8 +1204,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
label_ptr, offsetof(CPUTLBEntry, addr_read)); label_ptr, offsetof(CPUTLBEntry, addr_read));
/* TLB Hit. */ /* TLB Hit. */
tcg_out_qemu_ld_direct(s, data_reg, data_reg2, tcg_out_qemu_ld_direct(s, data_reg, data_reg2, TCG_REG_L0, 0, opc);
tcg_target_call_iarg_regs[0], 0, opc);
/* jmp label2 */ /* jmp label2 */
tcg_out8(s, OPC_JMP_short); tcg_out8(s, OPC_JMP_short);
...@@ -1226,14 +1237,10 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, ...@@ -1226,14 +1237,10 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx], tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx],
mem_index); mem_index);
/* XXX/FIXME: suboptimal */ /* XXX/FIXME: suboptimal */
tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3], tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3], TCG_REG_L2);
tcg_target_call_iarg_regs[2]); tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2], TCG_REG_L1);
tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2], tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1], TCG_REG_L0);
tcg_target_call_iarg_regs[1]); tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], TCG_AREG0);
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]); tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]);
...@@ -1299,11 +1306,9 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, ...@@ -1299,11 +1306,9 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
use the ADDR32 prefix. For now, do nothing. */ use the ADDR32 prefix. For now, do nothing. */
if (offset != GUEST_BASE) { if (offset != GUEST_BASE) {
tcg_out_movi(s, TCG_TYPE_I64, tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L0, GUEST_BASE);
tcg_target_call_iarg_regs[0], GUEST_BASE); tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_L0, base);
tgen_arithr(s, ARITH_ADD + P_REXW, base = TCG_REG_L0;
tcg_target_call_iarg_regs[0], base);
base = tcg_target_call_iarg_regs[0];
offset = 0; offset = 0;
} }
} }
...@@ -1324,8 +1329,8 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi, ...@@ -1324,8 +1329,8 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
/* ??? Ideally we wouldn't need a scratch register. For user-only, /* ??? Ideally we wouldn't need a scratch register. For user-only,
we could perform the bswap twice to restore the original value we could perform the bswap twice to restore the original value
instead of moving to the scratch. But as it is, the L constraint instead of moving to the scratch. But as it is, the L constraint
means that the second argument reg is definitely free here. */ means that TCG_REG_L1 is definitely free here. */
int scratch = tcg_target_call_iarg_regs[1]; const int scratch = TCG_REG_L1;
switch (sizeop) { switch (sizeop) {
case 0: case 0:
...@@ -1398,8 +1403,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, ...@@ -1398,8 +1403,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
label_ptr, offsetof(CPUTLBEntry, addr_write)); label_ptr, offsetof(CPUTLBEntry, addr_write));
/* TLB Hit. */ /* TLB Hit. */
tcg_out_qemu_st_direct(s, data_reg, data_reg2, tcg_out_qemu_st_direct(s, data_reg, data_reg2, TCG_REG_L0, 0, opc);
tcg_target_call_iarg_regs[0], 0, opc);
/* jmp label2 */ /* jmp label2 */
tcg_out8(s, OPC_JMP_short); tcg_out8(s, OPC_JMP_short);
...@@ -1434,18 +1438,14 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, ...@@ -1434,18 +1438,14 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
stack_adjust += 4; stack_adjust += 4;
#else #else
tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32), tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32),
tcg_target_call_iarg_regs[1], data_reg); TCG_REG_L1, data_reg);
tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2], mem_index); tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_L2, mem_index);
stack_adjust = 0; stack_adjust = 0;
/* XXX/FIXME: suboptimal */ /* XXX/FIXME: suboptimal */
tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3], tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3], TCG_REG_L2);
tcg_target_call_iarg_regs[2]); tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2], TCG_REG_L1);
tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2], tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1], TCG_REG_L0);
tcg_target_call_iarg_regs[1]); tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], TCG_AREG0);
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]); tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]);
...@@ -1472,11 +1472,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, ...@@ -1472,11 +1472,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
use the ADDR32 prefix. For now, do nothing. */ use the ADDR32 prefix. For now, do nothing. */
if (offset != GUEST_BASE) { if (offset != GUEST_BASE) {
tcg_out_movi(s, TCG_TYPE_I64, tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L0, GUEST_BASE);
tcg_target_call_iarg_regs[0], GUEST_BASE); tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_L0, base);
tgen_arithr(s, ARITH_ADD + P_REXW, base = TCG_REG_L0;
tcg_target_call_iarg_regs[0], base);
base = tcg_target_call_iarg_regs[0];
offset = 0; offset = 0;
} }
} }
...@@ -2061,15 +2059,17 @@ static void tcg_target_qemu_prologue(TCGContext *s) ...@@ -2061,15 +2059,17 @@ static void tcg_target_qemu_prologue(TCGContext *s)
#if TCG_TARGET_REG_BITS == 32 #if TCG_TARGET_REG_BITS == 32
tcg_out_ld(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP, tcg_out_ld(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP,
(ARRAY_SIZE(tcg_target_callee_save_regs) + 1) * 4); (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, tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
(ARRAY_SIZE(tcg_target_callee_save_regs) + 2) * 4); /* jmp *tb. */
tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, TCG_REG_ESP,
(ARRAY_SIZE(tcg_target_callee_save_regs) + 2) * 4
+ stack_addend);
#else #else
tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]); 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); tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
/* jmp *tb. */ /* jmp *tb. */
tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, tcg_target_call_iarg_regs[1]); tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, tcg_target_call_iarg_regs[1]);
#endif
/* TB epilogue */ /* TB epilogue */
tb_ret_addr = s->code_ptr; tb_ret_addr = s->code_ptr;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册