FPControlWord.h 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #pragma once
  5. #include <Jolt/Core/NonCopyable.h>
  6. JPH_NAMESPACE_BEGIN
  7. #ifdef JPH_USE_SSE
  8. /// Helper class that needs to be put on the stack to update the state of the floating point control word.
  9. /// This state is kept per thread.
  10. template <uint Value, uint Mask>
  11. class FPControlWord : public NonCopyable
  12. {
  13. public:
  14. FPControlWord()
  15. {
  16. mPrevState = _mm_getcsr();
  17. _mm_setcsr((mPrevState & ~Mask) | Value);
  18. }
  19. ~FPControlWord()
  20. {
  21. _mm_setcsr((_mm_getcsr() & ~Mask) | (mPrevState & Mask));
  22. }
  23. private:
  24. uint mPrevState;
  25. };
  26. #elif defined(JPH_CPU_ARM) && defined(JPH_COMPILER_MSVC)
  27. /// Helper class that needs to be put on the stack to update the state of the floating point control word.
  28. /// This state is kept per thread.
  29. template <unsigned int Value, unsigned int Mask>
  30. class FPControlWord : public NonCopyable
  31. {
  32. public:
  33. FPControlWord()
  34. {
  35. // Read state before change
  36. _controlfp_s(&mPrevState, 0, 0);
  37. // Update the state
  38. unsigned int dummy;
  39. _controlfp_s(&dummy, Value, Mask);
  40. }
  41. ~FPControlWord()
  42. {
  43. // Restore state
  44. unsigned int dummy;
  45. _controlfp_s(&dummy, mPrevState, Mask);
  46. }
  47. private:
  48. unsigned int mPrevState;
  49. };
  50. #elif defined(JPH_CPU_ARM) && defined(JPH_USE_NEON)
  51. /// Helper class that needs to be put on the stack to update the state of the floating point control word.
  52. /// This state is kept per thread.
  53. template <uint64 Value, uint64 Mask>
  54. class FPControlWord : public NonCopyable
  55. {
  56. public:
  57. FPControlWord()
  58. {
  59. uint64 val;
  60. asm volatile("mrs %0, fpcr" : "=r" (val));
  61. mPrevState = val;
  62. val &= ~Mask;
  63. val |= Value;
  64. asm volatile("msr fpcr, %0" : /* no output */ : "r" (val));
  65. }
  66. ~FPControlWord()
  67. {
  68. uint64 val;
  69. asm volatile("mrs %0, fpcr" : "=r" (val));
  70. val &= ~Mask;
  71. val |= mPrevState & Mask;
  72. asm volatile("msr fpcr, %0" : /* no output */ : "r" (val));
  73. }
  74. private:
  75. uint64 mPrevState;
  76. };
  77. #elif defined(JPH_CPU_ARM)
  78. /// Helper class that needs to be put on the stack to update the state of the floating point control word.
  79. /// This state is kept per thread.
  80. template <uint32 Value, uint32 Mask>
  81. class FPControlWord : public NonCopyable
  82. {
  83. public:
  84. FPControlWord()
  85. {
  86. uint32 val;
  87. asm volatile("vmrs %0, fpscr" : "=r" (val));
  88. mPrevState = val;
  89. val &= ~Mask;
  90. val |= Value;
  91. asm volatile("vmsr fpscr, %0" : /* no output */ : "r" (val));
  92. }
  93. ~FPControlWord()
  94. {
  95. uint32 val;
  96. asm volatile("vmrs %0, fpscr" : "=r" (val));
  97. val &= ~Mask;
  98. val |= mPrevState & Mask;
  99. asm volatile("vmsr fpscr, %0" : /* no output */ : "r" (val));
  100. }
  101. private:
  102. uint32 mPrevState;
  103. };
  104. #elif defined(JPH_CPU_WASM)
  105. // Not supported
  106. #else
  107. #error Unsupported CPU architecture
  108. #endif
  109. JPH_NAMESPACE_END