[PATCH v2] target/i386: Set aliased x87 exponent bits to all 1s for MMX register writes

Simon Scherer <[email protected]>
Newsgroups org.nongnu.qemu-devel
Message-ID <[email protected]>
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]>
Reviewed-by: Richard Henderson <[email protected]>
---
v2: use offsetof(CPUX86State, fpregs[op->n].d.high) directly instead of
    reusing MMX_OFFSET() + offsetof(floatx80, high), per Richard's review.

 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..2c36e41303 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,
+                             offsetof(CPUX86State, fpregs[op->n].d.high));
+        }
         break;
     case X86_OP_SSE:
         if (!op->has_ea && (s->prefix & PREFIX_VEX) && op->ot <= MO_128) {
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.