Alexandre Julliard : msvcrt: Implement _control87() and _statusfp() for ARM64.
Alexandre Julliard
julliard at winehq.org
Thu Oct 31 17:39:30 CDT 2019
Module: wine
Branch: master
Commit: 6f912787a0292ccb2897fbd75ccb751c1906442a
URL: https://source.winehq.org/git/wine.git/?a=commit;h=6f912787a0292ccb2897fbd75ccb751c1906442a
Author: Alexandre Julliard <julliard at winehq.org>
Date: Thu Oct 31 22:20:14 2019 +0100
msvcrt: Implement _control87() and _statusfp() for ARM64.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/msvcrt/math.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 63 insertions(+), 9 deletions(-)
diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c
index 0779a8f022..f56ec9dcf0 100644
--- a/dlls/msvcrt/math.c
+++ b/dlls/msvcrt/math.c
@@ -971,16 +971,27 @@ void CDECL _statusfp2( unsigned int *x86_sw, unsigned int *sse2_sw )
*/
unsigned int CDECL _statusfp(void)
{
+ unsigned int flags = 0;
#if defined(__i386__) || defined(__x86_64__)
unsigned int x86_sw, sse2_sw;
_statusfp2( &x86_sw, &sse2_sw );
/* FIXME: there's no definition for ambiguous status, just return all status bits for now */
- return x86_sw | sse2_sw;
+ flags = x86_sw | sse2_sw;
+#elif defined(__aarch64__)
+ unsigned long fpsr;
+
+ __asm__ __volatile__( "mrs %0, fpsr" : "=r" (fpsr) );
+ if (fpsr & 0x1) flags |= MSVCRT__SW_INVALID;
+ if (fpsr & 0x2) flags |= MSVCRT__SW_ZERODIVIDE;
+ if (fpsr & 0x4) flags |= MSVCRT__SW_OVERFLOW;
+ if (fpsr & 0x8) flags |= MSVCRT__SW_UNDERFLOW;
+ if (fpsr & 0x10) flags |= MSVCRT__SW_INEXACT;
+ if (fpsr & 0x80) flags |= MSVCRT__SW_DENORMAL;
#else
FIXME( "not implemented\n" );
- return 0;
#endif
+ return flags;
}
/*********************************************************************
@@ -1012,6 +1023,18 @@ unsigned int CDECL _clearfp(void)
fpword &= ~0x3f;
__asm__ __volatile__( "ldmxcsr %0" : : "m" (fpword) );
}
+#elif defined(__aarch64__)
+ unsigned long fpsr;
+
+ __asm__ __volatile__( "mrs %0, fpsr" : "=r" (fpsr) );
+ if (fpsr & 0x1) flags |= MSVCRT__SW_INVALID;
+ if (fpsr & 0x2) flags |= MSVCRT__SW_ZERODIVIDE;
+ if (fpsr & 0x4) flags |= MSVCRT__SW_OVERFLOW;
+ if (fpsr & 0x8) flags |= MSVCRT__SW_UNDERFLOW;
+ if (fpsr & 0x10) flags |= MSVCRT__SW_INEXACT;
+ if (fpsr & 0x80) flags |= MSVCRT__SW_DENORMAL;
+ fpsr &= ~0x9f;
+ __asm__ __volatile__( "msr fpsr, %0" :: "r" (fpsr) );
#else
FIXME( "not implemented\n" );
#endif
@@ -1201,17 +1224,48 @@ int CDECL __control87_2( unsigned int newval, unsigned int mask,
*/
unsigned int CDECL _control87(unsigned int newval, unsigned int mask)
{
+ unsigned int flags = 0;
#if defined(__i386__) || defined(__x86_64__)
- unsigned int x86_cw, sse2_cw;
-
- __control87_2( newval, mask, &x86_cw, &sse2_cw );
-
- if ((x86_cw ^ sse2_cw) & (MSVCRT__MCW_EM | MSVCRT__MCW_RC)) x86_cw |= MSVCRT__EM_AMBIGUOUS;
- return x86_cw;
+ unsigned int sse2_cw;
+
+ __control87_2( newval, mask, &flags, &sse2_cw );
+
+ if ((flags ^ sse2_cw) & (MSVCRT__MCW_EM | MSVCRT__MCW_RC)) flags |= MSVCRT__EM_AMBIGUOUS;
+#elif defined(__aarch64__)
+ unsigned long fpcr;
+
+ __asm__ __volatile__( "mrs %0, fpcr" : "=r" (fpcr) );
+ if (!(fpcr & 0x100)) flags |= MSVCRT__EM_INVALID;
+ if (!(fpcr & 0x200)) flags |= MSVCRT__EM_ZERODIVIDE;
+ if (!(fpcr & 0x400)) flags |= MSVCRT__EM_OVERFLOW;
+ if (!(fpcr & 0x800)) flags |= MSVCRT__EM_UNDERFLOW;
+ if (!(fpcr & 0x1000)) flags |= MSVCRT__EM_INEXACT;
+ if (!(fpcr & 0x8000)) flags |= MSVCRT__EM_DENORMAL;
+ switch (fpcr & 0xc00000)
+ {
+ case 0x400000: flags |= MSVCRT__RC_UP; break;
+ case 0x800000: flags |= MSVCRT__RC_DOWN; break;
+ case 0xc00000: flags |= MSVCRT__RC_CHOP; break;
+ }
+ flags = (flags & ~mask) | (newval & mask);
+ fpcr &= ~0xc09f00ul;
+ if (!(flags & MSVCRT__EM_INVALID)) fpcr |= 0x100;
+ if (!(flags & MSVCRT__EM_ZERODIVIDE)) fpcr |= 0x200;
+ if (!(flags & MSVCRT__EM_OVERFLOW)) fpcr |= 0x400;
+ if (!(flags & MSVCRT__EM_UNDERFLOW)) fpcr |= 0x800;
+ if (!(flags & MSVCRT__EM_INEXACT)) fpcr |= 0x1000;
+ if (!(flags & MSVCRT__EM_DENORMAL)) fpcr |= 0x8000;
+ switch (flags & MSVCRT__MCW_RC)
+ {
+ case MSVCRT__RC_CHOP: fpcr |= 0xc00000; break;
+ case MSVCRT__RC_UP: fpcr |= 0x400000; break;
+ case MSVCRT__RC_DOWN: fpcr |= 0x800000; break;
+ }
+ __asm__ __volatile__( "msr fpcr, %0" :: "r" (fpcr) );
#else
FIXME( "not implemented\n" );
- return 0;
#endif
+ return flags;
}
/*********************************************************************
More information about the wine-cvs
mailing list