mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-03-24 22:15:07 +00:00
tcg/i386: Extend addresses for 32-bit guests
Removing the ??? comment explaining why it (mostly) worked. Backports commit ee8ba9e4d8458b8bba5455a7ae704620c4f2ef4b from qemu
This commit is contained in:
parent
17c1f027c1
commit
95e666c547
|
@ -1537,8 +1537,8 @@ static inline void setup_guest_base_seg(TCGContext *s) { }
|
||||||
#endif /* SOFTMMU */
|
#endif /* SOFTMMU */
|
||||||
|
|
||||||
static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
|
static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
|
||||||
TCGReg base, intptr_t ofs, int seg,
|
TCGReg base, int index, intptr_t ofs,
|
||||||
TCGMemOp memop)
|
int seg, TCGMemOp memop)
|
||||||
{
|
{
|
||||||
const TCGMemOp real_bswap = memop & MO_BSWAP;
|
const TCGMemOp real_bswap = memop & MO_BSWAP;
|
||||||
TCGMemOp bswap = real_bswap;
|
TCGMemOp bswap = real_bswap;
|
||||||
|
@ -1551,13 +1551,16 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
|
||||||
|
|
||||||
switch (memop & MO_SSIZE) {
|
switch (memop & MO_SSIZE) {
|
||||||
case MO_UB:
|
case MO_UB:
|
||||||
tcg_out_modrm_offset(s, OPC_MOVZBL + seg, datalo, base, ofs);
|
tcg_out_modrm_sib_offset(s, OPC_MOVZBL + seg, datalo,
|
||||||
|
base, index, 0, ofs);
|
||||||
break;
|
break;
|
||||||
case MO_SB:
|
case MO_SB:
|
||||||
tcg_out_modrm_offset(s, OPC_MOVSBL + P_REXW + seg, datalo, base, ofs);
|
tcg_out_modrm_sib_offset(s, OPC_MOVSBL + P_REXW + seg, datalo,
|
||||||
|
base, index, 0, ofs);
|
||||||
break;
|
break;
|
||||||
case MO_UW:
|
case MO_UW:
|
||||||
tcg_out_modrm_offset(s, OPC_MOVZWL + seg, datalo, base, ofs);
|
tcg_out_modrm_sib_offset(s, OPC_MOVZWL + seg, datalo,
|
||||||
|
base, index, 0, ofs);
|
||||||
if (real_bswap) {
|
if (real_bswap) {
|
||||||
tcg_out_rolw_8(s, datalo);
|
tcg_out_rolw_8(s, datalo);
|
||||||
}
|
}
|
||||||
|
@ -1565,20 +1568,22 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
|
||||||
case MO_SW:
|
case MO_SW:
|
||||||
if (real_bswap) {
|
if (real_bswap) {
|
||||||
if (s->have_movbe) {
|
if (s->have_movbe) {
|
||||||
tcg_out_modrm_offset(s, OPC_MOVBE_GyMy + P_DATA16 + seg,
|
tcg_out_modrm_sib_offset(s, OPC_MOVBE_GyMy + P_DATA16 + seg,
|
||||||
datalo, base, ofs);
|
datalo, base, index, 0, ofs);
|
||||||
} else {
|
} else {
|
||||||
tcg_out_modrm_offset(s, OPC_MOVZWL + seg, datalo, base, ofs);
|
tcg_out_modrm_sib_offset(s, OPC_MOVZWL + seg, datalo,
|
||||||
|
base, index, 0, ofs);
|
||||||
tcg_out_rolw_8(s, datalo);
|
tcg_out_rolw_8(s, datalo);
|
||||||
}
|
}
|
||||||
tcg_out_modrm(s, OPC_MOVSWL + P_REXW, datalo, datalo);
|
tcg_out_modrm_sib_offset(s, OPC_MOVSWL + P_REXW + seg,
|
||||||
|
datalo, base, index, 0, ofs);
|
||||||
} else {
|
} else {
|
||||||
tcg_out_modrm_offset(s, OPC_MOVSWL + P_REXW + seg,
|
tcg_out_modrm_offset(s, OPC_MOVSWL + P_REXW + seg,
|
||||||
datalo, base, ofs);
|
datalo, base, ofs);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MO_UL:
|
case MO_UL:
|
||||||
tcg_out_modrm_offset(s, movop + seg, datalo, base, ofs);
|
tcg_out_modrm_sib_offset(s, movop + seg, datalo, base, index, 0, ofs);
|
||||||
if (bswap) {
|
if (bswap) {
|
||||||
tcg_out_bswap32(s, datalo);
|
tcg_out_bswap32(s, datalo);
|
||||||
}
|
}
|
||||||
|
@ -1586,19 +1591,22 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
|
||||||
#if TCG_TARGET_REG_BITS == 64
|
#if TCG_TARGET_REG_BITS == 64
|
||||||
case MO_SL:
|
case MO_SL:
|
||||||
if (real_bswap) {
|
if (real_bswap) {
|
||||||
tcg_out_modrm_offset(s, movop + seg, datalo, base, ofs);
|
tcg_out_modrm_sib_offset(s, movop + seg, datalo,
|
||||||
|
base, index, 0, ofs);
|
||||||
if (bswap) {
|
if (bswap) {
|
||||||
tcg_out_bswap32(s, datalo);
|
tcg_out_bswap32(s, datalo);
|
||||||
}
|
}
|
||||||
tcg_out_ext32s(s, datalo, datalo);
|
tcg_out_ext32s(s, datalo, datalo);
|
||||||
} else {
|
} else {
|
||||||
tcg_out_modrm_offset(s, OPC_MOVSLQ + seg, datalo, base, ofs);
|
tcg_out_modrm_sib_offset(s, OPC_MOVSLQ + seg, datalo,
|
||||||
|
base, index, 0, ofs);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case MO_Q:
|
case MO_Q:
|
||||||
if (TCG_TARGET_REG_BITS == 64) {
|
if (TCG_TARGET_REG_BITS == 64) {
|
||||||
tcg_out_modrm_offset(s, movop + P_REXW + seg, datalo, base, ofs);
|
tcg_out_modrm_sib_offset(s, movop + P_REXW + seg, datalo,
|
||||||
|
base, index, 0, ofs);
|
||||||
if (bswap) {
|
if (bswap) {
|
||||||
tcg_out_bswap64(s, datalo);
|
tcg_out_bswap64(s, datalo);
|
||||||
}
|
}
|
||||||
|
@ -1609,11 +1617,15 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
|
||||||
datahi = t;
|
datahi = t;
|
||||||
}
|
}
|
||||||
if (base != datalo) {
|
if (base != datalo) {
|
||||||
tcg_out_modrm_offset(s, movop + seg, datalo, base, ofs);
|
tcg_out_modrm_sib_offset(s, movop + seg, datalo,
|
||||||
tcg_out_modrm_offset(s, movop + seg, datahi, base, ofs + 4);
|
base, index, 0, ofs);
|
||||||
|
tcg_out_modrm_sib_offset(s, movop + seg, datahi,
|
||||||
|
base, index, 0, ofs + 4);
|
||||||
} else {
|
} else {
|
||||||
tcg_out_modrm_offset(s, movop + seg, datahi, base, ofs + 4);
|
tcg_out_modrm_sib_offset(s, movop + seg, datahi,
|
||||||
tcg_out_modrm_offset(s, movop + seg, datalo, base, ofs);
|
base, index, 0, ofs + 4);
|
||||||
|
tcg_out_modrm_sib_offset(s, movop + seg, datalo,
|
||||||
|
base, index, 0, ofs);
|
||||||
}
|
}
|
||||||
if (bswap) {
|
if (bswap) {
|
||||||
tcg_out_bswap32(s, datalo);
|
tcg_out_bswap32(s, datalo);
|
||||||
|
@ -1656,7 +1668,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
|
||||||
label_ptr, offsetof(CPUTLBEntry, addr_read));
|
label_ptr, offsetof(CPUTLBEntry, addr_read));
|
||||||
|
|
||||||
/* TLB Hit. */
|
/* TLB Hit. */
|
||||||
tcg_out_qemu_ld_direct(s, datalo, datahi, TCG_REG_L1, 0, 0, opc);
|
tcg_out_qemu_ld_direct(s, datalo, datahi, TCG_REG_L1, -1, 0, 0, opc);
|
||||||
|
|
||||||
/* Record the current context of a load into ldst label */
|
/* Record the current context of a load into ldst label */
|
||||||
add_qemu_ldst_label(s, true, oi, datalo, datahi, addrlo, addrhi,
|
add_qemu_ldst_label(s, true, oi, datalo, datahi, addrlo, addrhi,
|
||||||
|
@ -1665,24 +1677,33 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
|
||||||
{
|
{
|
||||||
int32_t offset = GUEST_BASE;
|
int32_t offset = GUEST_BASE;
|
||||||
TCGReg base = addrlo;
|
TCGReg base = addrlo;
|
||||||
|
int index = -1;
|
||||||
int seg = 0;
|
int seg = 0;
|
||||||
|
|
||||||
/* ??? We assume all operations have left us with register contents
|
/* For a 32-bit guest, the high 32 bits may contain garbage.
|
||||||
that are zero extended. So far this appears to be true. If we
|
We can do this with the ADDR32 prefix if we're not using
|
||||||
want to enforce this, we can either do an explicit zero-extension
|
a guest base, or when using segmentation. Otherwise we
|
||||||
here, or (if GUEST_BASE == 0, or a segment register is in use)
|
need to zero-extend manually. */
|
||||||
use the ADDR32 prefix. For now, do nothing. */
|
if (GUEST_BASE == 0 || guest_base_flags) {
|
||||||
if (GUEST_BASE && s->guest_base_flags) {
|
|
||||||
seg = s->guest_base_flags;
|
seg = s->guest_base_flags;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
} else if (TCG_TARGET_REG_BITS == 64 && offset != GUEST_BASE) {
|
if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
|
||||||
tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L1, GUEST_BASE);
|
seg |= P_ADDR32;
|
||||||
tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_L1, base);
|
}
|
||||||
base = TCG_REG_L1;
|
} else if (TCG_TARGET_REG_BITS == 64) {
|
||||||
offset = 0;
|
if (TARGET_LONG_BITS == 32) {
|
||||||
|
tcg_out_ext32u(s, TCG_REG_L0, base);
|
||||||
|
base = TCG_REG_L0;
|
||||||
|
}
|
||||||
|
if (offset != GUEST_BASE) {
|
||||||
|
tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L1, GUEST_BASE);
|
||||||
|
index = TCG_REG_L1;
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tcg_out_qemu_ld_direct(s, datalo, datahi, base, offset, seg, opc);
|
tcg_out_qemu_ld_direct(s, datalo, datahi,
|
||||||
|
base, index, offset, seg, opc);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1800,19 +1821,29 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
|
||||||
TCGReg base = addrlo;
|
TCGReg base = addrlo;
|
||||||
int seg = 0;
|
int seg = 0;
|
||||||
|
|
||||||
/* ??? We assume all operations have left us with register contents
|
/* See comment in tcg_out_qemu_ld re zero-extension of addrlo. */
|
||||||
that are zero extended. So far this appears to be true. If we
|
if (GUEST_BASE == 0 || guest_base_flags) {
|
||||||
want to enforce this, we can either do an explicit zero-extension
|
|
||||||
here, or (if GUEST_BASE == 0, or a segment register is in use)
|
|
||||||
use the ADDR32 prefix. For now, do nothing. */
|
|
||||||
if (GUEST_BASE && s->guest_base_flags) {
|
|
||||||
seg = s->guest_base_flags;
|
seg = s->guest_base_flags;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
} else if (TCG_TARGET_REG_BITS == 64 && offset != GUEST_BASE) {
|
if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
|
||||||
tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L1, GUEST_BASE);
|
seg |= P_ADDR32;
|
||||||
tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_L1, base);
|
}
|
||||||
|
} else if (TCG_TARGET_REG_BITS == 64) {
|
||||||
|
/* ??? Note that we can't use the same SIB addressing scheme
|
||||||
|
as for loads, since we require L0 free for bswap. */
|
||||||
|
if (offset != GUEST_BASE) {
|
||||||
|
if (TARGET_LONG_BITS == 32) {
|
||||||
|
tcg_out_ext32u(s, TCG_REG_L0, base);
|
||||||
|
base = TCG_REG_L0;
|
||||||
|
}
|
||||||
|
tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L1, GUEST_BASE);
|
||||||
|
tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_L1, base);
|
||||||
|
base = TCG_REG_L1;
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
} else if (TARGET_LONG_BITS == 32) {
|
||||||
|
tcg_out_ext32u(s, TCG_REG_L1, base);
|
||||||
base = TCG_REG_L1;
|
base = TCG_REG_L1;
|
||||||
offset = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tcg_out_qemu_st_direct(s, datalo, datahi, base, offset, seg, opc);
|
tcg_out_qemu_st_direct(s, datalo, datahi, base, offset, seg, opc);
|
||||||
|
|
Loading…
Reference in a new issue