From afdbd9ebdc6021590f3ad4dc4e025cbc3dd1776c Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 16 Nov 2019 17:40:55 -0800 Subject: [PATCH] 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 --- .../Core/Interpreter/InterpreterCore.cpp | 19 +++++++++++++ Source/Interface/Core/JIT/Arm64/JIT.cpp | 14 ++++++++++ Source/Interface/Core/JIT/x86_64/JIT.cpp | 14 ++++++++++ Source/Interface/Core/OpcodeDispatcher.cpp | 27 +++++++++++++------ Source/Interface/Core/OpcodeDispatcher.h | 7 +++++ Source/Interface/IR/IR.json | 20 ++++++++++++++ 6 files changed, 93 insertions(+), 8 deletions(-) diff --git a/Source/Interface/Core/Interpreter/InterpreterCore.cpp b/Source/Interface/Core/Interpreter/InterpreterCore.cpp index dcd6c149c..ad7a2b0c7 100644 --- a/Source/Interface/Core/Interpreter/InterpreterCore.cpp +++ b/Source/Interface/Core/Interpreter/InterpreterCore.cpp @@ -1022,6 +1022,25 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) { memcpy(GDP, &Dst, 16); break; } + case IR::OP_VSLI: { + auto Op = IROp->C(); + __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(); + __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(Tmp); \ diff --git a/Source/Interface/Core/JIT/Arm64/JIT.cpp b/Source/Interface/Core/JIT/Arm64/JIT.cpp index f4d35fd89..d7ece7763 100644 --- a/Source/Interface/Core/JIT/Arm64/JIT.cpp +++ b/Source/Interface/Core/JIT/Arm64/JIT.cpp @@ -1480,6 +1480,20 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView const } break; } + case IR::OP_VSLI: { + auto Op = IROp->C(); + 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(); + 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(); switch (Op->ElementSize) { diff --git a/Source/Interface/Core/JIT/x86_64/JIT.cpp b/Source/Interface/Core/JIT/x86_64/JIT.cpp index a09d0ca65..bcdff60e6 100644 --- a/Source/Interface/Core/JIT/x86_64/JIT.cpp +++ b/Source/Interface/Core/JIT/x86_64/JIT.cpp @@ -1562,6 +1562,20 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView const break; } + case IR::OP_VSLI: { + auto Op = IROp->C(); + 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(); + 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(); vpalignr(GetDst(Node), GetSrc(Op->Header.Args[0].ID()), GetSrc(Op->Header.Args[1].ID()), Op->Index); diff --git a/Source/Interface/Core/OpcodeDispatcher.cpp b/Source/Interface/Core/OpcodeDispatcher.cpp index 5a2dc3b1f..2312cd8cf 100644 --- a/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/Source/Interface/Core/OpcodeDispatcher.cpp @@ -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}, diff --git a/Source/Interface/Core/OpcodeDispatcher.h b/Source/Interface/Core/OpcodeDispatcher.h index 83e4dea17..e13439150 100644 --- a/Source/Interface/Core/OpcodeDispatcher.h +++ b/Source/Interface/Core/OpcodeDispatcher.h @@ -182,6 +182,7 @@ public: template void PSLL(OpcodeArgs); void PSRLDQ(OpcodeArgs); + void PSLLDQ(OpcodeArgs); void MOVDDUPOp(OpcodeArgs); template @@ -281,6 +282,12 @@ public: IRPair _VExtr(uint8_t RegisterSize, uint8_t ElementSize, OrderedNode *ssa0, OrderedNode *ssa1, uint8_t Index) { return _VExtr(ssa0, ssa1, RegisterSize, ElementSize, Index); } + IRPair _VSLI(uint8_t RegisterSize, uint8_t ElementSize, OrderedNode *ssa0, uint8_t ByteShift) { + return _VSLI(ssa0, RegisterSize, ElementSize, ByteShift); + } + IRPair _VSRI(uint8_t RegisterSize, uint8_t ElementSize, OrderedNode *ssa0, uint8_t ByteShift) { + return _VSRI(ssa0, RegisterSize, ElementSize, ByteShift); + } IRPair _Jump() { return _Jump(InvalidNode); } diff --git a/Source/Interface/IR/IR.json b/Source/Interface/IR/IR.json index dc1b772ff..12af5d7ce 100644 --- a/Source/Interface/IR/IR.json +++ b/Source/Interface/IR/IR.json @@ -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"