From 554bbb6bab9279cec8583f1e6e8f05997de0af4a Mon Sep 17 00:00:00 2001 From: Roman Masanin <36927roma@gmail.com> Date: Sun, 1 Aug 2021 17:30:41 +0300 Subject: [PATCH] [CRT/ARM] Floating point control functions implementation (#3870) Implement controlfp, statusfp, fpreset, clearfp. CORE-17757 CORE-17604 --- sdk/include/crt/float.h | 8 +++ sdk/lib/crt/float/arm/__getfp.s | 25 +++++++++ sdk/lib/crt/float/arm/__setfp.s | 25 +++++++++ sdk/lib/crt/float/arm/_clearfp.c | 22 ++++++++ sdk/lib/crt/float/arm/_clearfp.s | 24 --------- sdk/lib/crt/float/arm/_controlfp.c | 83 ++++++++++++++++++++++++++++++ sdk/lib/crt/float/arm/_controlfp.s | 24 --------- sdk/lib/crt/float/arm/_fpreset.c | 13 +++++ sdk/lib/crt/float/arm/_fpreset.s | 24 --------- sdk/lib/crt/float/arm/_statusfp.c | 24 +++++++++ sdk/lib/crt/float/arm/_statusfp.s | 24 --------- sdk/lib/crt/float/arm/fpscr.h | 41 +++++++++++++++ sdk/lib/crt/float/float.cmake | 12 +++-- 13 files changed, 249 insertions(+), 100 deletions(-) create mode 100644 sdk/lib/crt/float/arm/__getfp.s create mode 100644 sdk/lib/crt/float/arm/__setfp.s create mode 100644 sdk/lib/crt/float/arm/_clearfp.c delete mode 100644 sdk/lib/crt/float/arm/_clearfp.s create mode 100644 sdk/lib/crt/float/arm/_controlfp.c delete mode 100644 sdk/lib/crt/float/arm/_controlfp.s create mode 100644 sdk/lib/crt/float/arm/_fpreset.c delete mode 100644 sdk/lib/crt/float/arm/_fpreset.s create mode 100644 sdk/lib/crt/float/arm/_statusfp.c delete mode 100644 sdk/lib/crt/float/arm/_statusfp.s create mode 100644 sdk/lib/crt/float/arm/fpscr.h diff --git a/sdk/include/crt/float.h b/sdk/include/crt/float.h index cd3c191a4ed..b5681293421 100644 --- a/sdk/include/crt/float.h +++ b/sdk/include/crt/float.h @@ -77,6 +77,14 @@ #define _FPCLASS_PINF 0x0200 /* Positive Infinity */ #endif /* __MINGW_FPCLASS_DEFINED */ +/* _statusfp bit flags */ +#define _SW_INEXACT 0x00000001 /* inexact (precision) */ +#define _SW_UNDERFLOW 0x00000002 /* underflow */ +#define _SW_OVERFLOW 0x00000004 /* overflow */ +#define _SW_ZERODIVIDE 0x00000008 /* zero divide */ +#define _SW_INVALID 0x00000010 /* invalid */ +#define _SW_DENORMAL 0x00080000 /* denormal status bit */ + /* invalid subconditions (_SW_INVALID also set) */ #define _SW_UNEMULATED 0x0040 /* unemulated instruction */ #define _SW_SQRTNEG 0x0080 /* square root of a neg number */ diff --git a/sdk/lib/crt/float/arm/__getfp.s b/sdk/lib/crt/float/arm/__getfp.s new file mode 100644 index 00000000000..f55f966329a --- /dev/null +++ b/sdk/lib/crt/float/arm/__getfp.s @@ -0,0 +1,25 @@ +/* + * PROJECT: ReactOS CRT library + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: ARM fpscr getter + * COPYRIGHT: Copyright 2021 Roman Masanin <36927roma@gmail.com> + */ + +/* INCLUDES ******************************************************************/ + +#include + +/* CODE **********************************************************************/ + + TEXTAREA + + LEAF_ENTRY __getfp + + VMRS R0,FPSCR + + BX LR + + LEAF_END __getfp + + END +/* EOF */ diff --git a/sdk/lib/crt/float/arm/__setfp.s b/sdk/lib/crt/float/arm/__setfp.s new file mode 100644 index 00000000000..10491970adf --- /dev/null +++ b/sdk/lib/crt/float/arm/__setfp.s @@ -0,0 +1,25 @@ +/* + * PROJECT: ReactOS CRT library + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: ARM fpscr setter + * COPYRIGHT: Copyright 2021 Roman Masanin <36927roma@gmail.com> + */ + +/* INCLUDES ******************************************************************/ + +#include + +/* CODE **********************************************************************/ + + TEXTAREA + + LEAF_ENTRY __setfp + + VMSR FPSCR,R0 + + BX LR + + LEAF_END __setfp + + END +/* EOF */ diff --git a/sdk/lib/crt/float/arm/_clearfp.c b/sdk/lib/crt/float/arm/_clearfp.c new file mode 100644 index 00000000000..9b295e58900 --- /dev/null +++ b/sdk/lib/crt/float/arm/_clearfp.c @@ -0,0 +1,22 @@ +/* + * PROJECT: ReactOS CRT library + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: Implementation of _clearfp + * COPYRIGHT: Copyright 2021 Roman Masanin <36927roma@gmail.com> + */ + +#include "fpscr.h" + +unsigned int _clearfp(void) +{ + ARM_FPSCR fpscr; + unsigned int status; + + fpscr.raw = __getfp(); + status = _statusfp(); + + fpscr.data.exception = fpscr.data.exception & ~ARM_CW_STATUS_MASK; + + __setfp(fpscr.raw); + return status; +} diff --git a/sdk/lib/crt/float/arm/_clearfp.s b/sdk/lib/crt/float/arm/_clearfp.s deleted file mode 100644 index 25275fe1746..00000000000 --- a/sdk/lib/crt/float/arm/_clearfp.s +++ /dev/null @@ -1,24 +0,0 @@ -/* - * COPYRIGHT: BSD - See COPYING.ARM in the top level directory - * PROJECT: ReactOS CRT library - * PURPOSE: Implementation of _clearfp - * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#include - -/* CODE **********************************************************************/ - - TEXTAREA - - LEAF_ENTRY _clearfp - - __assertfail - bx lr - - LEAF_END _clearfp - - END -/* EOF */ diff --git a/sdk/lib/crt/float/arm/_controlfp.c b/sdk/lib/crt/float/arm/_controlfp.c new file mode 100644 index 00000000000..2c697841ea2 --- /dev/null +++ b/sdk/lib/crt/float/arm/_controlfp.c @@ -0,0 +1,83 @@ +/* + * PROJECT: ReactOS CRT library + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: Implementation of _controlfp + * COPYRIGHT: Copyright 2021 Roman Masanin <36927roma@gmail.com> + */ + +#include +#include "fpscr.h" + +unsigned int CDECL _controlfp(unsigned int newval, unsigned int mask) +{ + return _control87(newval, mask & ~_EM_DENORMAL); +} + +unsigned int CDECL _control87(unsigned int newval, unsigned int mask) +{ + ARM_FPSCR fpscr; + unsigned int flags = 0; + + TRACE("(%08x, %08x): Called\n", newval, mask); + + /* Get fp control word */ + fpscr.raw = __getfp(); + + TRACE("Control word before : %08x\n", fpscr.raw); + + /* Convert into mask constants */ + if (!(fpscr.data.ex_control & ARM_CW_IM)) flags |= _EM_INVALID; + if (!(fpscr.data.ex_control & ARM_CW_ZM)) flags |= _EM_ZERODIVIDE; + if (!(fpscr.data.ex_control & ARM_CW_OM)) flags |= _EM_OVERFLOW; + if (!(fpscr.data.ex_control & ARM_CW_UM)) flags |= _EM_UNDERFLOW; + if (!(fpscr.data.ex_control & ARM_CW_PM)) flags |= _EM_INEXACT; + if (!(fpscr.data.ex_control & ARM_CW_DM)) flags |= _EM_DENORMAL; + + switch (fpscr.data.rounding_mode) + { + case ARM_CW_RC_ZERO: flags |= _RC_UP|_RC_DOWN; break; + case ARM_CW_RC_UP: flags |= _RC_UP; break; + case ARM_CW_RC_DOWN: flags |= _RC_DOWN; break; + } + + /* Mask with parameters */ + flags = (flags & ~mask) | (newval & mask); + + /* Convert (masked) value back to fp word */ + fpscr.raw = 0; + if (!(flags & _EM_INVALID)) fpscr.data.ex_control |= ARM_CW_IM; + if (!(flags & _EM_ZERODIVIDE)) fpscr.data.ex_control |= ARM_CW_ZM; + if (!(flags & _EM_OVERFLOW)) fpscr.data.ex_control |= ARM_CW_OM; + if (!(flags & _EM_UNDERFLOW)) fpscr.data.ex_control |= ARM_CW_UM; + if (!(flags & _EM_INEXACT)) fpscr.data.ex_control |= ARM_CW_PM; + if (!(flags & _EM_DENORMAL)) fpscr.data.ex_control |= ARM_CW_DM; + + switch (flags & (_RC_UP | _RC_DOWN)) + { + case _RC_UP|_RC_DOWN: fpscr.data.rounding_mode = ARM_CW_RC_ZERO; break; + case _RC_UP: fpscr.data.rounding_mode = ARM_CW_RC_UP; break; + case _RC_DOWN: fpscr.data.rounding_mode = ARM_CW_RC_DOWN; break; + case _RC_NEAR: fpscr.data.rounding_mode = ARM_CW_RC_NEAREST; break; + } + + TRACE("Control word after : %08x\n", fpscr.raw); + + /* Put fp control word */ + __setfp(fpscr.raw); + + return flags; +} + +int CDECL _controlfp_s(unsigned int *cur, unsigned int newval, unsigned int mask) +{ + unsigned int val; + + if (!MSVCRT_CHECK_PMT( !(newval & mask & ~(_MCW_EM | _MCW_RC | _MCW_DN)) )) + { + if (cur) *cur = _controlfp(0, 0); /* retrieve it anyway */ + return EINVAL; + } + val = _controlfp(newval, mask); + if (cur) *cur = val; + return 0; +} diff --git a/sdk/lib/crt/float/arm/_controlfp.s b/sdk/lib/crt/float/arm/_controlfp.s deleted file mode 100644 index e7cbf13cb6e..00000000000 --- a/sdk/lib/crt/float/arm/_controlfp.s +++ /dev/null @@ -1,24 +0,0 @@ -/* - * COPYRIGHT: BSD - See COPYING.ARM in the top level directory - * PROJECT: ReactOS CRT library - * PURPOSE: Implementation of _controlfp - * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#include - -/* CODE **********************************************************************/ - - TEXTAREA - - LEAF_ENTRY _controlfp - - __assertfail - bx lr - - LEAF_END _controlfp - - END -/* EOF */ diff --git a/sdk/lib/crt/float/arm/_fpreset.c b/sdk/lib/crt/float/arm/_fpreset.c new file mode 100644 index 00000000000..3ddfad1fef6 --- /dev/null +++ b/sdk/lib/crt/float/arm/_fpreset.c @@ -0,0 +1,13 @@ +/* + * PROJECT: ReactOS CRT library + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: Implementation of _fpreset + * COPYRIGHT: Copyright 2021 Roman Masanin <36927roma@gmail.com> + */ + +#include "fpscr.h" + +void _fpreset(void) +{ + __setfp(0x0); +} diff --git a/sdk/lib/crt/float/arm/_fpreset.s b/sdk/lib/crt/float/arm/_fpreset.s deleted file mode 100644 index caba746d382..00000000000 --- a/sdk/lib/crt/float/arm/_fpreset.s +++ /dev/null @@ -1,24 +0,0 @@ -/* - * COPYRIGHT: BSD - See COPYING.ARM in the top level directory - * PROJECT: ReactOS CRT library - * PURPOSE: Implementation of _fpreset - * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#include - -/* CODE **********************************************************************/ - - TEXTAREA - - LEAF_ENTRY _fpreset - - __assertfail - bx lr - - LEAF_END _fpreset - - END -/* EOF */ diff --git a/sdk/lib/crt/float/arm/_statusfp.c b/sdk/lib/crt/float/arm/_statusfp.c new file mode 100644 index 00000000000..553b8241370 --- /dev/null +++ b/sdk/lib/crt/float/arm/_statusfp.c @@ -0,0 +1,24 @@ +/* + * PROJECT: ReactOS CRT library + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: Implementation of _statusfp + * COPYRIGHT: Copyright 2021 Roman Masanin <36927roma@gmail.com> + */ + +#include "fpscr.h" + +unsigned int _statusfp(void) +{ + unsigned int flags = 0; + ARM_FPSCR fpscr; + + fpscr.raw = __getfp(); + + if (fpscr.data.exception & ARM_CW_IM) flags |= _SW_INVALID; + if (fpscr.data.exception & ARM_CW_ZM) flags |= _SW_ZERODIVIDE; + if (fpscr.data.exception & ARM_CW_OM) flags |= _SW_OVERFLOW; + if (fpscr.data.exception & ARM_CW_UM) flags |= _SW_UNDERFLOW; + if (fpscr.data.exception & ARM_CW_PM) flags |= _SW_INEXACT; + if (fpscr.data.exception & ARM_CW_DM) flags |= _SW_DENORMAL; + return flags; +} diff --git a/sdk/lib/crt/float/arm/_statusfp.s b/sdk/lib/crt/float/arm/_statusfp.s deleted file mode 100644 index 1c810985f3e..00000000000 --- a/sdk/lib/crt/float/arm/_statusfp.s +++ /dev/null @@ -1,24 +0,0 @@ -/* - * COPYRIGHT: BSD - See COPYING.ARM in the top level directory - * PROJECT: ReactOS CRT library - * PURPOSE: Implementation of _statusfp - * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#include - -/* CODE **********************************************************************/ - - TEXTAREA - - LEAF_ENTRY _statusfp - - __assertfail - bx lr - - LEAF_END _statusfp - - END -/* EOF */ diff --git a/sdk/lib/crt/float/arm/fpscr.h b/sdk/lib/crt/float/arm/fpscr.h new file mode 100644 index 00000000000..a3ddd1d9eed --- /dev/null +++ b/sdk/lib/crt/float/arm/fpscr.h @@ -0,0 +1,41 @@ +/* + * PROJECT: ReactOS CRT library + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: Headers for ARM fpcsr + * COPYRIGHT: Copyright 2021 Roman Masanin <36927roma@gmail.com> + */ + +#include + +#define ARM_CW_STATUS_MASK 0x9F +#define ARM_CW_IM (1 << 0) /* Invalid operation mask */ +#define ARM_CW_ZM (1 << 1) /* Zero divide mask */ +#define ARM_CW_OM (1 << 2) /* Overflow mask */ +#define ARM_CW_UM (1 << 3) /* Underflow mask */ +#define ARM_CW_PM (1 << 4) /* Precision mask */ +#define ARM_CW_DM (1 << 7) /* Denormal operand mask */ + +#define ARM_CW_RC_NEAREST 0 /* round to nearest */ +#define ARM_CW_RC_UP 1 /* round up */ +#define ARM_CW_RC_DOWN 2 /* round down */ +#define ARM_CW_RC_ZERO 3 /* round toward zero (chop) */ + +typedef union _ARM_FPSCR +{ + unsigned int raw; + struct + { + unsigned int exception: 8; + unsigned int ex_control: 8; + unsigned int len: 3; + unsigned int unused3: 1; + unsigned int stride: 2; + unsigned int rounding_mode: 2; + unsigned int flush_to_zero: 1; + unsigned int unused4: 3; + unsigned int status_flag: 4; + } data; +} ARM_FPSCR; + +void __setfp(unsigned int); +unsigned int __getfp(void); diff --git a/sdk/lib/crt/float/float.cmake b/sdk/lib/crt/float/float.cmake index 5693f11e186..8f16c995a09 100644 --- a/sdk/lib/crt/float/float.cmake +++ b/sdk/lib/crt/float/float.cmake @@ -33,10 +33,14 @@ elseif(ARCH STREQUAL "amd64") float/amd64/logb.S ) elseif(ARCH STREQUAL "arm") + list(APPEND CRT_FLOAT_SOURCE + float/arm/_clearfp.c + float/arm/_controlfp.c + float/arm/_fpreset.c + float/arm/_statusfp.c + ) list(APPEND CRT_FLOAT_ASM_SOURCE - float/arm/_clearfp.s - float/arm/_controlfp.s - float/arm/_fpreset.s - float/arm/_statusfp.s + float/arm/__getfp.s + float/arm/__setfp.s ) endif()