diff options
| author | flacs <tilkax@gmail.com> | 2015-06-10 15:30:48 +0200 |
|---|---|---|
| committer | flacs <tilkax@gmail.com> | 2015-06-10 15:30:48 +0200 |
| commit | 6bc85995bd6902acae5ae4efd627aa445f352fff (patch) | |
| tree | 9fe64622008156cdaf29962b019bab862161caf3 /Source/Core | |
| parent | 9b8eb55cd47f436df63f9367a6b612908c6d4dbd (diff) | |
| parent | d32914787178353eaeeff6f9c419abdd28a1528e (diff) | |
Merge pull request #2586 from Tilka/interpreter_nans
Interpreter: optimize NaN checks
Diffstat (limited to 'Source/Core')
| -rw-r--r-- | Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h | 48 |
1 files changed, 27 insertions, 21 deletions
diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h index 795bab7b0e..5392cc7ee0 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h @@ -4,6 +4,7 @@ #pragma once +#include <cmath> #include <limits> #include "Common/CPUDetect.h" @@ -83,11 +84,11 @@ inline double Force25Bit(double d) inline double NI_mul(double a, double b) { - if (a != a) return a; - if (b != b) return b; double t = a * b; - if (t != t) + if (std::isnan(t)) { + if (std::isnan(a)) return a; + if (std::isnan(b)) return b; SetFPException(FPSCR_VXIMZ); return PPC_NAN; } @@ -96,11 +97,11 @@ inline double NI_mul(double a, double b) inline double NI_add(double a, double b) { - if (a != a) return a; - if (b != b) return b; double t = a + b; - if (t != t) + if (std::isnan(t)) { + if (std::isnan(a)) return a; + if (std::isnan(b)) return b; SetFPException(FPSCR_VXISI); return PPC_NAN; } @@ -109,31 +110,35 @@ inline double NI_add(double a, double b) inline double NI_sub(double a, double b) { - if (a != a) return a; - if (b != b) return b; double t = a - b; - if (t != t) + if (std::isnan(t)) { + if (std::isnan(a)) return a; + if (std::isnan(b)) return b; SetFPException(FPSCR_VXISI); return PPC_NAN; } return t; } +// FMA instructions on PowerPC are weird: +// They calculate (a * c) + b, but the order in which +// inputs are checked for NaN is still a, b, c. inline double NI_madd(double a, double c, double b, bool negate = false) { - if (a != a) return a; - if (b != b) return b; - if (c != c) return c; double t = a * c; - if (t != t) + if (std::isnan(t)) { + if (std::isnan(a)) return a; + if (std::isnan(b)) return b; // ! + if (std::isnan(c)) return c; SetFPException(FPSCR_VXIMZ); return PPC_NAN; } - t = t + b; - if (t != t) + t += b; + if (std::isnan(t)) { + if (std::isnan(b)) return b; SetFPException(FPSCR_VXISI); return PPC_NAN; } @@ -142,19 +147,20 @@ inline double NI_madd(double a, double c, double b, bool negate = false) inline double NI_msub(double a, double c, double b, bool negate = false) { - if (a != a) return a; - if (b != b) return b; - if (c != c) return c; double t = a * c; - if (t != t) + if (std::isnan(t)) { + if (std::isnan(a)) return a; + if (std::isnan(b)) return b; // ! + if (std::isnan(c)) return c; SetFPException(FPSCR_VXIMZ); return PPC_NAN; } - t = t - b; - if (t != t) + t -= b; + if (std::isnan(t)) { + if (std::isnan(b)) return b; SetFPException(FPSCR_VXISI); return PPC_NAN; } |
