Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
tcg/i386: Honor 64-bit atomicity in 32-bit mode
Use the fpu to perform 64-bit loads and stores.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
  • Loading branch information
rth7680 committed May 16, 2023
1 parent 5db1106 commit 8f04e29
Showing 1 changed file with 38 additions and 6 deletions.
44 changes: 38 additions & 6 deletions tcg/i386/tcg-target.c.inc
Expand Up @@ -468,6 +468,10 @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
#define OPC_GRP5 (0xff)
#define OPC_GRP14 (0x73 | P_EXT | P_DATA16)

#define OPC_ESCDF (0xdf)
#define ESCDF_FILD_m64 5
#define ESCDF_FISTP_m64 7

/* Group 1 opcode extensions for 0x80-0x83.
These are also used as modifiers for OPC_ARITH. */
#define ARITH_ADD 0
Expand Down Expand Up @@ -2086,7 +2090,20 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
datalo = datahi;
datahi = t;
}
if (h.base == datalo || h.index == datalo) {
if (h.aa.atom == MO_64) {
/*
* Atomicity requires that we use use a single 8-byte load.
* For simplicity and code size, always use the FPU for this.
* Similar insns using SSE/AVX are merely larger.
* Load from memory in one go, then store back to the stack,
* from whence we can load into the correct integer regs.
*/
tcg_out_modrm_sib_offset(s, OPC_ESCDF + h.seg, ESCDF_FILD_m64,
h.base, h.index, 0, h.ofs);
tcg_out_modrm_offset(s, OPC_ESCDF, ESCDF_FISTP_m64, TCG_REG_ESP, 0);
tcg_out_modrm_offset(s, movop, datalo, TCG_REG_ESP, 0);
tcg_out_modrm_offset(s, movop, datahi, TCG_REG_ESP, 4);
} else if (h.base == datalo || h.index == datalo) {
tcg_out_modrm_sib_offset(s, OPC_LEA, datahi,
h.base, h.index, 0, h.ofs);
tcg_out_modrm_offset(s, movop + h.seg, datalo, datahi, 0);
Expand Down Expand Up @@ -2156,12 +2173,27 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
if (TCG_TARGET_REG_BITS == 64) {
tcg_out_modrm_sib_offset(s, movop + P_REXW + h.seg, datalo,
h.base, h.index, 0, h.ofs);
break;
}
if (use_movbe) {
TCGReg t = datalo;
datalo = datahi;
datahi = t;
}
if (h.aa.atom == MO_64) {
/*
* Atomicity requires that we use use one 8-byte store.
* For simplicity, and code size, always use the FPU for this.
* Similar insns using SSE/AVX are merely larger.
* Assemble the 8-byte quantity in required endianness
* on the stack, load to coproc unit, and store.
*/
tcg_out_modrm_offset(s, movop, datalo, TCG_REG_ESP, 0);
tcg_out_modrm_offset(s, movop, datahi, TCG_REG_ESP, 4);
tcg_out_modrm_offset(s, OPC_ESCDF, ESCDF_FILD_m64, TCG_REG_ESP, 0);
tcg_out_modrm_sib_offset(s, OPC_ESCDF + h.seg, ESCDF_FISTP_m64,
h.base, h.index, 0, h.ofs);
} else {
if (use_movbe) {
TCGReg t = datalo;
datalo = datahi;
datahi = t;
}
tcg_out_modrm_sib_offset(s, movop + h.seg, datalo,
h.base, h.index, 0, h.ofs);
tcg_out_modrm_sib_offset(s, movop + h.seg, datahi,
Expand Down

0 comments on commit 8f04e29

Please sign in to comment.