summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorTillmann Karras <tilkax@gmail.com>2014-03-09 19:34:58 +0100
committerTillmann Karras <tilkax@gmail.com>2014-03-09 19:34:58 +0100
commit9ef64245fa164b20db592fa866f846feb9559b14 (patch)
treeb86d1da439095ac61a6f32e19d1b7e0e06bf29ed /Source/Core
parentd71aef8843afd91cb5c8deb6111acd1e6d431531 (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.h39
-rw-r--r--Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h9
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;
}