https://git.reactos.org/?p=reactos.git;a=commitdiff;h=554bbb6bab9279cec8583f1e6e8f05997de0af4a

commit 554bbb6bab9279cec8583f1e6e8f05997de0af4a
Author:     Roman Masanin <[email protected]>
AuthorDate: Sun Aug 1 17:30:41 2021 +0300
Commit:     Stanislav Motylkov <[email protected]>
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 <[email protected]>
+ */
+
+/* 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 <[email protected]>
+ */
+
+/* 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 <[email protected]>
+ */
+
+#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 ([email protected])
- */
-
-/* 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 <[email protected]>
+ */
+
+#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 ([email protected])
- */
-
-/* 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 <[email protected]>
+ */
+
+#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 ([email protected])
- */
-
-/* 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 <[email protected]>
+ */
+
+#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 ([email protected])
- */
-
-/* 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 <[email protected]>
+ */
+
+#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()

Reply via email to