[PATCH 2/2] msvcrt: Implement _control87/_statusfp/fesetenv for arm

Martin Storsjo martin at martin.st
Sun Aug 1 16:04:31 CDT 2021


This is essentially the same as for aarch64, except the bits that
are split over two registers, fpsr and fpcr in aarch64, are all
located in one single register fpscr on arm.

Signed-off-by: Martin Storsjo <martin at martin.st>
---
 dlls/msvcrt/math.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c
index 81ae9b02a61..3c85b1dc23b 100644
--- a/dlls/msvcrt/math.c
+++ b/dlls/msvcrt/math.c
@@ -5206,6 +5206,16 @@ unsigned int CDECL _statusfp(void)
     if (fpsr & 0x8)  flags |= _SW_UNDERFLOW;
     if (fpsr & 0x10) flags |= _SW_INEXACT;
     if (fpsr & 0x80) flags |= _SW_DENORMAL;
+#elif defined(__arm__)
+    DWORD fpscr;
+
+    __asm__ __volatile__( "vmrs %0, fpscr" : "=r" (fpscr) );
+    if (fpscr & 0x1)  flags |= _SW_INVALID;
+    if (fpscr & 0x2)  flags |= _SW_ZERODIVIDE;
+    if (fpscr & 0x4)  flags |= _SW_OVERFLOW;
+    if (fpscr & 0x8)  flags |= _SW_UNDERFLOW;
+    if (fpscr & 0x10) flags |= _SW_INEXACT;
+    if (fpscr & 0x80) flags |= _SW_DENORMAL;
 #else
     FIXME( "not implemented\n" );
 #endif
@@ -5253,6 +5263,18 @@ unsigned int CDECL _clearfp(void)
     if (fpsr & 0x80) flags |= _SW_DENORMAL;
     fpsr &= ~0x9f;
     __asm__ __volatile__( "msr fpsr, %0" :: "r" (fpsr) );
+#elif defined(__arm__)
+    DWORD fpscr;
+
+    __asm__ __volatile__( "vmrs %0, fpscr" : "=r" (fpscr) );
+    if (fpscr & 0x1)  flags |= _SW_INVALID;
+    if (fpscr & 0x2)  flags |= _SW_ZERODIVIDE;
+    if (fpscr & 0x4)  flags |= _SW_OVERFLOW;
+    if (fpscr & 0x8)  flags |= _SW_UNDERFLOW;
+    if (fpscr & 0x10) flags |= _SW_INEXACT;
+    if (fpscr & 0x80) flags |= _SW_DENORMAL;
+    fpscr &= ~0x9f;
+    __asm__ __volatile__( "vmsr fpscr, %0" :: "r" (fpscr) );
 #else
     FIXME( "not implemented\n" );
 #endif
@@ -5535,6 +5557,37 @@ unsigned int CDECL _control87(unsigned int newval, unsigned int mask)
     case _RC_DOWN: fpcr |= 0x800000; break;
     }
     __asm__ __volatile__( "msr fpcr, %0" :: "r" (fpcr) );
+#elif defined(__arm__)
+    DWORD fpscr;
+
+    __asm__ __volatile__( "vmrs %0, fpscr" : "=r" (fpscr) );
+    if (!(fpscr & 0x100))  flags |= _EM_INVALID;
+    if (!(fpscr & 0x200))  flags |= _EM_ZERODIVIDE;
+    if (!(fpscr & 0x400))  flags |= _EM_OVERFLOW;
+    if (!(fpscr & 0x800))  flags |= _EM_UNDERFLOW;
+    if (!(fpscr & 0x1000)) flags |= _EM_INEXACT;
+    if (!(fpscr & 0x8000)) flags |= _EM_DENORMAL;
+    switch (fpscr & 0xc00000)
+    {
+    case 0x400000: flags |= _RC_UP; break;
+    case 0x800000: flags |= _RC_DOWN; break;
+    case 0xc00000: flags |= _RC_CHOP; break;
+    }
+    flags = (flags & ~mask) | (newval & mask);
+    fpscr &= ~0xc09f00ul;
+    if (!(flags & _EM_INVALID))    fpscr |= 0x100;
+    if (!(flags & _EM_ZERODIVIDE)) fpscr |= 0x200;
+    if (!(flags & _EM_OVERFLOW))   fpscr |= 0x400;
+    if (!(flags & _EM_UNDERFLOW))  fpscr |= 0x800;
+    if (!(flags & _EM_INEXACT))    fpscr |= 0x1000;
+    if (!(flags & _EM_DENORMAL))   fpscr |= 0x8000;
+    switch (flags & _MCW_RC)
+    {
+    case _RC_CHOP: fpscr |= 0xc00000; break;
+    case _RC_UP:   fpscr |= 0x400000; break;
+    case _RC_DOWN: fpscr |= 0x800000; break;
+    }
+    __asm__ __volatile__( "vmsr fpscr, %0" :: "r" (fpscr) );
 #else
     FIXME( "not implemented\n" );
 #endif
@@ -6002,6 +6055,19 @@ int CDECL fesetenv(const fenv_t *env)
     if (env->_Fe_stat & _SW_DENORMAL)   fpsr |= 0x80;
     __asm__ __volatile__( "msr fpsr, %0" :: "r" (fpsr) );
     return 0;
+#elif defined(__arm__)
+    _control87(env->_Fe_ctl, 0xffffffff);
+    DWORD fpscr;
+    __asm__ __volatile__( "vmrs %0, fpscr" : "=r" (fpscr) );
+    fpscr &= ~0x9f;
+    if (env->_Fe_stat & _SW_INVALID)    fpscr |= 0x1;
+    if (env->_Fe_stat & _SW_ZERODIVIDE) fpscr |= 0x2;
+    if (env->_Fe_stat & _SW_OVERFLOW)   fpscr |= 0x4;
+    if (env->_Fe_stat & _SW_UNDERFLOW)  fpscr |= 0x8;
+    if (env->_Fe_stat & _SW_INEXACT)    fpscr |= 0x10;
+    if (env->_Fe_stat & _SW_DENORMAL)   fpscr |= 0x80;
+    __asm__ __volatile__( "vmsr fpscr, %0" :: "r" (fpscr) );
+    return 0;
 #else
     FIXME( "not implemented\n" );
 #endif
-- 
2.25.1




More information about the wine-devel mailing list