fenv.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 377 行
C
377 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Implementation of Floating-point environment for C99.
*
****************************************************************************/
#include "variety.h"
#include <fenv.h>
#include <inttypes.h>
/***************************************************************************/
#ifdef __386__
/* 32-bit versions */
_WCRTDATA const fenv_t __fenv_h_default_environment = {
0x127f, /*CW*/
0,
0, /*SW*/
0,
0xffff, /*TAG*/
0,
0,0,0,0,0,0,
};
/* Load floating-point environment from memory to hardware */
extern void fenv_load( const fenv_t *env );
#pragma aux fenv_load = \
"fldenv [eax]" \
parm [eax] \
modify exact nomemory [];
/* Store floating-point environment from hardware to memory */
extern void fenv_store( fenv_t *env );
#pragma aux fenv_store = \
"fstenv [eax]" \
parm [eax] \
modify exact [];
/* Load floating-point control word from memory to hardware */
extern void fpcw_load( const uint16_t *control );
#pragma aux fpcw_load = \
"fldcw [eax]" \
parm [eax] \
modify exact nomemory [];
/* Store floating-point control word from hardware to memory */
extern void fpcw_store( uint16_t *control );
#pragma aux fpcw_store = \
"fnstcw [eax]" \
parm [eax] \
modify exact [];
/* Store floating-point status word from hardware to memory */
extern void fpsw_store( uint16_t *status );
#pragma aux fpsw_store = \
"fnstsw [eax]" \
parm [eax] \
modify exact [];
#else
/* 16-bit versions */
_WCRTDATA const fenv_t __fenv_h_default_environment = {
0x127f, /*CW*/
0, /*SW*/
0xffff, /*TAG*/
0,0,0,0,
};
#if defined( __SMALL__ ) || defined( __MEDIUM__ )
/* no need to load seg regs */
#define DATA_SEG
#else
/* seg reg needs to be loaded to point to data */
#define DATA_SEG es
#endif
/* Load floating-point environment from memory to hardware */
extern void fenv_load( const fenv_t *env );
#pragma aux fenv_load = \
"fldenv [di]" \
parm [DATA_SEG di] \
modify exact nomemory [];
/* Store floating-point environment from hardware to memory */
extern void fenv_store( fenv_t *env );
#pragma aux fenv_store = \
"fstenv [di]" \
parm [DATA_SEG di] \
modify exact [];
/* Load floating-point control word from memory to hardware */
extern void fpcw_load( const uint16_t *control );
#pragma aux fpcw_load = \
"fldcw [di]" \
parm [DATA_SEG di] \
modify exact nomemory [];
/* Store floating-point control word from hardware to memory */
extern void fpcw_store( uint16_t *control );
#pragma aux fpcw_store = \
"fnstcw [di]" \
parm [DATA_SEG di] \
modify exact [];
/* Store floating-point status word from hardware to memory */
extern void fpsw_store( uint16_t *status );
#pragma aux fpsw_store = \
"fnstsw [di]" \
parm [DATA_SEG di] \
modify exact [];
#endif
/* FPU wait */
extern void fwait( void );
#pragma aux fwait = \
"fwait" \
modify exact [] nomemory;
/****************************************************************************
* exception handling functions
****************************************************************************/
/*
The feclearexcept function clears the supported floating-point exceptions
represented by its argument.
*/
_WCRTLINK int feclearexcept( int excepts )
/****************************************/
{
fenv_t env;
fenv_store( &env );
env.status_word &= ~excepts;
fenv_load( &env );
return( 0 );
}
/*
The fegetexceptflag function stores an implementation-defined
representation of the states of the floating-point status flags
indicated by the argument excepts in the object pointed to by
the argument flagp.
*/
_WCRTLINK int fegetexceptflag( fexcept_t *flagp, int excepts )
/************************************************************/
{
uint16_t status;
fpsw_store( &status );
*flagp = excepts & status & FE_ALL_EXCEPT;
return( 0 );
}
/*
The feraiseexcept function raises the supported floating-point
exceptions represented by its argument. The order in which
these floating-point exceptions are raised is unspecified, except
as stated in F.7.6. Whether the feraiseexcept function additionally
raises the inexact floating-point exception whenever it raises the
overflow or underflow floating-point exception is implementation-defined.
*/
_WCRTLINK int feraiseexcept( int excepts )
/****************************************/
{
fenv_t env;
fenv_store( &env );
env.status_word |= excepts & FE_ALL_EXCEPT;
fenv_load( &env );
fwait(); /* Make sure exception gets triggered now */
return( 0 );
}
/*
_feenableexcept is an OW extension to unmask the given fpu exception
*/
_WCRTLINK void __feenableexcept( int excepts )
/********************************************/
{
uint16_t status;
fpcw_store( &status );
status &= ~FE_ALL_EXCEPT;
status |= excepts ^ FE_ALL_EXCEPT;
fpcw_load( &status );
}
/*
_fedisableexcept is an OW extension to mask the given fpu exception
*/
_WCRTLINK void __fedisableexcept( int excepts )
/*********************************************/
{
uint16_t status;
fpcw_store( &status );
status &= ~FE_ALL_EXCEPT;
status |= excepts;
fpcw_load( &status );
}
/*
The fesetexceptflag function sets the floating-point status flags
indicated by the argument excepts to the states stored in the object
pointed to by flagp. The value of *flagp shall have been set by a
previous call to fegetexceptflag whose second argument represented
at least those floating-point exceptions represented by the argument
excepts. This function does not raise floating-point exceptions,
but only sets the state of the flags.
*/
_WCRTLINK int fesetexceptflag( const fexcept_t *flagp, int excepts )
/******************************************************************/
{
fenv_t env;
fenv_store( &env );
env.status_word &= ~FE_ALL_EXCEPT;
env.status_word |= excepts & *flagp & FE_ALL_EXCEPT;
fenv_load( &env );
return( 0 );
}
/*
The fetestexcept function determines which of a specified
subset of the floatingpoint exception flags are currently set.
The excepts argument specifies the floatingpoint status flags
to be queried.
Returns: the value of the bitwise OR of the floating-point
exception macros corresponding to the currently set floating-point
exceptions included in excepts.
*/
_WCRTLINK int fetestexcept( int excepts )
/***************************************/
{
fexcept_t curr;
fegetexceptflag( &curr, excepts );
return( curr );
}
/****************************************************************************
* rounding mode functions
****************************************************************************/
/*
The fegetround function gets the current rounding direction.
*/
_WCRTLINK int fegetround( void )
/******************************/
{
uint16_t status;
fpcw_store( &status );
return( status & 0x0C00 );
}
/*
The fesetround function sets the current rounding direction.
*/
_WCRTLINK int fesetround( int round )
/***********************************/
{
uint16_t status;
switch( round ) {
case FE_TONEAREST:
case FE_DOWNWARD:
case FE_TOWARDZERO:
case FE_UPWARD:
fpcw_store( &status );
status &= ~0x0C00;
status |= (uint16_t)round;
fpcw_load( &status );
return( 0 );
}
return( 1 );
}
/****************************************************************************
* FPU environment functions
****************************************************************************/
/*
The fegetenv function stores the current floating-point environment
in the object pointed to by envp.
*/
_WCRTLINK int fegetenv( fenv_t *envp )
/************************************/
{
fenv_store( envp );
return( 0 );
}
/*
The feholdexcept function saves the current floating-point environment
in the object pointed to by envp, clears the floating-point status
flags, and then installs a non-stop (continue on floating-point exceptions)
mode, if available, for all floating-point exceptions.
Returns: zero if and only if non-stop floating-point exception handling
was successfully installed.
*/
_WCRTLINK int feholdexcept( fenv_t *envp )
/****************************************/
{
uint16_t status;
fenv_store( envp );
status = envp->control_word | FE_ALL_EXCEPT;
fpcw_load( &status );
return( 0 );
}
/*
The fesetenv function establishes the floating-point environment represented
by the object pointed to by envp. The argument envp shall point to an object
set by a call to fegetenv or feholdexcept, or equal a floating-point
environment macro. Note that fesetenv merely installs the state of the
floating-point status flags represented through its argument, and does not
raise these floating-point exceptions.
*/
_WCRTLINK int fesetenv( const fenv_t *envp )
/******************************************/
{
fenv_load( envp );
return( 0 );
}
/*
The feupdateenv function saves the currently raised floating-point exceptions
in its automatic storage, installs the floating-point environment represented
by the object pointed to by envp, and then raises the saved floating-point
exceptions. The argument envp shall point to an object set by a call to
feholdexcept or fegetenv, or equal a floating-point environment macro.
*/
_WCRTLINK int feupdateenv( const fenv_t *envp )
/*********************************************/
{
uint16_t status;
fpsw_store( &status );
fenv_load( envp );
feraiseexcept( status & FE_ALL_EXCEPT );
return( 0 );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?