[PATCH 2/3] msvcrt: Implement fesetenv for arm64

Martin Storsjö martin at martin.st
Wed Aug 4 05:21:26 CDT 2021


This uses _control87 for setting the control bits, and implements
the mirror operation of _statusfp.

Fix the implementation of fenv_encode for non-x86 architectures to
not do the x87/sse bit duplication.

Signed-off-by: Martin Storsjö <martin at martin.st>
---
This uses fenv_decode for consistency with the other codepaths, even
if it's a no-op on this architecture.
---
 dlls/msvcrt/math.c | 32 +++++++++++++++++++++++++++-----
 1 file changed, 27 insertions(+), 5 deletions(-)

diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c
index 2ba810a9903..6f98d2ffaff 100644
--- a/dlls/msvcrt/math.c
+++ b/dlls/msvcrt/math.c
@@ -5626,7 +5626,7 @@ int CDECL _controlfp_s(unsigned int *cur, unsigned int newval, unsigned int mask
     return 0;
 }
 
-#if _MSVCR_VER >= 140
+#if _MSVCR_VER >= 140 && (defined(__i386__) || defined(__x86_64__))
 enum fenv_masks
 {
     FENV_X_INVALID = 0x00100010,
@@ -5689,7 +5689,6 @@ static __msvcrt_ulong fenv_encode(unsigned int x, unsigned int y)
 }
 
 /* decodes x87/sse control/status word, returns FALSE on error */
-#if (defined(__i386__) || defined(__x86_64__))
 static BOOL fenv_decode(__msvcrt_ulong enc, unsigned int *x, unsigned int *y)
 {
     *x = *y = 0;
@@ -5723,21 +5722,18 @@ static BOOL fenv_decode(__msvcrt_ulong enc, unsigned int *x, unsigned int *y)
     }
     return TRUE;
 }
-#endif
 #elif _MSVCR_VER >= 120
 static __msvcrt_ulong fenv_encode(unsigned int x, unsigned int y)
 {
     return x | y;
 }
 
-#if (defined(__i386__) || defined(__x86_64__))
 static BOOL fenv_decode(__msvcrt_ulong enc, unsigned int *x, unsigned int *y)
 {
     *x = *y = enc;
     return TRUE;
 }
 #endif
-#endif
 
 #if _MSVCR_VER>=120
 /*********************************************************************
@@ -6038,6 +6034,32 @@ int CDECL fesetenv(const fenv_t *env)
         __asm__ __volatile__( "ldmxcsr %0" : : "m" (fpword) );
     }
 
+    return 0;
+#elif defined(__aarch64__)
+    ULONG_PTR fpsr;
+    unsigned int unused_cw, fp_cw, unused_stat, fp_stat;
+
+    if (!env->_Fe_ctl && !env->_Fe_stat) {
+        _fpreset();
+        return 0;
+    }
+
+    if (!fenv_decode(env->_Fe_ctl, &unused_cw, &fp_cw))
+        return 1;
+    if (!fenv_decode(env->_Fe_stat, &unused_stat, &fp_stat))
+        return 1;
+
+    _control87(fp_cw, 0xffffffff);
+
+    __asm__ __volatile__( "mrs %0, fpsr" : "=r" (fpsr) );
+    fpsr &= ~0x9f;
+    if (fp_stat & _SW_INVALID)    fpsr |= 0x1;
+    if (fp_stat & _SW_ZERODIVIDE) fpsr |= 0x2;
+    if (fp_stat & _SW_OVERFLOW)   fpsr |= 0x4;
+    if (fp_stat & _SW_UNDERFLOW)  fpsr |= 0x8;
+    if (fp_stat & _SW_INEXACT)    fpsr |= 0x10;
+    if (fp_stat & _SW_DENORMAL)   fpsr |= 0x80;
+    __asm__ __volatile__( "msr fpsr, %0" :: "r" (fpsr) );
     return 0;
 #else
     FIXME( "not implemented\n" );
-- 
2.25.1




More information about the wine-devel mailing list