mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-25 08:00:43 +01:00
Merge pull request #2093 from lioncash/shrn
IR: Handle 256-bit VUShrNI/VUShrNI2
This commit is contained in:
3 files changed
+210
-60
No files matched your search
@@ -1695,46 +1695,52 @@ DEF_OP(VShlI) {
|
||||
}
|
||||
|
||||
DEF_OP(VUShrNI) {
|
||||
auto Op = IROp->C<IR::IROp_VUShrNI>();
|
||||
const auto Op = IROp->C<IR::IROp_VUShrNI>();
|
||||
const uint8_t OpSize = IROp->Size;
|
||||
|
||||
void *Src = GetSrc<void*>(Data->SSAData, Op->Vector);
|
||||
uint8_t BitShift = Op->BitShift;
|
||||
uint8_t Tmp[16]{};
|
||||
const uint8_t BitShift = Op->BitShift;
|
||||
uint8_t Tmp[Core::CPUState::XMM_AVX_REG_SIZE]{};
|
||||
|
||||
const uint8_t Elements = OpSize / (Op->Header.ElementSize << 1);
|
||||
const uint8_t ElementSize = Op->Header.ElementSize;
|
||||
const uint8_t Elements = OpSize / (ElementSize << 1);
|
||||
const auto Func = [BitShift](auto a, auto min, auto max) {
|
||||
return BitShift >= (sizeof(a) * 8) ? 0 : a >> BitShift;
|
||||
};
|
||||
|
||||
switch (Op->Header.ElementSize) {
|
||||
switch (ElementSize) {
|
||||
DO_VECTOR_1SRC_2TYPE_OP(1, uint8_t, uint16_t, Func, 0, 0)
|
||||
DO_VECTOR_1SRC_2TYPE_OP(2, uint16_t, uint32_t, Func, 0, 0)
|
||||
DO_VECTOR_1SRC_2TYPE_OP(4, uint32_t, uint64_t, Func, 0, 0)
|
||||
default: LOGMAN_MSG_A_FMT("Unknown Element Size: {}", Op->Header.ElementSize); break;
|
||||
default:
|
||||
LOGMAN_MSG_A_FMT("Unknown Element Size: {}", ElementSize);
|
||||
break;
|
||||
}
|
||||
memcpy(GDP, Tmp, OpSize);
|
||||
}
|
||||
|
||||
DEF_OP(VUShrNI2) {
|
||||
auto Op = IROp->C<IR::IROp_VUShrNI2>();
|
||||
const auto Op = IROp->C<IR::IROp_VUShrNI2>();
|
||||
const uint8_t OpSize = IROp->Size;
|
||||
|
||||
void *Src1 = GetSrc<void*>(Data->SSAData, Op->VectorLower);
|
||||
void *Src2 = GetSrc<void*>(Data->SSAData, Op->VectorUpper);
|
||||
uint8_t BitShift = Op->BitShift;
|
||||
uint8_t Tmp[16];
|
||||
const uint8_t BitShift = Op->BitShift;
|
||||
uint8_t Tmp[Core::CPUState::XMM_AVX_REG_SIZE];
|
||||
|
||||
const uint8_t Elements = OpSize / (Op->Header.ElementSize << 1);
|
||||
const uint8_t ElementSize = Op->Header.ElementSize;
|
||||
const uint8_t Elements = OpSize / (ElementSize << 1);
|
||||
const auto Func = [BitShift](auto a, auto min, auto max) {
|
||||
return BitShift >= (sizeof(a) * 8) ? 0 : a >> BitShift;
|
||||
};
|
||||
|
||||
switch (Op->Header.ElementSize) {
|
||||
switch (ElementSize) {
|
||||
DO_VECTOR_1SRC_2TYPE_OP_TOP(1, uint8_t, uint16_t, Func, 0, 0)
|
||||
DO_VECTOR_1SRC_2TYPE_OP_TOP(2, uint16_t, uint32_t, Func, 0, 0)
|
||||
DO_VECTOR_1SRC_2TYPE_OP_TOP(4, uint32_t, uint64_t, Func, 0, 0)
|
||||
default: LOGMAN_MSG_A_FMT("Unknown Element Size: {}", Op->Header.ElementSize); break;
|
||||
default:
|
||||
LOGMAN_MSG_A_FMT("Unknown Element Size: {}", ElementSize);
|
||||
break;
|
||||
}
|
||||
memcpy(GDP, Tmp, OpSize);
|
||||
}
|
||||
|
||||
+109
-31
@@ -3970,45 +3970,123 @@ DEF_OP(VShlI) {
|
||||
}
|
||||
|
||||
DEF_OP(VUShrNI) {
|
||||
auto Op = IROp->C<IR::IROp_VUShrNI>();
|
||||
const auto Op = IROp->C<IR::IROp_VUShrNI>();
|
||||
const auto OpSize = IROp->Size;
|
||||
|
||||
switch (Op->Header.ElementSize) {
|
||||
case 1: {
|
||||
shrn(GetDst(Node).V8B(), GetSrc(Op->Vector.ID()).V8H(), Op->BitShift);
|
||||
break;
|
||||
const auto BitShift = Op->BitShift;
|
||||
const auto ElementSize = Op->Header.ElementSize;
|
||||
const auto Is256Bit = OpSize == Core::CPUState::XMM_AVX_REG_SIZE;
|
||||
|
||||
const auto Dst = GetDst(Node);
|
||||
const auto Vector = GetSrc(Op->Vector.ID());
|
||||
|
||||
if (HostSupportsSVE && Is256Bit) {
|
||||
switch (ElementSize) {
|
||||
case 1: {
|
||||
shrnb(Dst.Z().VnB(), Vector.Z().VnH(), BitShift);
|
||||
uzp1(Dst.Z().VnB(), Dst.Z().VnB(), Dst.Z().VnB());
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
shrnb(Dst.Z().VnH(), Vector.Z().VnS(), BitShift);
|
||||
uzp1(Dst.Z().VnH(), Dst.Z().VnH(), Dst.Z().VnH());
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
shrnb(Dst.Z().VnS(), Vector.Z().VnD(), BitShift);
|
||||
uzp1(Dst.Z().VnS(), Dst.Z().VnS(), Dst.Z().VnS());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOGMAN_MSG_A_FMT("Unknown Element Size: {}", ElementSize);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
shrn(GetDst(Node).V4H(), GetSrc(Op->Vector.ID()).V4S(), Op->BitShift);
|
||||
break;
|
||||
} else {
|
||||
switch (ElementSize) {
|
||||
case 1: {
|
||||
shrn(Dst.V8B(), Vector.V8H(), BitShift);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
shrn(Dst.V4H(), Vector.V4S(), BitShift);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
shrn(Dst.V2S(), Vector.V2D(), BitShift);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOGMAN_MSG_A_FMT("Unknown Element Size: {}", ElementSize);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
shrn(GetDst(Node).V2S(), GetSrc(Op->Vector.ID()).V2D(), Op->BitShift);
|
||||
break;
|
||||
}
|
||||
default: LOGMAN_MSG_A_FMT("Unknown Element Size: {}", Op->Header.ElementSize); break;
|
||||
}
|
||||
}
|
||||
|
||||
DEF_OP(VUShrNI2) {
|
||||
auto Op = IROp->C<IR::IROp_VUShrNI2>();
|
||||
mov(VTMP1, GetSrc(Op->VectorLower.ID()));
|
||||
switch (Op->Header.ElementSize) {
|
||||
case 1: {
|
||||
shrn2(VTMP1.V16B(), GetSrc(Op->VectorUpper.ID()).V8H(), Op->BitShift);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
shrn2(VTMP1.V8H(), GetSrc(Op->VectorUpper.ID()).V4S(), Op->BitShift);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
shrn2(VTMP1.V4S(), GetSrc(Op->VectorUpper.ID()).V2D(), Op->BitShift);
|
||||
break;
|
||||
}
|
||||
default: LOGMAN_MSG_A_FMT("Unknown Element Size: {}", Op->Header.ElementSize); break;
|
||||
}
|
||||
const auto Op = IROp->C<IR::IROp_VUShrNI2>();
|
||||
const auto OpSize = IROp->Size;
|
||||
|
||||
mov(GetDst(Node), VTMP1);
|
||||
const auto BitShift = Op->BitShift;
|
||||
const auto ElementSize = Op->Header.ElementSize;
|
||||
const auto Is256Bit = OpSize == Core::CPUState::XMM_AVX_REG_SIZE;
|
||||
|
||||
const auto Dst = GetDst(Node);
|
||||
const auto VectorLower = GetSrc(Op->VectorLower.ID());
|
||||
const auto VectorUpper = GetSrc(Op->VectorUpper.ID());
|
||||
|
||||
if (HostSupportsSVE && Is256Bit) {
|
||||
mov(VTMP1.Z().VnD(), VectorLower.Z().VnD());
|
||||
|
||||
const auto Mask = PRED_TMP_16B;
|
||||
|
||||
switch (ElementSize) {
|
||||
case 1: {
|
||||
shrnb(VTMP2.Z().VnB(), VectorUpper.Z().VnH(), BitShift);
|
||||
uzp1(VTMP2.Z().VnB(), VTMP2.Z().VnB(), VTMP2.Z().VnB());
|
||||
splice(VTMP1.Z().VnB(), Mask, VTMP1.Z().VnB(), VTMP2.Z().VnB());
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
shrnb(VTMP2.Z().VnH(), VectorUpper.Z().VnS(), BitShift);
|
||||
uzp1(VTMP2.Z().VnH(), VTMP2.Z().VnH(), VTMP2.Z().VnH());
|
||||
splice(VTMP1.Z().VnH(), Mask, VTMP1.Z().VnH(), VTMP2.Z().VnH());
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
shrnb(VTMP2.Z().VnS(), VectorUpper.Z().VnD(), BitShift);
|
||||
uzp1(VTMP2.Z().VnS(), VTMP2.Z().VnS(), VTMP2.Z().VnS());
|
||||
splice(VTMP1.Z().VnS(), Mask, VTMP1.Z().VnS(), VTMP2.Z().VnS());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOGMAN_MSG_A_FMT("Unknown Element Size: {}", ElementSize);
|
||||
return;
|
||||
}
|
||||
|
||||
mov(Dst.Z().VnD(), VTMP1.Z().VnD());
|
||||
} else {
|
||||
mov(VTMP1, VectorLower);
|
||||
|
||||
switch (ElementSize) {
|
||||
case 1: {
|
||||
shrn2(VTMP1.V16B(), VectorUpper.V8H(), BitShift);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
shrn2(VTMP1.V8H(), VectorUpper.V4S(), BitShift);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
shrn2(VTMP1.V4S(), VectorUpper.V2D(), BitShift);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOGMAN_MSG_A_FMT("Unknown Element Size: {}", ElementSize);
|
||||
return;
|
||||
}
|
||||
|
||||
mov(Dst, VTMP1);
|
||||
}
|
||||
}
|
||||
|
||||
DEF_OP(VSXTL) {
|
||||
|
||||
+83
-17
@@ -2196,75 +2196,141 @@ DEF_OP(VShlI) {
|
||||
}
|
||||
|
||||
DEF_OP(VUShrNI) {
|
||||
auto Op = IROp->C<IR::IROp_VUShrNI>();
|
||||
movapd(GetDst(Node), GetSrc(Op->Vector.ID()));
|
||||
const auto Op = IROp->C<IR::IROp_VUShrNI>();
|
||||
const auto OpSize = IROp->Size;
|
||||
|
||||
const auto BitShift = Op->BitShift;
|
||||
const auto ElementSize = Op->Header.ElementSize;
|
||||
const auto Is256Bit = OpSize == Core::CPUState::XMM_AVX_REG_SIZE;
|
||||
|
||||
const auto Dst = GetDst(Node);
|
||||
const auto DstYMM = ToYMM(Dst);
|
||||
const auto Vector = GetSrc(Op->Vector.ID());
|
||||
|
||||
vmovapd(DstYMM, ToYMM(Vector));
|
||||
vpxor(xmm15, xmm15, xmm15);
|
||||
switch (Op->Header.ElementSize) {
|
||||
|
||||
switch (ElementSize) {
|
||||
case 1: {
|
||||
psrlw(GetDst(Node), Op->BitShift);
|
||||
if (Is256Bit) {
|
||||
vpsrlw(DstYMM, DstYMM, BitShift);
|
||||
} else {
|
||||
vpsrlw(Dst, Dst, BitShift);
|
||||
}
|
||||
// <8 x i16> -> <8 x i8>
|
||||
mov(rax, 0x0E'0C'0A'08'06'04'02'00); // Lower
|
||||
mov(rcx, 0x80'80'80'80'80'80'80'80); // Upper
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
psrld(GetDst(Node), Op->BitShift);
|
||||
if (Is256Bit) {
|
||||
vpsrld(DstYMM, DstYMM, BitShift);
|
||||
} else {
|
||||
vpsrld(Dst, Dst, BitShift);
|
||||
}
|
||||
// <4 x i32> -> <4 x i16>
|
||||
mov(rax, 0x0D'0C'09'08'05'04'01'00); // Lower
|
||||
mov(rcx, 0x80'80'80'80'80'80'80'80); // Upper
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
psrlq(GetDst(Node), Op->BitShift);
|
||||
if (Is256Bit) {
|
||||
vpsrlq(DstYMM, DstYMM, BitShift);
|
||||
} else {
|
||||
vpsrlq(Dst, Dst, BitShift);
|
||||
}
|
||||
// <2 x i64> -> <2 x i32>
|
||||
mov(rax, 0x0B'0A'09'08'03'02'01'00); // Lower
|
||||
mov(rcx, 0x80'80'80'80'80'80'80'80); // Upper
|
||||
break;
|
||||
}
|
||||
default: LOGMAN_MSG_A_FMT("Unknown Element Size: {}", Op->Header.ElementSize); break;
|
||||
default:
|
||||
LOGMAN_MSG_A_FMT("Unknown Element Size: {}", ElementSize);
|
||||
return;
|
||||
}
|
||||
|
||||
vmovq(xmm15, rax);
|
||||
vmovq(xmm14, rcx);
|
||||
punpcklqdq(xmm15, xmm14);
|
||||
pshufb(GetDst(Node), xmm15);
|
||||
if (Is256Bit) {
|
||||
vinserti128(ymm15, ymm15, xmm15, 1);
|
||||
vpshufb(DstYMM, DstYMM, ymm15);
|
||||
vextracti128(xmm14, DstYMM, 1);
|
||||
punpcklqdq(Dst, xmm14);
|
||||
} else {
|
||||
vpshufb(Dst, Dst, xmm15);
|
||||
}
|
||||
}
|
||||
|
||||
DEF_OP(VUShrNI2) {
|
||||
// Src1 = Lower results
|
||||
// Src2 = Upper Results
|
||||
auto Op = IROp->C<IR::IROp_VUShrNI2>();
|
||||
movapd(xmm13, GetSrc(Op->VectorUpper.ID()));
|
||||
switch (Op->Header.ElementSize) {
|
||||
const auto Op = IROp->C<IR::IROp_VUShrNI2>();
|
||||
const auto OpSize = IROp->Size;
|
||||
|
||||
const auto BitShift = Op->BitShift;
|
||||
const auto ElementSize = Op->Header.ElementSize;
|
||||
const auto Is256Bit = OpSize == Core::CPUState::XMM_AVX_REG_SIZE;
|
||||
|
||||
const auto Dst = GetDst(Node);
|
||||
const auto VectorLower = GetSrc(Op->VectorLower.ID());
|
||||
const auto VectorUpper = GetSrc(Op->VectorUpper.ID());
|
||||
|
||||
vmovapd(ymm13, ToYMM(VectorUpper));
|
||||
switch (ElementSize) {
|
||||
case 1: {
|
||||
psrlw(xmm13, Op->BitShift);
|
||||
if (Is256Bit) {
|
||||
vpsrlw(ymm13, ymm13, BitShift);
|
||||
} else {
|
||||
vpsrlw(xmm13, xmm13, BitShift);
|
||||
}
|
||||
// <8 x i16> -> <8 x i8>
|
||||
mov(rax, 0x80'80'80'80'80'80'80'80); // Lower
|
||||
mov(rcx, 0x0E'0C'0A'08'06'04'02'00); // Upper
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
psrld(xmm13, Op->BitShift);
|
||||
if (Is256Bit) {
|
||||
vpsrld(ymm13, ymm13, BitShift);
|
||||
} else {
|
||||
vpsrld(xmm13, xmm13, BitShift);
|
||||
}
|
||||
// <4 x i32> -> <4 x i16>
|
||||
mov(rax, 0x80'80'80'80'80'80'80'80); // Lower
|
||||
mov(rcx, 0x0D'0C'09'08'05'04'01'00); // Upper
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
psrlq(xmm13, Op->BitShift);
|
||||
if (Is256Bit) {
|
||||
vpsrlq(ymm13, ymm13, BitShift);
|
||||
} else {
|
||||
vpsrlq(xmm13, xmm13, BitShift);
|
||||
}
|
||||
// <2 x i64> -> <2 x i32>
|
||||
mov(rax, 0x80'80'80'80'80'80'80'80); // Lower
|
||||
mov(rcx, 0x0B'0A'09'08'03'02'01'00); // Upper
|
||||
break;
|
||||
}
|
||||
default: LOGMAN_MSG_A_FMT("Unknown Element Size: {}", Op->Header.ElementSize); break;
|
||||
default:
|
||||
LOGMAN_MSG_A_FMT("Unknown Element Size: {}", ElementSize);
|
||||
return;
|
||||
}
|
||||
|
||||
vmovq(xmm15, rax);
|
||||
vmovq(xmm14, rcx);
|
||||
punpcklqdq(xmm15, xmm14);
|
||||
vpshufb(xmm14, xmm13, xmm15);
|
||||
vpor(GetDst(Node), xmm14, GetSrc(Op->VectorLower.ID()));
|
||||
if (Is256Bit) {
|
||||
vinserti128(ymm15, ymm15, xmm15, 1);
|
||||
vpshufb(ymm14, ymm13, ymm15);
|
||||
vextracti128(xmm12, ymm14, 1);
|
||||
punpckhqdq(xmm14, xmm12);
|
||||
|
||||
vmovapd(Dst, VectorLower);
|
||||
vinserti128(ToYMM(Dst), ToYMM(Dst), xmm14, 1);
|
||||
} else {
|
||||
vpshufb(xmm14, xmm13, xmm15);
|
||||
vpor(Dst, xmm14, VectorLower);
|
||||
}
|
||||
}
|
||||
|
||||
DEF_OP(VSXTL) {
|
||||
|
||||
Reference in new issue
Block a user