https://git.reactos.org/?p=reactos.git;a=commitdiff;h=76086220fa4c0d8a7e7ac88cf1d01cdbeb445df5

commit 76086220fa4c0d8a7e7ac88cf1d01cdbeb445df5
Author:     Timo Kreuzer <[email protected]>
AuthorDate: Wed Jul 13 20:27:42 2022 +0200
Commit:     Timo Kreuzer <[email protected]>
CommitDate: Mon Aug 22 11:22:08 2022 +0200

    [CRT] Fix amd64 floating point control functions
---
 sdk/include/crt/float.h              |   4 ++
 sdk/lib/crt/float/amd64/_clearfp.c   |  23 ++++++++
 sdk/lib/crt/float/amd64/_control87.c |  39 ++++++++++++
 sdk/lib/crt/float/amd64/_controlfp.c |  13 ++++
 sdk/lib/crt/float/amd64/_fpreset.c   |  14 +++++
 sdk/lib/crt/float/amd64/_statusfp.c  |  33 +++++++++++
 sdk/lib/crt/float/amd64/clearfp.S    |  15 -----
 sdk/lib/crt/float/amd64/fpreset.S    |  13 ----
 sdk/lib/crt/float/amd64/machfpcw.c   | 111 +++++++++++++++++++++++++++++++++++
 sdk/lib/crt/float/float.cmake        |  10 ++--
 10 files changed, 243 insertions(+), 32 deletions(-)

diff --git a/sdk/include/crt/float.h b/sdk/include/crt/float.h
index b5681293421..8c42b3f9d04 100644
--- a/sdk/include/crt/float.h
+++ b/sdk/include/crt/float.h
@@ -59,6 +59,10 @@
 #define        _PC_24          0x00020000
 #define        _PC_53          0x00010000
 #define        _PC_64          0x00000000
+#define _DN_SAVE       0x00000000
+#define _DN_FLUSH      0x01000000
+#define _DN_FLUSH_OPERANDS_SAVE_RESULTS 0x02000000
+#define _DN_SAVE_OPERANDS_FLUSH_RESULTS 0x03000000
 
 /* These are also defined in Mingw math.h, needed to work around
    GCC build issues.  */
