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@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