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"