31#if defined(__x86_64__) || defined(_M_X64) || defined(_M_IX86) \
32 || (defined(__i386__) && defined(__SSE__))
33 #define DSPARK_DENORMAL_X86 1
34 #include <immintrin.h>
35#elif (defined(__aarch64__) || defined(_M_ARM64)) && (defined(__GNUC__) || defined(__clang__))
36 #define DSPARK_DENORMAL_ARM64_ASM 1
37#elif defined(_M_ARM64) && defined(_MSC_VER)
38 #define DSPARK_DENORMAL_ARM64_MSVC 1
40#elif defined(__arm__) && defined(__ARM_FP) && (defined(__GNUC__) || defined(__clang__))
41 #define DSPARK_DENORMAL_ARM32 1
93#if defined(DSPARK_DENORMAL_X86)
94 previousState_ = _mm_getcsr();
96 _mm_setcsr(
static_cast<unsigned int>(previousState_) | 0x8040u);
98#elif defined(DSPARK_DENORMAL_ARM64_ASM)
99 unsigned long long fpcr;
100 __asm__ __volatile__(
"mrs %0, fpcr" :
"=r"(fpcr));
101 previousState_ = fpcr;
102 fpcr |= (1ULL << 24);
103 __asm__ __volatile__(
"msr fpcr, %0" : :
"r"(fpcr));
105#elif defined(DSPARK_DENORMAL_ARM64_MSVC)
106 const long long fpcr = _ReadStatusReg(ARM64_FPCR);
107 previousState_ =
static_cast<uint64_t
>(fpcr);
108 _WriteStatusReg(ARM64_FPCR, fpcr | (1LL << 24));
110#elif defined(DSPARK_DENORMAL_ARM32)
112 __asm__ __volatile__(
"vmrs %0, fpscr" :
"=r"(fpscr));
113 previousState_ = fpscr;
115 __asm__ __volatile__(
"vmsr fpscr, %0" : :
"r"(fpscr));
130#if defined(DSPARK_DENORMAL_X86)
131 _mm_setcsr(
static_cast<unsigned int>(previousState_));
133#elif defined(DSPARK_DENORMAL_ARM64_ASM)
134 const unsigned long long fpcr =
static_cast<unsigned long long>(previousState_);
135 __asm__ __volatile__(
"msr fpcr, %0" : :
"r"(fpcr));
137#elif defined(DSPARK_DENORMAL_ARM64_MSVC)
138 _WriteStatusReg(ARM64_FPCR,
static_cast<long long>(previousState_));
140#elif defined(DSPARK_DENORMAL_ARM32)
141 const unsigned int fpscr =
static_cast<unsigned int>(previousState_);
142 __asm__ __volatile__(
"vmsr fpscr, %0" : :
"r"(fpscr));
153 [[nodiscard]]
static constexpr bool isActive() noexcept
155#if defined(DSPARK_DENORMAL_X86) || defined(DSPARK_DENORMAL_ARM64_ASM) \
156 || defined(DSPARK_DENORMAL_ARM64_MSVC) || defined(DSPARK_DENORMAL_ARM32)
171 uint64_t previousState_ = 0;
176#undef DSPARK_DENORMAL_X86
177#undef DSPARK_DENORMAL_ARM64_ASM
178#undef DSPARK_DENORMAL_ARM64_MSVC
179#undef DSPARK_DENORMAL_ARM32
RAII scope guard to disable denormalised (subnormal) floating-point numbers.
DenormalGuard & operator=(const DenormalGuard &)=delete
DenormalGuard(const DenormalGuard &)=delete
DenormalGuard & operator=(DenormalGuard &&)=delete
static constexpr bool isActive() noexcept
True when this build has a real flush-to-zero implementation.
DenormalGuard(DenormalGuard &&)=delete
~DenormalGuard() noexcept
Destroys the guard, restoring the exact FP state captured at construction.
DenormalGuard() noexcept
Constructs the guard, saving the current FP state and enabling FTZ (plus DAZ on x86).
Main namespace for the DSPark framework.