[CRT] Fix amd64 floating point control functions

This commit is contained in:
Timo Kreuzer 2022-07-13 20:27:42 +02:00
parent 39f11249ff
commit 76086220fa
10 changed files with 243 additions and 32 deletions

View file

@ -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. */

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -1,15 +0,0 @@
#include <asm.inc>
.code64
PUBLIC _clearfp
FUNC _clearfp
.ENDPROLOG
fnclex
ENDFUNC
END

View file

@ -1,13 +0,0 @@
#include <asm.inc>
.code64
PUBLIC _fpreset
FUNC _fpreset
.endprolog
fninit
ret
ENDFUNC
END

View file

@ -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;
}

View file

@ -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")