diff options
| author | Tillmann Karras <tilkax@gmail.com> | 2013-10-24 22:05:53 +0200 |
|---|---|---|
| committer | Tillmann Karras <tilkax@gmail.com> | 2013-11-13 06:24:58 +0100 |
| commit | cd069fdce1bd7a30f99f3bed9dfe0af60cd562d8 (patch) | |
| tree | bbc527f22fa5303c21b9bd36d57deb89e42c1a2d /Source/Core/Common | |
| parent | 466a7afde336d381e250d51e4c268c769e072a02 (diff) | |
Interpreter: software-based flush-to-zero
bDAZ is now called bFlushToZero to better reflect what it's actually
used for.
I decided not to support any hardware-based flush-to-zero on systems
that don't support this for both inputs _and_ outputs. It makes the code
cleaner and the intersection of CPUs that support SSE2 but not DAZ
should be very small.
Diffstat (limited to 'Source/Core/Common')
| -rw-r--r-- | Source/Core/Common/Src/CPUDetect.h | 5 | ||||
| -rw-r--r-- | Source/Core/Common/Src/MathUtil.h | 4 | ||||
| -rw-r--r-- | Source/Core/Common/Src/x64CPUDetect.cpp | 8 | ||||
| -rw-r--r-- | Source/Core/Common/Src/x64FPURoundMode.cpp | 2 |
4 files changed, 14 insertions, 5 deletions
diff --git a/Source/Core/Common/Src/CPUDetect.h b/Source/Core/Common/Src/CPUDetect.h index eab62d3d19..967be0949b 100644 --- a/Source/Core/Common/Src/CPUDetect.h +++ b/Source/Core/Common/Src/CPUDetect.h @@ -45,7 +45,10 @@ struct CPUInfo bool bAES; // FXSAVE/FXRSTOR bool bFXSR; - bool bDAZ; + // This flag indicates that the hardware supports some mode + // in which denormal inputs _and_ outputs are automatically set to (signed) zero. + // TODO: ARM + bool bFlushToZero; bool bLAHFSAHF64; bool bLongMode; diff --git a/Source/Core/Common/Src/MathUtil.h b/Source/Core/Common/Src/MathUtil.h index 31772c3c60..f085c6ed2b 100644 --- a/Source/Core/Common/Src/MathUtil.h +++ b/Source/Core/Common/Src/MathUtil.h @@ -64,10 +64,10 @@ inline float FlushToZero(float f) return x.f; } -inline double FlushToZeroAsFloat(double d) +inline double FlushToZero(double d) { IntDouble x; x.d = d; - if ((x.i & DOUBLE_EXP) < 0x3800000000000000ULL) + if ((x.i & DOUBLE_EXP) == 0) x.i &= DOUBLE_SIGN; // turn into signed zero return x.d; } diff --git a/Source/Core/Common/Src/x64CPUDetect.cpp b/Source/Core/Common/Src/x64CPUDetect.cpp index 182cca5224..d6f36eb142 100644 --- a/Source/Core/Common/Src/x64CPUDetect.cpp +++ b/Source/Core/Common/Src/x64CPUDetect.cpp @@ -162,6 +162,7 @@ void CPUInfo::Detect() if ((cpu_id[2] >> 20) & 1) bSSE4_2 = true; if ((cpu_id[2] >> 25) & 1) bAES = true; + // To check DAZ support, we first need to check FXSAVE support. if ((cpu_id[3] >> 24) & 1) { // We can use FXSAVE. @@ -181,7 +182,12 @@ void CPUInfo::Detect() // lowest byte of MXCSR_MASK if ((fx_state[0x1C] >> 6) & 1) - bDAZ = true; + { + // On x86, the FTZ field (supported since SSE1) only flushes denormal _outputs_ to zero, + // now that we checked DAZ support (flushing denormal _inputs_ to zero), + // we can set our generic flag. + bFlushToZero = true; + } } // AVX support requires 3 separate checks: diff --git a/Source/Core/Common/Src/x64FPURoundMode.cpp b/Source/Core/Common/Src/x64FPURoundMode.cpp index a8b0d16809..f46c6000eb 100644 --- a/Source/Core/Common/Src/x64FPURoundMode.cpp +++ b/Source/Core/Common/Src/x64FPURoundMode.cpp @@ -103,7 +103,7 @@ namespace FPURoundMode }; if (nonIEEEMode) { - csr |= denormalLUT[cpu_info.bDAZ]; + csr |= denormalLUT[cpu_info.bFlushToZero]; } _mm_setcsr(csr); } |
