https://git.reactos.org/?p=reactos.git;a=commitdiff;h=554bbb6bab9279cec8583…
commit 554bbb6bab9279cec8583f1e6e8f05997de0af4a
Author: Roman Masanin <36927roma(a)gmail.com>
AuthorDate: Sun Aug 1 17:30:41 2021 +0300
Commit: Stanislav Motylkov <x86corez(a)gmail.com>
CommitDate: Wed Sep 8 16:04:48 2021 +0300
[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(-)
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(a)gmail.com>
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <kxarm.h>
+
+/* 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(a)gmail.com>
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <kxarm.h>
+
+/* 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(a)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(a)reactos.org)
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <kxarm.h>
-
-/* 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(a)gmail.com>
+ */
+
+#include <precomp.h>
+#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(a)reactos.org)
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <kxarm.h>
-
-/* 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(a)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(a)reactos.org)
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <kxarm.h>
-
-/* 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(a)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(a)reactos.org)
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <kxarm.h>
-
-/* 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(a)gmail.com>
+ */
+
+#include <float.h>
+
+#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()