From 1c2f8dece57054a57dd629eeec75fdd248dec032 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 26 Sep 2020 17:38:56 -0700 Subject: [PATCH 1/3] Fixes typo in x86 VUXTL2 This was supposed to shift right, not shift left This IR op wasn't being used so it went unnoticed --- External/FEXCore/Source/Interface/Core/JIT/x86_64/JIT.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/External/FEXCore/Source/Interface/Core/JIT/x86_64/JIT.cpp b/External/FEXCore/Source/Interface/Core/JIT/x86_64/JIT.cpp index c12e1880f..50c008d3c 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/x86_64/JIT.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/x86_64/JIT.cpp @@ -3474,7 +3474,7 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView const } case IR::OP_VUXTL2: { auto Op = IROp->C(); - vpslldq(GetDst(Node), GetSrc(Op->Header.Args[0].ID()), OpSize / 2); + vpsrldq(GetDst(Node), GetSrc(Op->Header.Args[0].ID()), OpSize / 2); switch (Op->Header.ElementSize) { case 2: pmovzxbw(GetDst(Node), GetDst(Node)); From b409855605ac4c6211f6f7c82e40351d7d975333 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 26 Sep 2020 17:39:59 -0700 Subject: [PATCH 2/3] Implements PMADDUBSW in the Opdispatcher This is some weirdly specific instruction --- .../Interface/Core/OpcodeDispatcher.cpp | 63 +++++++++++++++++++ .../Source/Interface/Core/OpcodeDispatcher.h | 1 + .../Interface/Core/X86Tables/H0F38Tables.cpp | 4 +- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index ad7ee5259..28de145e7 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -7606,6 +7606,67 @@ void OpDispatchBuilder::PMADDWD(OpcodeArgs) { StoreResult(FPRClass, Op, Res, -1); } +void OpDispatchBuilder::PMADDUBSW(OpcodeArgs) { + // This is a pretty curious operation + // Does four MADD operations across 8 8bit signed and unsigned integers and accumulates to 16bit integers in the destination WITH saturation + // + // x86 PMADDUBSW: mm1, mm2 + // mm1[15:0] = SaturateSigned16(((s8)mm2[15:8] * (u8)mm1[15:8]) + ((s8)mm2[7:0] * (u8)mm1[7:0])) + // mm1[31:16] = SaturateSigned16(((s8)mm2[31:24] * (u8)mm1[31:24]) + ((s8)mm2[23:16] * (u8)mm1[23:16])) + // mm1[47:32] = SaturateSigned16(((s8)mm2[47:40] * (u8)mm1[47:40]) + ((s8)mm2[39:32] * (u8)mm1[39:32])) + // mm1[63:48] = SaturateSigned16(((s8)mm2[63:56] * (u8)mm1[63:56]) + ((s8)mm2[55:48] * (u8)mm1[55:48])) + // Extends to larger registers + auto Size = GetSrcSize(Op); + + OrderedNode *Src1 = LoadSource(FPRClass, Op, Op->Dest, Op->Flags, -1); + OrderedNode *Src2 = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1); + + if (Size == 8) { + // 64bit is more efficient + + // Src1 is unsigned + auto Src1_16b = _VUXTL(Size * 2, 1, Src1); // [7:0 ], [15:8], [23:16], [31:24], [39:32], [47:40], [55:48], [63:56] + + // Src2 is signed + auto Src2_16b = _VSXTL(Size * 2, 1, Src2); // [7:0 ], [15:8], [23:16], [31:24], [39:32], [47:40], [55:48], [63:56] + + auto ResMul_L = _VSMull(Size * 2, 2, Src1_16b, Src2_16b); + auto ResMul_H = _VSMull2(Size * 2, 2, Src1_16b, Src2_16b); + + // Now add pairwise across the vector + auto ResAdd = _VAddP(Size * 2, 4, ResMul_L, ResMul_H); + + // Add saturate back down to 16bit + OrderedNode *Res = _VSQXTN(Size * 2, 4, ResAdd); + StoreResult(FPRClass, Op, Res, -1); + } + else { + // Src1 is unsigned + auto Src1_16b_L = _VUXTL(Size, 1, Src1); // [7:0 ], [15:8], [23:16], [31:24], [39:32], [47:40], [55:48], [63:56] + auto Src1_16b_H = _VUXTL2(Size, 1, Src1); // Offset to +64bits [7:0 ], [15:8], [23:16], [31:24], [39:32], [47:40], [55:48], [63:56] + + // Src2 is signed + auto Src2_16b_L = _VSXTL(Size, 1, Src2); // [7:0 ], [15:8], [23:16], [31:24], [39:32], [47:40], [55:48], [63:56] + auto Src2_16b_H = _VSXTL2(Size, 1, Src2); // Offset to +64bits [7:0 ], [15:8], [23:16], [31:24], [39:32], [47:40], [55:48], [63:56] + + auto ResMul_L = _VSMull(Size, 2, Src1_16b_L, Src2_16b_L); + auto ResMul_L_H = _VSMull2(Size, 2, Src1_16b_L, Src2_16b_L); + + auto ResMul_H = _VSMull(Size, 2, Src1_16b_H, Src2_16b_H); + auto ResMul_H_H = _VSMull2(Size, 2, Src1_16b_H, Src2_16b_H); + + // Now add pairwise across the vector + auto ResAdd_L = _VAddP(Size, 4, ResMul_L, ResMul_L_H); + auto ResAdd_H = _VAddP(Size, 4, ResMul_H, ResMul_H_H); + + // Add saturate back down to 16bit + OrderedNode *Res = _VSQXTN(Size, 4, ResAdd_L); + Res = _VSQXTN2(Size, 4, Res, ResAdd_H); + + StoreResult(FPRClass, Op, Res, -1); + } +} + template void OpDispatchBuilder::PMULHW(OpcodeArgs) { auto Size = GetSrcSize(Op); @@ -8685,6 +8746,8 @@ constexpr uint16_t PF_F2 = 3; {OPD(PF_38_66, 0x01), 1, &OpDispatchBuilder::PHADD<2>}, {OPD(PF_38_NONE, 0x02), 1, &OpDispatchBuilder::PHADD<4>}, {OPD(PF_38_66, 0x02), 1, &OpDispatchBuilder::PHADD<4>}, + {OPD(PF_38_NONE, 0x04), 1, &OpDispatchBuilder::PMADDUBSW}, + {OPD(PF_38_66, 0x04), 1, &OpDispatchBuilder::PMADDUBSW}, {OPD(PF_38_NONE, 0x05), 1, &OpDispatchBuilder::PHSUB<2>}, {OPD(PF_38_66, 0x05), 1, &OpDispatchBuilder::PHSUB<2>}, {OPD(PF_38_NONE, 0x06), 1, &OpDispatchBuilder::PHSUB<4>}, diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 3d3e43900..42a33b8cb 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -408,6 +408,7 @@ public: void ADDSUBPOp(OpcodeArgs); void PMADDWD(OpcodeArgs); + void PMADDUBSW(OpcodeArgs); template void PMULHW(OpcodeArgs); diff --git a/External/FEXCore/Source/Interface/Core/X86Tables/H0F38Tables.cpp b/External/FEXCore/Source/Interface/Core/X86Tables/H0F38Tables.cpp index dee053bf7..b7380bc01 100644 --- a/External/FEXCore/Source/Interface/Core/X86Tables/H0F38Tables.cpp +++ b/External/FEXCore/Source/Interface/Core/X86Tables/H0F38Tables.cpp @@ -18,8 +18,8 @@ void InitializeH0F38Tables() { {OPD(PF_38_66, 0x02), 1, X86InstInfo{"PHADDD", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}}, {OPD(PF_38_NONE, 0x03), 1, X86InstInfo{"PHADDSW", TYPE_UNDEC, FLAGS_NONE, 0, nullptr}}, {OPD(PF_38_66, 0x03), 1, X86InstInfo{"PHADDSW", TYPE_UNDEC, FLAGS_NONE, 0, nullptr}}, - {OPD(PF_38_NONE, 0x04), 1, X86InstInfo{"PMADDUBSW", TYPE_UNDEC, FLAGS_NONE, 0, nullptr}}, - {OPD(PF_38_66, 0x04), 1, X86InstInfo{"PMADDUBSW", TYPE_UNDEC, FLAGS_NONE, 0, nullptr}}, + {OPD(PF_38_NONE, 0x04), 1, X86InstInfo{"PMADDUBSW", TYPE_INST, GenFlagsSameSize(SIZE_64BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS | FLAGS_SF_MMX, 0, nullptr}}, + {OPD(PF_38_66, 0x04), 1, X86InstInfo{"PMADDUBSW", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}}, {OPD(PF_38_NONE, 0x05), 1, X86InstInfo{"PHSUBW", TYPE_INST, GenFlagsSameSize(SIZE_64BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS | FLAGS_SF_MMX, 0, nullptr}}, {OPD(PF_38_66, 0x05), 1, X86InstInfo{"PHSUBW", TYPE_INST, GenFlagsSameSize(SIZE_128BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS, 0, nullptr}}, {OPD(PF_38_NONE, 0x06), 1, X86InstInfo{"PHSUBD", TYPE_INST, GenFlagsSameSize(SIZE_64BIT) | FLAGS_MODRM | FLAGS_XMM_FLAGS | FLAGS_SF_MMX, 0, nullptr}}, From 5ebc3b5ac7d02e32eaa4507e1bd738ca9c00caa7 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 26 Sep 2020 17:40:36 -0700 Subject: [PATCH 3/3] Implements PMADDUBSW unit tests Both MMX and XMM variants --- unittests/ASM/H0F38/66_04.asm | 61 ++++++++++++++++++++++++++++++++ unittests/ASM/H0F38/XX_04.asm | 66 +++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 unittests/ASM/H0F38/66_04.asm create mode 100644 unittests/ASM/H0F38/XX_04.asm diff --git a/unittests/ASM/H0F38/66_04.asm b/unittests/ASM/H0F38/66_04.asm new file mode 100644 index 000000000..28df5a705 --- /dev/null +++ b/unittests/ASM/H0F38/66_04.asm @@ -0,0 +1,61 @@ +%ifdef CONFIG +{ + "RegData": { + "XMM0": ["0x0", "0x0"], + "XMM1": ["0xFE02FE02FE02FE02", "0xFE02FE02FE02FE02"], + "XMM2": ["0x7F7F7F7F7F7F7F7F", "0x7F7F7F7F7F7F7F7F"], + "XMM3": ["0x7FFF7FFF7FFF7FFF", "0x7FFF7FFF7FFF7FFF"], + "XMM4": ["0x057306BC07B808B8", "0xBC53BC0EBAE5BA2E"], + "XMM5": ["0xA473A5BCA6B8A7B8", "0x0553070E07E5092E"] + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x0 +mov [rdx + 8 * 0], rax +mov [rdx + 8 * 1], rax + +mov rax, -1 +mov [rdx + 8 * 2], rax +mov [rdx + 8 * 3], rax + +mov rax, 0x7F7F7F7F7F7F7F7F +mov [rdx + 8 * 4], rax +mov [rdx + 8 * 5], rax + +mov rax, 0x8141824383448445 +mov [rdx + 8 * 6], rax +mov rax, 0x21F223F323F424F5 +mov [rdx + 8 * 7], rax + +mov rax, 0xE251E352E453E554 +mov [rdx + 8 * 8], rax +mov rax, 0x71A972A873A774A6 +mov [rdx + 8 * 9], rax + +; Zero +movaps xmm0, [rdx + 8 * 0] +pmaddubsw xmm0, [rdx + 8 * 0] + +; -1 +movaps xmm1, [rdx + 8 * 2] +pmaddubsw xmm1, [rdx + 8 * 2] + +; 127 +movaps xmm2, [rdx + 8 * 4] +pmaddubsw mm2, [rdx + 8 * 4] + +; 255 and 127 +movaps xmm3, [rdx + 8 * 2] +pmaddubsw xmm3, [rdx + 8 * 4] + +; Mixture +movaps xmm4, [rdx + 8 * 6] +pmaddubsw xmm4, [rdx + 8 * 8] + +movaps xmm5, [rdx + 8 * 8] +pmaddubsw xmm5, [rdx + 8 * 6] + +hlt diff --git a/unittests/ASM/H0F38/XX_04.asm b/unittests/ASM/H0F38/XX_04.asm new file mode 100644 index 000000000..1d3d654c8 --- /dev/null +++ b/unittests/ASM/H0F38/XX_04.asm @@ -0,0 +1,66 @@ +%ifdef CONFIG +{ + "RegData": { + "MM0": "0x0", + "MM1": "0xFE02FE02FE02FE02", + "MM2": "0x7E027E027E027E02", + "MM3": "0x7FFF7FFF7FFF7FFF", + "MM4": "0x0D130E5F0EB90F99", + "MM5": "0x2D132E5F2FB93099", + "MM6": "0x483B48E649914A3C", + "MM7": "0x283B28E629912A3C" + } +} +%endif + +mov rdx, 0xe0000000 + +mov rax, 0x0 +mov [rdx + 8 * 0], rax + +mov rax, -1 +mov [rdx + 8 * 1], rax + +mov rax, 0x7F7F7F7F7F7F7F7F +mov [rdx + 8 * 2], rax + +mov rax, 0x8141824383448445 +mov [rdx + 8 * 6], rax +mov rax, 0x21F223F323F424F5 +mov [rdx + 8 * 7], rax + +mov rax, 0xE251E352E453E554 +mov [rdx + 8 * 8], rax +mov rax, 0x71A972A873A774A6 +mov [rdx + 8 * 9], rax + +; Zero +movq mm0, [rdx + 8 * 0] +pmaddubsw mm0, [rdx + 8 * 0] + +; -1 +movq mm1, [rdx + 8 * 1] +pmaddubsw mm1, [rdx + 8 * 1] + +; 127 +movq mm2, [rdx + 8 * 2] +pmaddubsw mm2, [rdx + 8 * 2] + +; 255 and 127 +movq mm3, [rdx + 8 * 1] +pmaddubsw mm3, [rdx + 8 * 2] + +; Mixture +movq mm4, [rdx + 8 * 6] +pmaddubsw mm4, [rdx + 8 * 7] + +movq mm5, [rdx + 8 * 7] +pmaddubsw mm5, [rdx + 8 * 6] + +movq mm6, [rdx + 8 * 8] +pmaddubsw mm6, [rdx + 8 * 9] + +movq mm7, [rdx + 8 * 9] +pmaddubsw mm7, [rdx + 8 * 8] + +hlt