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