Index: Source/platform/audio/DenormalDisabler.h |
diff --git a/Source/platform/audio/DenormalDisabler.h b/Source/platform/audio/DenormalDisabler.h |
index d953c82138ad636c838e0a1916b07c16dff3321e..38af14da1bf852223e5977ae27c7cf4149bfcec4 100644 |
--- a/Source/platform/audio/DenormalDisabler.h |
+++ b/Source/platform/audio/DenormalDisabler.h |
@@ -34,11 +34,18 @@ namespace WebCore { |
// Deal with denormals. They can very seriously impact performance on x86. |
// Define HAVE_DENORMAL if we support flushing denormals to zero. |
+ |
#if OS(WIN) && COMPILER(MSVC) |
+// Windows compiled using MSVC with SSE2 |
#define HAVE_DENORMAL 1 |
#endif |
#if COMPILER(GCC) && (CPU(X86) || CPU(X86_64)) |
+// X86 chips can flush denormals |
+#define HAVE_DENORMAL 1 |
+#endif |
+ |
+#if CPU(ARM) || CPU(ARM64) |
#define HAVE_DENORMAL 1 |
#endif |
@@ -48,43 +55,34 @@ public: |
DenormalDisabler() |
: m_savedCSR(0) |
{ |
-#if OS(WIN) && COMPILER(MSVC) |
- // Save the current state, and set mode to flush denormals. |
- // |
- // http://stackoverflow.com/questions/637175/possible-bug-in-controlfp-s-may-not-restore-control-word-correctly |
- _controlfp_s(&m_savedCSR, 0, 0); |
- unsigned unused; |
- _controlfp_s(&unused, _DN_FLUSH, _MCW_DN); |
-#else |
- m_savedCSR = getCSR(); |
- setCSR(m_savedCSR | 0x8040); |
-#endif |
+ disableDenormals(); |
} |
~DenormalDisabler() |
{ |
-#if OS(WIN) && COMPILER(MSVC) |
- unsigned unused; |
- _controlfp_s(&unused, m_savedCSR, _MCW_DN); |
-#else |
- setCSR(m_savedCSR); |
-#endif |
+ restoreState(); |
} |
// This is a nop if we can flush denormals to zero in hardware. |
static inline float flushDenormalFloatToZero(float f) |
{ |
-#if OS(WIN) && COMPILER(MSVC) && (!_M_IX86_FP) |
- // For systems using x87 instead of sse, there's no hardware support |
- // to flush denormals automatically. Hence, we need to flush |
- // denormals to zero manually. |
- return (fabs(f) < FLT_MIN) ? 0.0f : f; |
-#else |
return f; |
-#endif |
} |
private: |
+ unsigned m_savedCSR; |
+ |
#if COMPILER(GCC) && (CPU(X86) || CPU(X86_64)) |
+ inline void disableDenormals() |
+ { |
+ m_savedCSR = getCSR(); |
+ setCSR(m_savedCSR | 0x8040); |
+ } |
+ |
+ inline void restoreState() |
+ { |
+ setCSR(m_savedCSR); |
+ } |
+ |
inline int getCSR() |
{ |
int result; |
@@ -98,9 +96,57 @@ private: |
asm volatile("ldmxcsr %0" : : "m" (temp)); |
} |
+#elif OS(WIN) && COMPILER(MSVC) |
+ inline void disableDenormals() |
+ { |
+ // Save the current state, and set mode to flush denormals. |
+ // |
+ // http://stackoverflow.com/questions/637175/possible-bug-in-controlfp-s-may-not-restore-control-word-correctly |
+ _controlfp_s(&m_savedCSR, 0, 0); |
+ unsigned unused; |
+ _controlfp_s(&unused, _DN_FLUSH, _MCW_DN); |
+ } |
+ |
+ inline void restoreState() |
+ { |
+ unsigned unused; |
+ _controlfp_s(&unused, m_savedCSR, _MCW_DN); |
+ } |
+#elif CPU(ARM) || CPU(ARM64) |
+ inline void disableDenormals() |
+ { |
+ m_savedCSR = getStatusWord(); |
+ // Bit 24 is the flush-to-zero mode control bit. Setting it to 1 flushes denormals to 0. |
+ setStatusWord(m_savedCSR | (1 << 24)); |
+ } |
+ |
+ inline void restoreState() |
+ { |
+ setStatusWord(m_savedCSR); |
+ } |
+ |
+ inline int getStatusWord() |
+ { |
+ int result; |
+#if CPU(ARM64) |
+ asm volatile("mrs %[result], FPCR" : [result] "=r" (result)); |
+#else |
+ asm volatile("vmrs %[result], FPSCR" : [result] "=r" (result)); |
+#endif |
+ return result; |
+ } |
+ |
+ inline void setStatusWord(int a) |
+ { |
+#if CPU(ARM64) |
+ asm volatile("msr FPCR, %[src]" : : [src] "r" (a)); |
+#else |
+ asm volatile("vmsr FPSCR, %[src]" : : [src] "r" (a)); |
+#endif |
+ } |
+ |
#endif |
- unsigned m_savedCSR; |
}; |
#else |