From 79ffd11c1db45e28a0d9e92ef21ea4e2180e251b Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Thu, 12 Mar 2020 16:33:00 -0700 Subject: [PATCH] Cleans up and renames the CVT ops Fixes issue #14. A lot of these were named in very confusing ways. Makes them very explicit about what the operation is doing --- .../Core/Interpreter/InterpreterCore.cpp | 148 ++++++++++++------ .../Source/Interface/Core/JIT/Arm64/JIT.cpp | 36 +---- .../Source/Interface/Core/JIT/x86_64/JIT.cpp | 69 +++----- .../Interface/Core/LLVMJIT/LLVMCore.cpp | 9 -- .../Interface/Core/OpcodeDispatcher.cpp | 129 ++++++++------- .../Source/Interface/Core/OpcodeDispatcher.h | 13 +- External/FEXCore/Source/Interface/IR/IR.json | 50 +++--- 7 files changed, 233 insertions(+), 221 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/Interpreter/InterpreterCore.cpp b/External/FEXCore/Source/Interface/Core/Interpreter/InterpreterCore.cpp index 98d0beee8..3db3cffdd 100644 --- a/External/FEXCore/Source/Interface/Core/Interpreter/InterpreterCore.cpp +++ b/External/FEXCore/Source/Interface/Core/Interpreter/InterpreterCore.cpp @@ -1086,17 +1086,6 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) { GD = CompResult ? ArgTrue : ArgFalse; break; } - case IR::OP_EXTRACTELEMENT: { - auto ExtractElementOp = IROp->C(); - - uintptr_t DstPtr = GetDest(*WrapperOp); - uintptr_t SrcPtr = GetSrc(ExtractElementOp->Header.Args[0]); - - // Offset to the element offset - SrcPtr += IROp->Size * ExtractElementOp->Idx; - memcpy(reinterpret_cast(DstPtr), reinterpret_cast(SrcPtr), IROp->Size); - break; - } case IR::OP_CAS: { auto Op = IROp->C(); auto Size = OpSize; @@ -2399,8 +2388,8 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) { memcpy(GDP, Tmp, Op->RegisterSize); break; } - case IR::OP_VUCVTF: { - auto Op = IROp->C(); + case IR::OP_VECTOR_UTOF: { + auto Op = IROp->C(); void *Src = GetSrc(Op->Header.Args[0]); uint8_t Tmp[16]; @@ -2415,8 +2404,8 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) { memcpy(GDP, Tmp, Op->RegisterSize); break; } - case IR::OP_VSCVTF: { - auto Op = IROp->C(); + case IR::OP_VECTOR_STOF: { + auto Op = IROp->C(); void *Src = GetSrc(Op->Header.Args[0]); uint8_t Tmp[16]; @@ -2431,6 +2420,38 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) { memcpy(GDP, Tmp, Op->RegisterSize); break; } + case IR::OP_VECTOR_FTOZU: { + auto Op = IROp->C(); + void *Src = GetSrc(Op->Header.Args[0]); + uint8_t Tmp[16]; + + uint8_t Elements = Op->RegisterSize / Op->ElementSize; + + auto Func = [](auto a, auto max) { return a; }; + switch (Op->ElementSize) { + DO_VECTOR_1SRC_2TYPE_OP(4, uint32_t, float, Func, 0) + DO_VECTOR_1SRC_2TYPE_OP(8, uint64_t, double, Func, 0) + default: LogMan::Msg::A("Unknown Element Size: %d", Op->ElementSize); break; + } + memcpy(GDP, Tmp, Op->RegisterSize); + break; + } + case IR::OP_VECTOR_FTOZS: { + auto Op = IROp->C(); + void *Src = GetSrc(Op->Header.Args[0]); + uint8_t Tmp[16]; + + uint8_t Elements = Op->RegisterSize / Op->ElementSize; + + auto Func = [](auto a, auto max) { return a; }; + switch (Op->ElementSize) { + DO_VECTOR_1SRC_2TYPE_OP(4, int32_t, float, Func, 0) + DO_VECTOR_1SRC_2TYPE_OP(8, int64_t, double, Func, 0) + default: LogMan::Msg::A("Unknown Element Size: %d", Op->ElementSize); break; + } + memcpy(GDP, Tmp, Op->RegisterSize); + break; + } case IR::OP_VUMULL: { auto Op = IROp->C(); void *Src1 = GetSrc(Op->Header.Args[0]); @@ -2469,36 +2490,6 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) { memcpy(GDP, Tmp, Op->RegisterSize); break; } - case IR::OP_VFCVTL: { - auto Op = IROp->C(); - void *Src = GetSrc(Op->Header.Args[0]); - uint8_t Tmp[16]; - - uint8_t Elements = Op->RegisterSize / Op->ElementSize; - - auto Func = [](auto a, auto max) { return a; }; - switch (Op->ElementSize) { - DO_VECTOR_1SRC_2TYPE_OP(4, double, float, Func, 0) - default: LogMan::Msg::A("Unknown Element Size: %d", Op->ElementSize); break; - } - memcpy(GDP, Tmp, Op->RegisterSize); - break; - } - case IR::OP_VFCVTN: { - auto Op = IROp->C(); - void *Src = GetSrc(Op->Header.Args[0]); - uint8_t Tmp[16]; - - uint8_t Elements = Op->RegisterSize / Op->ElementSize; - - auto Func = [](auto a, auto max) { return a; }; - switch (Op->ElementSize) { - DO_VECTOR_1SRC_2TYPE_OP(8, float, double, Func, 0) - default: LogMan::Msg::A("Unknown Element Size: %d", Op->ElementSize); break; - } - memcpy(GDP, Tmp, Op->RegisterSize); - break; - } case IR::OP_VSXTL: { auto Op = IROp->C(); void *Src = GetSrc(Op->Header.Args[0]); @@ -3055,9 +3046,8 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) { memcpy(GDP, &Dst, Op->RegisterSize); break; } - - case IR::OP_SCVTF: { - auto Op = IROp->C(); + case IR::OP_FLOAT_FROMGPR_S: { + auto Op = IROp->C(); if (Op->ElementSize == 8) { double Dst = (double)*GetSrc(Op->Header.Args[0]); memcpy(GDP, &Dst, Op->ElementSize); @@ -3068,8 +3058,20 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) { } break; } - case IR::OP_FCVTZS: { - auto Op = IROp->C(); + case IR::OP_FLOAT_FROMGPR_U: { + auto Op = IROp->C(); + if (Op->ElementSize == 8) { + double Dst = (double)*GetSrc(Op->Header.Args[0]); + memcpy(GDP, &Dst, Op->ElementSize); + } + else { + float Dst = (float)*GetSrc(Op->Header.Args[0]); + memcpy(GDP, &Dst, Op->ElementSize); + } + break; + } + case IR::OP_FLOAT_TOGPR_ZS: { + auto Op = IROp->C(); if (Op->ElementSize == 8) { int64_t Dst = (int64_t)*GetSrc(Op->Header.Args[0]); memcpy(GDP, &Dst, Op->ElementSize); @@ -3080,8 +3082,20 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) { } break; } - case IR::OP_FCVTF: { - auto Op = IROp->C(); + case IR::OP_FLOAT_TOGPR_ZU: { + auto Op = IROp->C(); + if (Op->ElementSize == 8) { + uint64_t Dst = (uint64_t)*GetSrc(Op->Header.Args[0]); + memcpy(GDP, &Dst, Op->ElementSize); + } + else { + uint32_t Dst = (uint32_t)*GetSrc(Op->Header.Args[0]); + memcpy(GDP, &Dst, Op->ElementSize); + } + break; + } + case IR::OP_FLOAT_FTOF: { + auto Op = IROp->C(); uint16_t Conv = (Op->DstElementSize << 8) | Op->SrcElementSize; switch (Conv) { case 0x0804: { // Double <- Float @@ -3098,6 +3112,36 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) { } break; } + case IR::OP_VECTOR_FTOF: { + auto Op = IROp->C(); + void *Src = GetSrc(Op->Header.Args[0]); + uint8_t Tmp[16]; + + uint16_t Conv = (Op->DstElementSize << 8) | Op->SrcElementSize; + + auto Func = [](auto a, auto max) { return a; }; + switch (Conv) { + case 0x0804: { // Double <- float + uint8_t Elements = Op->RegisterSize / Op->SrcElementSize; + switch (Op->SrcElementSize) { + DO_VECTOR_1SRC_2TYPE_OP(4, double, float, Func, 0) + } + break; + } + case 0x0408: { // Float <- Double + uint8_t Elements = Op->RegisterSize / Op->SrcElementSize; + switch (Op->SrcElementSize) { + DO_VECTOR_1SRC_2TYPE_OP(8, float, double, Func, 0) + } + break; + + break; + } + default: LogMan::Msg::A("Unknown Conversion Type : 0%04x", Conv); break; + } + memcpy(GDP, Tmp, Op->RegisterSize); + break; + } #define DO_SCALAR_COMPARE_OP(size, type, type2, func) \ case size: { \ auto *Dst_d = reinterpret_cast(Tmp); \ diff --git a/External/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp b/External/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp index e77e6af6b..b0d4a6c44 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp @@ -511,26 +511,6 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView const break; } - case IR::OP_EXTRACTELEMENT: { - auto Op = IROp->C(); - - uint64_t PhysReg = RAPass->GetNodeRegister(Op->Header.Args[0].ID()); - if (PhysReg >= FPRBase) { - switch (OpSize) { - case 4: - umov(GetDst(Node), GetSrc(Op->Header.Args[0].ID()).V4S(), Op->Idx); - break; - case 8: - umov(GetDst(Node), GetSrc(Op->Header.Args[0].ID()).V2D(), Op->Idx); - break; - default: LogMan::Msg::A("Unhandled ExtractElementSize: %d", OpSize); - } - } - else { - LogMan::Msg::A("Can't handle extract from GPR yet"); - } - break; - } case IR::OP_VEXTRACTTOGPR: { auto Op = IROp->C(); switch (OpSize) { @@ -773,14 +753,14 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView const } case IR::OP_NEG: { auto Op = IROp->C(); - switch (Op->SrcSize / 8) { + switch (OpSize) { case 4: neg(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); break; case 8: neg(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); break; - default: LogMan::Msg::A("Unsupported Not size: %d", Op->SrcSize / 8); + default: LogMan::Msg::A("Unsupported Not size: %d", OpSize); } break; } @@ -917,14 +897,14 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView const } case IR::OP_NOT: { auto Op = IROp->C(); - switch (Op->SrcSize / 8) { + switch (OpSize) { case 4: mvn(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); break; case 8: mvn(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); break; - default: LogMan::Msg::A("Unsupported Not size: %d", Op->SrcSize / 8); + default: LogMan::Msg::A("Unsupported Not size: %d", OpSize); } break; } @@ -2256,8 +2236,8 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView const } break; } - case IR::OP_SCVTF: { - auto Op = IROp->C(); + case IR::OP_FLOAT_FROMGPR_S: { + auto Op = IROp->C(); if (Op->ElementSize == 8) { scvtf(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); } @@ -2265,8 +2245,8 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView const scvtf(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); break; } - case IR::OP_FCVTZS: { - auto Op = IROp->C(); + case IR::OP_FLOAT_TOGPR_ZS: { + auto Op = IROp->C(); if (Op->ElementSize == 8) { fcvtzs(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); } diff --git a/External/FEXCore/Source/Interface/Core/JIT/x86_64/JIT.cpp b/External/FEXCore/Source/Interface/Core/JIT/x86_64/JIT.cpp index 844fde21c..9c2f33217 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/x86_64/JIT.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/x86_64/JIT.cpp @@ -1905,32 +1905,6 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView const } break; } - case IR::OP_EXTRACTELEMENT: { - auto Op = IROp->C(); - - uint64_t PhysReg = RAPass->GetNodeRegister(Op->Header.Args[0].ID()); - if (PhysReg >= XMMBase) { - switch (OpSize) { - case 1: - pextrb(GetDst(Node), GetSrc(Op->Header.Args[0].ID()), Op->Idx); - break; - case 2: - pextrw(GetDst(Node), GetSrc(Op->Header.Args[0].ID()), Op->Idx); - break; - case 4: - pextrd(GetDst(Node), GetSrc(Op->Header.Args[0].ID()), Op->Idx); - break; - case 8: - pextrq(GetDst(Node), GetSrc(Op->Header.Args[0].ID()), Op->Idx); - break; - default: LogMan::Msg::A("Unhandled ExtractElementSize: %d", OpSize); - } - } - else { - LogMan::Msg::A("Can't handle extract from GPR yet"); - } - break; - } case IR::OP_VINSELEMENT: { auto Op = IROp->C(); movapd(xmm15, GetSrc(Op->Header.Args[0].ID())); @@ -2443,8 +2417,8 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView const } break; } - case IR::OP_VSCVTF: { - auto Op = IROp->C(); + case IR::OP_VECTOR_STOF: { + auto Op = IROp->C(); switch (Op->ElementSize) { case 4: cvtdq2ps(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); @@ -2465,23 +2439,20 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView const } break; } - case IR::OP_VFCVTL: { - auto Op = IROp->C(); - switch (Op->ElementSize) { - case 4: + case IR::OP_VECTOR_FTOF: { + auto Op = IROp->C(); + uint16_t Conv = (Op->DstElementSize << 8) | Op->SrcElementSize; + + switch (Conv) { + case 0x0804: { // Double <- Float cvtps2pd(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); - break; - default: LogMan::Msg::A("Unknown Element Size: %d", Op->ElementSize); break; - } - break; - } - case IR::OP_VFCVTN: { - auto Op = IROp->C(); - switch (Op->ElementSize) { - case 8: + break; + } + case 0x0408: { // Float <- Double cvtpd2ps(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); - break; - default: LogMan::Msg::A("Unknown Element Size: %d", Op->ElementSize); break; + break; + } + default: LogMan::Msg::A("Unknown Conversion Type : 0%04x", Conv); break; } break; } @@ -2895,8 +2866,8 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView const } break; } - case IR::OP_SCVTF: { - auto Op = IROp->C(); + case IR::OP_FLOAT_FROMGPR_S: { + auto Op = IROp->C(); if (Op->ElementSize == 8) { cvtsi2sd(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); } @@ -2904,8 +2875,8 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView const cvtsi2ss(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); break; } - case IR::OP_FCVTZS: { - auto Op = IROp->C(); + case IR::OP_FLOAT_TOGPR_ZS: { + auto Op = IROp->C(); if (Op->ElementSize == 8) { cvttsd2si(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); } @@ -2913,8 +2884,8 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView const cvttss2si(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); break; } - case IR::OP_FCVTF: { - auto Op = IROp->C(); + case IR::OP_FLOAT_FTOF: { + auto Op = IROp->C(); uint16_t Conv = (Op->DstElementSize << 8) | Op->SrcElementSize; switch (Conv) { case 0x0804: { // Double <- Float diff --git a/External/FEXCore/Source/Interface/Core/LLVMJIT/LLVMCore.cpp b/External/FEXCore/Source/Interface/Core/LLVMJIT/LLVMCore.cpp index 9cbd92685..86bb0cbcf 100644 --- a/External/FEXCore/Source/Interface/Core/LLVMJIT/LLVMCore.cpp +++ b/External/FEXCore/Source/Interface/Core/LLVMJIT/LLVMCore.cpp @@ -940,15 +940,6 @@ void LLVMJITCore::HandleIR(FEXCore::IR::IRListView const *IR, IR::NodeWrap SetDest(*WrapperOp, Result); break; } - // The IR's current representation of vectors is actually an array - case IR::OP_EXTRACTELEMENT: { - auto Op = IROp->C(); - auto Src = GetSrc(Op->Header.Args[0]); - std::vector Idxs = {Op->Idx}; - auto Result = JITState.IRBuilder->CreateExtractValue(Src, Idxs); - SetDest(*WrapperOp, Result); - break; - } case IR::OP_LOADCONTEXT: { auto Op = IROp->C(); auto Value = CreateContextPtr(Op->Offset, Op->Size); diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index ab84febd3..d47fcf184 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -1099,10 +1099,10 @@ void OpDispatchBuilder::CPUIDOp(OpcodeArgs) { OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1); auto Res = _CPUID(Src); - _StoreContext(FPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RAX]), _ExtractElement(Res, 0)); - _StoreContext(FPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RBX]), _ExtractElement(Res, 1)); - _StoreContext(FPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDX]), _ExtractElement(Res, 2)); - _StoreContext(FPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RCX]), _ExtractElement(Res, 3)); + _StoreContext(GPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RAX]), _Zext(32, _VExtractToGPR(16, 4, Res, 0))); + _StoreContext(GPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RBX]), _Zext(32, _VExtractToGPR(16, 4, Res, 1))); + _StoreContext(GPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDX]), _Zext(32, _VExtractToGPR(16, 4, Res, 2))); + _StoreContext(GPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RCX]), _Zext(32, _VExtractToGPR(16, 4, Res, 3))); } template @@ -2723,33 +2723,6 @@ void OpDispatchBuilder::PCMPGTOp(OpcodeArgs) { StoreResult(FPRClass, Op, ALUOp, -1); } -void OpDispatchBuilder::MOVDOp(OpcodeArgs) { - if (Op->Dest.TypeNone.Type == FEXCore::X86Tables::DecodedOperand::TYPE_GPR && - Op->Dest.TypeGPR.GPR >= FEXCore::X86State::REG_XMM_0) { - OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1); - // When destination is XMM then it is zext to 128bit - uint64_t SrcSize = GetSrcSize(Op) * 8; - while (SrcSize != 128) { - Src = _Zext(SrcSize, Src); - SrcSize *= 2; - } - StoreResult(FPRClass, Op, Op->Dest, Src, -1); - } - else { - // Destination is GPR or mem - // Extract from XMM first - uint8_t ElementSize = 4; - if (Op->Flags & X86Tables::DecodeFlags::FLAG_REX_WIDENING) - ElementSize = 8; - OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0],Op->Flags, -1); - - Src = _VExtractToGPR(GetSrcSize(Op), ElementSize, Src, 0); - - StoreResult(GPRClass, Op, Op->Dest, Src, -1); - } - -} - void OpDispatchBuilder::CMPXCHGOp(OpcodeArgs) { // CMPXCHG ModRM, reg, {RAX} // MemData = *ModRM.dest @@ -3921,7 +3894,6 @@ void OpDispatchBuilder::PSLLI(OpcodeArgs) { StoreResult(FPRClass, Op, Shift, -1); } - template void OpDispatchBuilder::PSLL(OpcodeArgs) { OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[SrcIndex], Op->Flags, -1); @@ -4004,7 +3976,7 @@ void OpDispatchBuilder::MOVDDUPOp(OpcodeArgs) { } template -void OpDispatchBuilder::CVT(OpcodeArgs) { +void OpDispatchBuilder::CVTGPR_To_FPR(OpcodeArgs) { OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1); if (Op->Flags & X86Tables::DecodeFlags::FLAG_REX_WIDENING) { @@ -4024,9 +3996,9 @@ void OpDispatchBuilder::CVT(OpcodeArgs) { } if (Signed) - Src = _SCVTF(Src, DstElementSize); + Src = _Float_FromGPR_S(Src, DstElementSize); else - Src = _UCVTF(Src, DstElementSize); + Src = _Float_FromGPR_U(Src, DstElementSize); OrderedNode *Dest = LoadSource_WithOpSize(FPRClass, Op, Op->Dest, 16, Op->Flags, -1); @@ -4036,19 +4008,19 @@ void OpDispatchBuilder::CVT(OpcodeArgs) { } template -void OpDispatchBuilder::FCVT(OpcodeArgs) { +void OpDispatchBuilder::CVTFPR_To_GPR(OpcodeArgs) { OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1); if (Signed) - Src = _FCVTZS(Src, SrcElementSize); + Src = _Float_ToGPR_ZS(Src, SrcElementSize); else - Src = _FCVTZU(Src, SrcElementSize); + Src = _Float_ToGPR_ZU(Src, SrcElementSize); StoreResult_WithOpSize(GPRClass, Op, Op->Dest, Src, SrcElementSize, -1); } template -void OpDispatchBuilder::VFCVT(OpcodeArgs) { +void OpDispatchBuilder::Vector_CVT_Int_To_Float(OpcodeArgs) { OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1); size_t ElementSize = SrcElementSize; @@ -4059,39 +4031,77 @@ void OpDispatchBuilder::VFCVT(OpcodeArgs) { } if (Signed) - Src = _VSCVTF(Src, Size, ElementSize); + Src = _Vector_SToF(Src, Size, ElementSize); else - Src = _VUCVTF(Src, Size, ElementSize); + Src = _Vector_UToF(Src, Size, ElementSize); StoreResult(FPRClass, Op, Src, -1); } +template +void OpDispatchBuilder::Vector_CVT_Float_To_Int(OpcodeArgs) { + OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1); + + if (Signed) + Src = _Vector_FToZS(Src, 16, SrcElementSize); + else + Src = _Vector_FToZU(Src, 16, SrcElementSize); + + StoreResult_WithOpSize(FPRClass, Op, Op->Dest, Src, SrcElementSize, -1); +} + template -void OpDispatchBuilder::FCVTF(OpcodeArgs) { +void OpDispatchBuilder::Scalar_CVT_Float_To_Float(OpcodeArgs) { OrderedNode *Dest = LoadSource(FPRClass, Op, Op->Dest, Op->Flags, -1); OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1); - Src = _FCVTF(Src, DstElementSize, SrcElementSize); + Src = _Float_FToF(Src, DstElementSize, SrcElementSize); Src = _VInsElement(16, DstElementSize, 0, 0, Dest, Src); StoreResult(FPRClass, Op, Src, -1); } template -void OpDispatchBuilder::VFCVTF(OpcodeArgs) { +void OpDispatchBuilder::Vector_CVT_Float_To_Float(OpcodeArgs) { OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1); size_t Size = GetDstSize(Op); if (DstElementSize > SrcElementSize) { - Src = _VFCVTL(Src, Size, SrcElementSize); + Src = _Vector_FToF(Src, Size, SrcElementSize << 1, SrcElementSize); } else { - Src = _VFCVTN(Src, Size, SrcElementSize); + Src = _Vector_FToF(Src, Size, SrcElementSize >> 1, SrcElementSize); } StoreResult(FPRClass, Op, Src, -1); } +void OpDispatchBuilder::MOVBetweenGPR_FPR(OpcodeArgs) { + if (Op->Dest.TypeNone.Type == FEXCore::X86Tables::DecodedOperand::TYPE_GPR && + Op->Dest.TypeGPR.GPR >= FEXCore::X86State::REG_XMM_0) { + OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1); + // When destination is XMM then it is zext to 128bit + uint64_t SrcSize = GetSrcSize(Op) * 8; + while (SrcSize != 128) { + Src = _Zext(SrcSize, Src); + SrcSize *= 2; + } + StoreResult(FPRClass, Op, Op->Dest, Src, -1); + } + else { + // Destination is GPR or mem + // Extract from XMM first + uint8_t ElementSize = 4; + if (Op->Flags & X86Tables::DecodeFlags::FLAG_REX_WIDENING) + ElementSize = 8; + OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0],Op->Flags, -1); + + Src = _VExtractToGPR(GetSrcSize(Op), ElementSize, Src, 0); + + StoreResult(GPRClass, Op, Op->Dest, Src, -1); + } +} + void OpDispatchBuilder::TZCNT(OpcodeArgs) { OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1); @@ -4620,14 +4630,16 @@ void InstallOpcodeHandlers() { {0x17, 1, &OpDispatchBuilder::MOVUPSOp}, {0x28, 2, &OpDispatchBuilder::MOVUPSOp}, {0x50, 1, &OpDispatchBuilder::MOVMSKOp<4>}, + {0x51, 1, &OpDispatchBuilder::VectorUnaryOp}, + {0x52, 1, &OpDispatchBuilder::VectorUnaryOp}, {0x54, 1, &OpDispatchBuilder::VectorALUOp}, {0x55, 1, &OpDispatchBuilder::ANDNOp}, {0x56, 1, &OpDispatchBuilder::VectorALUOp}, {0x57, 1, &OpDispatchBuilder::VectorALUOp}, {0x58, 1, &OpDispatchBuilder::VectorALUOp}, {0x59, 1, &OpDispatchBuilder::VectorALUOp}, - {0x5A, 1, &OpDispatchBuilder::VFCVTF<8, 4>}, - {0x5B, 1, &OpDispatchBuilder::VFCVT<4, true, false>}, + {0x5A, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Float<8, 4>}, + {0x5B, 1, &OpDispatchBuilder::Vector_CVT_Int_To_Float<4, true, false>}, {0x5C, 1, &OpDispatchBuilder::VectorALUOp}, {0x5D, 1, &OpDispatchBuilder::VectorALUOp}, {0x5E, 1, &OpDispatchBuilder::VectorALUOp}, @@ -4752,13 +4764,13 @@ void InstallOpcodeHandlers() { {0x10, 2, &OpDispatchBuilder::MOVSSOp}, {0x16, 1, &OpDispatchBuilder::MOVSHDUPOp}, {0x19, 7, &OpDispatchBuilder::NOPOp}, - {0x2A, 1, &OpDispatchBuilder::CVT<4, true>}, - {0x2C, 1, &OpDispatchBuilder::FCVT<4, true>}, + {0x2A, 1, &OpDispatchBuilder::CVTGPR_To_FPR<4, true>}, + {0x2C, 1, &OpDispatchBuilder::CVTFPR_To_GPR<4, true>}, {0x51, 1, &OpDispatchBuilder::VectorUnaryOp}, {0x52, 1, &OpDispatchBuilder::VectorUnaryOp}, {0x58, 1, &OpDispatchBuilder::VectorScalarALUOp}, {0x59, 1, &OpDispatchBuilder::VectorScalarALUOp}, - {0x5A, 1, &OpDispatchBuilder::FCVTF<8, 4>}, + {0x5A, 1, &OpDispatchBuilder::Scalar_CVT_Float_To_Float<8, 4>}, {0x5C, 1, &OpDispatchBuilder::VectorScalarALUOp}, {0x5D, 1, &OpDispatchBuilder::VectorScalarALUOp}, {0x5E, 1, &OpDispatchBuilder::VectorScalarALUOp}, @@ -4770,20 +4782,20 @@ void InstallOpcodeHandlers() { {0xB8, 1, &OpDispatchBuilder::PopcountOp}, {0xBC, 2, &OpDispatchBuilder::TZCNT}, {0xC2, 1, &OpDispatchBuilder::VFCMPOp<4, true>}, - {0xE6, 1, &OpDispatchBuilder::VFCVT<4, true, true>}, + {0xE6, 1, &OpDispatchBuilder::Vector_CVT_Int_To_Float<4, true, true>}, }; const std::vector> RepNEModOpTable = { {0x10, 2, &OpDispatchBuilder::MOVSDOp}, {0x12, 1, &OpDispatchBuilder::MOVDDUPOp}, {0x19, 7, &OpDispatchBuilder::NOPOp}, - {0x2A, 1, &OpDispatchBuilder::CVT<8, true>}, - {0x2C, 1, &OpDispatchBuilder::FCVT<8, true>}, + {0x2A, 1, &OpDispatchBuilder::CVTGPR_To_FPR<8, true>}, + {0x2C, 1, &OpDispatchBuilder::CVTFPR_To_GPR<8, true>}, {0x51, 1, &OpDispatchBuilder::VectorUnaryOp}, //x52 = Invalid {0x58, 1, &OpDispatchBuilder::VectorScalarALUOp}, {0x59, 1, &OpDispatchBuilder::VectorScalarALUOp}, - {0x5A, 1, &OpDispatchBuilder::FCVTF<4, 8>}, + {0x5A, 1, &OpDispatchBuilder::Scalar_CVT_Float_To_Float<4, 8>}, {0x5C, 1, &OpDispatchBuilder::VectorScalarALUOp}, {0x5D, 1, &OpDispatchBuilder::VectorScalarALUOp}, {0x5E, 1, &OpDispatchBuilder::VectorScalarALUOp}, @@ -4810,7 +4822,8 @@ void InstallOpcodeHandlers() { {0x57, 1, &OpDispatchBuilder::VectorALUOp}, {0x58, 1, &OpDispatchBuilder::VectorALUOp}, {0x59, 1, &OpDispatchBuilder::VectorALUOp}, - {0x5A, 1, &OpDispatchBuilder::VFCVTF<4, 8>}, + {0x5A, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Float<4, 8>}, + {0x5B, 1, &OpDispatchBuilder::CVTFPR_To_GPR<4, true>}, {0x5C, 1, &OpDispatchBuilder::VectorALUOp}, {0x5D, 1, &OpDispatchBuilder::VectorALUOp}, {0x5E, 1, &OpDispatchBuilder::VectorALUOp}, @@ -4827,7 +4840,7 @@ void InstallOpcodeHandlers() { {0x6A, 1, &OpDispatchBuilder::PUNPCKHOp<4>}, {0x6C, 1, &OpDispatchBuilder::PUNPCKLOp<8>}, {0x6D, 1, &OpDispatchBuilder::PUNPCKHOp<8>}, - {0x6E, 1, &OpDispatchBuilder::MOVDOp}, + {0x6E, 1, &OpDispatchBuilder::MOVBetweenGPR_FPR}, {0x6F, 1, &OpDispatchBuilder::MOVUPSOp}, {0x70, 1, &OpDispatchBuilder::PSHUFDOp<4, true>}, @@ -4836,7 +4849,7 @@ void InstallOpcodeHandlers() { {0x75, 1, &OpDispatchBuilder::PCMPEQOp<2>}, {0x76, 1, &OpDispatchBuilder::PCMPEQOp<4>}, {0x78, 1, nullptr}, // GROUP 17 - {0x7E, 1, &OpDispatchBuilder::MOVDOp}, + {0x7E, 1, &OpDispatchBuilder::MOVBetweenGPR_FPR}, {0x7F, 1, &OpDispatchBuilder::MOVUPSOp}, {0xC2, 1, &OpDispatchBuilder::VFCMPOp<8, false>}, {0xC4, 1, &OpDispatchBuilder::PINSROp<2>}, diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index eb89194c5..cda78af62 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -233,15 +233,18 @@ public: void PSRAIOp(OpcodeArgs); void MOVDDUPOp(OpcodeArgs); template - void CVT(OpcodeArgs); + void CVTGPR_To_FPR(OpcodeArgs); template - void FCVT(OpcodeArgs); + void CVTFPR_To_GPR(OpcodeArgs); template - void VFCVT(OpcodeArgs); + void Vector_CVT_Int_To_Float(OpcodeArgs); template - void FCVTF(OpcodeArgs); + void Scalar_CVT_Float_To_Float(OpcodeArgs); template - void VFCVTF(OpcodeArgs); + void Vector_CVT_Float_To_Float(OpcodeArgs); + template + void Vector_CVT_Float_To_Int(OpcodeArgs); + void MOVBetweenGPR_FPR(OpcodeArgs); void TZCNT(OpcodeArgs); void MOVSSOp(OpcodeArgs); template diff --git a/External/FEXCore/Source/Interface/IR/IR.json b/External/FEXCore/Source/Interface/IR/IR.json index a55c5e73c..d0b96aca7 100644 --- a/External/FEXCore/Source/Interface/IR/IR.json +++ b/External/FEXCore/Source/Interface/IR/IR.json @@ -544,7 +544,7 @@ ] }, - "FCVTZU": { + "Float_ToGPR_ZU": { "HasDest": true, "DestSize": "ElementSize", "SSAArgs": "1", @@ -553,7 +553,7 @@ ] }, - "FCVTZS": { + "Float_ToGPR_ZS": { "HasDest": true, "DestSize": "ElementSize", "SSAArgs": "1", @@ -562,15 +562,6 @@ ] }, - "ExtractElement": { - "HasDest": true, - "DestSize": "GetOpSize(ssa0)", - "SSAArgs": "1", - "Args": [ - "uint8_t", "Idx" - ] - }, - "Print": { "SSAArgs": "1" }, @@ -1114,7 +1105,8 @@ ] }, - "UCVTF": { + "Float_FromGPR_U": { + "Desc": "Scalar op: Converts unsigned GPR to Scalar float", "HasDest": true, "SSAArgs": "1", "Args": [ @@ -1122,7 +1114,8 @@ ] }, - "SCVTF": { + "Float_FromGPR_S": { + "Desc": "Scalar op: Converts signed GPR to Scalar float", "HasDest": true, "SSAArgs": "1", "Args": [ @@ -1130,15 +1123,18 @@ ] }, - "VUCVTF": { + "Float_FToF": { + "Desc": "Scalar op: Converts float from one size to another", "HasDest": true, "SSAArgs": "1", "Args": [ - "uint8_t", "RegisterSize", - "uint8_t", "ElementSize" + "uint8_t", "DstElementSize", + "uint8_t", "SrcElementSize" ] }, - "VSCVTF": { + + "Vector_UToF": { + "Desc": "Vector op: Converts unsigned integer to same size float", "HasDest": true, "SSAArgs": "1", "Args": [ @@ -1147,7 +1143,8 @@ ] }, - "VFCVTL": { + "Vector_SToF": { + "Desc": "Vector op: Converts signed integer to same size float", "HasDest": true, "SSAArgs": "1", "Args": [ @@ -1156,7 +1153,8 @@ ] }, - "VFCVTN": { + "Vector_FToZU": { + "Desc": "Vector op: Converts float to unsigned integer, rounding towards zero", "HasDest": true, "SSAArgs": "1", "Args": [ @@ -1165,10 +1163,22 @@ ] }, - "FCVTF": { + "Vector_FToZS": { + "Desc": "Vector op: Converts float to signed integer, rounding towards zero", "HasDest": true, "SSAArgs": "1", "Args": [ + "uint8_t", "RegisterSize", + "uint8_t", "ElementSize" + ] + }, + + "Vector_FToF": { + "Desc": "Vector op: Converts float from source element size to destination size (fp32<->fp64)", + "HasDest": true, + "SSAArgs": "1", + "Args": [ + "uint8_t", "RegisterSize", "uint8_t", "DstElementSize", "uint8_t", "SrcElementSize" ]