From ac5d09885eeaa86118dc042fb366fc4d7f976e07 Mon Sep 17 00:00:00 2001 From: Lioncache Date: Mon, 13 Feb 2023 12:41:57 -0500 Subject: [PATCH] OpcodeDispatcher: Handle VPSHUFB --- .../Interface/Core/OpcodeDispatcher.cpp | 1 + .../Source/Interface/Core/OpcodeDispatcher.h | 2 + .../Core/OpcodeDispatcher/Vector.cpp | 19 +++++- .../Interface/Core/X86Tables/VEXTables.cpp | 2 +- unittests/ASM/VEX/vpshufb.asm | 62 +++++++++++++++++++ 5 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 unittests/ASM/VEX/vpshufb.asm diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 281e10bbf..0d68f3e48 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -6013,6 +6013,7 @@ void OpDispatchBuilder::InstallHostSpecificOpcodeHandlers() { {OPD(1, 0b01, 0xFD), 1, &OpDispatchBuilder::AVXVectorALUOp}, {OPD(1, 0b01, 0xFE), 1, &OpDispatchBuilder::AVXVectorALUOp}, + {OPD(2, 0b01, 0x00), 1, &OpDispatchBuilder::VPSHUFBOp}, {OPD(2, 0b01, 0x01), 1, &OpDispatchBuilder::VHADDPOp}, {OPD(2, 0b01, 0x02), 1, &OpDispatchBuilder::VHADDPOp}, diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 5e730df46..89c30138e 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -493,6 +493,8 @@ public: template void VPMULLOp(OpcodeArgs); + void VPSHUFBOp(OpcodeArgs); + template void VPSLLOp(OpcodeArgs); void VPSLLDQOp(OpcodeArgs); diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index 13235fecf..6ce5d8845 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -969,6 +969,11 @@ OrderedNode* OpDispatchBuilder::PSHUFBOpImpl(OpcodeArgs, const X86Tables::Decode OrderedNode *Src2Node = LoadSource(FPRClass, Op, Src2, Op->Flags, -1); const auto SrcSize = GetSrcSize(Op); + const auto Is256Bit = SrcSize == Core::CPUState::XMM_AVX_REG_SIZE; + + // We perform the 256-bit version as two 128-bit operations due to + // the lane splitting behavior, so cap the maximum size at 16. + const auto SanitizedSrcSize = std::min(SrcSize, uint8_t{16}); // PSHUFB doesn't 100% match VTBL behaviour // VTBL will set the element zero if the index is greater than @@ -984,7 +989,14 @@ OrderedNode* OpDispatchBuilder::PSHUFBOpImpl(OpcodeArgs, const X86Tables::Decode OrderedNode *MaskVector = _VectorImm(SrcSize, 1, MaskImm); OrderedNode *MaskedIndices = _VAnd(SrcSize, SrcSize, Src2Node, MaskVector); - return _VTBL1(SrcSize, Src1Node, MaskedIndices); + OrderedNode *Low = _VTBL1(SanitizedSrcSize, Src1Node, MaskedIndices); + if (!Is256Bit) { + return Low; + } + + OrderedNode *HighSrc1 = _VInsElement(SrcSize, 16, 0, 1, Src1Node, Src1Node); + OrderedNode *High = _VTBL1(SanitizedSrcSize, HighSrc1, MaskedIndices); + return _VInsElement(SrcSize, 16, 1, 0, Low, High); } void OpDispatchBuilder::PSHUFBOp(OpcodeArgs) { @@ -992,6 +1004,11 @@ void OpDispatchBuilder::PSHUFBOp(OpcodeArgs) { StoreResult(FPRClass, Op, Result, -1); } +void OpDispatchBuilder::VPSHUFBOp(OpcodeArgs) { + OrderedNode *Result = PSHUFBOpImpl(Op, Op->Src[0], Op->Src[1]); + StoreResult(FPRClass, Op, Result, -1); +} + template void OpDispatchBuilder::PSHUFDOp(OpcodeArgs) { static_assert(ElementSize != 0); diff --git a/External/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp b/External/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp index c70ab87fa..8b99e24d6 100644 --- a/External/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp +++ b/External/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp @@ -259,7 +259,7 @@ void InitializeVEXTables() { {OPD(1, 0b01, 0xFE), 1, X86InstInfo{"VPADDD", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_VEX_1ST_SRC | FLAGS_XMM_FLAGS, 0, nullptr}}, // VEX Map 2 - {OPD(2, 0b01, 0x00), 1, X86InstInfo{"VPSHUFB", TYPE_UNDEC, FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}}, + {OPD(2, 0b01, 0x00), 1, X86InstInfo{"VPSHUFB", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_VEX_1ST_SRC | FLAGS_XMM_FLAGS, 0, nullptr}}, {OPD(2, 0b01, 0x01), 1, X86InstInfo{"VPHADDW", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_VEX_1ST_SRC | FLAGS_XMM_FLAGS, 0, nullptr}}, {OPD(2, 0b01, 0x02), 1, X86InstInfo{"VPHADDD", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_VEX_1ST_SRC | FLAGS_XMM_FLAGS, 0, nullptr}}, {OPD(2, 0b01, 0x03), 1, X86InstInfo{"VPHADDSW", TYPE_UNDEC, FLAGS_NONE, 0, nullptr}}, diff --git a/unittests/ASM/VEX/vpshufb.asm b/unittests/ASM/VEX/vpshufb.asm new file mode 100644 index 000000000..861020764 --- /dev/null +++ b/unittests/ASM/VEX/vpshufb.asm @@ -0,0 +1,62 @@ +%ifdef CONFIG +{ + "HostFeatures": ["AVX"], + "RegData": { + "XMM5": ["0x4848484848484848", "0x4848484848484848", "0x0000000000000000", "0x0000000000000000"], + "XMM6": ["0x0000000000000000", "0x0000000000000000", "0x0000000000000000", "0x0000000000000000"], + "XMM7": ["0x0000000000000000", "0x0000000000000000", "0x0000000000000000", "0x0000000000000000"], + "XMM8": ["0x4847464544434241", "0x5857565554535251", "0x0000000000000000", "0x0000000000000000"], + "XMM9": ["0x4848484848484848", "0x4848484848484848", "0x5858585858585858", "0x5858585858585858"], + "XMM10": ["0x0000000000000000", "0x0000000000000000", "0x0000000000000000", "0x0000000000000000"], + "XMM11": ["0x0000000000000000", "0x0000000000000000", "0x0000000000000000", "0x0000000000000000"], + "XMM12": ["0x4847464544434241", "0x5857565554535251", "0x5847464544434241", "0x4857565554535251"] + } +} +%endif + +lea rdx, [rel .data] + +vmovaps ymm0, [rdx] +vmovaps ymm1, [rdx + 32 * 1] +vmovaps ymm2, [rdx + 32 * 2] +vmovaps ymm3, [rdx + 32 * 3] +vmovaps ymm4, [rdx + 32 * 4] + +vpshufb xmm5, xmm0, xmm1 +vpshufb xmm6, xmm0, xmm2 +vpshufb xmm7, xmm0, xmm3 +vpshufb xmm8, xmm0, xmm4 + +vpshufb ymm9, ymm0, ymm1 +vpshufb ymm10, ymm0, ymm2 +vpshufb ymm11, ymm0, ymm3 +vpshufb ymm12, ymm0, ymm4 + +hlt + +align 32 +.data: +dq 0x4142434445464748 +dq 0x5152535455565758 +dq 0x4142434445464758 +dq 0x5152535455565748 + +dq 0 +dq 0 +dq 0 +dq 0 + +dq -1 +dq -1 +dq -1 +dq -1 + +dq 0x8080808080808080 +dq 0x8080808080808080 +dq 0x8080808080808080 +dq 0x8080808080808080 + +dq 0x0001020304050607 +dq 0x08090A0B0C0D0E0F +dq 0x0001020304050607 +dq 0x08090A0B0C0D0E0F