From b71a9e658f669de41ca9799fe15a463452b08199 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 2 Jun 2018 15:26:26 -0400 Subject: [PATCH 1/2] Interpreter_FloatingPoint: Don't store to destination in frsqrte if VE or ZE is set and a relevant exception occurs As explained within commit a08ad82ace064f961b13369c96a0f3b48ca7ca5c, if an invalid exception occurs and VE is set, then the destination register should remain unchanged. Ditto for when ZE is set and a zero divide exception occurs. --- .../Interpreter/Interpreter_FloatingPoint.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp index 91504ede1a..a8e6c7451f 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp @@ -422,36 +422,39 @@ void Interpreter::fresx(UGeckoInstruction inst) void Interpreter::frsqrtex(UGeckoInstruction inst) { const double b = rPS0(inst.FB); - const double result = Common::ApproximateReciprocalSquareRoot(b); + + const auto compute_result = [inst](double value) { + const double result = Common::ApproximateReciprocalSquareRoot(value); + rPS0(inst.FD) = result; + PowerPC::UpdateFPRF(result); + }; if (b < 0.0) { SetFPException(FPSCR_VXSQRT); if (FPSCR.VE == 0) - PowerPC::UpdateFPRF(result); + compute_result(b); } else if (b == 0.0) { SetFPException(FPSCR_ZX); if (FPSCR.ZE == 0) - PowerPC::UpdateFPRF(result); + compute_result(b); } else if (Common::IsSNAN(b)) { SetFPException(FPSCR_VXSNAN); if (FPSCR.VE == 0) - PowerPC::UpdateFPRF(result); + compute_result(b); } else { - PowerPC::UpdateFPRF(result); + compute_result(b); } - rPS0(inst.FD) = result; - if (inst.Rc) Helper_UpdateCR1(); } From 21add26b71c8af145dfe472dbd215df475c6cb57 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 2 Jun 2018 15:30:51 -0400 Subject: [PATCH 2/2] Interpreter_FloatingPoint: Clear FPSCR.FI and FPSCR.FR in invalid operation cases As explained within 179d73ac0d2873ebf2dedd7a4069ea5ded4a66f1, the table within the Programming Environments Manual for PowerPC lists the FI and FR bits as cleared for invalid operation cases. So, we amend the relevant cases here in order to be accurate to hardware. --- .../Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp index a8e6c7451f..3782c748a5 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp @@ -432,6 +432,8 @@ void Interpreter::frsqrtex(UGeckoInstruction inst) if (b < 0.0) { SetFPException(FPSCR_VXSQRT); + FPSCR.FI = 0; + FPSCR.FR = 0; if (FPSCR.VE == 0) compute_result(b); @@ -446,6 +448,8 @@ void Interpreter::frsqrtex(UGeckoInstruction inst) else if (Common::IsSNAN(b)) { SetFPException(FPSCR_VXSNAN); + FPSCR.FI = 0; + FPSCR.FR = 0; if (FPSCR.VE == 0) compute_result(b);