From fc052efb91f234f7fefeb2b8c92cd65fe0dc7bd6 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 30 Apr 2025 17:37:10 -0700 Subject: [PATCH] FEXCore: Fixes x87 reduced precision With the change from #4538 I had accidentally broken x87 reduced precision. This is due to the fact that we accidentally lost ABI information about interpreter fallbacks supporting `preserve_all` or not. So now instead of having some ABI callbacks supporting it and some not, just force usage of `preserve_all` if it is supported by the compiler entirely. Fixes Steam when x87 reduced precision is enabled. --- .../Core/Interpreter/Fallbacks/F80Fallbacks.h | 18 ++-- .../Fallbacks/InterpreterFallbacks.cpp | 90 +++++++++---------- .../Core/Interpreter/InterpreterOps.h | 3 +- FEXCore/Source/Interface/Core/JIT/JIT.cpp | 10 +-- 4 files changed, 60 insertions(+), 61 deletions(-) diff --git a/FEXCore/Source/Interface/Core/Interpreter/Fallbacks/F80Fallbacks.h b/FEXCore/Source/Interface/Core/Interpreter/Fallbacks/F80Fallbacks.h index 79fd38f8b..d30b1d448 100644 --- a/FEXCore/Source/Interface/Core/Interpreter/Fallbacks/F80Fallbacks.h +++ b/FEXCore/Source/Interface/Core/Interpreter/Fallbacks/F80Fallbacks.h @@ -301,7 +301,7 @@ struct OpHandlers { template<> struct OpHandlers { - static double handle(uint16_t FCW, double src, FEXCore::Core::CpuStateFrame* Frame) { + FEXCORE_PRESERVE_ALL_ATTR static double handle(uint16_t FCW, double src, FEXCore::Core::CpuStateFrame* Frame) { FEXCORE_PROFILE_INSTANT_INCREMENT(Frame->Thread, AccumulatedFloatFallbackCount, 1); return sin(src); } @@ -309,7 +309,7 @@ struct OpHandlers { template<> struct OpHandlers { - static double handle(uint16_t FCW, double src, FEXCore::Core::CpuStateFrame* Frame) { + FEXCORE_PRESERVE_ALL_ATTR static double handle(uint16_t FCW, double src, FEXCore::Core::CpuStateFrame* Frame) { FEXCORE_PROFILE_INSTANT_INCREMENT(Frame->Thread, AccumulatedFloatFallbackCount, 1); return cos(src); } @@ -317,7 +317,7 @@ struct OpHandlers { template<> struct OpHandlers { - static double handle(uint16_t FCW, double src, FEXCore::Core::CpuStateFrame* Frame) { + FEXCORE_PRESERVE_ALL_ATTR static double handle(uint16_t FCW, double src, FEXCore::Core::CpuStateFrame* Frame) { FEXCORE_PROFILE_INSTANT_INCREMENT(Frame->Thread, AccumulatedFloatFallbackCount, 1); return tan(src); } @@ -325,7 +325,7 @@ struct OpHandlers { template<> struct OpHandlers { - static double handle(uint16_t FCW, double src, FEXCore::Core::CpuStateFrame* Frame) { + FEXCORE_PRESERVE_ALL_ATTR static double handle(uint16_t FCW, double src, FEXCore::Core::CpuStateFrame* Frame) { FEXCORE_PROFILE_INSTANT_INCREMENT(Frame->Thread, AccumulatedFloatFallbackCount, 1); return exp2(src) - 1.0; } @@ -333,7 +333,7 @@ struct OpHandlers { template<> struct OpHandlers { - static double handle(uint16_t FCW, double src1, double src2, FEXCore::Core::CpuStateFrame* Frame) { + FEXCORE_PRESERVE_ALL_ATTR static double handle(uint16_t FCW, double src1, double src2, FEXCore::Core::CpuStateFrame* Frame) { FEXCORE_PROFILE_INSTANT_INCREMENT(Frame->Thread, AccumulatedFloatFallbackCount, 1); return atan2(src1, src2); } @@ -341,7 +341,7 @@ struct OpHandlers { template<> struct OpHandlers { - static double handle(uint16_t FCW, double src1, double src2, FEXCore::Core::CpuStateFrame* Frame) { + FEXCORE_PRESERVE_ALL_ATTR static double handle(uint16_t FCW, double src1, double src2, FEXCore::Core::CpuStateFrame* Frame) { FEXCORE_PROFILE_INSTANT_INCREMENT(Frame->Thread, AccumulatedFloatFallbackCount, 1); return fmod(src1, src2); } @@ -349,7 +349,7 @@ struct OpHandlers { template<> struct OpHandlers { - static double handle(uint16_t FCW, double src1, double src2, FEXCore::Core::CpuStateFrame* Frame) { + FEXCORE_PRESERVE_ALL_ATTR static double handle(uint16_t FCW, double src1, double src2, FEXCore::Core::CpuStateFrame* Frame) { FEXCORE_PROFILE_INSTANT_INCREMENT(Frame->Thread, AccumulatedFloatFallbackCount, 1); return remainder(src1, src2); } @@ -357,7 +357,7 @@ struct OpHandlers { template<> struct OpHandlers { - static double handle(uint16_t FCW, double src1, double src2, FEXCore::Core::CpuStateFrame* Frame) { + FEXCORE_PRESERVE_ALL_ATTR static double handle(uint16_t FCW, double src1, double src2, FEXCore::Core::CpuStateFrame* Frame) { FEXCORE_PROFILE_INSTANT_INCREMENT(Frame->Thread, AccumulatedFloatFallbackCount, 1); return src2 * log2(src1); } @@ -365,7 +365,7 @@ struct OpHandlers { template<> struct OpHandlers { - static double handle(uint16_t FCW, double src1, double src2, FEXCore::Core::CpuStateFrame* Frame) { + FEXCORE_PRESERVE_ALL_ATTR static double handle(uint16_t FCW, double src1, double src2, FEXCore::Core::CpuStateFrame* Frame) { FEXCORE_PROFILE_INSTANT_INCREMENT(Frame->Thread, AccumulatedFloatFallbackCount, 1); if (src1 == 0.0) { // src1 might be +/- zero return src1; // this will return negative or positive zero if when appropriate diff --git a/FEXCore/Source/Interface/Core/Interpreter/Fallbacks/InterpreterFallbacks.cpp b/FEXCore/Source/Interface/Core/Interpreter/Fallbacks/InterpreterFallbacks.cpp index eee36c26d..3f50867ce 100644 --- a/FEXCore/Source/Interface/Core/Interpreter/Fallbacks/InterpreterFallbacks.cpp +++ b/FEXCore/Source/Interface/Core/Interpreter/Fallbacks/InterpreterFallbacks.cpp @@ -12,18 +12,7 @@ namespace FEXCore::CPU { template static FallbackInfo GetFallbackInfo(R (*fn)(Args...), FEXCore::Core::FallbackHandlerIndex HandlerIndex) { - return {FABI_UNKNOWN, HandlerIndex, false}; -} - -template<> -FallbackInfo GetFallbackInfo(double (*fn)(uint16_t, double, FEXCore::Core::CpuStateFrame*), FEXCore::Core::FallbackHandlerIndex HandlerIndex) { - return {FABI_F64_I16_F64_PTR, HandlerIndex, false}; -} - -template<> -FallbackInfo -GetFallbackInfo(double (*fn)(uint16_t, double, double, FEXCore::Core::CpuStateFrame*), FEXCore::Core::FallbackHandlerIndex HandlerIndex) { - return {FABI_F64_I16_F64_F64_PTR, HandlerIndex, false}; + return {FABI_UNKNOWN, HandlerIndex}; } void InterpreterOps::FillFallbackIndexPointers(Core::FallbackABIInfo* Info, uint64_t* ABIHandlers) { @@ -116,7 +105,7 @@ void InterpreterOps::FillFallbackIndexPointers(Core::FallbackABIInfo* Info, uint reinterpret_cast(&FEXCore::CPU::OpHandlers::handle)}; } -bool InterpreterOps::GetFallbackHandler(bool SupportsPreserveAllABI, const IR::IROp_Header* IROp, FallbackInfo* Info) { +bool InterpreterOps::GetFallbackHandler(const IR::IROp_Header* IROp, FallbackInfo* Info) { const auto OpSize = IROp->Size; switch (IROp->Op) { case IR::OP_F80CVTTO: { @@ -124,11 +113,11 @@ bool InterpreterOps::GetFallbackHandler(bool SupportsPreserveAllABI, const IR::I switch (Op->SrcSize) { case IR::OpSize::i32Bit: { - *Info = {FABI_F80_I16_F32_PTR, Core::OPINDEX_F80CVTTO_4, SupportsPreserveAllABI}; + *Info = {FABI_F80_I16_F32_PTR, Core::OPINDEX_F80CVTTO_4}; return true; } case IR::OpSize::i64Bit: { - *Info = {FABI_F80_I16_F64_PTR, Core::OPINDEX_F80CVTTO_8, SupportsPreserveAllABI}; + *Info = {FABI_F80_I16_F64_PTR, Core::OPINDEX_F80CVTTO_8}; return true; } default: LogMan::Msg::DFmt("Unhandled size: {}", OpSize); @@ -138,11 +127,11 @@ bool InterpreterOps::GetFallbackHandler(bool SupportsPreserveAllABI, const IR::I case IR::OP_F80CVT: { switch (OpSize) { case IR::OpSize::i32Bit: { - *Info = {FABI_F32_I16_F80_PTR, Core::OPINDEX_F80CVT_4, SupportsPreserveAllABI}; + *Info = {FABI_F32_I16_F80_PTR, Core::OPINDEX_F80CVT_4}; return true; } case IR::OpSize::i64Bit: { - *Info = {FABI_F64_I16_F80_PTR, Core::OPINDEX_F80CVT_8, SupportsPreserveAllABI}; + *Info = {FABI_F64_I16_F80_PTR, Core::OPINDEX_F80CVT_8}; return true; } default: LogMan::Msg::DFmt("Unhandled size: {}", OpSize); @@ -155,25 +144,25 @@ bool InterpreterOps::GetFallbackHandler(bool SupportsPreserveAllABI, const IR::I switch (OpSize) { case IR::OpSize::i16Bit: { if (Op->Truncate) { - *Info = {FABI_I16_I16_F80_PTR, Core::OPINDEX_F80CVTINT_TRUNC2, SupportsPreserveAllABI}; + *Info = {FABI_I16_I16_F80_PTR, Core::OPINDEX_F80CVTINT_TRUNC2}; } else { - *Info = {FABI_I16_I16_F80_PTR, Core::OPINDEX_F80CVTINT_2, SupportsPreserveAllABI}; + *Info = {FABI_I16_I16_F80_PTR, Core::OPINDEX_F80CVTINT_2}; } return true; } case IR::OpSize::i32Bit: { if (Op->Truncate) { - *Info = {FABI_I32_I16_F80_PTR, Core::OPINDEX_F80CVTINT_TRUNC4, SupportsPreserveAllABI}; + *Info = {FABI_I32_I16_F80_PTR, Core::OPINDEX_F80CVTINT_TRUNC4}; } else { - *Info = {FABI_I32_I16_F80_PTR, Core::OPINDEX_F80CVTINT_4, SupportsPreserveAllABI}; + *Info = {FABI_I32_I16_F80_PTR, Core::OPINDEX_F80CVTINT_4}; } return true; } case IR::OpSize::i64Bit: { if (Op->Truncate) { - *Info = {FABI_I64_I16_F80_PTR, Core::OPINDEX_F80CVTINT_TRUNC8, SupportsPreserveAllABI}; + *Info = {FABI_I64_I16_F80_PTR, Core::OPINDEX_F80CVTINT_TRUNC8}; } else { - *Info = {FABI_I64_I16_F80_PTR, Core::OPINDEX_F80CVTINT_8, SupportsPreserveAllABI}; + *Info = {FABI_I64_I16_F80_PTR, Core::OPINDEX_F80CVTINT_8}; } return true; } @@ -182,7 +171,7 @@ bool InterpreterOps::GetFallbackHandler(bool SupportsPreserveAllABI, const IR::I break; } case IR::OP_F80CMP: { - *Info = {FABI_I64_I16_F80_F80_PTR, (Core::FallbackHandlerIndex)(Core::OPINDEX_F80CMP), SupportsPreserveAllABI}; + *Info = {FABI_I64_I16_F80_F80_PTR, (Core::FallbackHandlerIndex)(Core::OPINDEX_F80CMP)}; return true; } @@ -191,11 +180,11 @@ bool InterpreterOps::GetFallbackHandler(bool SupportsPreserveAllABI, const IR::I switch (Op->SrcSize) { case IR::OpSize::i16Bit: { - *Info = {FABI_F80_I16_I16_PTR, Core::OPINDEX_F80CVTTOINT_2, SupportsPreserveAllABI}; + *Info = {FABI_F80_I16_I16_PTR, Core::OPINDEX_F80CVTTOINT_2}; return true; } case IR::OpSize::i32Bit: { - *Info = {FABI_F80_I16_I32_PTR, Core::OPINDEX_F80CVTTOINT_4, SupportsPreserveAllABI}; + *Info = {FABI_F80_I16_I32_PTR, Core::OPINDEX_F80CVTTOINT_4}; return true; } default: LogMan::Msg::DFmt("Unhandled size: {}", OpSize); @@ -203,16 +192,16 @@ bool InterpreterOps::GetFallbackHandler(bool SupportsPreserveAllABI, const IR::I break; } -#define COMMON_UNARY_X87_OP(OP) \ - case IR::OP_F80##OP: { \ - *Info = {FABI_F80_I16_F80_PTR, Core::OPINDEX_F80##OP, SupportsPreserveAllABI}; \ - return true; \ +#define COMMON_UNARY_X87_OP(OP) \ + case IR::OP_F80##OP: { \ + *Info = {FABI_F80_I16_F80_PTR, Core::OPINDEX_F80##OP}; \ + return true; \ } -#define COMMON_BINARY_X87_OP(OP) \ - case IR::OP_F80##OP: { \ - *Info = {FABI_F80_I16_F80_F80_PTR, Core::OPINDEX_F80##OP, SupportsPreserveAllABI}; \ - return true; \ +#define COMMON_BINARY_X87_OP(OP) \ + case IR::OP_F80##OP: { \ + *Info = {FABI_F80_I16_F80_F80_PTR, Core::OPINDEX_F80##OP}; \ + return true; \ } #define COMMON_F64_OP(OP) \ @@ -221,6 +210,17 @@ bool InterpreterOps::GetFallbackHandler(bool SupportsPreserveAllABI, const IR::I return true; \ } +#define COMMON_UNARY_F64_OP(OP) \ + case IR::OP_F64##OP: { \ + *Info = {FABI_F64_I16_F64_PTR, Core::OPINDEX_F64##OP}; \ + return true; \ + } +#define COMMON_BINARY_F64_OP(OP) \ + case IR::OP_F64##OP: { \ + *Info = {FABI_F64_I16_F64_F64_PTR, Core::OPINDEX_F64##OP}; \ + return true; \ + } + // Unary COMMON_UNARY_X87_OP(ROUND) COMMON_UNARY_X87_OP(F2XM1) @@ -245,21 +245,21 @@ bool InterpreterOps::GetFallbackHandler(bool SupportsPreserveAllABI, const IR::I COMMON_BINARY_X87_OP(SCALE) // Double Precision Unary - COMMON_F64_OP(F2XM1) - COMMON_F64_OP(TAN) - COMMON_F64_OP(SIN) - COMMON_F64_OP(COS) + COMMON_UNARY_F64_OP(F2XM1) + COMMON_UNARY_F64_OP(TAN) + COMMON_UNARY_F64_OP(SIN) + COMMON_UNARY_F64_OP(COS) // Double Precision Binary - COMMON_F64_OP(FYL2X) - COMMON_F64_OP(ATAN) - COMMON_F64_OP(FPREM1) - COMMON_F64_OP(FPREM) - COMMON_F64_OP(SCALE) + COMMON_BINARY_F64_OP(FYL2X) + COMMON_BINARY_F64_OP(ATAN) + COMMON_BINARY_F64_OP(FPREM1) + COMMON_BINARY_F64_OP(FPREM) + COMMON_BINARY_F64_OP(SCALE) // SSE4.2 Fallbacks - case IR::OP_VPCMPESTRX: *Info = {FABI_I32_I64_I64_V128_V128_I16, Core::OPINDEX_VPCMPESTRX, SupportsPreserveAllABI}; return true; - case IR::OP_VPCMPISTRX: *Info = {FABI_I32_V128_V128_I16, Core::OPINDEX_VPCMPISTRX, SupportsPreserveAllABI}; return true; + case IR::OP_VPCMPESTRX: *Info = {FABI_I32_I64_I64_V128_V128_I16, Core::OPINDEX_VPCMPESTRX}; return true; + case IR::OP_VPCMPISTRX: *Info = {FABI_I32_V128_V128_I16, Core::OPINDEX_VPCMPISTRX}; return true; default: break; } diff --git a/FEXCore/Source/Interface/Core/Interpreter/InterpreterOps.h b/FEXCore/Source/Interface/Core/Interpreter/InterpreterOps.h index c063d2ca9..7df77c8e0 100644 --- a/FEXCore/Source/Interface/Core/Interpreter/InterpreterOps.h +++ b/FEXCore/Source/Interface/Core/Interpreter/InterpreterOps.h @@ -34,12 +34,11 @@ enum FallbackABI { struct FallbackInfo { FallbackABI ABI; FEXCore::Core::FallbackHandlerIndex HandlerIndex; - bool SupportsPreserveAllABI; }; class InterpreterOps { public: static void FillFallbackIndexPointers(Core::FallbackABIInfo* Info, uint64_t* ABIHandlers); - static bool GetFallbackHandler(bool SupportsPreserveAllABI, const IR::IROp_Header* IROp, FallbackInfo* Info); + static bool GetFallbackHandler(const IR::IROp_Header* IROp, FallbackInfo* Info); }; } // namespace FEXCore::CPU diff --git a/FEXCore/Source/Interface/Core/JIT/JIT.cpp b/FEXCore/Source/Interface/Core/JIT/JIT.cpp index e514e06ca..0d0780822 100644 --- a/FEXCore/Source/Interface/Core/JIT/JIT.cpp +++ b/FEXCore/Source/Interface/Core/JIT/JIT.cpp @@ -82,7 +82,7 @@ namespace FEXCore::CPU { void Arm64JITCore::Op_Unhandled(const IR::IROp_Header* IROp, IR::NodeID Node) { FallbackInfo Info; - if (!InterpreterOps::GetFallbackHandler(CTX->HostFeatures.SupportsPreserveAllABI, IROp, &Info)) { + if (!InterpreterOps::GetFallbackHandler(IROp, &Info)) { #if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED LOGMAN_MSG_A_FMT("Unhandled IR Op: {}", FEXCore::IR::GetName(IROp->Op)); #endif @@ -144,7 +144,7 @@ void Arm64JITCore::Op_Unhandled(const IR::IROp_Header* IROp, IR::NodeID Node) { str(ARMEmitter::XReg::lr, ARMEmitter::Reg::rsp, -16); const auto Src1 = GetVReg(IROp->Args[0].ID()); - mov(VTMP1.D(), Src1.D()); + fmov(VTMP1.D(), Src1.D()); ldr(TMP1, STATE_PTR(CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex].ABIHandler)); ldr(TMP4, STATE_PTR(CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex].Func)); @@ -223,7 +223,7 @@ void Arm64JITCore::Op_Unhandled(const IR::IROp_Header* IROp, IR::NodeID Node) { str(ARMEmitter::XReg::lr, ARMEmitter::Reg::rsp, -16); const auto Src1 = GetVReg(IROp->Args[0].ID()); - mov(VTMP1.D(), Src1.D()); + fmov(VTMP1.D(), Src1.D()); ldr(TMP1, STATE_PTR(CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex].ABIHandler)); ldr(TMP4, STATE_PTR(CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex].Func)); @@ -244,8 +244,8 @@ void Arm64JITCore::Op_Unhandled(const IR::IROp_Header* IROp, IR::NodeID Node) { const auto Src1 = GetVReg(IROp->Args[0].ID()); const auto Src2 = GetVReg(IROp->Args[1].ID()); - mov(VTMP1.D(), Src1.D()); - mov(VTMP2.D(), Src2.D()); + fmov(VTMP1.D(), Src1.D()); + fmov(VTMP2.D(), Src2.D()); ldr(TMP1, STATE_PTR(CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex].ABIHandler)); ldr(TMP4, STATE_PTR(CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex].Func));