x64FPURoundMode.cpp 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. // Copyright 2013 Dolphin Emulator Project
  2. // Licensed under GPLv2+
  3. // Refer to the license.txt file included.
  4. #include <cfenv>
  5. #include "Common/CommonTypes.h"
  6. #include "Common/CPUDetect.h"
  7. #include "Common/FPURoundMode.h"
  8. #include "Common/Intrinsics.h"
  9. namespace FPURoundMode
  10. {
  11. // Get the default SSE states here.
  12. static u32 saved_sse_state = _mm_getcsr();
  13. static const u32 default_sse_state = _mm_getcsr();
  14. void SetRoundMode(int mode)
  15. {
  16. // Convert PowerPC to native rounding mode.
  17. static const int rounding_mode_lut[] = {
  18. FE_TONEAREST,
  19. FE_TOWARDZERO,
  20. FE_UPWARD,
  21. FE_DOWNWARD
  22. };
  23. fesetround(rounding_mode_lut[mode]);
  24. }
  25. void SetPrecisionMode(PrecisionMode /* mode */)
  26. {
  27. //x64 doesn't need this - fpu is done with SSE
  28. }
  29. void SetSIMDMode(int rounding_mode, bool non_ieee_mode)
  30. {
  31. // OR-mask for disabling FPU exceptions (bits 7-12 in the MXCSR register)
  32. const u32 EXCEPTION_MASK = 0x1F80;
  33. // Flush-To-Zero (non-IEEE mode: denormal outputs are set to +/- 0)
  34. const u32 FTZ = 0x8000;
  35. // lookup table for FPSCR.RN-to-MXCSR.RC translation
  36. static const u32 simd_rounding_table[] =
  37. {
  38. (0 << 13) | EXCEPTION_MASK, // nearest
  39. (3 << 13) | EXCEPTION_MASK, // -inf
  40. (2 << 13) | EXCEPTION_MASK, // +inf
  41. (1 << 13) | EXCEPTION_MASK, // zero
  42. };
  43. u32 csr = simd_rounding_table[rounding_mode];
  44. if (non_ieee_mode)
  45. {
  46. csr |= FTZ;
  47. }
  48. _mm_setcsr(csr);
  49. }
  50. void SaveSIMDState()
  51. {
  52. saved_sse_state = _mm_getcsr();
  53. }
  54. void LoadSIMDState()
  55. {
  56. _mm_setcsr(saved_sse_state);
  57. }
  58. void LoadDefaultSIMDState()
  59. {
  60. _mm_setcsr(default_sse_state);
  61. }
  62. }