xref: /reactos/sdk/lib/crt/float/amd64/machfpcw.c (revision e944dfa7)
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