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