Piotr Caban : msvcrt: Introduce _setfp helper on aarch64.

Alexandre Julliard julliard at winehq.org
Wed Aug 4 16:41:38 CDT 2021


Module: wine
Branch: master
Commit: 63f3f4283f89366d8c83857e4c93666fa60ac73b
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=63f3f4283f89366d8c83857e4c93666fa60ac73b

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Wed Aug  4 18:05:06 2021 +0200

msvcrt: Introduce _setfp helper on aarch64.

Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/msvcrt/math.c | 169 +++++++++++++++++++++++++++--------------------------
 1 file changed, 85 insertions(+), 84 deletions(-)

diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c
index b27b6391a6f..ff945ff4bae 100644
--- a/dlls/msvcrt/math.c
+++ b/dlls/msvcrt/math.c
@@ -5235,7 +5235,7 @@ static BOOL _setfp_sse( unsigned int *cw, unsigned int cw_mask,
 }
 #endif
 
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
 static BOOL _setfp( unsigned int *cw, unsigned int cw_mask,
         unsigned int *sw, unsigned int sw_mask )
 {
@@ -5355,6 +5355,86 @@ static BOOL _setfp( unsigned int *cw, unsigned int cw_mask,
     return TRUE;
 #elif defined(__x86_64__)
     return _setfp_sse(cw, cw_mask, sw, sw_mask);
+#elif defined(__aarch64__)
+    ULONG_PTR old_fpsr = 0, fpsr = 0, old_fpcr = 0, fpcr = 0;
+    unsigned int flags;
+
+    cw_mask &= _MCW_EM | _MCW_RC;
+    sw_mask &= _MCW_EM;
+
+    if (sw)
+    {
+        __asm__ __volatile__( "mrs %0, fpsr" : "=r" (fpsr) );
+        old_fpsr = fpsr;
+
+        flags = 0;
+        if (fpsr & 0x1) flags |= _SW_INVALID;
+        if (fpsr & 0x2) flags |= _SW_ZERODIVIDE;
+        if (fpsr & 0x4) flags |= _SW_OVERFLOW;
+        if (fpsr & 0x8) flags |= _SW_UNDERFLOW;
+        if (fpsr & 0x10) flags |= _SW_INEXACT;
+        if (fpsr & 0x80) flags |= _SW_DENORMAL;
+
+        *sw = (flags & ~sw_mask) | (*sw & sw_mask);
+        TRACE("aarch64 update sw %08x to %08x\n", flags, *sw);
+        fpsr &= ~0x9f;
+        if (*sw & _SW_INVALID) fpsr |= 0x1;
+        if (*sw & _SW_ZERODIVIDE) fpsr |= 0x2;
+        if (*sw & _SW_OVERFLOW) fpsr |= 0x4;
+        if (*sw & _SW_UNDERFLOW) fpsr |= 0x8;
+        if (*sw & _SW_INEXACT) fpsr |= 0x10;
+        if (*sw & _SW_DENORMAL) fpsr |= 0x80;
+        *sw = flags;
+    }
+
+    if (cw)
+    {
+        __asm__ __volatile__( "mrs %0, fpcr" : "=r" (fpcr) );
+        old_fpcr = fpcr;
+
+        flags = 0;
+        if (!(fpcr & 0x100)) flags |= _EM_INVALID;
+        if (!(fpcr & 0x200)) flags |= _EM_ZERODIVIDE;
+        if (!(fpcr & 0x400)) flags |= _EM_OVERFLOW;
+        if (!(fpcr & 0x800)) flags |= _EM_UNDERFLOW;
+        if (!(fpcr & 0x1000)) flags |= _EM_INEXACT;
+        if (!(fpcr & 0x8000)) flags |= _EM_DENORMAL;
+        switch (fpcr & 0xc00000)
+        {
+        case 0x400000: flags |= _RC_UP; break;
+        case 0x800000: flags |= _RC_DOWN; break;
+        case 0xc00000: flags |= _RC_CHOP; break;
+        }
+
+        *cw = (flags & ~cw_mask) | (*cw & cw_mask);
+        TRACE("aarch64 update cw %08x to %08x\n", flags, *cw);
+        fpcr &= ~0xc09f00ul;
+        if (!(*cw & _EM_INVALID)) fpcr |= 0x100;
+        if (!(*cw & _EM_ZERODIVIDE)) fpcr |= 0x200;
+        if (!(*cw & _EM_OVERFLOW)) fpcr |= 0x400;
+        if (!(*cw & _EM_UNDERFLOW)) fpcr |= 0x800;
+        if (!(*cw & _EM_INEXACT)) fpcr |= 0x1000;
+        if (!(*cw & _EM_DENORMAL)) fpcr |= 0x8000;
+        switch (*cw & _MCW_RC)
+        {
+        case _RC_CHOP: fpcr |= 0xc00000; break;
+        case _RC_UP: fpcr |= 0x400000; break;
+        case _RC_DOWN: fpcr |= 0x800000; break;
+        }
+    }
+
+    /* mask exceptions if needed */
+    if (old_fpcr != fpcr && ~(old_fpcr >> 8) & fpsr & 0x9f != fpsr & 0x9f)
+    {
+        ULONG_PTR mask = fpcr & ~0x9f00;
+        __asm__ __volatile__( "msr fpcr, %0" :: "r" (mask) );
+    }
+
+    if (old_fpsr != fpsr)
+        __asm__ __volatile__( "msr fpsr, %0" :: "r" (fpsr) );
+    if (old_fpcr != fpcr)
+        __asm__ __volatile__( "msr fpcr, %0" :: "r" (fpcr) );
+    return TRUE;
 #endif
 #else
     FIXME("not implemented\n");
@@ -5392,18 +5472,8 @@ unsigned int CDECL _statusfp(void)
     _statusfp2( &x86_sw, &sse2_sw );
     /* FIXME: there's no definition for ambiguous status, just return all status bits for now */
     flags = x86_sw | sse2_sw;
-#elif defined(__x86_64__)
+#elif defined(__x86_64__) || defined(__aarch64__)
     _setfp(NULL, 0, &flags, 0);
-#elif defined(__aarch64__)
-    ULONG_PTR fpsr;
-
-    __asm__ __volatile__( "mrs %0, fpsr" : "=r" (fpsr) );
-    if (fpsr & 0x1)  flags |= _SW_INVALID;
-    if (fpsr & 0x2)  flags |= _SW_ZERODIVIDE;
-    if (fpsr & 0x4)  flags |= _SW_OVERFLOW;
-    if (fpsr & 0x8)  flags |= _SW_UNDERFLOW;
-    if (fpsr & 0x10) flags |= _SW_INEXACT;
-    if (fpsr & 0x80) flags |= _SW_DENORMAL;
 #elif defined(__arm__) && !defined(__SOFTFP__)
     DWORD fpscr;
 
@@ -5435,20 +5505,8 @@ unsigned int CDECL _clearfp(void)
         _setfp_sse(NULL, 0, &sse_sw, _MCW_EM);
         flags |= sse_sw;
     }
-#elif defined(__x86_64__)
+#elif defined(__x86_64__) || defined(__aarch64__)
     _setfp(NULL, 0, &flags, _MCW_EM);
-#elif defined(__aarch64__)
-    ULONG_PTR fpsr;
-
-    __asm__ __volatile__( "mrs %0, fpsr" : "=r" (fpsr) );
-    if (fpsr & 0x1)  flags |= _SW_INVALID;
-    if (fpsr & 0x2)  flags |= _SW_ZERODIVIDE;
-    if (fpsr & 0x4)  flags |= _SW_OVERFLOW;
-    if (fpsr & 0x8)  flags |= _SW_UNDERFLOW;
-    if (fpsr & 0x10) flags |= _SW_INEXACT;
-    if (fpsr & 0x80) flags |= _SW_DENORMAL;
-    fpsr &= ~0x9f;
-    __asm__ __volatile__( "msr fpsr, %0" :: "r" (fpsr) );
 #elif defined(__arm__) && !defined(__SOFTFP__)
     DWORD fpscr;
 
@@ -5550,40 +5608,9 @@ unsigned int CDECL _control87(unsigned int newval, unsigned int mask)
 
     if ((flags ^ sse2_cw) & (_MCW_EM | _MCW_RC)) flags |= _EM_AMBIGUOUS;
     flags |= sse2_cw;
-#elif defined(__x86_64__)
+#elif defined(__x86_64__) || defined(__aarch64__)
     flags = newval;
     _setfp(&flags, mask, NULL, 0);
-#elif defined(__aarch64__)
-    ULONG_PTR fpcr;
-
-    __asm__ __volatile__( "mrs %0, fpcr" : "=r" (fpcr) );
-    if (!(fpcr & 0x100))  flags |= _EM_INVALID;
-    if (!(fpcr & 0x200))  flags |= _EM_ZERODIVIDE;
-    if (!(fpcr & 0x400))  flags |= _EM_OVERFLOW;
-    if (!(fpcr & 0x800))  flags |= _EM_UNDERFLOW;
-    if (!(fpcr & 0x1000)) flags |= _EM_INEXACT;
-    if (!(fpcr & 0x8000)) flags |= _EM_DENORMAL;
-    switch (fpcr & 0xc00000)
-    {
-    case 0x400000: flags |= _RC_UP; break;
-    case 0x800000: flags |= _RC_DOWN; break;
-    case 0xc00000: flags |= _RC_CHOP; break;
-    }
-    flags = (flags & ~mask) | (newval & mask);
-    fpcr &= ~0xc09f00ul;
-    if (!(flags & _EM_INVALID)) fpcr |= 0x100;
-    if (!(flags & _EM_ZERODIVIDE)) fpcr |= 0x200;
-    if (!(flags & _EM_OVERFLOW)) fpcr |= 0x400;
-    if (!(flags & _EM_UNDERFLOW)) fpcr |= 0x800;
-    if (!(flags & _EM_INEXACT)) fpcr |= 0x1000;
-    if (!(flags & _EM_DENORMAL)) fpcr |= 0x8000;
-    switch (flags & _MCW_RC)
-    {
-    case _RC_CHOP: fpcr |= 0xc00000; break;
-    case _RC_UP:   fpcr |= 0x400000; break;
-    case _RC_DOWN: fpcr |= 0x800000; break;
-    }
-    __asm__ __volatile__( "msr fpcr, %0" :: "r" (fpcr) );
 #elif defined(__arm__) && !defined(__SOFTFP__)
     DWORD fpscr;
 
@@ -5966,7 +5993,7 @@ void CDECL _fpreset(void)
  */
 int CDECL fesetenv(const fenv_t *env)
 {
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
     unsigned int x87_cw, cw, x87_stat, stat;
     unsigned int mask;
 
@@ -6003,32 +6030,6 @@ int CDECL fesetenv(const fenv_t *env)
         return 1;
     return 0;
 #endif
-#elif defined(__aarch64__)
-    ULONG_PTR fpsr;
-    unsigned int tmp, fp_cw, fp_stat;
-
-    if (!env->_Fe_ctl && !env->_Fe_stat) {
-        _fpreset();
-        return 0;
-    }
-
-    if (!fenv_decode(env->_Fe_ctl, &tmp, &fp_cw))
-        return 1;
-    if (!fenv_decode(env->_Fe_stat, &tmp, &fp_stat))
-        return 1;
-
-    _control87(_MCW_EM, _MCW_EM);
-    __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) );
-    _control87(fp_cw, 0xffffffff);
-    return 0;
 #elif defined(__arm__) && !defined(__SOFTFP__)
     DWORD fpscr;
     unsigned int tmp, fp_cw, fp_stat;




More information about the wine-cvs mailing list