diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 103631715..74f375db3 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -5963,6 +5963,7 @@ void OpDispatchBuilder::InstallHostSpecificOpcodeHandlers() { {OPD(2, 0b01, 0x00), 1, &OpDispatchBuilder::VPSHUFBOp}, {OPD(2, 0b01, 0x01), 1, &OpDispatchBuilder::VHADDPOp}, {OPD(2, 0b01, 0x02), 1, &OpDispatchBuilder::VHADDPOp}, + {OPD(2, 0b01, 0x03), 1, &OpDispatchBuilder::VPHADDSWOp}, {OPD(2, 0b01, 0x05), 1, &OpDispatchBuilder::VPHSUBOp<2>}, {OPD(2, 0b01, 0x06), 1, &OpDispatchBuilder::VPHSUBOp<4>}, diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 7207576d0..f88663c7a 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -437,17 +437,21 @@ public: void VANDNOp(OpcodeArgs); + void VBLENDPDOp(OpcodeArgs); + void VPBLENDDOp(OpcodeArgs); + void VPBLENDWOp(OpcodeArgs); + template void VBROADCASTOp(OpcodeArgs); template void VDPPOp(OpcodeArgs); + void VEXTRACT128Op(OpcodeArgs); + template void VHADDPOp(OpcodeArgs); - void VEXTRACT128Op(OpcodeArgs); - void VINSERTOp(OpcodeArgs); void VINSERTPSOp(OpcodeArgs); @@ -474,16 +478,14 @@ public: void VPALIGNROp(OpcodeArgs); - void VBLENDPDOp(OpcodeArgs); - void VPBLENDDOp(OpcodeArgs); - void VPBLENDWOp(OpcodeArgs); - void VPERM2Op(OpcodeArgs); void VPERMQOp(OpcodeArgs); template void VPERMILImmOp(OpcodeArgs); + void VPHADDSWOp(OpcodeArgs); + void VPHMINPOSUWOp(OpcodeArgs); template @@ -812,6 +814,9 @@ private: const X86Tables::DecodedOperand& Src2, const X86Tables::DecodedOperand& Imm); + OrderedNode* PHADDSOpImpl(OpcodeArgs, const X86Tables::DecodedOperand& Src1, + const X86Tables::DecodedOperand& Src2); + OrderedNode* PHMINPOSUWOpImpl(OpcodeArgs); OrderedNode* PHSUBOpImpl(OpcodeArgs, const X86Tables::DecodedOperand& Src1, diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index 7ad7c5f02..0b36b0446 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -3244,38 +3244,56 @@ void OpDispatchBuilder::VPHSUBOp<2>(OpcodeArgs); template void OpDispatchBuilder::VPHSUBOp<4>(OpcodeArgs); -void OpDispatchBuilder::PHADDS(OpcodeArgs) { - auto Size = GetSrcSize(Op); - OrderedNode *Dest = LoadSource(FPRClass, Op, Op->Dest, Op->Flags, -1); - OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1); +OrderedNode* OpDispatchBuilder::PHADDSOpImpl(OpcodeArgs, const X86Tables::DecodedOperand& Src1, + const X86Tables::DecodedOperand& Src2) { + const auto Size = GetSrcSize(Op); + + OrderedNode *Src1Node = LoadSource(FPRClass, Op, Src1, Op->Flags, -1); + OrderedNode *Src2Node = LoadSource(FPRClass, Op, Src2, Op->Flags, -1); if (Size == 8) { // Implementation is more efficient for 8byte registers - auto Dest_Larger = _VSXTL(Size * 2, 2, Dest); - auto Src_Larger = _VSXTL(Size * 2, 2, Src); + OrderedNode *Src1_Larger = _VSXTL(Size * 2, 2, Src1Node); + OrderedNode *Src2_Larger = _VSXTL(Size * 2, 2, Src2Node); - OrderedNode *AddRes = _VAddP(Size * 2, 4, Dest_Larger, Src_Larger); + OrderedNode *AddRes = _VAddP(Size * 2, 4, Src1_Larger, Src2_Larger); // Saturate back down to the result - OrderedNode *Res = _VSQXTN(Size * 2, 4, AddRes); - StoreResult(FPRClass, Op, Res, -1); + return _VSQXTN(Size * 2, 4, AddRes); } - else { - auto Dest_Larger = _VSXTL(Size, 2, Dest); - auto Dest_Larger_H = _VSXTL2(Size, 2, Dest); - auto Src_Larger = _VSXTL(Size, 2, Src); - auto Src_Larger_H = _VSXTL2(Size, 2, Src); + OrderedNode *Src1_Larger = _VSXTL(Size, 2, Src1Node); + OrderedNode *Src1_Larger_H = _VSXTL2(Size, 2, Src1Node); - OrderedNode *AddRes_L = _VAddP(Size, 4, Dest_Larger, Dest_Larger_H); - OrderedNode *AddRes_H = _VAddP(Size, 4, Src_Larger, Src_Larger_H); + OrderedNode *Src2_Larger = _VSXTL(Size, 2, Src2Node); + OrderedNode *Src2_Larger_H = _VSXTL2(Size, 2, Src2Node); - // Saturate back down to the result - OrderedNode *Res = _VSQXTN(Size, 4, AddRes_L); - Res = _VSQXTN2(Size, 4, Res, AddRes_H); + OrderedNode *AddRes_L = _VAddP(Size, 4, Src1_Larger, Src1_Larger_H); + OrderedNode *AddRes_H = _VAddP(Size, 4, Src2_Larger, Src2_Larger_H); - StoreResult(FPRClass, Op, Res, -1); + // Saturate back down to the result + OrderedNode *Res = _VSQXTN(Size, 4, AddRes_L); + return _VSQXTN2(Size, 4, Res, AddRes_H); +} + +void OpDispatchBuilder::PHADDS(OpcodeArgs) { + OrderedNode *Result = PHADDSOpImpl(Op, Op->Dest, Op->Src[0]); + StoreResult(FPRClass, Op, Result, -1); +} + +void OpDispatchBuilder::VPHADDSWOp(OpcodeArgs) { + const auto SrcSize = GetSrcSize(Op); + const auto Is256Bit = SrcSize == Core::CPUState::XMM_AVX_REG_SIZE; + + OrderedNode *Result = PHADDSOpImpl(Op, Op->Src[0], Op->Src[1]); + OrderedNode *Dest = Result; + + if (Is256Bit) { + Dest = _VInsElement(SrcSize, 8, 1, 2, Result, Result); + Dest = _VInsElement(SrcSize, 8, 2, 1, Dest, Result); } + + StoreResult(FPRClass, Op, Dest, -1); } void OpDispatchBuilder::PHSUBS(OpcodeArgs) { diff --git a/External/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp b/External/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp index b9d8dc4c9..38639d8fe 100644 --- a/External/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp +++ b/External/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp @@ -262,7 +262,7 @@ void InitializeVEXTables() { {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}}, + {OPD(2, 0b01, 0x03), 1, X86InstInfo{"VPHADDSW", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_VEX_1ST_SRC | FLAGS_XMM_FLAGS, 0, nullptr}}, {OPD(2, 0b01, 0x04), 1, X86InstInfo{"VPMADDUBSW", TYPE_UNDEC, FLAGS_NONE, 0, nullptr}}, {OPD(2, 0b01, 0x05), 1, X86InstInfo{"VPHSUBW", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_VEX_1ST_SRC | FLAGS_XMM_FLAGS, 0, nullptr}}, {OPD(2, 0b01, 0x06), 1, X86InstInfo{"VPHSUBD", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_VEX_1ST_SRC | FLAGS_XMM_FLAGS, 0, nullptr}}, diff --git a/unittests/ASM/VEX/vphaddsw.asm b/unittests/ASM/VEX/vphaddsw.asm new file mode 100644 index 000000000..dbf3c4c65 --- /dev/null +++ b/unittests/ASM/VEX/vphaddsw.asm @@ -0,0 +1,48 @@ +%ifdef CONFIG +{ + "HostFeatures": ["AVX"], + "RegData": { + "XMM4": ["0x7FFF7FFF7FFF7FFF", "0x800080007FFF7FFF", "0x0000000000000000", "0x0000000000000000"], + "XMM5": ["0x800080007FFF7FFF", "0x7FFF7FFF7FFF7FFF", "0x0000000000000000", "0x0000000000000000"], + "XMM6": ["0x71836D874331472D", "0x800080007FFF7FFF", "0x0000000000000000", "0x0000000000000000"], + "XMM7": ["0x800080007FFF7FFF", "0x71836D874331472D", "0x0000000000000000", "0x0000000000000000"], + "XMM8": ["0x7FFF7FFF7FFF7FFF", "0x71836D874331472D", "0x0000000000000000", "0x0000000000000000"], + "XMM9": ["0x800080007FFF7FFF", "0x800080007FFF7FFF", "0x0000000000000000", "0x0000000000000000"], + "XMM10": ["0x71836D874331472D", "0x800080007FFF7FFF", "0x0000000000000000", "0x0000000000000000"] + } +} +%endif + +lea rdx, [rel .data] + +vmovaps xmm0, [rdx] +vmovaps xmm1, [rdx + 16] +vmovaps xmm2, [rdx + 32] +vmovaps xmm3, [rdx + 48] + +vphaddsw xmm4, xmm0, [rdx + 16] +vphaddsw xmm5, xmm1, [rdx] + +vphaddsw xmm6, xmm2, [rdx + 16] +vphaddsw xmm7, xmm3, [rdx + 32] + +vphaddsw xmm8, xmm0, [rdx + 32] +vphaddsw xmm9, xmm1, [rdx + 48] + +vphaddsw xmm10, xmm2, [rdx + 48] + +hlt + +align 32 +.data: +dq 0x4142434445464748 +dq 0x5152535455565758 + +dq 0x7F7F7F7F7F7F7F7F +dq 0x8080808080808080 + +dq 0x2119221823172416 +dq 0x3941384237433644 + +dq 0x7F7F7F7F7F7F7F7F +dq 0x8080808080808080 diff --git a/unittests/ASM/VEX/vphaddsw_256.asm b/unittests/ASM/VEX/vphaddsw_256.asm new file mode 100644 index 000000000..efd210c6b --- /dev/null +++ b/unittests/ASM/VEX/vphaddsw_256.asm @@ -0,0 +1,56 @@ +%ifdef CONFIG +{ + "HostFeatures": ["AVX"], + "RegData": { + "XMM4": ["0x7FFF7FFF7FFF7FFF", "0x800080007FFF7FFF", "0x7FFF7FFF7FFF7FFF", "0x7FFF7FFF80008000"], + "XMM5": ["0x800080007FFF7FFF", "0x7FFF7FFF7FFF7FFF", "0x7FFF7FFF80008000", "0x7FFF7FFF7FFF7FFF"], + "XMM6": ["0x71836D874331472D", "0x800080007FFF7FFF", "0x4331472D71836D87", "0x7FFF7FFF80008000"], + "XMM7": ["0x800080007FFF7FFF", "0x71836D874331472D", "0x7FFF7FFF80008000", "0x4331472D71836D87"], + "XMM8": ["0x7FFF7FFF7FFF7FFF", "0x71836D874331472D", "0x7FFF7FFF7FFF7FFF", "0x4331472D71836D87"], + "XMM9": ["0x800080007FFF7FFF", "0x800080007FFF7FFF", "0x7FFF7FFF80008000", "0x7FFF7FFF80008000"], + "XMM10": ["0x71836D874331472D", "0x800080007FFF7FFF", "0x4331472D71836D87", "0x7FFF7FFF80008000"] + } +} +%endif + +lea rdx, [rel .data] + +vmovaps ymm0, [rdx] +vmovaps ymm1, [rdx + 32] +vmovaps ymm2, [rdx + 64] +vmovaps ymm3, [rdx + 96] + +vphaddsw ymm4, ymm0, [rdx + 32] +vphaddsw ymm5, ymm1, [rdx] + +vphaddsw ymm6, ymm2, [rdx + 32] +vphaddsw ymm7, ymm3, [rdx + 64] + +vphaddsw ymm8, ymm0, [rdx + 64] +vphaddsw ymm9, ymm1, [rdx + 96] + +vphaddsw ymm10, ymm2, [rdx + 96] + +hlt + +align 32 +.data: +dq 0x4142434445464748 +dq 0x5152535455565758 +dq 0x5152535455565758 +dq 0x4142434445464748 + +dq 0x7F7F7F7F7F7F7F7F +dq 0x8080808080808080 +dq 0x8080808080808080 +dq 0x7F7F7F7F7F7F7F7F + +dq 0x2119221823172416 +dq 0x3941384237433644 +dq 0x3941384237433644 +dq 0x2119221823172416 + +dq 0x7F7F7F7F7F7F7F7F +dq 0x8080808080808080 +dq 0x8080808080808080 +dq 0x7F7F7F7F7F7F7F7F