1 /* 2 * PROJECT: ReactOS CRT library 3 * LICENSE: MIT (https://spdx.org/licenses/MIT) 4 * PURPOSE: Implementation of _controlfp 5 * COPYRIGHT: Copyright 2021 Roman Masanin <36927roma@gmail.com> 6 */ 7 8 #include <precomp.h> 9 #include "fpscr.h" 10 11 unsigned int CDECL _controlfp(unsigned int newval, unsigned int mask) 12 { 13 return _control87(newval, mask & ~_EM_DENORMAL); 14 } 15 16 unsigned int CDECL _control87(unsigned int newval, unsigned int mask) 17 { 18 ARM_FPSCR fpscr; 19 unsigned int flags = 0; 20 21 TRACE("(%08x, %08x): Called\n", newval, mask); 22 23 /* Get fp control word */ 24 fpscr.raw = __getfp(); 25 26 TRACE("Control word before : %08x\n", fpscr.raw); 27 28 /* Convert into mask constants */ 29 if (!(fpscr.data.ex_control & ARM_CW_IM)) flags |= _EM_INVALID; 30 if (!(fpscr.data.ex_control & ARM_CW_ZM)) flags |= _EM_ZERODIVIDE; 31 if (!(fpscr.data.ex_control & ARM_CW_OM)) flags |= _EM_OVERFLOW; 32 if (!(fpscr.data.ex_control & ARM_CW_UM)) flags |= _EM_UNDERFLOW; 33 if (!(fpscr.data.ex_control & ARM_CW_PM)) flags |= _EM_INEXACT; 34 if (!(fpscr.data.ex_control & ARM_CW_DM)) flags |= _EM_DENORMAL; 35 36 switch (fpscr.data.rounding_mode) 37 { 38 case ARM_CW_RC_ZERO: flags |= _RC_UP|_RC_DOWN; break; 39 case ARM_CW_RC_UP: flags |= _RC_UP; break; 40 case ARM_CW_RC_DOWN: flags |= _RC_DOWN; break; 41 } 42 43 /* Mask with parameters */ 44 flags = (flags & ~mask) | (newval & mask); 45 46 /* Convert (masked) value back to fp word */ 47 fpscr.raw = 0; 48 if (!(flags & _EM_INVALID)) fpscr.data.ex_control |= ARM_CW_IM; 49 if (!(flags & _EM_ZERODIVIDE)) fpscr.data.ex_control |= ARM_CW_ZM; 50 if (!(flags & _EM_OVERFLOW)) fpscr.data.ex_control |= ARM_CW_OM; 51 if (!(flags & _EM_UNDERFLOW)) fpscr.data.ex_control |= ARM_CW_UM; 52 if (!(flags & _EM_INEXACT)) fpscr.data.ex_control |= ARM_CW_PM; 53 if (!(flags & _EM_DENORMAL)) fpscr.data.ex_control |= ARM_CW_DM; 54 55 switch (flags & (_RC_UP | _RC_DOWN)) 56 { 57 case _RC_UP|_RC_DOWN: fpscr.data.rounding_mode = ARM_CW_RC_ZERO; break; 58 case _RC_UP: fpscr.data.rounding_mode = ARM_CW_RC_UP; break; 59 case _RC_DOWN: fpscr.data.rounding_mode = ARM_CW_RC_DOWN; break; 60 case _RC_NEAR: fpscr.data.rounding_mode = ARM_CW_RC_NEAREST; break; 61 } 62 63 TRACE("Control word after : %08x\n", fpscr.raw); 64 65 /* Put fp control word */ 66 __setfp(fpscr.raw); 67 68 return flags; 69 } 70 71