1 /* 2 * PROJECT: ReactOS CRT 3 * LICENSE: MIT (https://spdx.org/licenses/MIT) 4 * PURPOSE: Implementation of x64 floating point control word helper functions 5 * COPYRIGHT: Copyright 2022 Timo Kreuzer <timo.kreuzer@reactos.org> 6 */ 7 8 #include <float.h> 9 #include <xmmintrin.h> 10 11 #define _MM_DENORMALS_ARE_ZERO 0x0040 12 13 unsigned int _get_native_fpcw(void) 14 { 15 return _mm_getcsr(); 16 } 17 18 void _set_native_fpcw(unsigned int value) 19 { 20 _mm_setcsr(value); 21 } 22 23 unsigned int _fpcw_native_to_abstract(unsigned int native) 24 { 25 unsigned int rounding_mask, abstract = 0; 26 27 /* Handle exception mask */ 28 if (native & _MM_MASK_INVALID) 29 abstract |= _EM_INVALID; 30 if (native & _MM_MASK_DENORM) 31 abstract |= _EM_DENORMAL; 32 if (native & _MM_MASK_DIV_ZERO) 33 abstract |= _EM_ZERODIVIDE; 34 if (native & _MM_MASK_OVERFLOW) 35 abstract |= _EM_OVERFLOW; 36 if (native & _MM_MASK_UNDERFLOW) 37 abstract |= _EM_UNDERFLOW; 38 if (native & _MM_MASK_INEXACT) 39 abstract |= _EM_INEXACT; 40 41 /* Handle rounding mode */ 42 rounding_mask = (native & _MM_ROUND_MASK); 43 if (rounding_mask == _MM_ROUND_DOWN) 44 abstract |= _RC_DOWN; 45 else if(rounding_mask == _MM_ROUND_UP) 46 abstract |= _RC_UP; 47 else if (rounding_mask == _MM_ROUND_TOWARD_ZERO) 48 abstract |= _RC_CHOP; 49 50 /* Handle denormal control */ 51 if (native & _MM_DENORMALS_ARE_ZERO) 52 { 53 if (native & _MM_FLUSH_ZERO_MASK) 54 abstract |= _DN_FLUSH; 55 else 56 abstract |= _DN_FLUSH_OPERANDS_SAVE_RESULTS; 57 } 58 else 59 { 60 if (native & _MM_FLUSH_ZERO_MASK) 61 abstract |= _DN_SAVE_OPERANDS_FLUSH_RESULTS; 62 else 63 abstract |= _DN_SAVE; 64 } 65 66 return abstract; 67 } 68 69 unsigned int _fpcw_abstract_to_native(unsigned int abstract) 70 { 71 unsigned int rounding_mask, native = 0; 72 73 /* Handle exception mask */ 74 if (abstract & _EM_INVALID) 75 native |= _MM_MASK_INVALID; 76 if (abstract & _EM_DENORMAL) 77 native |= _MM_MASK_DENORM; 78 if (abstract & _EM_ZERODIVIDE) 79 native |= _MM_MASK_DIV_ZERO; 80 if (abstract & _EM_OVERFLOW) 81 native |= _MM_MASK_OVERFLOW; 82 if (abstract & _EM_UNDERFLOW) 83 native |= _MM_MASK_UNDERFLOW; 84 if (abstract & _EM_INEXACT) 85 native |= _MM_MASK_INEXACT; 86 87 /* Handle rounding mode */ 88 rounding_mask = (abstract & _MCW_RC); 89 if (rounding_mask == _RC_DOWN) 90 native |= _MM_ROUND_DOWN; 91 else if (rounding_mask == _RC_UP) 92 native |= _MM_ROUND_UP; 93 else if (rounding_mask == _RC_CHOP) 94 native |= _MM_ROUND_TOWARD_ZERO; 95 96 /* Handle Denormal Control */ 97 if ((abstract & _MCW_DN) == _DN_FLUSH) 98 { 99 native |= _MM_DENORMALS_ARE_ZERO | _MM_FLUSH_ZERO_MASK; 100 } 101 else if ((abstract & _MCW_DN) == _DN_FLUSH_OPERANDS_SAVE_RESULTS) 102 { 103 native |= _MM_DENORMALS_ARE_ZERO; 104 } 105 else if ((abstract & _MCW_DN) == _DN_SAVE_OPERANDS_FLUSH_RESULTS) 106 { 107 native |= _MM_FLUSH_ZERO_MASK; 108 } 109 110 return native; 111 } 112