diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h index ed15cef6da..1311f3958a 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h @@ -103,10 +103,9 @@ inline double NI_mul(double a, double b) if (std::isnan(t)) { if (Common::IsSNAN(a) || Common::IsSNAN(b)) - { SetFPException(FPSCR_VXSNAN); - FPSCR.ClearFIFR(); - } + + FPSCR.ClearFIFR(); if (std::isnan(a)) return MakeQuiet(a); @@ -114,7 +113,6 @@ inline double NI_mul(double a, double b) return MakeQuiet(b); SetFPException(FPSCR_VXIMZ); - FPSCR.ClearFIFR(); return PPC_NAN; } return t; @@ -127,10 +125,9 @@ inline double NI_div(double a, double b) if (std::isnan(t)) { if (Common::IsSNAN(a) || Common::IsSNAN(b)) - { SetFPException(FPSCR_VXSNAN); - FPSCR.ClearFIFR(); - } + + FPSCR.ClearFIFR(); if (std::isnan(a)) return MakeQuiet(a); @@ -142,18 +139,15 @@ inline double NI_div(double a, double b) if (a == 0.0) { SetFPException(FPSCR_VXZDZ); - FPSCR.ClearFIFR(); } else { SetFPException(FPSCR_ZX); - FPSCR.ClearFIFR(); } } else if (std::isinf(a) && std::isinf(b)) { SetFPException(FPSCR_VXIDI); - FPSCR.ClearFIFR(); } return PPC_NAN; @@ -169,10 +163,9 @@ inline double NI_add(double a, double b) if (std::isnan(t)) { if (Common::IsSNAN(a) || Common::IsSNAN(b)) - { SetFPException(FPSCR_VXSNAN); - FPSCR.ClearFIFR(); - } + + FPSCR.ClearFIFR(); if (std::isnan(a)) return MakeQuiet(a); @@ -180,10 +173,12 @@ inline double NI_add(double a, double b) return MakeQuiet(b); SetFPException(FPSCR_VXISI); - FPSCR.ClearFIFR(); return PPC_NAN; } + if (std::isinf(a) || std::isinf(b)) + FPSCR.ClearFIFR(); + return t; } @@ -194,10 +189,9 @@ inline double NI_sub(double a, double b) if (std::isnan(t)) { if (Common::IsSNAN(a) || Common::IsSNAN(b)) - { SetFPException(FPSCR_VXSNAN); - FPSCR.ClearFIFR(); - } + + FPSCR.ClearFIFR(); if (std::isnan(a)) return MakeQuiet(a); @@ -205,10 +199,12 @@ inline double NI_sub(double a, double b) return MakeQuiet(b); SetFPException(FPSCR_VXISI); - FPSCR.ClearFIFR(); return PPC_NAN; } + if (std::isinf(a) || std::isinf(b)) + FPSCR.ClearFIFR(); + return t; } @@ -222,10 +218,9 @@ inline double NI_madd(double a, double c, double b) if (std::isnan(t)) { if (Common::IsSNAN(a) || Common::IsSNAN(b) || Common::IsSNAN(c)) - { SetFPException(FPSCR_VXSNAN); - FPSCR.ClearFIFR(); - } + + FPSCR.ClearFIFR(); if (std::isnan(a)) return MakeQuiet(a); @@ -235,7 +230,6 @@ inline double NI_madd(double a, double c, double b) return MakeQuiet(c); SetFPException(FPSCR_VXIMZ); - FPSCR.ClearFIFR(); return PPC_NAN; } @@ -244,19 +238,20 @@ inline double NI_madd(double a, double c, double b) if (std::isnan(t)) { if (Common::IsSNAN(b)) - { SetFPException(FPSCR_VXSNAN); - FPSCR.ClearFIFR(); - } + + FPSCR.ClearFIFR(); if (std::isnan(b)) return MakeQuiet(b); SetFPException(FPSCR_VXISI); - FPSCR.ClearFIFR(); return PPC_NAN; } + if (std::isinf(a) || std::isinf(b) || std::isinf(c)) + FPSCR.ClearFIFR(); + return t; } @@ -267,10 +262,9 @@ inline double NI_msub(double a, double c, double b) if (std::isnan(t)) { if (Common::IsSNAN(a) || Common::IsSNAN(b) || Common::IsSNAN(c)) - { SetFPException(FPSCR_VXSNAN); - FPSCR.ClearFIFR(); - } + + FPSCR.ClearFIFR(); if (std::isnan(a)) return MakeQuiet(a); @@ -280,7 +274,6 @@ inline double NI_msub(double a, double c, double b) return MakeQuiet(c); SetFPException(FPSCR_VXIMZ); - FPSCR.ClearFIFR(); return PPC_NAN; } @@ -289,19 +282,20 @@ inline double NI_msub(double a, double c, double b) if (std::isnan(t)) { if (Common::IsSNAN(b)) - { SetFPException(FPSCR_VXSNAN); - FPSCR.ClearFIFR(); - } + + FPSCR.ClearFIFR(); if (std::isnan(b)) return MakeQuiet(b); SetFPException(FPSCR_VXISI); - FPSCR.ClearFIFR(); return PPC_NAN; } + if (std::isinf(a) || std::isinf(b) || std::isinf(c)) + FPSCR.ClearFIFR(); + return t; } diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp index 32f78343e9..5fe173dcbc 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp @@ -409,6 +409,9 @@ void Interpreter::fresx(UGeckoInstruction inst) } else { + if (std::isnan(b) || std::isinf(b)) + FPSCR.ClearFIFR(); + compute_result(b); } @@ -452,6 +455,9 @@ void Interpreter::frsqrtex(UGeckoInstruction inst) } else { + if (std::isnan(b) || std::isinf(b)) + FPSCR.ClearFIFR(); + compute_result(b); } diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Paired.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Paired.cpp index 380c9ac103..f3c55e7fc0 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Paired.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Paired.cpp @@ -124,11 +124,11 @@ void Interpreter::ps_res(UGeckoInstruction inst) FPSCR.ClearFIFR(); } - if (Common::IsSNAN(a) || Common::IsSNAN(b)) - { - SetFPException(FPSCR_VXSNAN); + if (std::isnan(a) || std::isinf(a) || std::isnan(b) || std::isinf(b)) FPSCR.ClearFIFR(); - } + + if (Common::IsSNAN(a) || Common::IsSNAN(b)) + SetFPException(FPSCR_VXSNAN); rPS0(inst.FD) = Common::ApproximateReciprocal(a); rPS1(inst.FD) = Common::ApproximateReciprocal(b); @@ -155,11 +155,11 @@ void Interpreter::ps_rsqrte(UGeckoInstruction inst) FPSCR.ClearFIFR(); } - if (Common::IsSNAN(ps0) || Common::IsSNAN(ps1)) - { - SetFPException(FPSCR_VXSNAN); + if (std::isnan(ps0) || std::isinf(ps0) || std::isnan(ps1) || std::isinf(ps1)) FPSCR.ClearFIFR(); - } + + if (Common::IsSNAN(ps0) || Common::IsSNAN(ps1)) + SetFPException(FPSCR_VXSNAN); rPS0(inst.FD) = ForceSingle(Common::ApproximateReciprocalSquareRoot(ps0)); rPS1(inst.FD) = ForceSingle(Common::ApproximateReciprocalSquareRoot(ps1));