mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-14 13:00:41 +02:00
Fixes issues with PSLLDQ and PSRLDQ
These are whole vector shift instructions and they shift by bytes rather than bits. You only get an immediate offset for the instruction. Implements two new IR ops to account for these instructions This also doesn't match AArch64 behaviour 100%, requires two instructions to emulate rather than the single one on the x86-side
This commit is contained in:
1 parent
af6eefb495
commit
afdbd9ebdc
6 files changed
+93
-8
No files matched your search
@@ -1022,6 +1022,25 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) {
|
||||
memcpy(GDP, &Dst, 16);
|
||||
break;
|
||||
}
|
||||
case IR::OP_VSLI: {
|
||||
auto Op = IROp->C<IR::IROp_VSLI>();
|
||||
__uint128_t Src1 = *GetSrc<__uint128_t*>(Op->Header.Args[0]);
|
||||
__uint128_t Src2 = Op->ByteShift;
|
||||
|
||||
__uint128_t Dst = Src1 << (Src2 * 8);
|
||||
memcpy(GDP, &Dst, 16);
|
||||
break;
|
||||
}
|
||||
case IR::OP_VSRI: {
|
||||
auto Op = IROp->C<IR::IROp_VSRI>();
|
||||
__uint128_t Src1 = *GetSrc<__uint128_t*>(Op->Header.Args[0]);
|
||||
__uint128_t Src2 = Op->ByteShift;
|
||||
|
||||
__uint128_t Dst = Src1 >> (Src2 * 8);
|
||||
memcpy(GDP, &Dst, 16);
|
||||
break;
|
||||
}
|
||||
|
||||
#define DO_VECTOR_OP(size, type, func) \
|
||||
case size: { \
|
||||
auto *Dst_d = reinterpret_cast<type*>(Tmp); \
|
||||
|
||||
@@ -1480,6 +1480,20 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView<true> const
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IR::OP_VSLI: {
|
||||
auto Op = IROp->C<IR::IROp_VSLI>();
|
||||
eor(VTMP1.V16B(), VTMP1.V16B(), VTMP1.V16B());
|
||||
sli(VTMP1.V16B(), GetSrc(Op->Header.Args[0].ID()).V16B(), Op->ByteShift);
|
||||
mov(GetDst(Node).V16B(), VTMP1.V16B());
|
||||
break;
|
||||
}
|
||||
case IR::OP_VSRI: {
|
||||
auto Op = IROp->C<IR::IROp_VSRI>();
|
||||
eor(VTMP1.V16B(), VTMP1.V16B(), VTMP1.V16B());
|
||||
sri(VTMP1.V16B(), GetSrc(Op->Header.Args[0].ID()).V16B(), Op->ByteShift);
|
||||
mov(GetDst(Node).V16B(), VTMP1.V16B());
|
||||
break;
|
||||
}
|
||||
case IR::OP_VUMIN: {
|
||||
auto Op = IROp->C<IR::IROp_VUMin>();
|
||||
switch (Op->ElementSize) {
|
||||
|
||||
@@ -1562,6 +1562,20 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView<true> const
|
||||
|
||||
break;
|
||||
}
|
||||
case IR::OP_VSLI: {
|
||||
auto Op = IROp->C<IR::IROp_VSLI>();
|
||||
movapd(xmm15, GetSrc(Op->Header.Args[0].ID()));
|
||||
pslldq(xmm15, Op->ByteShift);
|
||||
movapd(GetDst(Node), xmm15);
|
||||
break;
|
||||
}
|
||||
case IR::OP_VSRI: {
|
||||
auto Op = IROp->C<IR::IROp_VSRI>();
|
||||
movapd(xmm15, GetSrc(Op->Header.Args[0].ID()));
|
||||
psrldq(xmm15, Op->ByteShift);
|
||||
movapd(GetDst(Node), xmm15);
|
||||
break;
|
||||
}
|
||||
case IR::OP_VEXTR: {
|
||||
auto Op = IROp->C<IR::IROp_VExtr>();
|
||||
vpalignr(GetDst(Node), GetSrc(Op->Header.Args[0].ID()), GetSrc(Op->Header.Args[1].ID()), Op->Index);
|
||||
|
||||
@@ -3136,15 +3136,27 @@ void OpDispatchBuilder::PSLL(OpcodeArgs) {
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::PSRLDQ(OpcodeArgs) {
|
||||
OrderedNode *Src = LoadSource(Op, Op->Src1, Op->Flags, -1);
|
||||
LogMan::Throw::A(Op->Src1.TypeNone.Type == FEXCore::X86Tables::DecodedOperand::TYPE_LITERAL, "Src1 needs to be literal here");
|
||||
uint64_t Shift = Op->Src1.TypeLiteral.Literal;
|
||||
|
||||
OrderedNode *Dest = LoadSource(Op, Op->Dest, Op->Flags, -1);
|
||||
|
||||
// PSRLDQ shifts by bytes
|
||||
// Adjust input value by number of bytes
|
||||
Src = _Lshl(Src, _Constant(3));
|
||||
auto Size = GetDstSize(Op);
|
||||
|
||||
auto Shift = _Lshr(Dest, Src);
|
||||
StoreResult(Op, Shift, -1);
|
||||
auto Result = _VSRI(Size, 16, Dest, Shift);
|
||||
StoreResult(Op, Result, -1);
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::PSLLDQ(OpcodeArgs) {
|
||||
LogMan::Throw::A(Op->Src1.TypeNone.Type == FEXCore::X86Tables::DecodedOperand::TYPE_LITERAL, "Src1 needs to be literal here");
|
||||
uint64_t Shift = Op->Src1.TypeLiteral.Literal;
|
||||
|
||||
OrderedNode *Dest = LoadSource(Op, Op->Dest, Op->Flags, -1);
|
||||
|
||||
auto Size = GetDstSize(Op);
|
||||
|
||||
auto Result = _VSLI(Size, 16, Dest, Shift);
|
||||
StoreResult(Op, Result, -1);
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::MOVDDUPOp(OpcodeArgs) {
|
||||
@@ -3607,8 +3619,7 @@ constexpr uint16_t PF_F2 = 3;
|
||||
{OPD(FEXCore::X86Tables::TYPE_GROUP_14, PF_66, 2), 1, &OpDispatchBuilder::PSRLD<4>},
|
||||
{OPD(FEXCore::X86Tables::TYPE_GROUP_14, PF_66, 6), 1, &OpDispatchBuilder::PSLL<8, true>},
|
||||
{OPD(FEXCore::X86Tables::TYPE_GROUP_14, PF_66, 3), 1, &OpDispatchBuilder::PSRLDQ},
|
||||
// XXX: Causes issues with ld.so
|
||||
// {OPD(FEXCore::X86Tables::TYPE_GROUP_14, PF_66, 7), 1, &OpDispatchBuilder::PSLL<16, true>},
|
||||
{OPD(FEXCore::X86Tables::TYPE_GROUP_14, PF_66, 7), 1, &OpDispatchBuilder::PSLLDQ},
|
||||
|
||||
// GROUP 15
|
||||
{OPD(FEXCore::X86Tables::TYPE_GROUP_15, PF_NONE, 0), 1, &OpDispatchBuilder::FXSaveOp},
|
||||
|
||||
@@ -182,6 +182,7 @@ public:
|
||||
template<size_t ElementSize, bool Scalar>
|
||||
void PSLL(OpcodeArgs);
|
||||
void PSRLDQ(OpcodeArgs);
|
||||
void PSLLDQ(OpcodeArgs);
|
||||
void MOVDDUPOp(OpcodeArgs);
|
||||
|
||||
template<size_t ElementSize>
|
||||
@@ -281,6 +282,12 @@ public:
|
||||
IRPair<IROp_VExtr> _VExtr(uint8_t RegisterSize, uint8_t ElementSize, OrderedNode *ssa0, OrderedNode *ssa1, uint8_t Index) {
|
||||
return _VExtr(ssa0, ssa1, RegisterSize, ElementSize, Index);
|
||||
}
|
||||
IRPair<IROp_VSLI> _VSLI(uint8_t RegisterSize, uint8_t ElementSize, OrderedNode *ssa0, uint8_t ByteShift) {
|
||||
return _VSLI(ssa0, RegisterSize, ElementSize, ByteShift);
|
||||
}
|
||||
IRPair<IROp_VSRI> _VSRI(uint8_t RegisterSize, uint8_t ElementSize, OrderedNode *ssa0, uint8_t ByteShift) {
|
||||
return _VSRI(ssa0, RegisterSize, ElementSize, ByteShift);
|
||||
}
|
||||
IRPair<IROp_Jump> _Jump() {
|
||||
return _Jump(InvalidNode);
|
||||
}
|
||||
|
||||
@@ -563,6 +563,26 @@
|
||||
]
|
||||
},
|
||||
|
||||
"VSLI": {
|
||||
"HasDest": true,
|
||||
"SSAArgs": "1",
|
||||
"Args": [
|
||||
"uint8_t", "RegisterSize",
|
||||
"uint8_t", "ElementSize",
|
||||
"uint8_t", "ByteShift"
|
||||
]
|
||||
},
|
||||
|
||||
"VSRI": {
|
||||
"HasDest": true,
|
||||
"SSAArgs": "1",
|
||||
"Args": [
|
||||
"uint8_t", "RegisterSize",
|
||||
"uint8_t", "ElementSize",
|
||||
"uint8_t", "ByteShift"
|
||||
]
|
||||
},
|
||||
|
||||
"VBitcast": {
|
||||
"HasDest": true,
|
||||
"SSAArgs": "1"
|
||||
|
||||
Reference in new issue
Block a user