diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h index 795bab7b0e..90990b69d4 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h @@ -83,11 +83,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 (a != a) return a; + if (b != b) return b; SetFPException(FPSCR_VXIMZ); return PPC_NAN; } @@ -96,11 +96,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 (a != a) return a; + if (b != b) return b; SetFPException(FPSCR_VXISI); return PPC_NAN; } @@ -109,31 +109,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 (a != a) return a; + if (b != 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 (a != a) return a; + if (b != b) return b; // ! + if (c != c) return c; SetFPException(FPSCR_VXIMZ); return PPC_NAN; } t = t + b; if (t != t) { + if (b != b) return b; SetFPException(FPSCR_VXISI); return PPC_NAN; } @@ -142,12 +146,12 @@ 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 (a != a) return a; + if (b != b) return b; // ! + if (c != c) return c; SetFPException(FPSCR_VXIMZ); return PPC_NAN; } @@ -155,6 +159,7 @@ inline double NI_msub(double a, double c, double b, bool negate = false) t = t - b; if (t != t) { + if (b != b) return b; SetFPException(FPSCR_VXISI); return PPC_NAN; }