Last minute fixes for 2.4.

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJVsbQnAAoJEK0ScMxN0CebU/MIAKJf7l+T/pqSHEKU0nvBnKMf
 x+wEwv2KUqYaqqg1u03FSymYc7R7lAkIyAHegJwaB9QAifqUKmAIz4WXy98N+zrj
 3t/A8cfLlK/z92csR6FnL3RpqX2niTzy5pFbUbgrF5rzTFqDN/Z/jlkhvQfOBOtU
 CKyckUzRYzyM2YpHqguIYeL1uYQq25T9yXdja+3a+KXsr7nsn5ulyk4sI5E4a7Jj
 JOOp859gE7+6IQ0mdTgQBOPvNw/X7KjIWyoieOy662bR1rT6rcooQpKCGF/C5wxD
 qlgQsjXSfdVvrmzwAYh111+sAZ1KepRKXe0T3nYz1YO9VcGAlZAT9AlRjAffkxs=
 =8wGe
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20150723' into staging

Last minute fixes for 2.4.

# gpg: Signature made Fri Jul 24 04:42:31 2015 BST using RSA key ID 4DD0279B
# gpg: Good signature from "Richard Henderson <rth7680@gmail.com>"
# gpg:                 aka "Richard Henderson <rth@redhat.com>"
# gpg:                 aka "Richard Henderson <rth@twiddle.net>"

* remotes/rth/tags/pull-tcg-20150723:
  tcg/optimize: fix tcg_opt_gen_movi
  tcg/aarch64: use 32-bit offset for 32-bit softmmu emulation
  tcg/aarch64: use 32-bit offset for 32-bit user-mode emulation
  tcg/aarch64: add ext argument to tcg_out_insn_3310
  tcg/i386: Extend addresses for 32-bit guests

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2015-07-24 11:11:30 +01:00
commit 30fdfae49d
3 changed files with 109 additions and 70 deletions

View file

