fpu_ctrl.cpp 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. #include "config.h"
  2. #include "config_simd.h"
  3. #include "fpu_ctrl.h"
  4. #ifdef HAVE_INTRIN_H
  5. #include <intrin.h>
  6. #endif
  7. #if HAVE_SSE_INTRINSICS
  8. #include <emmintrin.h>
  9. #elif HAVE_SSE
  10. #include <xmmintrin.h>
  11. #endif
  12. #if HAVE_SSE && !defined(_MM_DENORMALS_ZERO_MASK)
  13. /* Some headers seem to be missing these? */
  14. #define _MM_DENORMALS_ZERO_MASK 0x0040u
  15. #define _MM_DENORMALS_ZERO_ON 0x0040u
  16. #endif
  17. #if !HAVE_SSE_INTRINSICS && HAVE_SSE
  18. #include "cpu_caps.h"
  19. #endif
  20. namespace {
  21. #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
  22. [[gnu::target("sse")]]
  23. #endif
  24. [[maybe_unused]]
  25. void disable_denormals(unsigned int *state [[maybe_unused]])
  26. {
  27. #if HAVE_SSE_INTRINSICS
  28. *state = _mm_getcsr();
  29. unsigned int sseState{*state};
  30. sseState &= ~(_MM_FLUSH_ZERO_MASK | _MM_DENORMALS_ZERO_MASK);
  31. sseState |= _MM_FLUSH_ZERO_ON | _MM_DENORMALS_ZERO_ON;
  32. _mm_setcsr(sseState);
  33. #elif HAVE_SSE
  34. *state = _mm_getcsr();
  35. unsigned int sseState{*state};
  36. sseState &= ~_MM_FLUSH_ZERO_MASK;
  37. sseState |= _MM_FLUSH_ZERO_ON;
  38. if((CPUCapFlags&CPU_CAP_SSE2))
  39. {
  40. sseState &= ~_MM_DENORMALS_ZERO_MASK;
  41. sseState |= _MM_DENORMALS_ZERO_ON;
  42. }
  43. _mm_setcsr(sseState);
  44. #endif
  45. }
  46. #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
  47. [[gnu::target("sse")]]
  48. #endif
  49. [[maybe_unused]]
  50. void reset_fpu(unsigned int state [[maybe_unused]])
  51. {
  52. #if HAVE_SSE_INTRINSICS || HAVE_SSE
  53. _mm_setcsr(state);
  54. #endif
  55. }
  56. } // namespace
  57. unsigned int FPUCtl::Set() noexcept
  58. {
  59. unsigned int state{};
  60. #if HAVE_SSE_INTRINSICS
  61. disable_denormals(&state);
  62. #elif HAVE_SSE
  63. if((CPUCapFlags&CPU_CAP_SSE))
  64. disable_denormals(&state);
  65. #endif
  66. return state;
  67. }
  68. void FPUCtl::Reset(unsigned int state [[maybe_unused]]) noexcept
  69. {
  70. #if HAVE_SSE_INTRINSICS
  71. reset_fpu(state);
  72. #elif HAVE_SSE
  73. if((CPUCapFlags&CPU_CAP_SSE))
  74. reset_fpu(state);
  75. #endif
  76. }