From 31504f85a7998db647d03241289300c8206c9081 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 24 May 2018 14:31:21 -0400 Subject: [PATCH 1/2] Interpreter_FloatingPoint: Don't update FPRF in frsqrte in certain exceptional cases If the FPSCR.VE bit is set and an invalid operand is passed in, then the FPRF shouldn't be updated. Similarly this is also the case when the FPSCR.ZE bit is set and negative or positive zero is passed in as the operand. --- .../Interpreter/Interpreter_FloatingPoint.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp index 98a5b8a2c0..f6d63087d7 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp @@ -410,19 +410,29 @@ void Interpreter::fresx(UGeckoInstruction inst) void Interpreter::frsqrtex(UGeckoInstruction inst) { - double b = rPS0(inst.FB); + const double b = rPS0(inst.FB); + const double result = Common::ApproximateReciprocalSquareRoot(b); if (b < 0.0) { SetFPException(FPSCR_VXSQRT); + + if (FPSCR.VE == 0) + PowerPC::UpdateFPRF(result); } else if (b == 0.0) { SetFPException(FPSCR_ZX); + + if (FPSCR.ZE == 0) + PowerPC::UpdateFPRF(result); + } + else + { + PowerPC::UpdateFPRF(result); } - rPS0(inst.FD) = Common::ApproximateReciprocalSquareRoot(b); - PowerPC::UpdateFPRF(rPS0(inst.FD)); + rPS0(inst.FD) = result; if (inst.Rc) Helper_UpdateCR1(); From 155bcb1649e35ec277babe5c864f2fe8f706ba2c Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 24 May 2018 14:37:05 -0400 Subject: [PATCH 2/2] Interpreter_FloatingPoint: Set FPSCR.VXSNAN if the input to frsqrte is a signaling NaN If the input is a signaling NaN, then we need to signal that via setting the FPSCR.VXSNAN bit. We also shouldn't update the FPRF flags if FPSCR.VE is set. --- .../Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp index f6d63087d7..e88d97b3cf 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp @@ -427,6 +427,13 @@ void Interpreter::frsqrtex(UGeckoInstruction inst) if (FPSCR.ZE == 0) PowerPC::UpdateFPRF(result); } + else if (Common::IsSNAN(b)) + { + SetFPException(FPSCR_VXSNAN); + + if (FPSCR.VE == 0) + PowerPC::UpdateFPRF(result); + } else { PowerPC::UpdateFPRF(result);