diff --git a/sdk/lib/crt/float/amd64/_clearfp.c 
b/sdk/lib/crt/float/amd64/_clearfp.c
new file mode 100644
index 00000000000..b03b3f10f79
--- /dev/null
+++ b/sdk/lib/crt/float/amd64/_clearfp.c
@@ -0,0 +1,23 @@
+/*
+ * PROJECT:     ReactOS CRT
+ * LICENSE:     MIT (https://spdx.org/licenses/MIT)
+ * PURPOSE:     x64 implementation of _clearfp
+ * COPYRIGHT:   Copyright 2022 Timo Kreuzer <[email protected]>
+ */
+
+#include <float.h>
+#include <xmmintrin.h>
+
+unsigned int __cdecl _clearfp(void)
+{
+    unsigned int retval;
+
+    /* Get current status value */
+    retval = _statusfp();
+
+    /* Clear the exception mask */
+    _mm_setcsr(_mm_getcsr() & ~_MM_EXCEPT_MASK);
+   
+    /* Return the previous state */
+    return retval;
+}
diff --git a/sdk/lib/crt/float/amd64/_control87.c 
b/sdk/lib/crt/float/amd64/_control87.c
new file mode 100644
index 00000000000..a9f07cf0836
--- /dev/null
+++ b/sdk/lib/crt/float/amd64/_control87.c
@@ -0,0 +1,39 @@
+/*
+ * PROJECT:     ReactOS CRT
+ * LICENSE:     MIT (https://spdx.org/licenses/MIT)
+ * PURPOSE:     Implementation of _control87
+ * COPYRIGHT:   Copyright 2022 Timo Kreuzer <[email protected]>
+ */
+
+#include <xmmintrin.h>
+#include <float.h>
+
+unsigned int _get_native_fpcw(void);
+void _set_native_fpcw(unsigned int value);
+unsigned int _fpcw_native_to_abstract(unsigned int native);
+unsigned int _fpcw_abstract_to_native(unsigned int abstract);
+
+unsigned int __cdecl _control87(unsigned int newval, unsigned int mask)
+{
+    unsigned int native, oldval, updated;
+
+    /* Sanatize the mask */
+    mask &= _MCW_DN | _MCW_EM | _MCW_RC;
+
+    /* Get native control word */
+    native = _get_native_fpcw();
+
+    /* Convert to abstract */
+    oldval = _fpcw_native_to_abstract(native);
+
+    /* Update it according to the given parameters */
+    updated = (oldval & ~mask) | (newval & mask);
+
+    /* Convert back to native */
+    native = _fpcw_abstract_to_native(updated);
+
+    /* Set the native value */
+    _set_native_fpcw(native);
+
+    return updated;
+}
diff --git a/sdk/lib/crt/float/amd64/_controlfp.c 
b/sdk/lib/crt/float/amd64/_controlfp.c
new file mode 100644
index 00000000000..f0ac11548ab
--- /dev/null
+++ b/sdk/lib/crt/float/amd64/_controlfp.c
@@ -0,0 +1,13 @@
+/*
+ * PROJECT:     ReactOS CRT
+ * LICENSE:     MIT (https://spdx.org/licenses/MIT)
+ * PURPOSE:     x64 implementation of _controlfp
+ * COPYRIGHT:   Copyright 2022 Timo Kreuzer <[email protected]>
+ */
+
+#include <float.h>
+
+unsigned int __cdecl _controlfp(unsigned int newval, unsigned int mask)
+{
+    return _control87(newval, mask & ~_EM_DENORMAL);
+}
diff --git a/sdk/lib/crt/float/amd64/_fpreset.c 
b/sdk/lib/crt/float/amd64/_fpreset.c
new file mode 100644
index 00000000000..b03885527a9
--- /dev/null
+++ b/sdk/lib/crt/float/amd64/_fpreset.c
@@ -0,0 +1,14 @@
+/*
+ * PROJECT:     ReactOS CRT
+ * LICENSE:     MIT (https://spdx.org/licenses/MIT)
+ * PURPOSE:     x64 implementation of _fpreset
+ * COPYRIGHT:   Copyright 2022 Timo Kreuzer <[email protected]>
+ */
+
+#include <xmmintrin.h>
+
+void __cdecl _fpreset(void)
+{
+    /* Mask everything */
+    _mm_setcsr(_MM_MASK_MASK);
+}
diff --git a/sdk/lib/crt/float/amd64/_statusfp.c 
b/sdk/lib/crt/float/amd64/_statusfp.c
new file mode 100644
index 00000000000..760e9bfe4be
--- /dev/null
+++ b/sdk/lib/crt/float/amd64/_statusfp.c
@@ -0,0 +1,33 @@
+/*
+ * PROJECT:     ReactOS CRT
+ * LICENSE:     MIT (https://spdx.org/licenses/MIT)
+ * PURPOSE:     x64 implementation of _statusfp
+ * COPYRIGHT:   Copyright 2022 Timo Kreuzer <[email protected]>
+ */
+
+#include <float.h>
+#include <xmmintrin.h>
+
+unsigned int __cdecl _statusfp(void)
+{
+    unsigned int mxcsr, status = 0;
+
+    /* Get MXCSR */
+    mxcsr = _mm_getcsr();
+
+    /* Convert to abstract status flags */
+    if (mxcsr & _MM_EXCEPT_INVALID)
+        status |= _SW_INVALID;
+    if (mxcsr & _MM_EXCEPT_DENORM)
+        status |= _SW_DENORMAL;
+    if (mxcsr & _MM_EXCEPT_DIV_ZERO)
+        status |= _SW_ZERODIVIDE;
+    if (mxcsr & _MM_EXCEPT_OVERFLOW)
+        status |= _SW_OVERFLOW;
+    if (mxcsr & _MM_EXCEPT_UNDERFLOW)
+        status |= _SW_UNDERFLOW;
+    if (mxcsr & _MM_EXCEPT_INEXACT)
+        status |= _SW_INEXACT;
+
+    return status;
+}
diff --git a/sdk/lib/crt/float/amd64/clearfp.S 
b/sdk/lib/crt/float/amd64/clearfp.S
deleted file mode 100644
index 2df94a9b383..00000000000
--- a/sdk/lib/crt/float/amd64/clearfp.S
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-#include <asm.inc>
-
-.code64
-
-PUBLIC _clearfp
-FUNC _clearfp
-    .ENDPROLOG
-    fnclex
-
-ENDFUNC
-
-END
diff --git a/sdk/lib/crt/float/amd64/fpreset.S 
b/sdk/lib/crt/float/amd64/fpreset.S
deleted file mode 100644
index bae9ed4c856..00000000000
--- a/sdk/lib/crt/float/amd64/fpreset.S
+++ /dev/null
@@ -1,13 +0,0 @@
-
-#include <asm.inc>
-
-.code64
-
-PUBLIC _fpreset
-FUNC _fpreset
-    .endprolog
-    fninit
-    ret
-ENDFUNC
-
-END
diff --git a/sdk/lib/crt/float/amd64/machfpcw.c 
b/sdk/lib/crt/float/amd64/machfpcw.c
new file mode 100644
index 00000000000..f74c7c5e1d9
--- /dev/null
+++ b/sdk/lib/crt/float/amd64/machfpcw.c
@@ -0,0 +1,111 @@
+/*
+ * PROJECT:     ReactOS CRT
+ * LICENSE:     MIT (https://spdx.org/licenses/MIT)
+ * PURPOSE:     Implementation of x64 floating point control word helper 
functions
+ * COPYRIGHT:   Copyright 2022 Timo Kreuzer <[email protected]>
+ */
+
+#include <float.h>
+#include <xmmintrin.h>
+
+#define _MM_DENORMALS_ARE_ZERO 0x0040
+
+unsigned int _get_native_fpcw(void)
+{
+    return _mm_getcsr();
+}
+
+void _set_native_fpcw(unsigned int value)
+{
+    _mm_setcsr(value);
+}
+
+unsigned int _fpcw_native_to_abstract(unsigned int native)
+{
+    unsigned int rounding_mask, abstract = 0;
+
+    /* Handle exception mask */
+    if (native & _MM_MASK_INVALID)
+        abstract |= _EM_INVALID;
+    if (native & _MM_MASK_DENORM)
+        abstract |= _EM_DENORMAL;
+    if (native & _MM_MASK_DIV_ZERO)
+        abstract |= _EM_ZERODIVIDE;
+    if (native & _MM_MASK_OVERFLOW)
+        abstract |= _EM_OVERFLOW;
+    if (native & _MM_MASK_UNDERFLOW)
+        abstract |= _EM_UNDERFLOW;
+    if (native & _MM_MASK_INEXACT)
+        abstract |= _EM_INEXACT;
+
+    /* Handle rounding mode */
+    rounding_mask = (native & _MM_ROUND_MASK);
+    if (rounding_mask == _MM_ROUND_DOWN)
+        abstract |= _RC_DOWN;
+    else if(rounding_mask == _MM_ROUND_UP)
+        abstract |= _RC_UP;
+    else if (rounding_mask == _MM_ROUND_TOWARD_ZERO)
+        abstract |= _RC_CHOP;
+
+    /* Handle denormal control */
+    if (native & _MM_DENORMALS_ARE_ZERO)
+    {
+        if (native & _MM_FLUSH_ZERO_MASK)
+            abstract |= _DN_FLUSH;
+        else
+            abstract |= _DN_FLUSH_OPERANDS_SAVE_RESULTS;
+    }
+    else
+    {
+        if (native & _MM_FLUSH_ZERO_MASK)
+            abstract |= _DN_SAVE_OPERANDS_FLUSH_RESULTS;
+        else
+            abstract |= _DN_SAVE;
+    }
+
+    return abstract;
+}
+
+unsigned int _fpcw_abstract_to_native(unsigned int abstract)
+{
+    unsigned int rounding_mask, native = 0;
+
+    /* Handle exception mask */
+    if (abstract & _EM_INVALID)
+        native |= _MM_MASK_INVALID;
+    if (abstract & _EM_DENORMAL)
+        native |= _MM_MASK_DENORM;
+    if (abstract & _EM_ZERODIVIDE)
+        native |= _MM_MASK_DIV_ZERO;
+    if (abstract & _EM_OVERFLOW)
+        native |= _MM_MASK_OVERFLOW;
+    if (abstract & _EM_UNDERFLOW)
+        native |= _MM_MASK_UNDERFLOW;
+    if (abstract & _EM_INEXACT)
+        native |= _MM_MASK_INEXACT;
+
+    /* Handle rounding mode */
+    rounding_mask = (abstract & _MCW_RC);
+    if (rounding_mask == _RC_DOWN)
+        native |= _MM_ROUND_DOWN;
+    else if (rounding_mask == _RC_UP)
+        native |= _MM_ROUND_UP;
+    else if (rounding_mask == _RC_CHOP)
+        native |= _MM_ROUND_TOWARD_ZERO;
+
+    /* Handle Denormal Control */
+    if ((abstract & _MCW_DN) == _DN_FLUSH)
+    {
+        native |= _MM_DENORMALS_ARE_ZERO | _MM_FLUSH_ZERO_MASK;
+    }
+    else if ((abstract & _MCW_DN) == _DN_FLUSH_OPERANDS_SAVE_RESULTS)
+    {
+        native |= _MM_DENORMALS_ARE_ZERO;
+    }
+    else if ((abstract & _MCW_DN) == _DN_SAVE_OPERANDS_FLUSH_RESULTS)
+    {
+        native |= _MM_FLUSH_ZERO_MASK;
+    }
+
+    return native;
+}
diff --git a/sdk/lib/crt/float/float.cmake b/sdk/lib/crt/float/float.cmake
index 8f16c995a09..e4189362f64 100644
--- a/sdk/lib/crt/float/float.cmake
+++ b/sdk/lib/crt/float/float.cmake
@@ -23,13 +23,15 @@ if(ARCH STREQUAL "i386")
     )
 elseif(ARCH STREQUAL "amd64")
     list(APPEND CRT_FLOAT_SOURCE
-        float/i386/cntrlfp.c
-        float/i386/statfp.c
+        float/amd64/_clearfp.c
+        float/amd64/_control87.c
+        float/amd64/_controlfp.c
+        float/amd64/_fpreset.c
+        float/amd64/_statusfp.c
+        float/amd64/machfpcw.c
     )
     list(APPEND CRT_FLOAT_ASM_SOURCE
-        float/amd64/clearfp.S
         float/amd64/getsetfpcw.S
-        float/amd64/fpreset.S
         float/amd64/logb.S
     )
 elseif(ARCH STREQUAL "arm")

Reply via email to