diff options
| author | Tillmann Karras <tilkax@gmail.com> | 2014-03-09 19:34:58 +0100 |
|---|---|---|
| committer | Tillmann Karras <tilkax@gmail.com> | 2014-03-09 19:34:58 +0100 |
| commit | 9ef64245fa164b20db592fa866f846feb9559b14 (patch) | |
| tree | b86d1da439095ac61a6f32e19d1b7e0e06bf29ed /Source/Core | |
| parent | d71aef8843afd91cb5c8deb6111acd1e6d431531 (diff) | |
MathUtil: fix IsQNAN()
The constants were one nibble too short and the lower 51 bits don't
actually have to be zero.
Diffstat (limited to 'Source/Core')
| -rw-r--r-- | Source/Core/Common/MathUtil.h | 39 | ||||
| -rw-r--r-- | Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h | 9 |
2 files changed, 28 insertions, 20 deletions
diff --git a/Source/Core/Common/MathUtil.h b/Source/Core/Common/MathUtil.h index 0febed3014..9ddacd6e1c 100644 --- a/Source/Core/Common/MathUtil.h +++ b/Source/Core/Common/MathUtil.h @@ -20,16 +20,18 @@ inline void Clamp(T* val, const T& min, const T& max) *val = max; } +// The most significant bit of the fraction is an is-quiet bit on all architectures we care about. static const u64 DOUBLE_SIGN = 0x8000000000000000ULL, - DOUBLE_EXP = 0x7FF0000000000000ULL, - DOUBLE_FRAC = 0x000FFFFFFFFFFFFFULL, - DOUBLE_ZERO = 0x0000000000000000ULL; + DOUBLE_EXP = 0x7FF0000000000000ULL, + DOUBLE_FRAC = 0x000FFFFFFFFFFFFFULL, + DOUBLE_ZERO = 0x0000000000000000ULL, + DOUBLE_QBIT = 0x0008000000000000ULL; static const u32 FLOAT_SIGN = 0x80000000, - FLOAT_EXP = 0x7F800000, - FLOAT_FRAC = 0x007FFFFF, - FLOAT_ZERO = 0x00000000; + FLOAT_EXP = 0x7F800000, + FLOAT_FRAC = 0x007FFFFF, + FLOAT_ZERO = 0x00000000; union IntDouble { double d; @@ -40,34 +42,41 @@ union IntFloat { u32 i; }; +inline bool IsINF(double d) +{ + IntDouble x; x.d = d; + return (x.i & ~DOUBLE_SIGN) == DOUBLE_EXP; +} + inline bool IsNAN(double d) { IntDouble x; x.d = d; - return ( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) && - ((x.i & DOUBLE_FRAC) != DOUBLE_ZERO) ); + return ((x.i & DOUBLE_EXP) == DOUBLE_EXP) && + ((x.i & DOUBLE_FRAC) != DOUBLE_ZERO); } inline bool IsQNAN(double d) { IntDouble x; x.d = d; - return ( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) && - ((x.i & 0x0007fffffffffffULL) == 0x000000000000000ULL) && - ((x.i & 0x000800000000000ULL) == 0x000800000000000ULL) ); + return ((x.i & DOUBLE_EXP) == DOUBLE_EXP) && + ((x.i & DOUBLE_QBIT) == DOUBLE_QBIT); } inline bool IsSNAN(double d) { IntDouble x; x.d = d; - return( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) && - ((x.i & DOUBLE_FRAC) != DOUBLE_ZERO) && - ((x.i & 0x0008000000000000ULL) == DOUBLE_ZERO) ); + return ((x.i & DOUBLE_EXP) == DOUBLE_EXP) && + ((x.i & DOUBLE_FRAC) != DOUBLE_ZERO) && + ((x.i & DOUBLE_QBIT) == DOUBLE_ZERO); } inline float FlushToZero(float f) { IntFloat x; x.f = f; if ((x.i & FLOAT_EXP) == 0) + { x.i &= FLOAT_SIGN; // turn into signed zero + } return x.f; } @@ -75,7 +84,9 @@ inline double FlushToZero(double d) { IntDouble x; x.d = d; if ((x.i & DOUBLE_EXP) == 0) + { x.i &= DOUBLE_SIGN; // turn into signed zero + } return x.d; } diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h index fa5e6ff2f4..72136d71d3 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h @@ -33,22 +33,19 @@ const u32 FPSCR_VXSQRT = (u32)1 << (31 - 22); const u32 FPSCR_VXCVI = (u32)1 << (31 - 23); const u32 FPSCR_VX_ANY = FPSCR_VXSNAN | FPSCR_VXISI | FPSCR_VXIDI | FPSCR_VXZDZ | - FPSCR_VXIMZ | FPSCR_VXVC | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI; + FPSCR_VXIMZ | FPSCR_VXVC | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI; const u32 FPSCR_ANY_X = FPSCR_OX | FPSCR_UX | FPSCR_ZX | FPSCR_XX | FPSCR_VX_ANY; const u64 PPC_NAN_U64 = 0x7ff8000000000000ull; const double PPC_NAN = *(double* const)&PPC_NAN_U64; -inline bool IsINF(double x) -{ - return ((*(u64*)&x) & ~DOUBLE_SIGN) == DOUBLE_EXP; -} - inline void SetFPException(u32 mask) { if ((FPSCR.Hex & mask) != mask) + { FPSCR.FX = 1; + } FPSCR.Hex |= mask; } |
