https://git.reactos.org/?p=reactos.git;a=commitdiff;h=76086220fa4c0d8a7e7ac…
commit 76086220fa4c0d8a7e7ac88cf1d01cdbeb445df5
Author: Timo Kreuzer <timo.kreuzer(a)reactos.org>
AuthorDate: Wed Jul 13 20:27:42 2022 +0200
Commit: Timo Kreuzer <timo.kreuzer(a)reactos.org>
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 <timo.kreuzer(a)reactos.org>
+ */
+
+#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 <timo.kreuzer(a)reactos.org>
+ */
+
+#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 <timo.kreuzer(a)reactos.org>
+ */
+
+#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 <timo.kreuzer(a)reactos.org>
+ */
+
+#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 <timo.kreuzer(a)reactos.org>
+ */
+
+#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 <timo.kreuzer(a)reactos.org>
+ */
+
+#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")