From f4c5ceba1cf9622f421338a1a00a6565753ff54e Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 27 May 2018 15:56:25 -0400 Subject: [PATCH 1/4] Interpreter_FPUtils: Set FPSCR.VXSNAN if either operand to NI_div is a signaling NaN If either operand is a signaling NaN, we need to signify that by setting the VXSNAN bit. This fixes NaN flag setting for fdiv, fdivs and ps_div instructions. --- .../Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h index 2d16cbea84..5a583b7892 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h @@ -113,13 +113,18 @@ inline double NI_mul(double a, double b) inline double NI_div(double a, double b) { - double t = a / b; + const double t = a / b; + if (std::isnan(t)) { + if (Common::IsSNAN(a) || Common::IsSNAN(b)) + SetFPException(FPSCR_VXSNAN); + if (std::isnan(a)) return MakeQuiet(a); if (std::isnan(b)) return MakeQuiet(b); + if (b == 0.0) { SetFPException(FPSCR_ZX); @@ -130,8 +135,10 @@ inline double NI_div(double a, double b) { SetFPException(FPSCR_VXIDI); } + return PPC_NAN; } + return t; } From b18dd442f7b6790936f9e9f0287236ead0aee53f Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 27 May 2018 16:08:23 -0400 Subject: [PATCH 2/4] Interpreter_FPUtils: Set FPSCR.VXSNAN if either operand to NI_sub is a signaling NaN If either operand is a signaling NaN, we need to signify this by setting the VXSNAN bit. This fixes NaN flag setting for fsub, fsubs, and ps_sub instructions. --- .../Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h index 5a583b7892..7273b62e7f 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h @@ -165,16 +165,22 @@ inline double NI_add(double a, double b) inline double NI_sub(double a, double b) { - double t = a - b; + const double t = a - b; + if (std::isnan(t)) { + if (Common::IsSNAN(a) || Common::IsSNAN(b)) + SetFPException(FPSCR_VXSNAN); + if (std::isnan(a)) return MakeQuiet(a); if (std::isnan(b)) return MakeQuiet(b); + SetFPException(FPSCR_VXISI); return PPC_NAN; } + return t; } From 3ebd713c33dec80d2416db9373e1e841ce180b29 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 27 May 2018 16:17:58 -0400 Subject: [PATCH 3/4] Interpreter_FPUtils: Set FPSCR.VXSNAN if any operand to NI_madd is a signaling NaN If any operand is a signaling NaN, we need to signify this by setting the VXSNAN bit. Fixes NaN flag setting for fmadd, fmadds, fnmadd, fnmadds, ps_madd, ps_nmadd, ps_madds0, and ps_madds1 --- .../Core/PowerPC/Interpreter/Interpreter_FPUtils.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h index 7273b62e7f..30340b0bb9 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h @@ -190,25 +190,37 @@ inline double NI_sub(double a, double b) inline double NI_madd(double a, double c, double b) { double t = a * c; + if (std::isnan(t)) { + if (Common::IsSNAN(a) || Common::IsSNAN(b) || Common::IsSNAN(c)) + SetFPException(FPSCR_VXSNAN); + if (std::isnan(a)) return MakeQuiet(a); if (std::isnan(b)) return MakeQuiet(b); // ! if (std::isnan(c)) return MakeQuiet(c); + SetFPException(FPSCR_VXIMZ); return PPC_NAN; } + t += b; + if (std::isnan(t)) { + if (Common::IsSNAN(b)) + SetFPException(FPSCR_VXSNAN); + if (std::isnan(b)) return MakeQuiet(b); + SetFPException(FPSCR_VXISI); return PPC_NAN; } + return t; } From a4cc8543513f9835b0c4f9c7e47e65d6c9cdd8dd Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 27 May 2018 16:24:22 -0400 Subject: [PATCH 4/4] Interpreter_FPUtils: Set FPSCR.VXSNAN if any operand to NI_msub is a signaling NaN If any operand is a signaling NaN, we need to signify this by setting the VXSNAN bit. Fixes NaN flag setting for fmsub, fmsubs, fnmsub, fnmsubs, ps_msub, and ps_nmsub instructions. --- .../Core/PowerPC/Interpreter/Interpreter_FPUtils.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h index 30340b0bb9..843b580fdd 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h @@ -227,26 +227,37 @@ inline double NI_madd(double a, double c, double b) inline double NI_msub(double a, double c, double b) { double t = a * c; + if (std::isnan(t)) { + if (Common::IsSNAN(a) || Common::IsSNAN(b) || Common::IsSNAN(c)) + SetFPException(FPSCR_VXSNAN); + if (std::isnan(a)) return MakeQuiet(a); if (std::isnan(b)) return MakeQuiet(b); // ! if (std::isnan(c)) return MakeQuiet(c); + SetFPException(FPSCR_VXIMZ); return PPC_NAN; } t -= b; + if (std::isnan(t)) { + if (Common::IsSNAN(b)) + SetFPException(FPSCR_VXSNAN); + if (std::isnan(b)) return MakeQuiet(b); + SetFPException(FPSCR_VXISI); return PPC_NAN; } + return t; }