126 lines
4.5 KiB
C
126 lines
4.5 KiB
C
|
|
/*
|
|
===============================================================================
|
|
|
|
This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
|
|
Arithmetic Package, Release 2.
|
|
|
|
Written by John R. Hauser. This work was made possible in part by the
|
|
International Computer Science Institute, located at Suite 600, 1947 Center
|
|
Street, Berkeley, California 94704. Funding was partially provided by the
|
|
National Science Foundation under grant MIP-9311980. The original version
|
|
of this code was written as part of a project to build a fixed-point vector
|
|
processor in collaboration with the University of California at Berkeley,
|
|
overseen by Profs. Nelson Morgan and John Wawrzynek. More information
|
|
is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
|
|
arithmetic/softfloat.html'.
|
|
|
|
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
|
|
has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
|
|
TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
|
|
PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
|
|
AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
|
|
|
|
Derivative works are acceptable, even for commercial purposes, so long as
|
|
(1) they include prominent notice that the work is derivative, and (2) they
|
|
include prominent notice akin to these three paragraphs for those parts of
|
|
this code that are retained.
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
/*
|
|
-------------------------------------------------------------------------------
|
|
Underflow tininess-detection mode, statically initialized to default value.
|
|
(The declaration in `softfloat.h' must match the `int8' type here.)
|
|
-------------------------------------------------------------------------------
|
|
*/
|
|
int8 float_detect_tininess = float_tininess_after_rounding;
|
|
|
|
/*
|
|
-------------------------------------------------------------------------------
|
|
Raises the exceptions specified by `flags'. Floating-point traps can be
|
|
defined here if desired. It is currently not possible for such a trap to
|
|
substitute a result value. If traps are not implemented, this routine
|
|
should be simply `float_exception_flags |= flags;'.
|
|
-------------------------------------------------------------------------------
|
|
*/
|
|
void float_raise( int8 flags )
|
|
{
|
|
|
|
float_exception_flags |= flags;
|
|
|
|
}
|
|
|
|
/*
|
|
-------------------------------------------------------------------------------
|
|
Internal canonical NaN format.
|
|
-------------------------------------------------------------------------------
|
|
*/
|
|
typedef struct {
|
|
flag sign;
|
|
bits32 high, low;
|
|
} commonNaNT;
|
|
|
|
/*
|
|
-------------------------------------------------------------------------------
|
|
The pattern for a default generated single-precision NaN.
|
|
-------------------------------------------------------------------------------
|
|
*/
|
|
enum {
|
|
float32_default_nan = 0xFFFFFFFF
|
|
};
|
|
|
|
/*
|
|
-------------------------------------------------------------------------------
|
|
Returns 1 if the single-precision floating-point value `a' is a NaN;
|
|
otherwise returns 0.
|
|
-------------------------------------------------------------------------------
|
|
*/
|
|
flag float32_is_nan( float32 a )
|
|
{
|
|
|
|
return ( 0xFF000000 < (bits32) ( a<<1 ) );
|
|
|
|
}
|
|
|
|
/*
|
|
-------------------------------------------------------------------------------
|
|
Returns 1 if the single-precision floating-point value `a' is a signaling
|
|
NaN; otherwise returns 0.
|
|
-------------------------------------------------------------------------------
|
|
*/
|
|
flag float32_is_signaling_nan( float32 a )
|
|
{
|
|
|
|
return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
|
|
|
|
}
|
|
|
|
/*
|
|
-------------------------------------------------------------------------------
|
|
Takes two single-precision floating-point values `a' and `b', one of which
|
|
is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
|
|
signaling NaN, the invalid exception is raised.
|
|
-------------------------------------------------------------------------------
|
|
*/
|
|
static float32 propagateFloat32NaN( float32 a, float32 b )
|
|
{
|
|
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
|
|
|
|
aIsNaN = float32_is_nan( a );
|
|
aIsSignalingNaN = float32_is_signaling_nan( a );
|
|
bIsNaN = float32_is_nan( b );
|
|
bIsSignalingNaN = float32_is_signaling_nan( b );
|
|
a |= 0x00400000;
|
|
b |= 0x00400000;
|
|
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
|
|
if ( aIsNaN ) {
|
|
return ( aIsSignalingNaN & bIsNaN ) ? b : a;
|
|
}
|
|
else {
|
|
return b;
|
|
}
|
|
|
|
}
|