From 815cdc5b3cddcc5d104611fcbcb5c080d7eca184 Mon Sep 17 00:00:00 2001 From: lioncash Date: Tue, 22 Nov 2022 03:01:42 +0000 Subject: [PATCH] OpcodeDispatcher: Handle VMOVSHDUP --- .../Interface/Core/OpcodeDispatcher.cpp | 1 + .../Source/Interface/Core/OpcodeDispatcher.h | 2 + .../Core/OpcodeDispatcher/Vector.cpp | 15 +++++++ .../Interface/Core/X86Tables/VEXTables.cpp | 2 +- unittests/ASM/VEX/vmovshdup.asm | 41 +++++++++++++++++++ 5 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 unittests/ASM/VEX/vmovshdup.asm diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index d68a0dfe4..efc39185c 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -5701,6 +5701,7 @@ void OpDispatchBuilder::InstallHostSpecificOpcodeHandlers() { {OPD(1, 0b00, 0x16), 1, &OpDispatchBuilder::VMOVHPOp}, {OPD(1, 0b01, 0x16), 1, &OpDispatchBuilder::VMOVHPOp}, + {OPD(1, 0b10, 0x16), 1, &OpDispatchBuilder::VMOVSHDUPOp}, {OPD(1, 0b00, 0x17), 1, &OpDispatchBuilder::VMOVHPOp}, {OPD(1, 0b01, 0x17), 1, &OpDispatchBuilder::VMOVHPOp}, diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 1e6a72aa0..0a2948848 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -411,6 +411,8 @@ public: void VMOVHPOp(OpcodeArgs); void VMOVLPOp(OpcodeArgs); + void VMOVSHDUPOp(OpcodeArgs); + // X87 Ops template void FLD(OpcodeArgs); diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index 873fbd15f..9205a9151 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -146,6 +146,21 @@ void OpDispatchBuilder::MOVSHDUPOp(OpcodeArgs) { StoreResult(FPRClass, Op, Result, -1); } +void OpDispatchBuilder::VMOVSHDUPOp(OpcodeArgs) { + OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1); + const auto SrcSize = GetSrcSize(Op); + const auto Is256Bit = SrcSize == Core::CPUState::XMM_AVX_REG_SIZE; + + OrderedNode *Result = _VInsElement(SrcSize, 4, 2, 3, Src, Src); + Result = _VInsElement(SrcSize, 4, 0, 1, Result, Src); + if (Is256Bit) { + Result = _VInsElement(SrcSize, 4, 4, 5, Result, Src); + Result = _VInsElement(SrcSize, 4, 6, 7, Result, Src); + } + + StoreResult_WithOpSize(FPRClass, Op, Op->Dest, Result, 32, -1); +} + void OpDispatchBuilder::MOVSLDUPOp(OpcodeArgs) { OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, 8); OrderedNode *Result = _VInsElement(16, 4, 3, 2, Src, Src); diff --git a/External/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp b/External/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp index 4fa036f93..aa1884f81 100644 --- a/External/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp +++ b/External/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp @@ -43,7 +43,7 @@ void InitializeVEXTables() { {OPD(1, 0b00, 0x16), 1, X86InstInfo{"VMOVHPS", TYPE_INST, GenFlagsSizes(SIZE_128BIT, SIZE_64BIT) | FLAGS_MODRM | FLAGS_SF_MOD_MEM_ONLY | FLAGS_XMM_FLAGS | FLAGS_VEX_1ST_SRC, 0, nullptr}}, {OPD(1, 0b01, 0x16), 1, X86InstInfo{"VMOVHPD", TYPE_INST, GenFlagsSizes(SIZE_128BIT, SIZE_64BIT) | FLAGS_MODRM | FLAGS_SF_MOD_MEM_ONLY | FLAGS_XMM_FLAGS | FLAGS_VEX_1ST_SRC, 0, nullptr}}, - {OPD(1, 0b10, 0x16), 1, X86InstInfo{"VMOVSHDUP", TYPE_UNDEC, FLAGS_NONE, 0, nullptr}}, + {OPD(1, 0b10, 0x16), 1, X86InstInfo{"VMOVSHDUP", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}}, {OPD(1, 0b00, 0x17), 1, X86InstInfo{"VMOVHPS", TYPE_INST, GenFlagsSizes(SIZE_64BIT, SIZE_128BIT) | FLAGS_MODRM | FLAGS_SF_MOD_MEM_ONLY | FLAGS_SF_MOD_DST | FLAGS_XMM_FLAGS, 0, nullptr}}, {OPD(1, 0b01, 0x17), 1, X86InstInfo{"VMOVHPD", TYPE_INST, GenFlagsSizes(SIZE_64BIT, SIZE_128BIT) | FLAGS_MODRM | FLAGS_SF_MOD_MEM_ONLY | FLAGS_SF_MOD_DST | FLAGS_XMM_FLAGS, 0, nullptr}}, diff --git a/unittests/ASM/VEX/vmovshdup.asm b/unittests/ASM/VEX/vmovshdup.asm new file mode 100644 index 000000000..464f78bc3 --- /dev/null +++ b/unittests/ASM/VEX/vmovshdup.asm @@ -0,0 +1,41 @@ +%ifdef CONFIG +{ + "HostFeatures": ["AVX"], + "RegData": { + "XMM1": ["0xEEEEEEEEEEEEEEEE", "0xCCCCCCCCCCCCCCCC", "0xAAAAAAAAAAAAAAAA", "0x0808080808080808"], + "XMM2": ["0xEEEEEEEEEEEEEEEE", "0xCCCCCCCCCCCCCCCC", "0x0000000000000000", "0x0000000000000000"], + "XMM3": ["0xEEEEEEEEFFFFFFFF", "0xCCCCCCCCDDDDDDDD", "0xAAAAAAAABBBBBBBB", "0x0808080809090909"], + "XMM4": ["0xEEEEEEEEEEEEEEEE", "0xCCCCCCCCCCCCCCCC", "0xAAAAAAAAAAAAAAAA", "0x0808080808080808"], + "XMM5": ["0xEEEEEEEEEEEEEEEE", "0xCCCCCCCCCCCCCCCC", "0x0000000000000000", "0x0000000000000000"], + "XMM6": ["0xEEEEEEEEEEEEEEEE", "0xCCCCCCCCCCCCCCCC", "0xAAAAAAAAAAAAAAAA", "0x0808080808080808"], + "XMM7": ["0xEEEEEEEEEEEEEEEE", "0xCCCCCCCCCCCCCCCC", "0x0000000000000000", "0x0000000000000000"] + } +} +%endif + +lea rdx, [rel .data] + +;; Broadcast across self +vmovaps ymm1, [rdx] +vmovshdup ymm1, ymm1 +; 128-bit version +vmovaps xmm2, [rdx] +vmovshdup xmm2, xmm2 + +;; Broadcast from different registers +vmovaps ymm3, [rdx] +vmovshdup ymm4, ymm3 +; 128-bit version +vmovshdup xmm5, xmm3 + +;; Broadcast from memory +vmovshdup ymm6, [rdx] +; 128-bit version +vmovshdup xmm7, [rdx] + +hlt + +align 32 +.data: +db 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0xEE, 0xEE, 0xEE, 0xDD, 0xDD, 0xDD, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC +db 0xBB, 0xBB, 0xBB, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08