From 965b963a6f62bec45c0810c01ab5a8a1aa231463 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 12 Apr 2018 01:40:55 -0400 Subject: [PATCH] Interpreter_FloatingPoint: Handle SNaNs properly in frsp If FPSCR[VE] is set, a result isn't supposed to be written to the destination, just the FPSCR[VXSNAN] bit gets set, and FPSCR[FR] and FPSCR[FI] get set to zero. If FPSCR[VE] isn't set, then we do write out a result, however, the FPSCR[FPRF] field is updated to signify a QNaN (yes, a QNaN, the FPRF field doesn't have a bit configuration for SNaNs). --- .../Interpreter/Interpreter_FloatingPoint.cpp | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp index 4529d2ebe8..69f3a93de8 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp @@ -272,12 +272,31 @@ void Interpreter::fselx(UGeckoInstruction inst) // PS1 is said to be undefined void Interpreter::frspx(UGeckoInstruction inst) // round to single { - double b = rPS0(inst.FB); - double rounded = ForceSingle(b); - SetFI(b != rounded); - FPSCR.FR = fabs(rounded) > fabs(b); - PowerPC::UpdateFPRF(rounded); - rPS0(inst.FD) = rPS1(inst.FD) = rounded; + const double b = rPS0(inst.FB); + const double rounded = ForceSingle(b); + + if (MathUtil::IsSNAN(b)) + { + SetFPException(FPSCR_VXSNAN); + + if (FPSCR.VE == 0) + { + rPS0(inst.FD) = rounded; + rPS1(inst.FD) = rounded; + PowerPC::UpdateFPRF(b); + } + + SetFI(0); + FPSCR.FR = 0; + } + else + { + SetFI(b != rounded); + FPSCR.FR = fabs(rounded) > fabs(b); + PowerPC::UpdateFPRF(rounded); + rPS0(inst.FD) = rounded; + rPS1(inst.FD) = rounded; + } if (inst.Rc) Helper_UpdateCR1();