From ca36ff0551456fffd98c769b0dc55e56b4fb25b6 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Thu, 25 Jun 2015 05:24:07 +0200 Subject: [PATCH 1/5] Interpreter: consolidate fdiv/fdivs/ps_div --- .../PowerPC/Interpreter/Interpreter_FPUtils.h | 22 +++++ .../Interpreter/Interpreter_FloatingPoint.cpp | 69 +------------- .../Interpreter/Interpreter_Paired.cpp | 93 +------------------ 3 files changed, 26 insertions(+), 158 deletions(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h index 5392cc7ee0..8fbd379c5b 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h @@ -95,6 +95,28 @@ inline double NI_mul(double a, double b) return t; } +inline double NI_div(double a, double b) +{ + double t = a / b; + if (std::isnan(t)) + { + if (std::isnan(a)) return a; + if (std::isnan(b)) return b; + if (b == 0.0) + { + SetFPException(FPSCR_ZX); + if (a == 0.0) + SetFPException(FPSCR_VXZDZ); + } + else if (std::isinf(a) && std::isinf(b)) + { + SetFPException(FPSCR_VXIDI); + } + return PPC_NAN; + } + return t; +} + inline double NI_add(double a, double b) { double t = a + b; diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp index c5eee4d0ea..fa4132c4ee 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp @@ -351,38 +351,7 @@ void Interpreter::faddsx(UGeckoInstruction _inst) void Interpreter::fdivx(UGeckoInstruction _inst) { - double a = rPS0(_inst.FA); - double b = rPS0(_inst.FB); - - if (a != a) - { - rPS0(_inst.FD) = a; - } - else if (b != b) - { - rPS0(_inst.FD) = b; - } - else - { - rPS0(_inst.FD) = ForceDouble(a / b); - if (b == 0.0) - { - if (a == 0.0) - { - SetFPException(FPSCR_VXZDZ); - rPS0(_inst.FD) = PPC_NAN; - } - SetFPException(FPSCR_ZX); - } - else - { - if (IsINF(a) && IsINF(b)) - { - SetFPException(FPSCR_VXIDI); - rPS0(_inst.FD) = PPC_NAN; - } - } - } + rPS0(_inst.FD) = ForceDouble(NI_div(rPS0(_inst.FA), rPS0(_inst.FB))); UpdateFPRF(rPS0(_inst.FD)); // FR,FI,OX,UX??? @@ -391,41 +360,7 @@ void Interpreter::fdivx(UGeckoInstruction _inst) } void Interpreter::fdivsx(UGeckoInstruction _inst) { - double a = rPS0(_inst.FA); - double b = rPS0(_inst.FB); - double res; - - if (a != a) - { - res = a; - } - else if (b != b) - { - res = b; - } - else - { - res = ForceSingle(a / b); - if (b == 0.0) - { - if (a == 0.0) - { - SetFPException(FPSCR_VXZDZ); - res = PPC_NAN; - } - SetFPException(FPSCR_ZX); - } - else - { - if (IsINF(a) && IsINF(b)) - { - SetFPException(FPSCR_VXIDI); - res = PPC_NAN; - } - } - } - - rPS0(_inst.FD) = rPS1(_inst.FD) = res; + rPS0(_inst.FD) = rPS1(_inst.FD) = ForceSingle(NI_div(rPS0(_inst.FA), rPS0(_inst.FB))); UpdateFPRF(rPS0(_inst.FD)); if (_inst.Rc) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Paired.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Paired.cpp index 2c9656bd8f..fc56a4a33d 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Paired.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Paired.cpp @@ -104,97 +104,8 @@ void Interpreter::ps_merge11(UGeckoInstruction _inst) // From here on, the real deal. void Interpreter::ps_div(UGeckoInstruction _inst) { - u32 ex_mask = 0; - - // PS0 - { - double a = rPS0(_inst.FA); - double b = rPS0(_inst.FB); - double &res = rPS0(_inst.FD); - - if (a != a) - { - res = a; - } - else if (b != b) - { - res = b; - } - else - { - if (b == 0.0) - { - ex_mask |= FPSCR_ZX; - if (rPS0(_inst.FA) == 0.0) - { - ex_mask |= FPSCR_VXZDZ; - res = PPC_NAN; - } - else - { - res = ForceSingle(a / b); - } - } - else - { - if (IsINF(a) && IsINF(b)) - { - ex_mask |= FPSCR_VXIDI; - res = PPC_NAN; - } - else - { - res = ForceSingle(a / b); - } - } - } - } - - // PS1 - { - double a = rPS1(_inst.FA); - double b = rPS1(_inst.FB); - double &res = rPS1(_inst.FD); - - if (a != a) - { - res = a; - } - else if (b != b) - { - res = b; - } - else - { - if (b == 0.0) - { - ex_mask |= FPSCR_ZX; - if (rPS0(_inst.FA) == 0.0) - { - ex_mask |= FPSCR_VXZDZ; - res = PPC_NAN; - } - else - { - res = ForceSingle(a / b); - } - } - else - { - if (IsINF(a) && IsINF(b)) - { - ex_mask |= FPSCR_VXIDI; - res = PPC_NAN; - } - else - { - res = ForceSingle(a / b); - } - } - } - } - - SetFPException(ex_mask); + rPS0(_inst.FD) = ForceSingle(NI_div(rPS0(_inst.FA), rPS0(_inst.FB))); + rPS1(_inst.FD) = ForceSingle(NI_div(rPS1(_inst.FA), rPS1(_inst.FB))); UpdateFPRF(rPS0(_inst.FD)); if (_inst.Rc) From b2c21e800abe0beb121f85a9adb235a8eb3b95c0 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Thu, 25 Jun 2015 06:05:40 +0200 Subject: [PATCH 2/5] Interpreter: drop unused macros --- Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h index 8fbd379c5b..dac55e608d 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h @@ -12,9 +12,6 @@ #include "Core/PowerPC/Gekko.h" #include "Core/PowerPC/Interpreter/Interpreter.h" -#define MIN_SINGLE 0xc7efffffe0000000ull -#define MAX_SINGLE 0x47efffffe0000000ull - const u64 PPC_NAN_U64 = 0x7ff8000000000000ull; const double PPC_NAN = *(double* const)&PPC_NAN_U64; From 174ada3a62d7835f877d534062883e75305fdf18 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Thu, 25 Jun 2015 06:26:24 +0200 Subject: [PATCH 3/5] Interpreter: assign directly instead via variables --- .../Interpreter/Interpreter_Paired.cpp | 60 +++++++------------ 1 file changed, 20 insertions(+), 40 deletions(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Paired.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Paired.cpp index fc56a4a33d..e8a0132413 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Paired.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Paired.cpp @@ -59,10 +59,8 @@ void Interpreter::ps_abs(UGeckoInstruction _inst) // These are just moves, double is OK. void Interpreter::ps_merge00(UGeckoInstruction _inst) { - double p0 = rPS0(_inst.FA); - double p1 = rPS0(_inst.FB); - rPS0(_inst.FD) = p0; - rPS1(_inst.FD) = p1; + rPS0(_inst.FD) = rPS0(_inst.FA); + rPS1(_inst.FD) = rPS0(_inst.FB); if (_inst.Rc) Helper_UpdateCR1(); @@ -70,10 +68,8 @@ void Interpreter::ps_merge00(UGeckoInstruction _inst) void Interpreter::ps_merge01(UGeckoInstruction _inst) { - double p0 = rPS0(_inst.FA); - double p1 = rPS1(_inst.FB); - rPS0(_inst.FD) = p0; - rPS1(_inst.FD) = p1; + rPS0(_inst.FD) = rPS0(_inst.FA); + rPS1(_inst.FD) = rPS1(_inst.FB); if (_inst.Rc) Helper_UpdateCR1(); @@ -81,10 +77,8 @@ void Interpreter::ps_merge01(UGeckoInstruction _inst) void Interpreter::ps_merge10(UGeckoInstruction _inst) { - double p0 = rPS1(_inst.FA); - double p1 = rPS0(_inst.FB); - rPS0(_inst.FD) = p0; - rPS1(_inst.FD) = p1; + rPS0(_inst.FD) = rPS1(_inst.FA); + rPS1(_inst.FD) = rPS0(_inst.FB); if (_inst.Rc) Helper_UpdateCR1(); @@ -92,10 +86,8 @@ void Interpreter::ps_merge10(UGeckoInstruction _inst) void Interpreter::ps_merge11(UGeckoInstruction _inst) { - double p0 = rPS1(_inst.FA); - double p1 = rPS1(_inst.FB); - rPS0(_inst.FD) = p0; - rPS1(_inst.FD) = p1; + rPS0(_inst.FD) = rPS1(_inst.FA); + rPS1(_inst.FD) = rPS1(_inst.FB); if (_inst.Rc) Helper_UpdateCR1(); @@ -236,10 +228,8 @@ void Interpreter::ps_nmadd(UGeckoInstruction _inst) void Interpreter::ps_sum0(UGeckoInstruction _inst) { - double p0 = ForceSingle(NI_add(rPS0(_inst.FA), rPS1(_inst.FB))); - double p1 = ForceSingle(rPS1(_inst.FC)); - rPS0(_inst.FD) = p0; - rPS1(_inst.FD) = p1; + rPS0(_inst.FD) = ForceSingle(NI_add(rPS0(_inst.FA), rPS1(_inst.FB))); + rPS1(_inst.FD) = ForceSingle(rPS1(_inst.FC)); UpdateFPRF(rPS0(_inst.FD)); if (_inst.Rc) @@ -248,10 +238,8 @@ void Interpreter::ps_sum0(UGeckoInstruction _inst) void Interpreter::ps_sum1(UGeckoInstruction _inst) { - double p0 = ForceSingle(rPS0(_inst.FC)); - double p1 = ForceSingle(NI_add(rPS0(_inst.FA), rPS1(_inst.FB))); - rPS0(_inst.FD) = p0; - rPS1(_inst.FD) = p1; + rPS0(_inst.FD) = ForceSingle(rPS0(_inst.FC)); + rPS1(_inst.FD) = ForceSingle(NI_add(rPS0(_inst.FA), rPS1(_inst.FB))); UpdateFPRF(rPS1(_inst.FD)); if (_inst.Rc) @@ -261,10 +249,8 @@ void Interpreter::ps_sum1(UGeckoInstruction _inst) void Interpreter::ps_muls0(UGeckoInstruction _inst) { double c0 = Force25Bit(rPS0(_inst.FC)); - double p0 = ForceSingle(NI_mul(rPS0(_inst.FA), c0)); - double p1 = ForceSingle(NI_mul(rPS1(_inst.FA), c0)); - rPS0(_inst.FD) = p0; - rPS1(_inst.FD) = p1; + rPS0(_inst.FD) = ForceSingle(NI_mul(rPS0(_inst.FA), c0)); + rPS1(_inst.FD) = ForceSingle(NI_mul(rPS1(_inst.FA), c0)); UpdateFPRF(rPS0(_inst.FD)); if (_inst.Rc) @@ -274,10 +260,8 @@ void Interpreter::ps_muls0(UGeckoInstruction _inst) void Interpreter::ps_muls1(UGeckoInstruction _inst) { double c1 = Force25Bit(rPS1(_inst.FC)); - double p0 = ForceSingle(NI_mul(rPS0(_inst.FA), c1)); - double p1 = ForceSingle(NI_mul(rPS1(_inst.FA), c1)); - rPS0(_inst.FD) = p0; - rPS1(_inst.FD) = p1; + rPS0(_inst.FD) = ForceSingle(NI_mul(rPS0(_inst.FA), c1)); + rPS1(_inst.FD) = ForceSingle(NI_mul(rPS1(_inst.FA), c1)); UpdateFPRF(rPS0(_inst.FD)); if (_inst.Rc) @@ -287,10 +271,8 @@ void Interpreter::ps_muls1(UGeckoInstruction _inst) void Interpreter::ps_madds0(UGeckoInstruction _inst) { double c0 = Force25Bit(rPS0(_inst.FC)); - double p0 = ForceSingle(NI_madd(rPS0(_inst.FA), c0, rPS0(_inst.FB))); - double p1 = ForceSingle(NI_madd(rPS1(_inst.FA), c0, rPS1(_inst.FB))); - rPS0(_inst.FD) = p0; - rPS1(_inst.FD) = p1; + rPS0(_inst.FD) = ForceSingle(NI_madd(rPS0(_inst.FA), c0, rPS0(_inst.FB))); + rPS1(_inst.FD) = ForceSingle(NI_madd(rPS1(_inst.FA), c0, rPS1(_inst.FB))); UpdateFPRF(rPS0(_inst.FD)); if (_inst.Rc) @@ -300,10 +282,8 @@ void Interpreter::ps_madds0(UGeckoInstruction _inst) void Interpreter::ps_madds1(UGeckoInstruction _inst) { double c1 = Force25Bit(rPS1(_inst.FC)); - double p0 = ForceSingle(NI_madd(rPS0(_inst.FA), c1, rPS0(_inst.FB))); - double p1 = ForceSingle(NI_madd(rPS1(_inst.FA), c1, rPS1(_inst.FB))); - rPS0(_inst.FD) = p0; - rPS1(_inst.FD) = p1; + rPS0(_inst.FD) = ForceSingle(NI_madd(rPS0(_inst.FA), c1, rPS0(_inst.FB))); + rPS1(_inst.FD) = ForceSingle(NI_madd(rPS1(_inst.FA), c1, rPS1(_inst.FB))); UpdateFPRF(rPS0(_inst.FD)); if (_inst.Rc) From b78310bbe562ee1c133d06739cf5a16167f10145 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Thu, 25 Jun 2015 22:29:31 +0200 Subject: [PATCH 4/5] Interpreter: simplify fres --- Source/Core/Common/MathUtil.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Core/Common/MathUtil.cpp b/Source/Core/Common/MathUtil.cpp index 07fa5bf293..a9252ddf55 100644 --- a/Source/Core/Common/MathUtil.cpp +++ b/Source/Core/Common/MathUtil.cpp @@ -209,23 +209,23 @@ double ApproximateReciprocal(double val) // Special case 0 if (mantissa == 0 && exponent == 0) - return sign ? -std::numeric_limits::infinity() : std::numeric_limits::infinity(); + return std::copysign(std::numeric_limits::infinity(), valf); // Special case NaN-ish numbers if (exponent == (0x7FFLL << 52)) { if (mantissa == 0) - return sign ? -0.0 : 0.0; + return std::copysign(0.0, valf); return 0.0 + valf; } // Special case small inputs if (exponent < (895LL << 52)) - return sign ? -std::numeric_limits::max() : std::numeric_limits::max(); + return std::copysign(std::numeric_limits::max(), valf); // Special case large inputs if (exponent >= (1149LL << 52)) - return sign ? -0.0f : 0.0f; + return std::copysign(0.0, valf); exponent = (0x7FDLL << 52) - exponent; From 2711d5201b88d47ac5b980f0d73eb0b688368f91 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Thu, 25 Jun 2015 05:25:17 +0200 Subject: [PATCH 5/5] Interpreter: turn SNaNs into QNaNs --- .../PowerPC/Interpreter/Interpreter_FPUtils.h | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h index dac55e608d..0c210fcc7d 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h @@ -76,6 +76,13 @@ inline double Force25Bit(double d) return x.d; } +inline double MakeQuiet(double d) +{ + MathUtil::IntDouble x(d); + x.i |= MathUtil::DOUBLE_QBIT; + return x.d; +} + // these functions allow globally modify operations behaviour // also, these may be used to set flags like FR, FI, OX, UX @@ -84,8 +91,8 @@ inline double NI_mul(double a, double b) double t = a * b; if (std::isnan(t)) { - if (std::isnan(a)) return a; - if (std::isnan(b)) return b; + if (std::isnan(a)) return MakeQuiet(a); + if (std::isnan(b)) return MakeQuiet(b); SetFPException(FPSCR_VXIMZ); return PPC_NAN; } @@ -97,8 +104,8 @@ inline double NI_div(double a, double b) double t = a / b; if (std::isnan(t)) { - if (std::isnan(a)) return a; - if (std::isnan(b)) return b; + if (std::isnan(a)) return MakeQuiet(a); + if (std::isnan(b)) return MakeQuiet(b); if (b == 0.0) { SetFPException(FPSCR_ZX); @@ -119,8 +126,8 @@ inline double NI_add(double a, double b) double t = a + b; if (std::isnan(t)) { - if (std::isnan(a)) return a; - if (std::isnan(b)) return b; + if (std::isnan(a)) return MakeQuiet(a); + if (std::isnan(b)) return MakeQuiet(b); SetFPException(FPSCR_VXISI); return PPC_NAN; } @@ -132,8 +139,8 @@ inline double NI_sub(double a, double b) double t = a - b; if (std::isnan(t)) { - if (std::isnan(a)) return a; - if (std::isnan(b)) return b; + if (std::isnan(a)) return MakeQuiet(a); + if (std::isnan(b)) return MakeQuiet(b); SetFPException(FPSCR_VXISI); return PPC_NAN; } @@ -148,16 +155,16 @@ inline double NI_madd(double a, double c, double b, bool negate = false) double t = a * c; if (std::isnan(t)) { - if (std::isnan(a)) return a; - if (std::isnan(b)) return b; // ! - if (std::isnan(c)) return c; + 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 (std::isnan(b)) return b; + if (std::isnan(b)) return MakeQuiet(b); SetFPException(FPSCR_VXISI); return PPC_NAN; } @@ -169,9 +176,9 @@ inline double NI_msub(double a, double c, double b, bool negate = false) double t = a * c; if (std::isnan(t)) { - if (std::isnan(a)) return a; - if (std::isnan(b)) return b; // ! - if (std::isnan(c)) return c; + 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; } @@ -179,7 +186,7 @@ inline double NI_msub(double a, double c, double b, bool negate = false) t -= b; if (std::isnan(t)) { - if (std::isnan(b)) return b; + if (std::isnan(b)) return MakeQuiet(b); SetFPException(FPSCR_VXISI); return PPC_NAN; }