mirror of https://gitee.com/openkylin/qemu.git
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:
parent
c170cb6649
commit
8d918718ed
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue