mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-25 10:00:44 +01:00
Merge pull request #435 from Sonicadvance1/pmaddubsw
Implements PMADDUBSW
This commit is contained in:
6 files changed
+194
-3
No files matched your search
@@ -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}},
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in new issue
Block a user