From 8a79f9099cebad4e4517ed7d89418ac23faef32f Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 23 May 2018 19:45:24 -0400 Subject: [PATCH 1/2] Interpreter_FloatingPoint: Set FPSCR.VXSNAN if input to fres is a signaling NaN fres is defined as having the VXSNAN bit set if an input to the instruction is a signaling NaN --- .../Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp index 98a5b8a2c0..18a33a1a5e 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp @@ -394,7 +394,7 @@ void Interpreter::fdivsx(UGeckoInstruction inst) // Single precision only. void Interpreter::fresx(UGeckoInstruction inst) { - double b = rPS0(inst.FB); + const double b = rPS0(inst.FB); rPS0(inst.FD) = rPS1(inst.FD) = Common::ApproximateReciprocal(b); if (b == 0.0) @@ -402,6 +402,11 @@ void Interpreter::fresx(UGeckoInstruction inst) SetFPException(FPSCR_ZX); } + if (Common::IsSNAN(b)) + { + SetFPException(FPSCR_VXSNAN); + } + PowerPC::UpdateFPRF(rPS0(inst.FD)); if (inst.Rc) From 34adc529a77d6efb64774ea23b69ac8835609b47 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 23 May 2018 23:31:56 -0400 Subject: [PATCH 2/2] Interpreter_FloatingPoint: Don't update the FPRF in fres in certain exceptional cases If FPSCR.ZE is set and a divide by zero exception is signaled, then the FPRF shouldn't be updated with a result. Similarly, if the input is an SNaN and FPSCR.VE is set, then the FPRF shouldn't be updated. --- .../Interpreter/Interpreter_FloatingPoint.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp index 18a33a1a5e..cab27b3dd7 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp @@ -395,19 +395,28 @@ void Interpreter::fdivsx(UGeckoInstruction inst) void Interpreter::fresx(UGeckoInstruction inst) { const double b = rPS0(inst.FB); - rPS0(inst.FD) = rPS1(inst.FD) = Common::ApproximateReciprocal(b); + const double result = Common::ApproximateReciprocal(b); + + rPS0(inst.FD) = rPS1(inst.FD) = result; if (b == 0.0) { SetFPException(FPSCR_ZX); - } - if (Common::IsSNAN(b)) + if (FPSCR.ZE == 0) + PowerPC::UpdateFPRF(result); + } + else if (Common::IsSNAN(b)) { SetFPException(FPSCR_VXSNAN); - } - PowerPC::UpdateFPRF(rPS0(inst.FD)); + if (FPSCR.VE == 0) + PowerPC::UpdateFPRF(result); + } + else + { + PowerPC::UpdateFPRF(result); + } if (inst.Rc) Helper_UpdateCR1();