^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) ===============================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) Arithmetic Package, Release 2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) Written by John R. Hauser. This work was made possible in part by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) International Computer Science Institute, located at Suite 600, 1947 Center
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) Street, Berkeley, California 94704. Funding was partially provided by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) National Science Foundation under grant MIP-9311980. The original version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) of this code was written as part of a project to build a fixed-point vector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) processor in collaboration with the University of California at Berkeley,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) overseen by Profs. Nelson Morgan and John Wawrzynek. More information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) is available through the Web page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) http://www.jhauser.us/arithmetic/SoftFloat-2b/SoftFloat-source.txt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) Derivative works are acceptable, even for commercial purposes, so long as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) (1) they include prominent notice that the work is derivative, and (2) they
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) include prominent notice akin to these three paragraphs for those parts of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) this code that are retained.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) ===============================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) Underflow tininess-detection mode, statically initialized to default value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) (The declaration in `softfloat.h' must match the `int8' type here.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) int8 float_detect_tininess = float_tininess_after_rounding;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) Raises the exceptions specified by `flags'. Floating-point traps can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) defined here if desired. It is currently not possible for such a trap to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) substitute a result value. If traps are not implemented, this routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) should be simply `float_exception_flags |= flags;'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) ScottB: November 4, 1998
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) Moved this function out of softfloat-specialize into fpmodule.c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) This effectively isolates all the changes required for integrating with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) Linux kernel into fpmodule.c. Porting to NetBSD should only require modifying
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) fpmodule.c to integrate with the NetBSD kernel (I hope!).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) void float_raise( int8 flags )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) float_exception_flags |= flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) Internal canonical NaN format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) typedef struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) flag sign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) bits64 high, low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) } commonNaNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) The pattern for a default generated single-precision NaN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define float32_default_nan 0xFFFFFFFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) Returns 1 if the single-precision floating-point value `a' is a NaN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) otherwise returns 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) flag float32_is_nan( float32 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return ( 0xFF000000 < (bits32) ( a<<1 ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) Returns 1 if the single-precision floating-point value `a' is a signaling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) NaN; otherwise returns 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) flag float32_is_signaling_nan( float32 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) Returns the result of converting the single-precision floating-point NaN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) exception is raised.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static commonNaNT float32ToCommonNaN( float32 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) commonNaNT z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) z.sign = a>>31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) z.low = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) z.high = ( (bits64) a )<<41;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) Returns the result of converting the canonical NaN `a' to the single-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) precision floating-point format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static float32 commonNaNToFloat32( commonNaNT a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) Takes two single-precision floating-point values `a' and `b', one of which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) signaling NaN, the invalid exception is raised.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static float32 propagateFloat32NaN( float32 a, float32 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) aIsNaN = float32_is_nan( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) aIsSignalingNaN = float32_is_signaling_nan( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) bIsNaN = float32_is_nan( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) bIsSignalingNaN = float32_is_signaling_nan( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) a |= 0x00400000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) b |= 0x00400000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if ( aIsNaN ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return ( aIsSignalingNaN & bIsNaN ) ? b : a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) The pattern for a default generated double-precision NaN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) Returns 1 if the double-precision floating-point value `a' is a NaN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) otherwise returns 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) flag float64_is_nan( float64 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) Returns 1 if the double-precision floating-point value `a' is a signaling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) NaN; otherwise returns 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) flag float64_is_signaling_nan( float64 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) Returns the result of converting the double-precision floating-point NaN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) exception is raised.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static commonNaNT float64ToCommonNaN( float64 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) commonNaNT z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) z.sign = a>>63;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) z.low = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) z.high = a<<12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) Returns the result of converting the canonical NaN `a' to the double-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) precision floating-point format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static float64 commonNaNToFloat64( commonNaNT a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) ( ( (bits64) a.sign )<<63 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) | LIT64( 0x7FF8000000000000 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) | ( a.high>>12 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) Takes two double-precision floating-point values `a' and `b', one of which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) signaling NaN, the invalid exception is raised.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static float64 propagateFloat64NaN( float64 a, float64 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) aIsNaN = float64_is_nan( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) aIsSignalingNaN = float64_is_signaling_nan( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) bIsNaN = float64_is_nan( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) bIsSignalingNaN = float64_is_signaling_nan( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) a |= LIT64( 0x0008000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) b |= LIT64( 0x0008000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if ( aIsNaN ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return ( aIsSignalingNaN & bIsNaN ) ? b : a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) #ifdef FLOATX80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) The pattern for a default generated extended double-precision NaN. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) `high' and `low' values hold the most- and least-significant bits,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) respectively.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) #define floatx80_default_nan_high 0xFFFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) #define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) Returns 1 if the extended double-precision floating-point value `a' is a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) NaN; otherwise returns 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) flag floatx80_is_nan( floatx80 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) Returns 1 if the extended double-precision floating-point value `a' is a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) signaling NaN; otherwise returns 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) flag floatx80_is_signaling_nan( floatx80 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) //register int lr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) bits64 aLow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) //__asm__("mov %0, lr" : : "g" (lr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) //fp_printk("floatx80_is_signalling_nan() called from 0x%08x\n",lr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) aLow = a.low & ~ LIT64( 0x4000000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) ( ( a.high & 0x7FFF ) == 0x7FFF )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) && (bits64) ( aLow<<1 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) && ( a.low == aLow );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) Returns the result of converting the extended double-precision floating-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) invalid exception is raised.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static commonNaNT floatx80ToCommonNaN( floatx80 a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) commonNaNT z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) z.sign = a.high>>15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) z.low = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) z.high = a.low<<1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) Returns the result of converting the canonical NaN `a' to the extended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) double-precision floating-point format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) static floatx80 commonNaNToFloatx80( commonNaNT a )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) floatx80 z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) z.__padding = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) Takes two extended double-precision floating-point values `a' and `b', one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) of which is a NaN, and returns the appropriate NaN result. If either `a' or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) `b' is a signaling NaN, the invalid exception is raised.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) -------------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) aIsNaN = floatx80_is_nan( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) aIsSignalingNaN = floatx80_is_signaling_nan( a );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) bIsNaN = floatx80_is_nan( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) bIsSignalingNaN = floatx80_is_signaling_nan( b );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) a.low |= LIT64( 0xC000000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) b.low |= LIT64( 0xC000000000000000 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if ( aIsNaN ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return ( aIsSignalingNaN & bIsNaN ) ? b : a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) #endif