Merge pull request #435 from Sonicadvance1/pmaddubsw

Implements PMADDUBSW
This commit is contained in:
Ryan Houdek authored and GitHub committed 2020-09-27 10:54:44 -07:00
commit a75e01efda
6 files changed
+194 -3

No files matched your search

+1 -1
View File
@@ -3474,7 +3474,7 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView<true> const
}
case IR::OP_VUXTL2: {
auto Op = IROp->C<IR::IROp_VUXTL2>();
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));
@@ -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<bool Signed>
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>},
@@ -408,6 +408,7 @@ public:
void ADDSUBPOp(OpcodeArgs);
void PMADDWD(OpcodeArgs);
void PMADDUBSW(OpcodeArgs);
template<bool Signed>
void PMULHW(OpcodeArgs);
@@ -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}},
+61
View File
@@ -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
+66
View File
@@ -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