@ -280,7 +280,7 @@ typedef enum {
I3312_LDRSHX = 0x38000000 | LDST_LD_S_X << 22 | MO_16 << 30,
I3312_LDRSWX = 0x38000000 | LDST_LD_S_X << 22 | MO_32 << 30,
I3312_TO_I3310 = 0x00206800,
I3312_TO_I3310 = 0x00200800,
I3312_TO_I3313 = 0x01000000,
/* Load/store register pair instructions. */
@ -496,13 +496,14 @@ static void tcg_out_insn_3509(TCGContext *s, AArch64Insn insn, TCGType ext,
}
static void tcg_out_insn_3310(TCGContext *s, AArch64Insn insn,
TCGReg rd, TCGReg base, TCGReg regoff)
TCGReg rd, TCGReg base, TCGType ext,
TCGReg regoff)
{
/* Note the AArch64Insn constants above are for C3.3.12. Adjust. */
tcg_out32(s, insn | I3312_TO_I3310 | regoff << 16 | base << 5 | rd);
tcg_out32(s, insn | I3312_TO_I3310 | regoff << 16 |
0x4000 | ext << 13 | base << 5 | rd);
}
static void tcg_out_insn_3312(TCGContext *s, AArch64Insn insn,
TCGReg rd, TCGReg rn, intptr_t offset)
{
@ -677,7 +678,7 @@ static void tcg_out_ldst(TCGContext *s, AArch64Insn insn,
/* Worst-case scenario, move offset to temp register, use reg offset. */
tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, offset);
tcg_out_ldst_r(s, insn, rd, rn, TCG_REG_TMP);
tcg_out_ldst_r(s, insn, rd, rn, TCG_TYPE_I64, TCG_REG_TMP);
}
static inline void tcg_out_mov(TCGContext *s,
@ -1108,51 +1109,52 @@ static void tcg_out_tlb_read(TCGContext *s, TCGReg addr_reg, TCGMemOp s_bits,
#endif /* CONFIG_SOFTMMU */
static void tcg_out_qemu_ld_direct(TCGContext *s, TCGMemOp memop, TCGType ext,
TCGReg data_r, TCGReg addr_r, TCGReg off_r)
TCGReg data_r, TCGReg addr_r,
TCGType otype, TCGReg off_r)
{
const TCGMemOp bswap = memop & MO_BSWAP;
switch (memop & MO_SSIZE) {
case MO_UB:
tcg_out_ldst_r(s, I3312_LDRB, data_r, addr_r, off_r);
tcg_out_ldst_r(s, I3312_LDRB, data_r, addr_r, otype, off_r);
break;
case MO_SB:
tcg_out_ldst_r(s, ext ? I3312_LDRSBX : I3312_LDRSBW,
data_r, addr_r, off_r);
data_r, addr_r, otype, off_r);
break;
case MO_UW:
tcg_out_ldst_r(s, I3312_LDRH, data_r, addr_r, off_r);
tcg_out_ldst_r(s, I3312_LDRH, data_r, addr_r, otype, off_r);
if (bswap) {
tcg_out_rev16(s, data_r, data_r);
}
break;
case MO_SW:
if (bswap) {
tcg_out_ldst_r(s, I3312_LDRH, data_r, addr_r, off_r);
tcg_out_ldst_r(s, I3312_LDRH, data_r, addr_r, otype, off_r);
tcg_out_rev16(s, data_r, data_r);
tcg_out_sxt(s, ext, MO_16, data_r, data_r);
} else {
tcg_out_ldst_r(s, ext ? I3312_LDRSHX : I3312_LDRSHW,
data_r, addr_r, off_r);
tcg_out_ldst_r(s, (ext ? I3312_LDRSHX : I3312_LDRSHW),
data_r, addr_r, otype, off_r);
}
break;
case MO_UL:
tcg_out_ldst_r(s, I3312_LDRW, data_r, addr_r, off_r);
tcg_out_ldst_r(s, I3312_LDRW, data_r, addr_r, otype, off_r);
if (bswap) {
tcg_out_rev32(s, data_r, data_r);
}
break;
case MO_SL:
if (bswap) {
tcg_out_ldst_r(s, I3312_LDRW, data_r, addr_r, off_r);
tcg_out_ldst_r(s, I3312_LDRW, data_r, addr_r, otype, off_r);
tcg_out_rev32(s, data_r, data_r);
tcg_out_sxt(s, TCG_TYPE_I64, MO_32, data_r, data_r);
} else {
tcg_out_ldst_r(s, I3312_LDRSWX, data_r, addr_r, off_r);
tcg_out_ldst_r(s, I3312_LDRSWX, data_r, addr_r, otype, off_r);
}
break;
case MO_Q:
tcg_out_ldst_r(s, I3312_LDRX, data_r, addr_r, off_r);
tcg_out_ldst_r(s, I3312_LDRX, data_r, addr_r, otype, off_r);
if (bswap) {
tcg_out_rev64(s, data_r, data_r);
}
@ -1163,34 +1165,35 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGMemOp memop, TCGType ext,
}
static void tcg_out_qemu_st_direct(TCGContext *s, TCGMemOp memop,
TCGReg data_r, TCGReg addr_r, TCGReg off_r)
TCGReg data_r, TCGReg addr_r,
TCGType otype, TCGReg off_r)
{
const TCGMemOp bswap = memop & MO_BSWAP;
switch (memop & MO_SIZE) {
case MO_8:
tcg_out_ldst_r(s, I3312_STRB, data_r, addr_r, off_r);
tcg_out_ldst_r(s, I3312_STRB, data_r, addr_r, otype, off_r);
break;
case MO_16:
if (bswap && data_r != TCG_REG_XZR) {
tcg_out_rev16(s, TCG_REG_TMP, data_r);
data_r = TCG_REG_TMP;
}
tcg_out_ldst_r(s, I3312_STRH, data_r, addr_r, off_r);
tcg_out_ldst_r(s, I3312_STRH, data_r, addr_r, otype, off_r);
break;
case MO_32:
if (bswap && data_r != TCG_REG_XZR) {
tcg_out_rev32(s, TCG_REG_TMP, data_r);
data_r = TCG_REG_TMP;
}
tcg_out_ldst_r(s, I3312_STRW, data_r, addr_r, off_r);
tcg_out_ldst_r(s, I3312_STRW, data_r, addr_r, otype, off_r);
break;
case MO_64:
if (bswap && data_r != TCG_REG_XZR) {
tcg_out_rev64(s, TCG_REG_TMP, data_r);
data_r = TCG_REG_TMP;
}
tcg_out_ldst_r(s, I3312_STRX, data_r, addr_r, off_r);
tcg_out_ldst_r(s, I3312_STRX, data_r, addr_r, otype, off_r);
break;
default:
tcg_abort();
@ -1201,18 +1204,21 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
TCGMemOpIdx oi, TCGType ext)
{
TCGMemOp memop = get_memop(oi);
const TCGType otype = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
#ifdef CONFIG_SOFTMMU
unsigned mem_index = get_mmuidx(oi);
TCGMemOp s_bits = memop & MO_SIZE;
tcg_insn_unit *label_ptr;
tcg_out_tlb_read(s, addr_reg, s_bits, &label_ptr, mem_index, 1);
tcg_out_qemu_ld_direct(s, memop, ext, data_reg, addr_reg, TCG_REG_X1);
tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
TCG_REG_X1, otype, addr_reg);
add_qemu_ldst_label(s, true, oi, ext, data_reg, addr_reg,
s->code_ptr, label_ptr);
#else /* !CONFIG_SOFTMMU */
tcg_out_qemu_ld_direct(s, memop, ext, data_reg, addr_reg,
GUEST_BASE ? TCG_REG_GUEST_BASE : TCG_REG_XZR);
tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
GUEST_BASE ? TCG_REG_GUEST_BASE : TCG_REG_XZR,
otype, addr_reg);
#endif /* CONFIG_SOFTMMU */
}
@ -1220,18 +1226,21 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
TCGMemOpIdx oi)
{
TCGMemOp memop = get_memop(oi);
const TCGType otype = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
#ifdef CONFIG_SOFTMMU
unsigned mem_index = get_mmuidx(oi);
TCGMemOp s_bits = memop & MO_SIZE;
tcg_insn_unit *label_ptr;
tcg_out_tlb_read(s, addr_reg, s_bits, &label_ptr, mem_index, 0);
tcg_out_qemu_st_direct(s, memop, data_reg, addr_reg, TCG_REG_X1);
tcg_out_qemu_st_direct(s, memop, data_reg,
TCG_REG_X1, otype, addr_reg);
add_qemu_ldst_label(s, false, oi, s_bits == MO_64, data_reg, addr_reg,
s->code_ptr, label_ptr);
#else /* !CONFIG_SOFTMMU */
tcg_out_qemu_st_direct(s, memop, data_reg, addr_reg,
GUEST_BASE ? TCG_REG_GUEST_BASE : TCG_REG_XZR);
tcg_out_qemu_st_direct(s, memop, data_reg,
GUEST_BASE ? TCG_REG_GUEST_BASE : TCG_REG_XZR,
otype, addr_reg);
#endif /* CONFIG_SOFTMMU */
}

