Per the Intel SDM (Vol 3, 15.2), writing an MMX register also sets bits 64-79 of the aliased x87 register to all 1s. gen_writeback() never does this for X86_OP_MMX destinations, so those bits keep whatever the x87 side left there (e.g. 0 after finit/fldz). A later x87 instruction such as fucomi/fucomip can then read a stale finite value where real hardware guarantees a NaN encoding, changing comparison results and flags.
Set the high 16 bits to 0xffff when writing back to a MMX register (not memory). Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4105 Signed-off-by: Simon Scherer <[email protected]> --- target/i386/tcg/emit.c.inc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index 473f415766..e2f0b4b1f7 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -352,6 +352,10 @@ static void gen_writeback(DisasContext *s, X86DecodedInsn *decode, int opn, TCGv } break; case X86_OP_MMX: + if (!op->has_ea) { + tcg_gen_st16_i32(tcg_constant_i32(0xffff), tcg_env, + MMX_OFFSET(op->n) + offsetof(floatx80, high)); + } break; case X86_OP_SSE: if (!op->has_ea && (s->prefix & PREFIX_VEX) && op->ot <= MO_128) { -- 2.53.0
