Per the Intel SDM, the CVTPI2PS and CVTPI2PD instructions cause a transition from x87 FPU to MMX technology operation (the x87 top-of-stack pointer is set to 0 and the tag word is set to all valid). CVTPI2PD's own description scopes this to the "xmm, mm" operand form only, explicitly excluding "xmm, m64". But CVTPI2PS's description states the transition unconditionally, without the same operand-form distinction.
Testing on real hardware shows CVTPI2PS actually behaves identically to CVTPI2PD despite the SDM wording: neither instruction performs the state transition when the source is a memory operand, only when it is an actual MMX register. This matches a similar Valgrind bug report and fix, see https://bugs.kde.org/show_bug.cgi?id=357059. gen_CVTPI2Px() currently calls gen_helper_enter_mmx() unconditionally, regardless of the source operand's form. Only call it when the source operand does not have an effective address, i.e. is a real MMX register. Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4394 Signed-off-by: Simon Scherer <[email protected]> --- target/i386/tcg/emit.c.inc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index c83ab80940..72c08beb2a 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -1919,7 +1919,15 @@ static void gen_CRC32(DisasContext *s, X86DecodedInsn *decode) static void gen_CVTPI2Px(DisasContext *s, X86DecodedInsn *decode) { - gen_helper_enter_mmx(tcg_env); + /* + * The x87->MMX transition only happens when the source is an MMX + * register, not for the memory-operand form. Confirmed on real + * hardware, contradicting the SDM's CVTPI2PS text. See + * https://bugs.kde.org/show_bug.cgi?id=357059. + */ + if (!decode->op[2].has_ea) { + gen_helper_enter_mmx(tcg_env); + } if (s->prefix & PREFIX_DATA) { gen_helper_cvtpi2pd(tcg_env, OP_PTR0, OP_PTR2); } else { -- 2.53.0
