From d57a034220399ff4660880fb508fa7c040cd9f46 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 8 Jun 2021 02:37:17 -0700 Subject: [PATCH] Fixes floating point conversion rounding bugs When floats and doubles were converting to integers we weren't doing the correct transformation. AArch64 provides direct ops for all four of the op types. So lets use them - f32 -> int64 - f32 -> int32 - f64 -> int64 - f64 -> int32 Doesn't fully fix the case of overflow for AArch64 since overflow behaviour is different. x86 returns 0x8000'0000 or 0x8000'0000'0000'0000 while AArch64 saturates to the maximum signed integers. Can't work around that without checking overflow flags. This does solve the typical case though. Fixes audio problems in all FMod games. --- .../Core/Interpreter/InterpreterOps.cpp | 161 +++++------------- .../Interface/Core/JIT/Arm64/ALUOps.cpp | 43 +++-- .../Core/JIT/Arm64/ConversionOps.cpp | 49 ------ .../Interface/Core/JIT/Arm64/JITClass.h | 5 - .../Interface/Core/JIT/x86_64/ALUOps.cpp | 65 ++++--- .../Core/JIT/x86_64/ConversionOps.cpp | 20 --- .../Interface/Core/JIT/x86_64/JITClass.h | 5 - .../Interface/Core/OpcodeDispatcher.cpp | 92 ++++------ .../Source/Interface/Core/OpcodeDispatcher.h | 10 +- External/FEXCore/Source/Interface/IR/IR.json | 104 +---------- .../FEXCore/include/FEXCore/IR/IREmitter.h | 3 - 11 files changed, 160 insertions(+), 397 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/Interpreter/InterpreterOps.cpp b/External/FEXCore/Source/Interface/Core/Interpreter/InterpreterOps.cpp index e10cee48c..d34fc702e 100644 --- a/External/FEXCore/Source/Interface/Core/Interpreter/InterpreterOps.cpp +++ b/External/FEXCore/Source/Interface/Core/Interpreter/InterpreterOps.cpp @@ -3349,22 +3349,6 @@ void InterpreterOps::InterpretIR(FEXCore::Core::InternalThreadState *Thread, uin memcpy(GDP, Tmp, OpSize); break; } - case IR::OP_VECTOR_UTOF: { - auto Op = IROp->C(); - void *Src = GetSrc(SSAData, Op->Header.Args[0]); - uint8_t Tmp[16]; - - uint8_t Elements = OpSize / Op->Header.ElementSize; - - auto Func = [](auto a, auto min, auto max) { return a; }; - switch (Op->Header.ElementSize) { - DO_VECTOR_1SRC_2TYPE_OP(4, float, uint32_t, Func, 0, 0) - DO_VECTOR_1SRC_2TYPE_OP(8, double, uint64_t, Func, 0, 0) - default: LOGMAN_MSG_A("Unknown Element Size: %d", Op->Header.ElementSize); break; - } - memcpy(GDP, Tmp, OpSize); - break; - } case IR::OP_VECTOR_STOF: { auto Op = IROp->C(); void *Src = GetSrc(SSAData, Op->Header.Args[0]); @@ -3381,22 +3365,6 @@ void InterpreterOps::InterpretIR(FEXCore::Core::InternalThreadState *Thread, uin memcpy(GDP, Tmp, OpSize); break; } - case IR::OP_VECTOR_FTOZU: { - auto Op = IROp->C(); - void *Src = GetSrc(SSAData, Op->Header.Args[0]); - uint8_t Tmp[16]; - - uint8_t Elements = OpSize / Op->Header.ElementSize; - - auto Func = [](auto a, auto min, auto max) { return a; }; - switch (Op->Header.ElementSize) { - DO_VECTOR_1SRC_2TYPE_OP(4, uint32_t, float, Func, 0, 0) - DO_VECTOR_1SRC_2TYPE_OP(8, uint64_t, double, Func, 0, 0) - default: LOGMAN_MSG_A("Unknown Element Size: %d", Op->Header.ElementSize); break; - } - memcpy(GDP, Tmp, OpSize); - break; - } case IR::OP_VECTOR_FTOZS: { auto Op = IROp->C(); void *Src = GetSrc(SSAData, Op->Header.Args[0]); @@ -3404,7 +3372,7 @@ void InterpreterOps::InterpretIR(FEXCore::Core::InternalThreadState *Thread, uin uint8_t Elements = OpSize / Op->Header.ElementSize; - auto Func = [](auto a, auto min, auto max) { return a; }; + auto Func = [](auto a, auto min, auto max) { return std::trunc(a); }; switch (Op->Header.ElementSize) { DO_VECTOR_1SRC_2TYPE_OP(4, int32_t, float, Func, 0, 0) DO_VECTOR_1SRC_2TYPE_OP(8, int64_t, double, Func, 0, 0) @@ -3413,22 +3381,6 @@ void InterpreterOps::InterpretIR(FEXCore::Core::InternalThreadState *Thread, uin memcpy(GDP, Tmp, OpSize); break; } - case IR::OP_VECTOR_FTOU: { - auto Op = IROp->C(); - void *Src = GetSrc(SSAData, Op->Header.Args[0]); - uint8_t Tmp[16]; - - uint8_t Elements = OpSize / Op->Header.ElementSize; - - auto Func = [](auto a, auto min, auto max) { return a; }; - switch (Op->Header.ElementSize) { - DO_VECTOR_1SRC_2TYPE_OP(4, uint32_t, float, Func, 0, 0) - DO_VECTOR_1SRC_2TYPE_OP(8, uint64_t, double, Func, 0, 0) - default: LOGMAN_MSG_A("Unknown Element Size: %d", Op->Header.ElementSize); break; - } - memcpy(GDP, Tmp, OpSize); - break; - } case IR::OP_VECTOR_FTOS: { auto Op = IROp->C(); void *Src = GetSrc(SSAData, Op->Header.Args[0]); @@ -3436,7 +3388,7 @@ void InterpreterOps::InterpretIR(FEXCore::Core::InternalThreadState *Thread, uin uint8_t Elements = OpSize / Op->Header.ElementSize; - auto Func = [](auto a, auto min, auto max) { return a; }; + auto Func = [](auto a, auto min, auto max) { return std::nearbyint(a); }; switch (Op->Header.ElementSize) { DO_VECTOR_1SRC_2TYPE_OP(4, int32_t, float, Func, 0, 0) DO_VECTOR_1SRC_2TYPE_OP(8, int64_t, double, Func, 0, 0) @@ -4381,78 +4333,57 @@ void InterpreterOps::InterpretIR(FEXCore::Core::InternalThreadState *Thread, uin } break; } - case IR::OP_FLOAT_FROMGPR_U: { - auto Op = IROp->C(); - uint16_t Conv = (Op->Header.ElementSize << 8) | Op->SrcElementSize; - switch (Conv) { - case 0x0404: { // Float <- int32_t - float Dst = (float)*GetSrc(SSAData, Op->Header.Args[0]); - memcpy(GDP, &Dst, Op->Header.ElementSize); - break; - } - case 0x0408: { // Float <- int64_t - float Dst = (float)*GetSrc(SSAData, Op->Header.Args[0]); - memcpy(GDP, &Dst, Op->Header.ElementSize); - break; - } - case 0x0804: { // Double <- int32_t - double Dst = (double)*GetSrc(SSAData, Op->Header.Args[0]); - memcpy(GDP, &Dst, Op->Header.ElementSize); - break; - } - case 0x0808: { // Double <- int64_t - double Dst = (double)*GetSrc(SSAData, Op->Header.Args[0]); - memcpy(GDP, &Dst, Op->Header.ElementSize); - break; - } - } - break; - } case IR::OP_FLOAT_TOGPR_ZS: { auto Op = IROp->C(); - if (Op->Header.ElementSize == 8) { - int64_t Dst = (int64_t)*GetSrc(SSAData, Op->Header.Args[0]); - memcpy(GDP, &Dst, Op->Header.ElementSize); - } - else { - int32_t Dst = (int32_t)*GetSrc(SSAData, Op->Header.Args[0]); - memcpy(GDP, &Dst, Op->Header.ElementSize); - } - break; - } - case IR::OP_FLOAT_TOGPR_ZU: { - auto Op = IROp->C(); - if (Op->Header.ElementSize == 8) { - uint64_t Dst = (uint64_t)*GetSrc(SSAData, Op->Header.Args[0]); - memcpy(GDP, &Dst, Op->Header.ElementSize); - } - else { - uint32_t Dst = (uint32_t)*GetSrc(SSAData, Op->Header.Args[0]); - memcpy(GDP, &Dst, Op->Header.ElementSize); + uint16_t Conv = (IROp->Size << 8) | Op->SrcElementSize; + switch (Conv) { + case 0x0804: { // int64_t <- float + int64_t Dst = (int64_t)std::trunc(*GetSrc(SSAData, Op->Header.Args[0])); + memcpy(GDP, &Dst, IROp->Size); + break; + } + case 0x0808: { // int64_t <- double + int64_t Dst = (int64_t)std::trunc(*GetSrc(SSAData, Op->Header.Args[0])); + memcpy(GDP, &Dst, IROp->Size); + break; + } + case 0x0404: { // int32_t <- float + int32_t Dst = (int32_t)std::trunc(*GetSrc(SSAData, Op->Header.Args[0])); + memcpy(GDP, &Dst, IROp->Size); + break; + } + case 0x0408: { // int32_t <- double + int32_t Dst = (int32_t)std::trunc(*GetSrc(SSAData, Op->Header.Args[0])); + memcpy(GDP, &Dst, IROp->Size); + break; + } } break; } case IR::OP_FLOAT_TOGPR_S: { auto Op = IROp->C(); - if (Op->Header.ElementSize == 8) { - int64_t Dst = (int64_t)*GetSrc(SSAData, Op->Header.Args[0]); - memcpy(GDP, &Dst, Op->Header.ElementSize); - } - else { - int32_t Dst = (int32_t)*GetSrc(SSAData, Op->Header.Args[0]); - memcpy(GDP, &Dst, Op->Header.ElementSize); - } - break; - } - case IR::OP_FLOAT_TOGPR_U: { - auto Op = IROp->C(); - if (Op->Header.ElementSize == 8) { - uint64_t Dst = (uint64_t)*GetSrc(SSAData, Op->Header.Args[0]); - memcpy(GDP, &Dst, Op->Header.ElementSize); - } - else { - uint32_t Dst = (uint32_t)*GetSrc(SSAData, Op->Header.Args[0]); - memcpy(GDP, &Dst, Op->Header.ElementSize); + uint16_t Conv = (IROp->Size << 8) | Op->SrcElementSize; + switch (Conv) { + case 0x0804: { // int64_t <- float + int64_t Dst = (int64_t)std::nearbyint(*GetSrc(SSAData, Op->Header.Args[0])); + memcpy(GDP, &Dst, IROp->Size); + break; + } + case 0x0808: { // int64_t <- double + int64_t Dst = (int64_t)std::nearbyint(*GetSrc(SSAData, Op->Header.Args[0])); + memcpy(GDP, &Dst, IROp->Size); + break; + } + case 0x0404: { // int32_t <- float + int32_t Dst = (int32_t)std::nearbyint(*GetSrc(SSAData, Op->Header.Args[0])); + memcpy(GDP, &Dst, IROp->Size); + break; + } + case 0x0408: { // int32_t <- double + int32_t Dst = (int32_t)std::nearbyint(*GetSrc(SSAData, Op->Header.Args[0])); + memcpy(GDP, &Dst, IROp->Size); + break; + } } break; } diff --git a/External/FEXCore/Source/Interface/Core/JIT/Arm64/ALUOps.cpp b/External/FEXCore/Source/Interface/Core/JIT/Arm64/ALUOps.cpp index 551013414..4ef0c2619 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/Arm64/ALUOps.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/Arm64/ALUOps.cpp @@ -969,34 +969,49 @@ DEF_OP(VExtractToGPR) { } } -DEF_OP(Float_ToGPR_ZU) { - LogMan::Msg::D("Unimplemented"); -} - DEF_OP(Float_ToGPR_ZS) { auto Op = IROp->C(); - if (Op->Header.ElementSize == 8) { - fcvtzs(GetReg(Node), GetSrc(Op->Header.Args[0].ID()).D()); + aarch64::Register Dst{}; + aarch64::VRegister Src{}; + if (Op->SrcElementSize == 8) { + Src = GetSrc(Op->Header.Args[0].ID()).D(); } else { - fcvtzs(GetReg(Node), GetSrc(Op->Header.Args[0].ID()).S()); + Src = GetSrc(Op->Header.Args[0].ID()).S(); } -} -DEF_OP(Float_ToGPR_U) { - LogMan::Msg::D("Unimplemented"); + if (IROp->Size == 8) { + Dst = GetReg(Node); + } + else { + Dst = GetReg(Node); + } + + fcvtzs(Dst, Src); } DEF_OP(Float_ToGPR_S) { auto Op = IROp->C(); - if (Op->Header.ElementSize == 8) { + + aarch64::Register Dst{}; + aarch64::VRegister Src{}; + if (Op->SrcElementSize == 8) { frinti(VTMP1.D(), GetSrc(Op->Header.Args[0].ID()).D()); - fcvtzs(GetReg(Node), VTMP1.D()); + Src = VTMP1.D(); } else { frinti(VTMP1.S(), GetSrc(Op->Header.Args[0].ID()).S()); - fcvtzs(GetReg(Node), VTMP1.S()); + Src = VTMP1.S(); } + + if (IROp->Size == 8) { + Dst = GetReg(Node); + } + else { + Dst = GetReg(Node); + } + + fcvtzs(Dst, Src); } DEF_OP(FCmp) { @@ -1087,9 +1102,7 @@ void Arm64JITCore::RegisterALUHandlers() { REGISTER_OP(SBFE, Sbfe); REGISTER_OP(SELECT, Select); REGISTER_OP(VEXTRACTTOGPR, VExtractToGPR); - REGISTER_OP(FLOAT_TOGPR_ZU, Float_ToGPR_ZU); REGISTER_OP(FLOAT_TOGPR_ZS, Float_ToGPR_ZS); - REGISTER_OP(FLOAT_TOGPR_U, Float_ToGPR_U); REGISTER_OP(FLOAT_TOGPR_S, Float_ToGPR_S); REGISTER_OP(FCMP, FCmp); diff --git a/External/FEXCore/Source/Interface/Core/JIT/Arm64/ConversionOps.cpp b/External/FEXCore/Source/Interface/Core/JIT/Arm64/ConversionOps.cpp index fa32124b3..adec5d3dd 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/Arm64/ConversionOps.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/Arm64/ConversionOps.cpp @@ -56,10 +56,6 @@ DEF_OP(VCastFromGPR) { } } -DEF_OP(Float_FromGPR_U) { - LOGMAN_MSG_A("Unimplemented"); -} - DEF_OP(Float_FromGPR_S) { auto Op = IROp->C(); uint16_t Conv = (Op->Header.ElementSize << 8) | Op->SrcElementSize; @@ -99,19 +95,6 @@ DEF_OP(Float_FToF) { } } -DEF_OP(Vector_UToF) { - auto Op = IROp->C(); - switch (Op->Header.ElementSize) { - case 4: - ucvtf(GetDst(Node).V4S(), GetSrc(Op->Header.Args[0].ID()).V4S()); - break; - case 8: - ucvtf(GetDst(Node).V2D(), GetSrc(Op->Header.Args[0].ID()).V2D()); - break; - default: LOGMAN_MSG_A("Unknown castGPR element size: %d", Op->Header.ElementSize); - } -} - DEF_OP(Vector_SToF) { auto Op = IROp->C(); switch (Op->Header.ElementSize) { @@ -125,19 +108,6 @@ DEF_OP(Vector_SToF) { } } -DEF_OP(Vector_FToZU) { - auto Op = IROp->C(); - switch (Op->Header.ElementSize) { - case 4: - fcvtzu(GetDst(Node).V4S(), GetSrc(Op->Header.Args[0].ID()).V4S()); - break; - case 8: - fcvtzu(GetDst(Node).V2D(), GetSrc(Op->Header.Args[0].ID()).V2D()); - break; - default: LOGMAN_MSG_A("Unknown castGPR element size: %d", Op->Header.ElementSize); - } -} - DEF_OP(Vector_FToZS) { auto Op = IROp->C(); switch (Op->Header.ElementSize) { @@ -151,21 +121,6 @@ DEF_OP(Vector_FToZS) { } } -DEF_OP(Vector_FToU) { - auto Op = IROp->C(); - switch (Op->Header.ElementSize) { - case 4: - frinti(GetDst(Node).V4S(), GetSrc(Op->Header.Args[0].ID()).V4S()); - fcvtzu(GetDst(Node).V4S(), GetDst(Node).V4S()); - break; - case 8: - frinti(GetDst(Node).V2D(), GetSrc(Op->Header.Args[0].ID()).V2D()); - fcvtzu(GetDst(Node).V2D(), GetDst(Node).V2D()); - break; - default: LOGMAN_MSG_A("Unknown castGPR element size: %d", Op->Header.ElementSize); - } -} - DEF_OP(Vector_FToS) { auto Op = IROp->C(); switch (Op->Header.ElementSize) { @@ -259,14 +214,10 @@ void Arm64JITCore::RegisterConversionHandlers() { #define REGISTER_OP(op, x) OpHandlers[FEXCore::IR::IROps::OP_##op] = &Arm64JITCore::Op_##x REGISTER_OP(VINSGPR, VInsGPR); REGISTER_OP(VCASTFROMGPR, VCastFromGPR); - REGISTER_OP(FLOAT_FROMGPR_U, Float_FromGPR_U); REGISTER_OP(FLOAT_FROMGPR_S, Float_FromGPR_S); REGISTER_OP(FLOAT_FTOF, Float_FToF); - REGISTER_OP(VECTOR_UTOF, Vector_UToF); REGISTER_OP(VECTOR_STOF, Vector_SToF); - REGISTER_OP(VECTOR_FTOZU, Vector_FToZU); REGISTER_OP(VECTOR_FTOZS, Vector_FToZS); - REGISTER_OP(VECTOR_FTOU, Vector_FToU); REGISTER_OP(VECTOR_FTOS, Vector_FToS); REGISTER_OP(VECTOR_FTOF, Vector_FToF); REGISTER_OP(VECTOR_FTOI, Vector_FToI); diff --git a/External/FEXCore/Source/Interface/Core/JIT/Arm64/JITClass.h b/External/FEXCore/Source/Interface/Core/JIT/Arm64/JITClass.h index 1b7425447..ae48558e0 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/Arm64/JITClass.h +++ b/External/FEXCore/Source/Interface/Core/JIT/Arm64/JITClass.h @@ -240,7 +240,6 @@ private: DEF_OP(VExtractToGPR); DEF_OP(Float_ToGPR_ZU); DEF_OP(Float_ToGPR_ZS); - DEF_OP(Float_ToGPR_U); DEF_OP(Float_ToGPR_S); DEF_OP(FCmp); @@ -277,14 +276,10 @@ private: ///< Conversion ops DEF_OP(VInsGPR); DEF_OP(VCastFromGPR); - DEF_OP(Float_FromGPR_U); DEF_OP(Float_FromGPR_S); DEF_OP(Float_FToF); - DEF_OP(Vector_UToF); DEF_OP(Vector_SToF); - DEF_OP(Vector_FToZU); DEF_OP(Vector_FToZS); - DEF_OP(Vector_FToU); DEF_OP(Vector_FToS); DEF_OP(Vector_FToF); DEF_OP(Vector_FToI); diff --git a/External/FEXCore/Source/Interface/Core/JIT/x86_64/ALUOps.cpp b/External/FEXCore/Source/Interface/Core/JIT/x86_64/ALUOps.cpp index 655a2f690..7a7206282 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/x86_64/ALUOps.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/x86_64/ALUOps.cpp @@ -1108,42 +1108,63 @@ DEF_OP(VExtractToGPR) { } } -DEF_OP(Float_ToGPR_ZU) { - LogMan::Msg::D("Unimplemented"); -} - DEF_OP(Float_ToGPR_ZS) { auto Op = IROp->C(); - if (Op->Header.ElementSize == 8) { - cvttsd2si(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); - } - else { - cvttss2si(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); - } -} -DEF_OP(Float_ToGPR_U) { - LogMan::Msg::D("Unimplemented"); + uint16_t Conv = (IROp->Size << 8) | Op->SrcElementSize; + switch (Conv) { + case 0x0804: // int64_t <- float + cvttss2si(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); + break; + case 0x0808: // int64_t <- double + cvttsd2si(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); + break; + case 0x0404: // int32_t <- float + cvttss2si(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); + break; + case 0x0408: // int32_t <- double + cvttsd2si(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); + break; + } } DEF_OP(Float_ToGPR_S) { auto Op = IROp->C(); - if (Op->Header.ElementSize == 8) { - cvtsd2si(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); - } - else { - cvtss2si(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); + uint16_t Conv = (IROp->Size << 8) | Op->SrcElementSize; + switch (Conv) { + case 0x0804: // int64_t <- float + cvtss2si(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); + break; + case 0x0808: // int64_t <- double + cvtsd2si(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); + break; + case 0x0404: // int32_t <- float + cvtss2si(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); + break; + case 0x0408: // int32_t <- double + cvtsd2si(GetDst(Node), GetSrc(Op->Header.Args[0].ID())); + break; } } DEF_OP(FCmp) { auto Op = IROp->C(); - if (Op->ElementSize == 4) { - ucomiss(GetSrc(Op->Header.Args[0].ID()), GetSrc(Op->Header.Args[1].ID())); + if (Op->Flags & (1 << IR::FCMP_FLAG_UNORDERED)) { + if (Op->ElementSize == 4) { + ucomiss(GetSrc(Op->Header.Args[0].ID()), GetSrc(Op->Header.Args[1].ID())); + } + else { + ucomisd(GetSrc(Op->Header.Args[0].ID()), GetSrc(Op->Header.Args[1].ID())); + } } else { - ucomisd(GetSrc(Op->Header.Args[0].ID()), GetSrc(Op->Header.Args[1].ID())); + if (Op->ElementSize == 4) { + comiss(GetSrc(Op->Header.Args[0].ID()), GetSrc(Op->Header.Args[1].ID())); + } + else { + comisd(GetSrc(Op->Header.Args[0].ID()), GetSrc(Op->Header.Args[1].ID())); + } } mov (rdx, 0); @@ -1217,9 +1238,7 @@ void X86JITCore::RegisterALUHandlers() { REGISTER_OP(SBFE, Sbfe); REGISTER_OP(SELECT, Select); REGISTER_OP(VEXTRACTTOGPR, VExtractToGPR); - REGISTER_OP(FLOAT_TOGPR_ZU, Float_ToGPR_ZU); REGISTER_OP(FLOAT_TOGPR_ZS, Float_ToGPR_ZS); - REGISTER_OP(FLOAT_TOGPR_U, Float_ToGPR_U); REGISTER_OP(FLOAT_TOGPR_S, Float_ToGPR_S); REGISTER_OP(FCMP, FCmp); #undef REGISTER_OP diff --git a/External/FEXCore/Source/Interface/Core/JIT/x86_64/ConversionOps.cpp b/External/FEXCore/Source/Interface/Core/JIT/x86_64/ConversionOps.cpp index 0581ebcff..8139c8861 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/x86_64/ConversionOps.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/x86_64/ConversionOps.cpp @@ -56,10 +56,6 @@ DEF_OP(VCastFromGPR) { } } -DEF_OP(Float_FromGPR_U) { - LOGMAN_MSG_A("Unimplemented"); -} - DEF_OP(Float_FromGPR_S) { auto Op = IROp->C(); uint16_t Conv = (Op->Header.ElementSize << 8) | Op->SrcElementSize; @@ -99,10 +95,6 @@ DEF_OP(Float_FToF) { } } -DEF_OP(Vector_UToF) { - LOGMAN_MSG_A("Unimplemented"); -} - DEF_OP(Vector_SToF) { auto Op = IROp->C(); switch (Op->Header.ElementSize) { @@ -125,10 +117,6 @@ DEF_OP(Vector_SToF) { } } -DEF_OP(Vector_FToZU) { - LOGMAN_MSG_A("Unimplemented"); -} - DEF_OP(Vector_FToZS) { auto Op = IROp->C(); switch (Op->Header.ElementSize) { @@ -142,10 +130,6 @@ DEF_OP(Vector_FToZS) { } } -DEF_OP(Vector_FToU) { - LOGMAN_MSG_A("Unimplemented"); -} - DEF_OP(Vector_FToS) { auto Op = IROp->C(); switch (Op->Header.ElementSize) { @@ -213,14 +197,10 @@ void X86JITCore::RegisterConversionHandlers() { #define REGISTER_OP(op, x) OpHandlers[FEXCore::IR::IROps::OP_##op] = &X86JITCore::Op_##x REGISTER_OP(VINSGPR, VInsGPR); REGISTER_OP(VCASTFROMGPR, VCastFromGPR); - REGISTER_OP(FLOAT_FROMGPR_U, Float_FromGPR_U); REGISTER_OP(FLOAT_FROMGPR_S, Float_FromGPR_S); REGISTER_OP(FLOAT_FTOF, Float_FToF); - REGISTER_OP(VECTOR_UTOF, Vector_UToF); REGISTER_OP(VECTOR_STOF, Vector_SToF); - REGISTER_OP(VECTOR_FTOZU, Vector_FToZU); REGISTER_OP(VECTOR_FTOZS, Vector_FToZS); - REGISTER_OP(VECTOR_FTOU, Vector_FToU); REGISTER_OP(VECTOR_FTOS, Vector_FToS); REGISTER_OP(VECTOR_FTOF, Vector_FToF); REGISTER_OP(VECTOR_FTOI, Vector_FToI); diff --git a/External/FEXCore/Source/Interface/Core/JIT/x86_64/JITClass.h b/External/FEXCore/Source/Interface/Core/JIT/x86_64/JITClass.h index 49e5024b1..5016b4256 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/x86_64/JITClass.h +++ b/External/FEXCore/Source/Interface/Core/JIT/x86_64/JITClass.h @@ -241,9 +241,7 @@ private: DEF_OP(Sbfe); DEF_OP(Select); DEF_OP(VExtractToGPR); - DEF_OP(Float_ToGPR_ZU); DEF_OP(Float_ToGPR_ZS); - DEF_OP(Float_ToGPR_U); DEF_OP(Float_ToGPR_S); DEF_OP(FCmp); DEF_OP(F80Cmp); @@ -281,14 +279,11 @@ private: ///< Conversion ops DEF_OP(VInsGPR); DEF_OP(VCastFromGPR); - DEF_OP(Float_FromGPR_U); DEF_OP(Float_FromGPR_S); DEF_OP(Float_FToF); DEF_OP(Vector_UToF); DEF_OP(Vector_SToF); - DEF_OP(Vector_FToZU); DEF_OP(Vector_FToZS); - DEF_OP(Vector_FToU); DEF_OP(Vector_FToS); DEF_OP(Vector_FToF); DEF_OP(Vector_FToI); diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index a7894b178..282e71085 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -6163,16 +6163,13 @@ void OpDispatchBuilder::MOVDDUPOp(OpcodeArgs) { StoreResult(FPRClass, Op, Res, -1); } -template +template void OpDispatchBuilder::CVTGPR_To_FPR(OpcodeArgs) { OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1); size_t GPRSize = GetSrcSize(Op); - if (Signed) - Src = _Float_FromGPR_S(DstElementSize, GPRSize, Src); - else - Src = _Float_FromGPR_U(DstElementSize, GPRSize, Src); + Src = _Float_FromGPR_S(DstElementSize, GPRSize, Src); OrderedNode *Dest = LoadSource_WithOpSize(FPRClass, Op, Op->Dest, 16, Op->Flags, -1); @@ -6181,7 +6178,7 @@ void OpDispatchBuilder::CVTGPR_To_FPR(OpcodeArgs) { StoreResult(FPRClass, Op, Src, -1); } -template +template void OpDispatchBuilder::CVTFPR_To_GPR(OpcodeArgs) { OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1); @@ -6189,32 +6186,18 @@ void OpDispatchBuilder::CVTFPR_To_GPR(OpcodeArgs) { // Source Element size is determined by instruction size_t GPRSize = GetDstSize(Op); + size_t ElementSize = SrcElementSize; if (HostRoundingMode) { - if (Signed) - Src = _Float_ToGPR_S(Src, SrcElementSize); - else - Src = _Float_ToGPR_U(Src, SrcElementSize); + Src = _Float_ToGPR_S(Src, ElementSize, GPRSize); } else { - if (Signed) - Src = _Float_ToGPR_ZS(Src, SrcElementSize); - else - Src = _Float_ToGPR_ZU(Src, SrcElementSize); - } - - if (GPRSize > SrcElementSize) { - if (Signed) { - Src = _Sext(SrcElementSize * 8, Src); - } - else { - Src = _Bfe(SrcElementSize * 8, 0, Src); - } + Src = _Float_ToGPR_ZS(Src, ElementSize, GPRSize); } StoreResult_WithOpSize(GPRClass, Op, Op->Dest, Src, GPRSize, -1); } -template +template void OpDispatchBuilder::Vector_CVT_Int_To_Float(OpcodeArgs) { OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1); @@ -6225,15 +6208,12 @@ void OpDispatchBuilder::Vector_CVT_Int_To_Float(OpcodeArgs) { ElementSize <<= 1; } - if (Signed) - Src = _Vector_SToF(Src, Size, ElementSize); - else - Src = _Vector_UToF(Src, Size, ElementSize); + Src = _Vector_SToF(Src, Size, ElementSize); StoreResult(FPRClass, Op, Src, -1); } -template +template void OpDispatchBuilder::Vector_CVT_Float_To_Int(OpcodeArgs) { OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1); @@ -6246,16 +6226,10 @@ void OpDispatchBuilder::Vector_CVT_Float_To_Int(OpcodeArgs) { } if (HostRoundingMode) { - if (Signed) - Src = _Vector_FToS(Src, Size, ElementSize); - else - Src = _Vector_FToU(Src, Size, ElementSize); + Src = _Vector_FToS(Src, Size, ElementSize); } else { - if (Signed) - Src = _Vector_FToZS(Src, Size, ElementSize); - else - Src = _Vector_FToZU(Src, Size, ElementSize); + Src = _Vector_FToZS(Src, Size, ElementSize); } StoreResult_WithOpSize(FPRClass, Op, Op->Dest, Src, Size, -1); @@ -6317,7 +6291,7 @@ void OpDispatchBuilder::MMX_To_XMM_Vector_CVT_Int_To_Float(OpcodeArgs) { StoreResult(FPRClass, Op, Dest, -1); } -template +template void OpDispatchBuilder::XMM_To_MMX_Vector_CVT_Float_To_Int(OpcodeArgs) { OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1); @@ -6330,16 +6304,10 @@ void OpDispatchBuilder::XMM_To_MMX_Vector_CVT_Float_To_Int(OpcodeArgs) { } if (HostRoundingMode) { - if (Signed) - Src = _Vector_FToS(Src, Size, ElementSize); - else - Src = _Vector_FToU(Src, Size, ElementSize); + Src = _Vector_FToS(Src, Size, ElementSize); } else { - if (Signed) - Src = _Vector_FToZS(Src, Size, ElementSize); - else - Src = _Vector_FToZU(Src, Size, ElementSize); + Src = _Vector_FToZS(Src, Size, ElementSize); } StoreResult_WithOpSize(FPRClass, Op, Op->Dest, Src, Size, -1); @@ -8846,8 +8814,8 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) { {0x28, 2, &OpDispatchBuilder::MOVUPSOp}, {0x2A, 1, &OpDispatchBuilder::MMX_To_XMM_Vector_CVT_Int_To_Float<4, true, false>}, {0x2B, 1, &OpDispatchBuilder::MOVAPSOp}, - {0x2C, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<4, true, false, false>}, - {0x2D, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<4, true, false, true>}, + {0x2C, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<4, false, false>}, + {0x2D, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<4, false, true>}, {0x2E, 2, &OpDispatchBuilder::UCOMISxOp<4>}, {0x50, 1, &OpDispatchBuilder::MOVMSKOp<4>}, {0x51, 1, &OpDispatchBuilder::VectorUnaryOp}, @@ -8860,7 +8828,7 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) { {0x58, 1, &OpDispatchBuilder::VectorALUOp}, {0x59, 1, &OpDispatchBuilder::VectorALUOp}, {0x5A, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Float<8, 4>}, - {0x5B, 1, &OpDispatchBuilder::Vector_CVT_Int_To_Float<4, true, false>}, + {0x5B, 1, &OpDispatchBuilder::Vector_CVT_Int_To_Float<4, false>}, {0x5C, 1, &OpDispatchBuilder::VectorALUOp}, {0x5D, 1, &OpDispatchBuilder::VectorALUOp}, {0x5E, 1, &OpDispatchBuilder::VectorALUOp}, @@ -9072,17 +9040,17 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) { {0x12, 1, &OpDispatchBuilder::MOVSLDUPOp}, {0x16, 1, &OpDispatchBuilder::MOVSHDUPOp}, {0x19, 7, &OpDispatchBuilder::NOPOp}, - {0x2A, 1, &OpDispatchBuilder::CVTGPR_To_FPR<4, true>}, + {0x2A, 1, &OpDispatchBuilder::CVTGPR_To_FPR<4>}, {0x2B, 1, &OpDispatchBuilder::MOVVectorOp}, - {0x2C, 1, &OpDispatchBuilder::CVTFPR_To_GPR<4, true, false>}, - {0x2D, 1, &OpDispatchBuilder::CVTFPR_To_GPR<4, true, true>}, + {0x2C, 1, &OpDispatchBuilder::CVTFPR_To_GPR<4, false>}, + {0x2D, 1, &OpDispatchBuilder::CVTFPR_To_GPR<4, true>}, {0x51, 1, &OpDispatchBuilder::VectorUnaryOp}, {0x52, 1, &OpDispatchBuilder::VectorUnaryOp}, {0x53, 1, &OpDispatchBuilder::VectorUnaryOp}, {0x58, 1, &OpDispatchBuilder::VectorScalarALUOp}, {0x59, 1, &OpDispatchBuilder::VectorScalarALUOp}, {0x5A, 1, &OpDispatchBuilder::Scalar_CVT_Float_To_Float<8, 4>}, - {0x5B, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<4, true, false, false>}, + {0x5B, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<4, false, false>}, {0x5C, 1, &OpDispatchBuilder::VectorScalarALUOp}, {0x5D, 1, &OpDispatchBuilder::VectorScalarALUOp}, {0x5E, 1, &OpDispatchBuilder::VectorScalarALUOp}, @@ -9096,17 +9064,17 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) { {0xBD, 1, &OpDispatchBuilder::LZCNT}, {0xC2, 1, &OpDispatchBuilder::VFCMPOp<4, true>}, {0xD6, 1, &OpDispatchBuilder::MOVQ2DQ}, - {0xE6, 1, &OpDispatchBuilder::Vector_CVT_Int_To_Float<4, true, true>}, + {0xE6, 1, &OpDispatchBuilder::Vector_CVT_Int_To_Float<4, true>}, }; const std::vector> RepNEModOpTable = { {0x10, 2, &OpDispatchBuilder::MOVSDOp}, {0x12, 1, &OpDispatchBuilder::MOVDDUPOp}, {0x19, 7, &OpDispatchBuilder::NOPOp}, - {0x2A, 1, &OpDispatchBuilder::CVTGPR_To_FPR<8, true>}, + {0x2A, 1, &OpDispatchBuilder::CVTGPR_To_FPR<8>}, {0x2B, 1, &OpDispatchBuilder::MOVVectorOp}, - {0x2C, 1, &OpDispatchBuilder::CVTFPR_To_GPR<8, true, false>}, - {0x2D, 1, &OpDispatchBuilder::CVTFPR_To_GPR<8, true, true>}, + {0x2C, 1, &OpDispatchBuilder::CVTFPR_To_GPR<8, false>}, + {0x2D, 1, &OpDispatchBuilder::CVTFPR_To_GPR<8, true>}, {0x51, 1, &OpDispatchBuilder::VectorUnaryOp}, //x52 = Invalid {0x58, 1, &OpDispatchBuilder::VectorScalarALUOp}, @@ -9122,7 +9090,7 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) { {0xD0, 1, &OpDispatchBuilder::ADDSUBPOp<4>}, {0xD6, 1, &OpDispatchBuilder::MOVQ2DQ}, {0xC2, 1, &OpDispatchBuilder::VFCMPOp<8, true>}, - {0xE6, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<8, true, true, true>}, + {0xE6, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<8, true, true>}, {0xF0, 1, &OpDispatchBuilder::MOVVectorOp}, }; @@ -9136,8 +9104,8 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) { {0x28, 2, &OpDispatchBuilder::MOVAPSOp}, {0x2A, 1, &OpDispatchBuilder::MMX_To_XMM_Vector_CVT_Int_To_Float<4, true, true>}, {0x2B, 1, &OpDispatchBuilder::MOVAPSOp}, - {0x2C, 1, &OpDispatchBuilder::XMM_To_MMX_Vector_CVT_Float_To_Int<8, true, true, false>}, - {0x2D, 1, &OpDispatchBuilder::XMM_To_MMX_Vector_CVT_Float_To_Int<8, true, true, true>}, + {0x2C, 1, &OpDispatchBuilder::XMM_To_MMX_Vector_CVT_Float_To_Int<8, true, false>}, + {0x2D, 1, &OpDispatchBuilder::XMM_To_MMX_Vector_CVT_Float_To_Int<8, true, true>}, {0x2E, 2, &OpDispatchBuilder::UCOMISxOp<8>}, {0x40, 16, &OpDispatchBuilder::CMOVOp}, @@ -9150,7 +9118,7 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) { {0x58, 1, &OpDispatchBuilder::VectorALUOp}, {0x59, 1, &OpDispatchBuilder::VectorALUOp}, {0x5A, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Float<4, 8>}, - {0x5B, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<4, true, false, true>}, + {0x5B, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<4, false, true>}, {0x5C, 1, &OpDispatchBuilder::VectorALUOp}, {0x5D, 1, &OpDispatchBuilder::VectorALUOp}, {0x5E, 1, &OpDispatchBuilder::VectorALUOp}, @@ -9208,7 +9176,7 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) { {0xE3, 1, &OpDispatchBuilder::PAVGOp<2>}, {0xE4, 1, &OpDispatchBuilder::PMULHW}, {0xE5, 1, &OpDispatchBuilder::PMULHW}, - {0xE6, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<8, true, true, false>}, + {0xE6, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<8, true, false>}, {0xE7, 1, &OpDispatchBuilder::MOVVectorOp}, {0xE8, 1, &OpDispatchBuilder::VectorALUOp}, {0xE9, 1, &OpDispatchBuilder::VectorALUOp}, diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 8b8298647..66bf86cf0 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -287,21 +287,21 @@ public: template void PAVGOp(OpcodeArgs); void MOVDDUPOp(OpcodeArgs); - template + template void CVTGPR_To_FPR(OpcodeArgs); - template + template void CVTFPR_To_GPR(OpcodeArgs); - template + template void Vector_CVT_Int_To_Float(OpcodeArgs); template void Scalar_CVT_Float_To_Float(OpcodeArgs); template void Vector_CVT_Float_To_Float(OpcodeArgs); - template + template void Vector_CVT_Float_To_Int(OpcodeArgs); template void MMX_To_XMM_Vector_CVT_Int_To_Float(OpcodeArgs); - template + template void XMM_To_MMX_Vector_CVT_Float_To_Int(OpcodeArgs); void MASKMOVOp(OpcodeArgs); void MOVBetweenGPR_FPR(OpcodeArgs); diff --git a/External/FEXCore/Source/Interface/IR/IR.json b/External/FEXCore/Source/Interface/IR/IR.json index 27077e753..22d47075f 100644 --- a/External/FEXCore/Source/Interface/IR/IR.json +++ b/External/FEXCore/Source/Interface/IR/IR.json @@ -1483,24 +1483,6 @@ ] }, - "Float_ToGPR_U": { - "Desc": ["Moves the scalar element to a GPR with conversion", - "Converts the 32bit or 64bit float to an unsigned integer", - "Rounding mode determined by host flag's rounding mode" - ], - "OpClass": "ALU", - "HasDest": true, - "DestClass": "GPR", - "DestSize": "ElementSize", - "SSAArgs": "1", - "SSANames": [ - "Scalar" - ], - "Args": [ - "uint8_t", "ElementSize" - ] - }, - "Float_ToGPR_S": { "Desc": ["Moves the scalar element to a GPR with conversion", "Converts the 32bit or 64bit float to an signed integer", @@ -1509,30 +1491,16 @@ "OpClass": "ALU", "HasDest": true, "DestClass": "GPR", - "DestSize": "ElementSize", + "DestSize": "DestElementSize", "SSAArgs": "1", "SSANames": [ "Scalar" ], - "Args": [ - "uint8_t", "ElementSize" - ] - }, - - "Float_ToGPR_ZU": { - "Desc": ["Moves the scalar element to a GPR with conversion", - "Converts the 32bit or 64bit float to an unsigned integer rounding towards zero (Truncating)" - ], - "OpClass": "ALU", - "HasDest": true, - "DestClass": "GPR", - "DestSize": "ElementSize", - "SSAArgs": "1", - "SSANames": [ - "Scalar" + "HelperArgs": [ + "uint8_t", "DestElementSize" ], "Args": [ - "uint8_t", "ElementSize" + "uint8_t", "SrcElementSize" ] }, @@ -1543,13 +1511,16 @@ "OpClass": "ALU", "HasDest": true, "DestClass": "GPR", - "DestSize": "ElementSize", + "DestSize": "DestElementSize", "SSAArgs": "1", "SSANames": [ "Scalar" ], + "HelperArgs": [ + "uint8_t", "DestElementSize" + ], "Args": [ - "uint8_t", "ElementSize" + "uint8_t", "SrcElementSize" ] }, @@ -3049,27 +3020,6 @@ ] }, - "Float_FromGPR_U": { - "OpClass": "Conv", - "Desc": ["Scalar op: Converts unsigned GPR to Scalar float", - "Zeroes the upper bits of the vector register" - ], - "HasDest": true, - "DestClass": "FPR", - "DestSize": "DstElementSize", - "NumElements": "1", - "SSAArgs": "1", - "SSANames": [ - "GPR" - ], - "HelperArgs": [ - "uint8_t", "DstElementSize" - ], - "Args": [ - "uint8_t", "SrcElementSize" - ] - }, - "Float_FromGPR_S": { "OpClass": "Conv", "Desc": ["Scalar op: Converts signed GPR to Scalar float", @@ -3146,25 +3096,6 @@ ] }, - "Vector_FToU": { - "OpClass": "Conv", - "Desc": ["Vector op: Converts float to unsigned integer", - "Rounding mode determined by host rounding mode" - ], - "HasDest": true, - "DestClass": "FPR", - "DestSize": "RegisterSize", - "NumElements": "RegisterSize / ElementSize", - "SSAArgs": "1", - "SSANames": [ - "Vector" - ], - "HelperArgs": [ - "uint8_t", "RegisterSize", - "uint8_t", "ElementSize" - ] - }, - "Vector_FToS": { "OpClass": "Conv", "Desc": ["Vector op: Converts float to signed integer, rounding towards zero", @@ -3184,23 +3115,6 @@ ] }, - "Vector_FToZU": { - "OpClass": "Conv", - "Desc": "Vector op: Converts float to unsigned integer, rounding towards zero", - "HasDest": true, - "DestClass": "FPR", - "DestSize": "RegisterSize", - "NumElements": "RegisterSize / ElementSize", - "SSAArgs": "1", - "SSANames": [ - "Vector" - ], - "HelperArgs": [ - "uint8_t", "RegisterSize", - "uint8_t", "ElementSize" - ] - }, - "Vector_FToZS": { "OpClass": "Conv", "Desc": "Vector op: Converts float to signed integer, rounding towards zero", diff --git a/External/FEXCore/include/FEXCore/IR/IREmitter.h b/External/FEXCore/include/FEXCore/IR/IREmitter.h index f5de5dc20..20919ef86 100644 --- a/External/FEXCore/include/FEXCore/IR/IREmitter.h +++ b/External/FEXCore/include/FEXCore/IR/IREmitter.h @@ -315,9 +315,6 @@ friend class FEXCore::IR::PassManager; IRPair _Vector_FToF(uint8_t RegisterSize, uint8_t DstElementSize, uint8_t SrcElementSize, OrderedNode *ssa0) { return _Vector_FToF(ssa0, SrcElementSize, RegisterSize, DstElementSize); } - IRPair _Float_FromGPR_U(uint8_t DstElementSize, uint8_t SrcElementSize, OrderedNode *ssa0) { - return _Float_FromGPR_U(ssa0, SrcElementSize, DstElementSize); - } IRPair _Float_FromGPR_S(uint8_t DstElementSize, uint8_t SrcElementSize, OrderedNode *ssa0) { return _Float_FromGPR_S(ssa0, SrcElementSize, DstElementSize); }