windows-nt/Source/XPSP1/NT/base/crts/fpw32/tran/i386/fpctrl.c
2020-09-26 16:20:57 +08:00

167 lines
2.4 KiB
C

/***
*fpctrl.c - fp low level control and status routines
*
* Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved.
*
*Purpose:
* IEEE control and status routines for internal use.
* These routines use machine specific constants while _controlfp,
* _statusfp, and _clearfp use an abstracted control/status word
*
*Revision History:
*
* 03-31-92 GDP written
* 05-12-92 GJF Rewrote fdivr as fdivrp st(1),st to work around C8-32
* assertions.
*
*/
#include <trans.h>
/*** _statfp
*() -
*
*Purpose:
* return user status word
*
*Entry:
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/
unsigned int _statfp()
{
short status;
_asm {
fstsw status
}
return status;
}
/*** _clrfp
*() -
*
*Purpose:
* return user status word and clear status
*
*Entry:
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/
unsigned int _clrfp()
{
short status;
_asm {
fnstsw status
fnclex
}
return status;
}
/*** _ctrlfp
*() -
*
*Purpose:
* return and set user control word
*
*Entry:
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/
unsigned int _ctrlfp(unsigned int newctrl, unsigned int _mask)
{
short oldCw;
short newCw;
_asm {
fstcw oldCw
}
newCw = (short) ((newctrl & _mask) | (oldCw & ~_mask));
_asm {
fldcw newCw
}
return oldCw;
}
/*** _set_statfp
*() -
*
*Purpose:
* force selected exception flags to 1
*
*Entry:
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/
static unsigned long over[3] = { 0x0, 0x80000000, 0x4410 };
static unsigned long under[3] = { 0x1, 0x80000000, 0x3000 };
void _set_statfp(unsigned int sw)
{
int itmp;
double tmp;
if (sw & ISW_INVALID) {
_asm {
fld tbyte ptr over
fistp itmp
fwait
}
}
if (sw & ISW_OVERFLOW) { // will also trigger precision
_asm {
fstsw ax
fld tbyte ptr over
fstp tmp
fwait
fstsw ax
}
}
if (sw & ISW_UNDERFLOW) { // will also trigger precision
_asm {
fld tbyte ptr under
fstp tmp
fwait
}
}
if (sw & ISW_ZERODIVIDE) {
_asm {
fldz
fld1
fdivrp st(1), st
fstp st(0)
fwait
}
}
if (sw & ISW_INEXACT) {
_asm {
fldpi
fstp tmp
fwait
}
}
}