Module: wine Branch: master Commit: 6f912787a0292ccb2897fbd75ccb751c1906442a URL: https://source.winehq.org/git/wine.git/?a=commit;h=6f912787a0292ccb2897fbd75...
Author: Alexandre Julliard julliard@winehq.org Date: Thu Oct 31 22:20:14 2019 +0100
msvcrt: Implement _control87() and _statusfp() for ARM64.
Signed-off-by: Alexandre Julliard julliard@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; }
/*********************************************************************