From c06468025cf500f301a0db42d0344815faa8e1fe Mon Sep 17 00:00:00 2001 From: Simon Scherer Date: Thu, 9 Jul 2026 09:44:39 +0200 Subject: [PATCH 1/2] unittests/ASM: Test movd prefixed with 0x66 --- unittests/ASM/FEX_bugs/o16_movd.asm | 64 +++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 unittests/ASM/FEX_bugs/o16_movd.asm diff --git a/unittests/ASM/FEX_bugs/o16_movd.asm b/unittests/ASM/FEX_bugs/o16_movd.asm new file mode 100644 index 000000000..a1d7d7f37 --- /dev/null +++ b/unittests/ASM/FEX_bugs/o16_movd.asm @@ -0,0 +1,64 @@ +%ifdef CONFIG +{ + "RegData": { + "RAX": "0xDEADBEEF11223344", + "RBX": "0x0000000011223344", + "RCX": "0xFEEDFEED11223344", + "XMM0": [ + "0x0000000011223344", + "0x0000000000000000", + "0xDEADBEEFCAFEBABE", + "0xDEADBEEFCAFEBABE" + ], + "XMM3": [ + "0x0000000011223344", + "0x0000000000000000", + "0xDEADBEEFCAFEBABE", + "0xDEADBEEFCAFEBABE" + ] + } +} +%endif + +lea rdx, [rel .data] +vmovdqa ymm0, [rdx] + + +;; movd XMM, GREG +mov rax, 0xDEADBEEF11223344 + +o16 movd xmm0, eax + + +;; movd GREG, XMM +vmovdqa ymm1, [rdx + 32] +mov rbx, 0xDEADBEEFCAFEBABE + +o16 movd ebx, xmm1 + + +;; movd MEM, XMM +vmovdqa ymm2, [rdx + 32] +o16 movd dword [rdx + 64], xmm2 + +mov rcx, qword [rdx + 64] + + +;; movd XMM, MEM +vmovdqa ymm3, [rdx] + +o16 movd xmm3, dword [rdx + 72] + + +hlt + + +align 4096 +.data: +; YMM0, YMM3 init +dq 0xDEADBEEFCAFEBABE, 0xDEADBEEFCAFEBABE, 0xDEADBEEFCAFEBABE, 0xDEADBEEFCAFEBABE +; YMM1, YMM2 init +dq 0xDEADBEEF11223344, 0xDEADBEEFCAFEBABE, 0xDEADBEEFCAFEBABE, 0xDEADBEEFCAFEBABE +; movd MEM, XMM result +dq 0xFEEDFEEDFEEDFEED +dq 0xDEADBEEF11223344 \ No newline at end of file From 4d7890142023deee2c85b104d3fd7e5e56fd3c48 Mon Sep 17 00:00:00 2001 From: Simon Scherer Date: Thu, 9 Jul 2026 11:14:31 +0200 Subject: [PATCH 2/2] OpcodeDispatcher: Fix movd when prefixed with 0x66 --- .../Core/OpcodeDispatcher/Vector.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index f5cffe898..849c8b02c 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -2839,11 +2839,15 @@ void OpDispatchBuilder::MOVBetweenGPR_FPR(OpcodeArgs, VectorOpType VectorType) { if (Op->Src[0].IsGPR()) { // Loading from GPR and moving to Vector. Ref Src = LoadSourceFPR_WithOpSize(Op, Op->Src[0], GetGPROpSize(), Op->Flags); + + const auto SrcSize = std::max(OpSize::i32Bit, OpSizeFromSrc(Op)); // zext to 128bit - Result = _VCastFromGPR(OpSize::i128Bit, OpSizeFromSrc(Op), Src); + Result = _VCastFromGPR(OpSize::i128Bit, SrcSize, Src); } else { // Loading from Memory as a scalar. Zero extend - Result = LoadSourceFPR(Op, Op->Src[0], Op->Flags); + + const auto SrcSize = std::max(OpSize::i32Bit, OpSizeFromSrc(Op)); + Result = LoadSourceFPR_WithOpSize(Op, Op->Src[0], SrcSize, Op->Flags); } StoreResult_WithAVXInsert(VectorType, RegClass::FPR, Op, Result); @@ -2851,14 +2855,19 @@ void OpDispatchBuilder::MOVBetweenGPR_FPR(OpcodeArgs, VectorOpType VectorType) { Ref Src = LoadSourceFPR(Op, Op->Src[0], Op->Flags); if (Op->Dest.IsGPR()) { - const auto ElementSize = OpSizeFromDst(Op); + const auto DstSize = std::max(OpSize::i32Bit, OpSizeFromDst(Op)); + // Extract element from GPR. Zero extending in the process. - Src = _VExtractToGPR(OpSizeFromSrc(Op), ElementSize, Src, 0); + Src = _VExtractToGPR(OpSizeFromSrc(Op), DstSize, Src, 0); StoreResultGPR(Op, Op->Dest, Src); + + StoreResultGPR_WithOpSize(Op, Op->Dest, Src, DstSize); } else { + const auto DstSize = std::max(OpSize::i32Bit, OpSizeFromDst(Op)); + // Storing first element to memory. Ref Dest = LoadSourceGPR(Op, Op->Dest, Op->Flags, {.LoadData = false}); - _StoreMemFPR(OpSizeFromDst(Op), Dest, Src, OpSize::i8Bit); + _StoreMemFPR(DstSize, Dest, Src, OpSize::i8Bit); } } }