From ee4de8a9b66dd2c94c538a884fb6590673ae29bc Mon Sep 17 00:00:00 2001 From: LinesPrower Date: Thu, 30 Apr 2009 17:07:25 +0000 Subject: [PATCH] Try to fix problems caused by incorrect denormalized floats handling. Fixes issue 398 (Sonic Unleashed hanging) git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3110 8ced0084-cf51-0410-be5f-012b33b47a6e --- .../Interpreter/Interpreter_FloatingPoint.cpp | 36 ++++++++++++++++++- .../Src/PowerPC/Jit64IL/Jit_FloatingPoint.cpp | 3 ++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp index e3f80cd9b6..8d5388b470 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp @@ -135,15 +135,34 @@ void Helper_UpdateCR1(double _fValue) PanicAlert("CR1"); } -bool IsNAN(double _dValue) +inline bool IsNAN(double _dValue) { return _dValue != _dValue; } +inline bool _IsNAN(float x) { + //return ((*(u32*)&x) & 0x7f800000UL) == 0x7f800000UL && ((*(u32*)&x) & 0x007fffffUL); + return x != x; +} + void fcmpo(UGeckoInstruction _inst) { + /* + float fa = static_cast(rPS0(_inst.FA)); + float fb = static_cast(rPS0(_inst.FB)); + // normalize + if (((*(u32*)&fa) & 0x7f800000UL) == 0) (*(u32*)&fa) &= 0x80000000UL; + if (((*(u32*)&fb) & 0x7f800000UL) == 0) (*(u32*)&fb) &= 0x80000000UL; + */ + + // normalize if conversion to float gives denormalized number + if ((riPS0(_inst.FA) & 0x7ff0000000000000ULL) < 0x3800000000000000ULL) + riPS0(_inst.FA) &= 0x8000000000000000ULL; + if ((riPS0(_inst.FB) & 0x7ff0000000000000ULL) < 0x3800000000000000ULL) + riPS0(_inst.FB) &= 0x8000000000000000ULL; double fa = rPS0(_inst.FA); double fb = rPS0(_inst.FB); + u32 compareResult; if (IsNAN(fa) || IsNAN(fb)) compareResult = 1; else if (fa < fb) compareResult = 8; @@ -164,6 +183,21 @@ void fcmpo(UGeckoInstruction _inst) void fcmpu(UGeckoInstruction _inst) { + + + /* + float fa = static_cast(rPS0(_inst.FA)); + float fb = static_cast(rPS0(_inst.FB)); + // normalize + if (((*(u32*)&fa) & 0x7f800000UL) == 0) (*(u32*)&fa) &= 0x80000000UL; + if (((*(u32*)&fb) & 0x7f800000UL) == 0) (*(u32*)&fb) &= 0x80000000UL; + */ + + // normalize if conversion to float gives denormalized number + if ((riPS0(_inst.FA) & 0x7ff0000000000000ULL) < 0x3800000000000000ULL) + riPS0(_inst.FA) &= 0x8000000000000000ULL; + if ((riPS0(_inst.FB) & 0x7ff0000000000000ULL) < 0x3800000000000000ULL) + riPS0(_inst.FB) &= 0x8000000000000000ULL; double fa = rPS0(_inst.FA); double fb = rPS0(_inst.FB); diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_FloatingPoint.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_FloatingPoint.cpp index b3f1f4829e..30d3a749fb 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_FloatingPoint.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_FloatingPoint.cpp @@ -102,6 +102,9 @@ void Jit64::fcmpx(UGeckoInstruction inst) { + // @TODO: conform this to the new fcmpo + Default(inst); return; + INSTRUCTION_START JITDISABLE(FloatingPoint) IREmitter::InstLoc lhs, rhs, res;