View file

@ -1434,8 +1434,8 @@ static inline void setup_guest_base_seg(void) { }
#endif /* SOFTMMU */
static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
TCGReg base, intptr_t ofs, int seg,
TCGMemOp memop)
TCGReg base, int index, intptr_t ofs,
int seg, TCGMemOp memop)
{
const TCGMemOp real_bswap = memop & MO_BSWAP;
TCGMemOp bswap = real_bswap;
@ -1448,13 +1448,16 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
switch (memop & MO_SSIZE) {
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;
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;
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) {
tcg_out_rolw_8(s, datalo);
}
@ -1462,20 +1465,21 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
case MO_SW:
if (real_bswap) {
if (have_movbe) {
tcg_out_modrm_offset(s, OPC_MOVBE_GyMy + P_DATA16 + seg,
datalo, base, ofs);
tcg_out_modrm_sib_offset(s, OPC_MOVBE_GyMy + P_DATA16 + seg,
datalo, base, index, 0, ofs);
} 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_modrm(s, OPC_MOVSWL + P_REXW, datalo, datalo);
} else {
tcg_out_modrm_offset(s, OPC_MOVSWL + P_REXW + seg,
datalo, base, ofs);
tcg_out_modrm_sib_offset(s, OPC_MOVSWL + P_REXW + seg,
datalo, base, index, 0, ofs);
}
break;
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) {
tcg_out_bswap32(s, datalo);
}
@ -1483,19 +1487,22 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
#if TCG_TARGET_REG_BITS == 64
case MO_SL:
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) {
tcg_out_bswap32(s, datalo);
}
tcg_out_ext32s(s, datalo, datalo);
} 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;
#endif
case MO_Q:
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) {
tcg_out_bswap64(s, datalo);
}
@ -1506,11 +1513,15 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
datahi = t;
}
if (base != datalo) {
tcg_out_modrm_offset(s, movop + seg, datalo, base, ofs);
tcg_out_modrm_offset(s, movop + seg, datahi, base, ofs + 4);
tcg_out_modrm_sib_offset(s, movop + seg, datalo,
base, index, 0, ofs);
tcg_out_modrm_sib_offset(s, movop + seg, datahi,
base, index, 0, ofs + 4);
} else {
tcg_out_modrm_offset(s, movop + seg, datahi, base, ofs + 4);
tcg_out_modrm_offset(s, movop + seg, datalo, base, ofs);
tcg_out_modrm_sib_offset(s, movop + seg, datahi,
base, index, 0, ofs + 4);
tcg_out_modrm_sib_offset(s, movop + seg, datalo,
base, index, 0, ofs);
}
if (bswap) {
tcg_out_bswap32(s, datalo);
@ -1553,7 +1564,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
label_ptr, offsetof(CPUTLBEntry, addr_read));
/* 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 */
add_qemu_ldst_label(s, true, oi, datalo, datahi, addrlo, addrhi,
@ -1562,24 +1573,33 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
{
int32_t offset = GUEST_BASE;
TCGReg base = addrlo;
int index = -1;
int seg = 0;
/* ??? We assume all operations have left us with register contents
that are zero extended. So far this appears to be true. If we
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 && guest_base_flags) {
/* For a 32-bit guest, the high 32 bits may contain garbage.
We can do this with the ADDR32 prefix if we're not using
a guest base, or when using segmentation. Otherwise we
need to zero-extend manually. */
if (GUEST_BASE == 0 || guest_base_flags) {
seg = guest_base_flags;
offset = 0;
} else if (TCG_TARGET_REG_BITS == 64 && offset != GUEST_BASE) {
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;
if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
seg |= P_ADDR32;
}
} else if (TCG_TARGET_REG_BITS == 64) {
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
}
@ -1697,19 +1717,29 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
TCGReg base = addrlo;
int seg = 0;
/* ??? We assume all operations have left us with register contents
that are zero extended. So far this appears to be true. If we
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 && guest_base_flags) {
/* See comment in tcg_out_qemu_ld re zero-extension of addrlo. */
if (GUEST_BASE == 0 || guest_base_flags) {
seg = guest_base_flags;
offset = 0;
} else if (TCG_TARGET_REG_BITS == 64 && offset != GUEST_BASE) {
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;
if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
seg |= P_ADDR32;
}
} 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;
}
}
tcg_out_qemu_st_direct(s, datalo, datahi, base, offset, seg, opc);

View file

@ -205,7 +205,7 @@ static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op, TCGArg *args,
temps[dst].state = TCG_TEMP_CONST;
temps[dst].val = val;
mask = val;
if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_mov_i32) {
if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_movi_i32) {
/* High bits of the destination are now garbage. */
mask |= ~0xffffffffull;
}