tcg/i386: Add support for w64 ABI

w64 uses the registers rcx, rdx, r8 and r9 for function arguments,
so it needs a different declaration of tcg_target_call_iarg_regs.

rax, rcx, rdx, r8, r9, r10 and r11 may be changed by function calls.

rbx, rbp, rdi, rsi, r12, r13, r14 and r15 remain unchanged by function calls.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Stefan Weil <sw@weilnetz.de>
This commit is contained in:
Stefan Weil 2012-04-12 20:46:32 +02:00
parent c170cb6649
commit 8d918718ed
1 changed files with 28 additions and 11 deletions

View File

@ -63,10 +63,15 @@ static const int tcg_target_reg_alloc_order[] = {
static const int tcg_target_call_iarg_regs[] = { static const int tcg_target_call_iarg_regs[] = {
#if TCG_TARGET_REG_BITS == 64 #if TCG_TARGET_REG_BITS == 64
#if defined(_WIN64)
TCG_REG_RCX,
TCG_REG_RDX,
#else
TCG_REG_RDI, TCG_REG_RDI,
TCG_REG_RSI, TCG_REG_RSI,
TCG_REG_RDX, TCG_REG_RDX,
TCG_REG_RCX, TCG_REG_RCX,
#endif
TCG_REG_R8, TCG_REG_R8,
TCG_REG_R9, TCG_REG_R9,
#else #else
@ -176,10 +181,10 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
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_REG_RSI); tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[0]);
tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDI); tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[1]);
#ifdef CONFIG_TCG_PASS_AREG0 #ifdef CONFIG_TCG_PASS_AREG0
tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDX); tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[2]);
#endif #endif
} else { } else {
tcg_regset_set32(ct->u.regs, 0, 0xff); tcg_regset_set32(ct->u.regs, 0, 0xff);
@ -1300,9 +1305,12 @@ 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_REG_RDI, GUEST_BASE); tcg_out_movi(s, TCG_TYPE_I64,
tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_RDI, base); tcg_target_call_iarg_regs[0], GUEST_BASE);
base = TCG_REG_RDI, offset = 0; tgen_arithr(s, ARITH_ADD + P_REXW,
tcg_target_call_iarg_regs[0], base);
base = tcg_target_call_iarg_regs[0];
offset = 0;
} }
} }
@ -1434,8 +1442,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
#endif #endif
#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_REG_RSI, data_reg); tcg_target_call_iarg_regs[1], data_reg);
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index); tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2], mem_index);
stack_adjust = 0; stack_adjust = 0;
#ifdef CONFIG_TCG_PASS_AREG0 #ifdef CONFIG_TCG_PASS_AREG0
/* XXX/FIXME: suboptimal */ /* XXX/FIXME: suboptimal */
@ -1474,9 +1482,12 @@ 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_REG_RDI, GUEST_BASE); tcg_out_movi(s, TCG_TYPE_I64,
tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_RDI, base); tcg_target_call_iarg_regs[0], GUEST_BASE);
base = TCG_REG_RDI, offset = 0; tgen_arithr(s, ARITH_ADD + P_REXW,
tcg_target_call_iarg_regs[0], base);
base = tcg_target_call_iarg_regs[0];
offset = 0;
} }
} }
@ -1977,6 +1988,10 @@ 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,
TCG_REG_RBX, TCG_REG_RBX,
#if defined(_WIN64)
TCG_REG_RDI,
TCG_REG_RSI,
#endif
TCG_REG_R12, TCG_REG_R12,
TCG_REG_R13, TCG_REG_R13,
TCG_REG_R14, /* Currently used for the global env. */ TCG_REG_R14, /* Currently used for the global env. */
@ -2064,8 +2079,10 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EDX); tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EDX);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_ECX); tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_ECX);
if (TCG_TARGET_REG_BITS == 64) { if (TCG_TARGET_REG_BITS == 64) {
#if !defined(_WIN64)
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RDI); tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RDI);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RSI); tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RSI);
#endif
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R8); tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R8);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R9); tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R9);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R10); tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R10);