diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index b66bfe623..b2f25c5b9 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -619,8 +619,8 @@ public: void VMOVLPOp(OpcodeArgs); void VMOVDDUPOp(OpcodeArgs); - void VMOVSHDUPOp(OpcodeArgs); - void VMOVSLDUPOp(OpcodeArgs); + void VMOVSHDUPOp(OpcodeArgs, bool IsAVX); + void VMOVSLDUPOp(OpcodeArgs, bool IsAVX); void VMOVSDOp(OpcodeArgs); void VMOVSSOp(OpcodeArgs); diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/SecondaryTables.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher/SecondaryTables.h index 47e012930..69893e1e3 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/SecondaryTables.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/SecondaryTables.h @@ -151,8 +151,8 @@ constexpr DispatchTableEntry OpDispatch_TwoByteOpTable[] = { constexpr DispatchTableEntry OpDispatch_SecondaryRepModTables[] = { {0x10, 2, &OpDispatchBuilder::MOVSSOp}, - {0x12, 1, &OpDispatchBuilder::VMOVSLDUPOp}, - {0x16, 1, &OpDispatchBuilder::VMOVSHDUPOp}, + {0x12, 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::VMOVSLDUPOp, false>}, + {0x16, 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::VMOVSHDUPOp, false>}, {0x2A, 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::InsertCVTGPR_To_FPR, OpSize::i32Bit>}, {0x2B, 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::MOVVectorNTOp, false>}, {0x2C, 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::CVTFPR_To_GPR, OpSize::i32Bit, false>}, diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index 5eed4cb6b..6f1b5dc8b 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -185,18 +185,28 @@ void OpDispatchBuilder::VMOVLPOp(OpcodeArgs) { } } -void OpDispatchBuilder::VMOVSHDUPOp(OpcodeArgs) { +void OpDispatchBuilder::VMOVSHDUPOp(OpcodeArgs, bool IsAVX) { const auto SrcSize = OpSizeFromSrc(Op); Ref Src = LoadSourceFPR(Op, Op->Src[0], Op->Flags); Ref Result = _VTrn2(SrcSize, OpSize::i32Bit, Src, Src); - StoreResultFPR(Op, Result); + + if (IsAVX) { + StoreResultFPR(Op, Result); + } else { + StoreResult_WithAVXInsert(VectorOpType::SSE, RegClass::FPR, Op, Result); + } } -void OpDispatchBuilder::VMOVSLDUPOp(OpcodeArgs) { +void OpDispatchBuilder::VMOVSLDUPOp(OpcodeArgs, bool IsAVX) { const auto SrcSize = OpSizeFromSrc(Op); Ref Src = LoadSourceFPR(Op, Op->Src[0], Op->Flags); Ref Result = _VTrn(SrcSize, OpSize::i32Bit, Src, Src); - StoreResultFPR(Op, Result); + + if (IsAVX) { + StoreResultFPR(Op, Result); + } else { + StoreResult_WithAVXInsert(VectorOpType::SSE, RegClass::FPR, Op, Result); + } } void OpDispatchBuilder::MOVScalarOpImpl(OpcodeArgs, IR::OpSize ElementSize) { diff --git a/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp b/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp index 372d5604a..c6f576509 100644 --- a/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp +++ b/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp @@ -474,7 +474,7 @@ namespace AVX256 { {OPD(1, 0b00, 0x12), 1, &OpDispatchBuilder::VMOVLPOp}, {OPD(1, 0b01, 0x12), 1, &OpDispatchBuilder::VMOVLPOp}, - {OPD(1, 0b10, 0x12), 1, &OpDispatchBuilder::VMOVSLDUPOp}, + {OPD(1, 0b10, 0x12), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::VMOVSLDUPOp, true>}, {OPD(1, 0b11, 0x12), 1, &OpDispatchBuilder::VMOVDDUPOp}, {OPD(1, 0b00, 0x13), 1, &OpDispatchBuilder::VMOVLPOp}, {OPD(1, 0b01, 0x13), 1, &OpDispatchBuilder::VMOVLPOp}, @@ -487,7 +487,7 @@ namespace AVX256 { {OPD(1, 0b00, 0x16), 1, &OpDispatchBuilder::VMOVHPOp}, {OPD(1, 0b01, 0x16), 1, &OpDispatchBuilder::VMOVHPOp}, - {OPD(1, 0b10, 0x16), 1, &OpDispatchBuilder::VMOVSHDUPOp}, + {OPD(1, 0b10, 0x16), 1, &OpDispatchBuilder::Bind<&OpDispatchBuilder::VMOVSHDUPOp, true>}, {OPD(1, 0b00, 0x17), 1, &OpDispatchBuilder::VMOVHPOp}, {OPD(1, 0b01, 0x17), 1, &OpDispatchBuilder::VMOVHPOp}, diff --git a/unittests/ASM/SSELanePreservation/movshdup.asm b/unittests/ASM/SSELanePreservation/movshdup.asm new file mode 100644 index 000000000..18e19d610 --- /dev/null +++ b/unittests/ASM/SSELanePreservation/movshdup.asm @@ -0,0 +1,24 @@ +%ifdef CONFIG +{ + "HostFeatures": ["AVX"], + "RegData": { + "XMM0": ["0xfdecd28ffdecd28f", "0x7d7ccd887d7ccd88", "0xccdbcfc31f3ff0f3", "0x108390defebac4be"], + "XMM1": ["0xfdecd28ffdecd28f", "0x7d7ccd887d7ccd88", "0", "0"] + } +} +%endif + +vmovapd ymm0, [rel .data] +vmovapd ymm1, [rel .data + (1 * 32)] + +movshdup xmm0, [rel .data] +vmovshdup xmm1, [rel .data] + +hlt + +align 32 +.data: +dq 0xfdecd28fab3fa4a5, 0x7d7ccd8836d09fc2, 0xccdbcfc31f3ff0f3, 0x108390defebac4be +dq 0x43cc1ad6970b4549, 0xbd7eb46a1278f793, 0xef673dac6e4cbb7b, 0x5b3d85d342718be9 +dq 0xc4be43cc1ad6970b, 0x4549bd7eb46a1278, 0xf793ef673dac6e4c, 0xbb7b5b3d85d34271 +dq 0x000043cc1ad6970b, 0x4549bd7eb46a1278, 0xf793ef673dac6e4c, 0xbb7b5b3d85d34271 diff --git a/unittests/ASM/SSELanePreservation/movsldup.asm b/unittests/ASM/SSELanePreservation/movsldup.asm new file mode 100644 index 000000000..e26d646a7 --- /dev/null +++ b/unittests/ASM/SSELanePreservation/movsldup.asm @@ -0,0 +1,24 @@ +%ifdef CONFIG +{ + "HostFeatures": ["AVX"], + "RegData": { + "XMM0": ["0xab3fa4a5ab3fa4a5", "0x36d09fc236d09fc2", "0xccdbcfc31f3ff0f3", "0x108390defebac4be"], + "XMM1": ["0xab3fa4a5ab3fa4a5", "0x36d09fc236d09fc2", "0", "0"] + } +} +%endif + +vmovapd ymm0, [rel .data] +vmovapd ymm1, [rel .data + (1 * 32)] + +movsldup xmm0, [rel .data] +vmovsldup xmm1, [rel .data] + +hlt + +align 32 +.data: +dq 0xfdecd28fab3fa4a5, 0x7d7ccd8836d09fc2, 0xccdbcfc31f3ff0f3, 0x108390defebac4be +dq 0x43cc1ad6970b4549, 0xbd7eb46a1278f793, 0xef673dac6e4cbb7b, 0x5b3d85d342718be9 +dq 0xc4be43cc1ad6970b, 0x4549bd7eb46a1278, 0xf793ef673dac6e4c, 0xbb7b5b3d85d34271 +dq 0x000043cc1ad6970b, 0x4549bd7eb46a1278, 0xf793ef673dac6e4c, 0xbb7b5b3d85d34271