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