[CRT/ARM] Floating point control functions implementation (#3870)

Implement controlfp, statusfp, fpreset, clearfp. CORE-17757 CORE-17604
This commit is contained in:
Roman Masanin 2021-08-01 17:30:41 +03:00 committed by Stanislav Motylkov
parent c188821f8b
commit 554bbb6bab
No known key found for this signature in database
GPG key ID: AFE513258CBA9E92
13 changed files with 249 additions and 100 deletions

View file

@ -77,6 +77,14 @@
#define _FPCLASS_PINF 0x0200 /* Positive Infinity */
#endif /* __MINGW_FPCLASS_DEFINED */
/* _statusfp bit flags */
#define _SW_INEXACT 0x00000001 /* inexact (precision) */
#define _SW_UNDERFLOW 0x00000002 /* underflow */
#define _SW_OVERFLOW 0x00000004 /* overflow */
#define _SW_ZERODIVIDE 0x00000008 /* zero divide */
#define _SW_INVALID 0x00000010 /* invalid */
#define _SW_DENORMAL 0x00080000 /* denormal status bit */
/* invalid subconditions (_SW_INVALID also set) */
#define _SW_UNEMULATED 0x0040 /* unemulated instruction */
#define _SW_SQRTNEG 0x0080 /* square root of a neg number */

View file

@ -0,0 +1,25 @@
/*
* PROJECT: ReactOS CRT library
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: ARM fpscr getter
* COPYRIGHT: Copyright 2021 Roman Masanin <36927roma@gmail.com>
*/
/* INCLUDES ******************************************************************/
#include <kxarm.h>
/* CODE **********************************************************************/
TEXTAREA
LEAF_ENTRY __getfp
VMRS R0,FPSCR
BX LR
LEAF_END __getfp
END
/* EOF */

View file

@ -0,0 +1,25 @@
/*
* PROJECT: ReactOS CRT library
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: ARM fpscr setter
* COPYRIGHT: Copyright 2021 Roman Masanin <36927roma@gmail.com>
*/
/* INCLUDES ******************************************************************/
#include <kxarm.h>
/* CODE **********************************************************************/
TEXTAREA
LEAF_ENTRY __setfp
VMSR FPSCR,R0
BX LR
LEAF_END __setfp
END
/* EOF */

View file

@ -0,0 +1,22 @@
/*
* PROJECT: ReactOS CRT library
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: Implementation of _clearfp
* COPYRIGHT: Copyright 2021 Roman Masanin <36927roma@gmail.com>
*/
#include "fpscr.h"
unsigned int _clearfp(void)
{
ARM_FPSCR fpscr;
unsigned int status;
fpscr.raw = __getfp();
status = _statusfp();
fpscr.data.exception = fpscr.data.exception & ~ARM_CW_STATUS_MASK;
__setfp(fpscr.raw);
return status;
}

View file

@ -1,24 +0,0 @@
/*
* COPYRIGHT: BSD - See COPYING.ARM in the top level directory
* PROJECT: ReactOS CRT library
* PURPOSE: Implementation of _clearfp
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include <kxarm.h>
/* CODE **********************************************************************/
TEXTAREA
LEAF_ENTRY _clearfp
__assertfail
bx lr
LEAF_END _clearfp
END
/* EOF */

View file

@ -0,0 +1,83 @@
/*
* PROJECT: ReactOS CRT library
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: Implementation of _controlfp
* COPYRIGHT: Copyright 2021 Roman Masanin <36927roma@gmail.com>
*/
#include <precomp.h>
#include "fpscr.h"
unsigned int CDECL _controlfp(unsigned int newval, unsigned int mask)
{
return _control87(newval, mask & ~_EM_DENORMAL);
}
unsigned int CDECL _control87(unsigned int newval, unsigned int mask)
{
ARM_FPSCR fpscr;
unsigned int flags = 0;
TRACE("(%08x, %08x): Called\n", newval, mask);
/* Get fp control word */
fpscr.raw = __getfp();
TRACE("Control word before : %08x\n", fpscr.raw);
/* Convert into mask constants */
if (!(fpscr.data.ex_control & ARM_CW_IM)) flags |= _EM_INVALID;
if (!(fpscr.data.ex_control & ARM_CW_ZM)) flags |= _EM_ZERODIVIDE;
if (!(fpscr.data.ex_control & ARM_CW_OM)) flags |= _EM_OVERFLOW;
if (!(fpscr.data.ex_control & ARM_CW_UM)) flags |= _EM_UNDERFLOW;
if (!(fpscr.data.ex_control & ARM_CW_PM)) flags |= _EM_INEXACT;
if (!(fpscr.data.ex_control & ARM_CW_DM)) flags |= _EM_DENORMAL;
switch (fpscr.data.rounding_mode)
{
case ARM_CW_RC_ZERO: flags |= _RC_UP|_RC_DOWN; break;
case ARM_CW_RC_UP: flags |= _RC_UP; break;
case ARM_CW_RC_DOWN: flags |= _RC_DOWN; break;
}
/* Mask with parameters */
flags = (flags & ~mask) | (newval & mask);
/* Convert (masked) value back to fp word */
fpscr.raw = 0;
if (!(flags & _EM_INVALID)) fpscr.data.ex_control |= ARM_CW_IM;
if (!(flags & _EM_ZERODIVIDE)) fpscr.data.ex_control |= ARM_CW_ZM;
if (!(flags & _EM_OVERFLOW)) fpscr.data.ex_control |= ARM_CW_OM;
if (!(flags & _EM_UNDERFLOW)) fpscr.data.ex_control |= ARM_CW_UM;
if (!(flags & _EM_INEXACT)) fpscr.data.ex_control |= ARM_CW_PM;
if (!(flags & _EM_DENORMAL)) fpscr.data.ex_control |= ARM_CW_DM;
switch (flags & (_RC_UP | _RC_DOWN))
{
case _RC_UP|_RC_DOWN: fpscr.data.rounding_mode = ARM_CW_RC_ZERO; break;
case _RC_UP: fpscr.data.rounding_mode = ARM_CW_RC_UP; break;
case _RC_DOWN: fpscr.data.rounding_mode = ARM_CW_RC_DOWN; break;
case _RC_NEAR: fpscr.data.rounding_mode = ARM_CW_RC_NEAREST; break;
}
TRACE("Control word after : %08x\n", fpscr.raw);
/* Put fp control word */
__setfp(fpscr.raw);
return flags;
}
int CDECL _controlfp_s(unsigned int *cur, unsigned int newval, unsigned int mask)
{
unsigned int val;
if (!MSVCRT_CHECK_PMT( !(newval & mask & ~(_MCW_EM | _MCW_RC | _MCW_DN)) ))
{
if (cur) *cur = _controlfp(0, 0); /* retrieve it anyway */
return EINVAL;
}
val = _controlfp(newval, mask);
if (cur) *cur = val;
return 0;
}

View file

@ -1,24 +0,0 @@
/*
* COPYRIGHT: BSD - See COPYING.ARM in the top level directory
* PROJECT: ReactOS CRT library
* PURPOSE: Implementation of _controlfp
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include <kxarm.h>
/* CODE **********************************************************************/
TEXTAREA
LEAF_ENTRY _controlfp
__assertfail
bx lr
LEAF_END _controlfp
END
/* EOF */

View file

@ -0,0 +1,13 @@
/*
* PROJECT: ReactOS CRT library
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: Implementation of _fpreset
* COPYRIGHT: Copyright 2021 Roman Masanin <36927roma@gmail.com>
*/
#include "fpscr.h"
void _fpreset(void)
{
__setfp(0x0);
}

View file

@ -1,24 +0,0 @@
/*
* COPYRIGHT: BSD - See COPYING.ARM in the top level directory
* PROJECT: ReactOS CRT library
* PURPOSE: Implementation of _fpreset
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include <kxarm.h>
/* CODE **********************************************************************/
TEXTAREA
LEAF_ENTRY _fpreset
__assertfail
bx lr
LEAF_END _fpreset
END
/* EOF */

View file

@ -0,0 +1,24 @@
/*
* PROJECT: ReactOS CRT library
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: Implementation of _statusfp
* COPYRIGHT: Copyright 2021 Roman Masanin <36927roma@gmail.com>
*/
#include "fpscr.h"
unsigned int _statusfp(void)
{
unsigned int flags = 0;
ARM_FPSCR fpscr;
fpscr.raw = __getfp();
if (fpscr.data.exception & ARM_CW_IM) flags |= _SW_INVALID;
if (fpscr.data.exception & ARM_CW_ZM) flags |= _SW_ZERODIVIDE;
if (fpscr.data.exception & ARM_CW_OM) flags |= _SW_OVERFLOW;
if (fpscr.data.exception & ARM_CW_UM) flags |= _SW_UNDERFLOW;
if (fpscr.data.exception & ARM_CW_PM) flags |= _SW_INEXACT;
if (fpscr.data.exception & ARM_CW_DM) flags |= _SW_DENORMAL;
return flags;
}

View file

@ -1,24 +0,0 @@
/*
* COPYRIGHT: BSD - See COPYING.ARM in the top level directory
* PROJECT: ReactOS CRT library
* PURPOSE: Implementation of _statusfp
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include <kxarm.h>
/* CODE **********************************************************************/
TEXTAREA
LEAF_ENTRY _statusfp
__assertfail
bx lr
LEAF_END _statusfp
END
/* EOF */

View file

@ -0,0 +1,41 @@
/*
* PROJECT: ReactOS CRT library
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: Headers for ARM fpcsr
* COPYRIGHT: Copyright 2021 Roman Masanin <36927roma@gmail.com>
*/
#include <float.h>
#define ARM_CW_STATUS_MASK 0x9F
#define ARM_CW_IM (1 << 0) /* Invalid operation mask */
#define ARM_CW_ZM (1 << 1) /* Zero divide mask */
#define ARM_CW_OM (1 << 2) /* Overflow mask */
#define ARM_CW_UM (1 << 3) /* Underflow mask */
#define ARM_CW_PM (1 << 4) /* Precision mask */
#define ARM_CW_DM (1 << 7) /* Denormal operand mask */
#define ARM_CW_RC_NEAREST 0 /* round to nearest */
#define ARM_CW_RC_UP 1 /* round up */
#define ARM_CW_RC_DOWN 2 /* round down */
#define ARM_CW_RC_ZERO 3 /* round toward zero (chop) */
typedef union _ARM_FPSCR
{
unsigned int raw;
struct
{
unsigned int exception: 8;
unsigned int ex_control: 8;
unsigned int len: 3;
unsigned int unused3: 1;
unsigned int stride: 2;
unsigned int rounding_mode: 2;
unsigned int flush_to_zero: 1;
unsigned int unused4: 3;
unsigned int status_flag: 4;
} data;
} ARM_FPSCR;
void __setfp(unsigned int);
unsigned int __getfp(void);

View file

@ -33,10 +33,14 @@ elseif(ARCH STREQUAL "amd64")
float/amd64/logb.S
)
elseif(ARCH STREQUAL "arm")
list(APPEND CRT_FLOAT_SOURCE
float/arm/_clearfp.c
float/arm/_controlfp.c
float/arm/_fpreset.c
float/arm/_statusfp.c
)
list(APPEND CRT_FLOAT_ASM_SOURCE
float/arm/_clearfp.s
float/arm/_controlfp.s
float/arm/_fpreset.s
float/arm/_statusfp.s
float/arm/__getfp.s
float/arm/__setfp.s
)
endif()