1129203Scognet/* $FreeBSD: releng/11.0/lib/libc/softfloat/templates/softfloat-specialize 129203 2004-05-14 12:13:06Z cognet $ */ 2129203Scognet 3129203Scognet/* 4129203Scognet=============================================================================== 5129203Scognet 6129203ScognetThis C source fragment is part of the SoftFloat IEC/IEEE Floating-point 7129203ScognetArithmetic Package, Release 2a. 8129203Scognet 9129203ScognetWritten by John R. Hauser. This work was made possible in part by the 10129203ScognetInternational Computer Science Institute, located at Suite 600, 1947 Center 11129203ScognetStreet, Berkeley, California 94704. Funding was partially provided by the 12129203ScognetNational Science Foundation under grant MIP-9311980. The original version 13129203Scognetof this code was written as part of a project to build a fixed-point vector 14129203Scognetprocessor in collaboration with the University of California at Berkeley, 15129203Scognetoverseen by Profs. Nelson Morgan and John Wawrzynek. More information 16129203Scognetis available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ 17129203Scognetarithmetic/SoftFloat.html'. 18129203Scognet 19129203ScognetTHIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort 20129203Scognethas been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT 21129203ScognetTIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO 22129203ScognetPERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY 23129203ScognetAND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. 24129203Scognet 25129203ScognetDerivative works are acceptable, even for commercial purposes, so long as 26129203Scognet(1) they include prominent notice that the work is derivative, and (2) they 27129203Scognetinclude prominent notice akin to these four paragraphs for those parts of 28129203Scognetthis code that are retained. 29129203Scognet 30129203Scognet=============================================================================== 31129203Scognet*/ 32129203Scognet 33129203Scognet/* 34129203Scognet------------------------------------------------------------------------------- 35129203ScognetUnderflow tininess-detection mode, statically initialized to default value. 36129203Scognet(The declaration in `softfloat.h' must match the `int8' type here.) 37129203Scognet------------------------------------------------------------------------------- 38129203Scognet*/ 39129203Scognetint8 float_detect_tininess = float_tininess_after_rounding; 40129203Scognet 41129203Scognet/* 42129203Scognet------------------------------------------------------------------------------- 43129203ScognetRaises the exceptions specified by `flags'. Floating-point traps can be 44129203Scognetdefined here if desired. It is currently not possible for such a trap to 45129203Scognetsubstitute a result value. If traps are not implemented, this routine 46129203Scognetshould be simply `float_exception_flags |= flags;'. 47129203Scognet------------------------------------------------------------------------------- 48129203Scognet*/ 49129203Scognetvoid float_raise( int8 flags ) 50129203Scognet{ 51129203Scognet 52129203Scognet float_exception_flags |= flags; 53129203Scognet 54129203Scognet} 55129203Scognet 56129203Scognet/* 57129203Scognet------------------------------------------------------------------------------- 58129203ScognetInternal canonical NaN format. 59129203Scognet------------------------------------------------------------------------------- 60129203Scognet*/ 61129203Scognettypedef struct { 62129203Scognet flag sign; 63129203Scognet bits64 high, low; 64129203Scognet} commonNaNT; 65129203Scognet 66129203Scognet/* 67129203Scognet------------------------------------------------------------------------------- 68129203ScognetThe pattern for a default generated single-precision NaN. 69129203Scognet------------------------------------------------------------------------------- 70129203Scognet*/ 71129203Scognet#define float32_default_nan 0xFFFFFFFF 72129203Scognet 73129203Scognet/* 74129203Scognet------------------------------------------------------------------------------- 75129203ScognetReturns 1 if the single-precision floating-point value `a' is a NaN; 76129203Scognetotherwise returns 0. 77129203Scognet------------------------------------------------------------------------------- 78129203Scognet*/ 79129203Scognetflag float32_is_nan( float32 a ) 80129203Scognet{ 81129203Scognet 82129203Scognet return ( 0xFF000000 < (bits32) ( a<<1 ) ); 83129203Scognet 84129203Scognet} 85129203Scognet 86129203Scognet/* 87129203Scognet------------------------------------------------------------------------------- 88129203ScognetReturns 1 if the single-precision floating-point value `a' is a signaling 89129203ScognetNaN; otherwise returns 0. 90129203Scognet------------------------------------------------------------------------------- 91129203Scognet*/ 92129203Scognetflag float32_is_signaling_nan( float32 a ) 93129203Scognet{ 94129203Scognet 95129203Scognet return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); 96129203Scognet 97129203Scognet} 98129203Scognet 99129203Scognet/* 100129203Scognet------------------------------------------------------------------------------- 101129203ScognetReturns the result of converting the single-precision floating-point NaN 102129203Scognet`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 103129203Scognetexception is raised. 104129203Scognet------------------------------------------------------------------------------- 105129203Scognet*/ 106129203Scognetstatic commonNaNT float32ToCommonNaN( float32 a ) 107129203Scognet{ 108129203Scognet commonNaNT z; 109129203Scognet 110129203Scognet if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 111129203Scognet z.sign = a>>31; 112129203Scognet z.low = 0; 113129203Scognet z.high = ( (bits64) a )<<41; 114129203Scognet return z; 115129203Scognet 116129203Scognet} 117129203Scognet 118129203Scognet/* 119129203Scognet------------------------------------------------------------------------------- 120129203ScognetReturns the result of converting the canonical NaN `a' to the single- 121129203Scognetprecision floating-point format. 122129203Scognet------------------------------------------------------------------------------- 123129203Scognet*/ 124129203Scognetstatic float32 commonNaNToFloat32( commonNaNT a ) 125129203Scognet{ 126129203Scognet 127129203Scognet return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); 128129203Scognet 129129203Scognet} 130129203Scognet 131129203Scognet/* 132129203Scognet------------------------------------------------------------------------------- 133129203ScognetTakes two single-precision floating-point values `a' and `b', one of which 134129203Scognetis a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 135129203Scognetsignaling NaN, the invalid exception is raised. 136129203Scognet------------------------------------------------------------------------------- 137129203Scognet*/ 138129203Scognetstatic float32 propagateFloat32NaN( float32 a, float32 b ) 139129203Scognet{ 140129203Scognet flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 141129203Scognet 142129203Scognet aIsNaN = float32_is_nan( a ); 143129203Scognet aIsSignalingNaN = float32_is_signaling_nan( a ); 144129203Scognet bIsNaN = float32_is_nan( b ); 145129203Scognet bIsSignalingNaN = float32_is_signaling_nan( b ); 146129203Scognet a |= 0x00400000; 147129203Scognet b |= 0x00400000; 148129203Scognet if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 149129203Scognet if ( aIsNaN ) { 150129203Scognet return ( aIsSignalingNaN & bIsNaN ) ? b : a; 151129203Scognet } 152129203Scognet else { 153129203Scognet return b; 154129203Scognet } 155129203Scognet 156129203Scognet} 157129203Scognet 158129203Scognet/* 159129203Scognet------------------------------------------------------------------------------- 160129203ScognetThe pattern for a default generated double-precision NaN. 161129203Scognet------------------------------------------------------------------------------- 162129203Scognet*/ 163129203Scognet#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF ) 164129203Scognet 165129203Scognet/* 166129203Scognet------------------------------------------------------------------------------- 167129203ScognetReturns 1 if the double-precision floating-point value `a' is a NaN; 168129203Scognetotherwise returns 0. 169129203Scognet------------------------------------------------------------------------------- 170129203Scognet*/ 171129203Scognetflag float64_is_nan( float64 a ) 172129203Scognet{ 173129203Scognet 174129203Scognet return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) ); 175129203Scognet 176129203Scognet} 177129203Scognet 178129203Scognet/* 179129203Scognet------------------------------------------------------------------------------- 180129203ScognetReturns 1 if the double-precision floating-point value `a' is a signaling 181129203ScognetNaN; otherwise returns 0. 182129203Scognet------------------------------------------------------------------------------- 183129203Scognet*/ 184129203Scognetflag float64_is_signaling_nan( float64 a ) 185129203Scognet{ 186129203Scognet 187129203Scognet return 188129203Scognet ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) 189129203Scognet && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); 190129203Scognet 191129203Scognet} 192129203Scognet 193129203Scognet/* 194129203Scognet------------------------------------------------------------------------------- 195129203ScognetReturns the result of converting the double-precision floating-point NaN 196129203Scognet`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 197129203Scognetexception is raised. 198129203Scognet------------------------------------------------------------------------------- 199129203Scognet*/ 200129203Scognetstatic commonNaNT float64ToCommonNaN( float64 a ) 201129203Scognet{ 202129203Scognet commonNaNT z; 203129203Scognet 204129203Scognet if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 205129203Scognet z.sign = a>>63; 206129203Scognet z.low = 0; 207129203Scognet z.high = a<<12; 208129203Scognet return z; 209129203Scognet 210129203Scognet} 211129203Scognet 212129203Scognet/* 213129203Scognet------------------------------------------------------------------------------- 214129203ScognetReturns the result of converting the canonical NaN `a' to the double- 215129203Scognetprecision floating-point format. 216129203Scognet------------------------------------------------------------------------------- 217129203Scognet*/ 218129203Scognetstatic float64 commonNaNToFloat64( commonNaNT a ) 219129203Scognet{ 220129203Scognet 221129203Scognet return 222129203Scognet ( ( (bits64) a.sign )<<63 ) 223129203Scognet | LIT64( 0x7FF8000000000000 ) 224129203Scognet | ( a.high>>12 ); 225129203Scognet 226129203Scognet} 227129203Scognet 228129203Scognet/* 229129203Scognet------------------------------------------------------------------------------- 230129203ScognetTakes two double-precision floating-point values `a' and `b', one of which 231129203Scognetis a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 232129203Scognetsignaling NaN, the invalid exception is raised. 233129203Scognet------------------------------------------------------------------------------- 234129203Scognet*/ 235129203Scognetstatic float64 propagateFloat64NaN( float64 a, float64 b ) 236129203Scognet{ 237129203Scognet flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 238129203Scognet 239129203Scognet aIsNaN = float64_is_nan( a ); 240129203Scognet aIsSignalingNaN = float64_is_signaling_nan( a ); 241129203Scognet bIsNaN = float64_is_nan( b ); 242129203Scognet bIsSignalingNaN = float64_is_signaling_nan( b ); 243129203Scognet a |= LIT64( 0x0008000000000000 ); 244129203Scognet b |= LIT64( 0x0008000000000000 ); 245129203Scognet if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 246129203Scognet if ( aIsNaN ) { 247129203Scognet return ( aIsSignalingNaN & bIsNaN ) ? b : a; 248129203Scognet } 249129203Scognet else { 250129203Scognet return b; 251129203Scognet } 252129203Scognet 253129203Scognet} 254129203Scognet 255129203Scognet#ifdef FLOATX80 256129203Scognet 257129203Scognet/* 258129203Scognet------------------------------------------------------------------------------- 259129203ScognetThe pattern for a default generated extended double-precision NaN. The 260129203Scognet`high' and `low' values hold the most- and least-significant bits, 261129203Scognetrespectively. 262129203Scognet------------------------------------------------------------------------------- 263129203Scognet*/ 264129203Scognet#define floatx80_default_nan_high 0xFFFF 265129203Scognet#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 266129203Scognet 267129203Scognet/* 268129203Scognet------------------------------------------------------------------------------- 269129203ScognetReturns 1 if the extended double-precision floating-point value `a' is a 270129203ScognetNaN; otherwise returns 0. 271129203Scognet------------------------------------------------------------------------------- 272129203Scognet*/ 273129203Scognetflag floatx80_is_nan( floatx80 a ) 274129203Scognet{ 275129203Scognet 276129203Scognet return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); 277129203Scognet 278129203Scognet} 279129203Scognet 280129203Scognet/* 281129203Scognet------------------------------------------------------------------------------- 282129203ScognetReturns 1 if the extended double-precision floating-point value `a' is a 283129203Scognetsignaling NaN; otherwise returns 0. 284129203Scognet------------------------------------------------------------------------------- 285129203Scognet*/ 286129203Scognetflag floatx80_is_signaling_nan( floatx80 a ) 287129203Scognet{ 288129203Scognet bits64 aLow; 289129203Scognet 290129203Scognet aLow = a.low & ~ LIT64( 0x4000000000000000 ); 291129203Scognet return 292129203Scognet ( ( a.high & 0x7FFF ) == 0x7FFF ) 293129203Scognet && (bits64) ( aLow<<1 ) 294129203Scognet && ( a.low == aLow ); 295129203Scognet 296129203Scognet} 297129203Scognet 298129203Scognet/* 299129203Scognet------------------------------------------------------------------------------- 300129203ScognetReturns the result of converting the extended double-precision floating- 301129203Scognetpoint NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the 302129203Scognetinvalid exception is raised. 303129203Scognet------------------------------------------------------------------------------- 304129203Scognet*/ 305129203Scognetstatic commonNaNT floatx80ToCommonNaN( floatx80 a ) 306129203Scognet{ 307129203Scognet commonNaNT z; 308129203Scognet 309129203Scognet if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 310129203Scognet z.sign = a.high>>15; 311129203Scognet z.low = 0; 312129203Scognet z.high = a.low<<1; 313129203Scognet return z; 314129203Scognet 315129203Scognet} 316129203Scognet 317129203Scognet/* 318129203Scognet------------------------------------------------------------------------------- 319129203ScognetReturns the result of converting the canonical NaN `a' to the extended 320129203Scognetdouble-precision floating-point format. 321129203Scognet------------------------------------------------------------------------------- 322129203Scognet*/ 323129203Scognetstatic floatx80 commonNaNToFloatx80( commonNaNT a ) 324129203Scognet{ 325129203Scognet floatx80 z; 326129203Scognet 327129203Scognet z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); 328129203Scognet z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; 329129203Scognet return z; 330129203Scognet 331129203Scognet} 332129203Scognet 333129203Scognet/* 334129203Scognet------------------------------------------------------------------------------- 335129203ScognetTakes two extended double-precision floating-point values `a' and `b', one 336129203Scognetof which is a NaN, and returns the appropriate NaN result. If either `a' or 337129203Scognet`b' is a signaling NaN, the invalid exception is raised. 338129203Scognet------------------------------------------------------------------------------- 339129203Scognet*/ 340129203Scognetstatic floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) 341129203Scognet{ 342129203Scognet flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 343129203Scognet 344129203Scognet aIsNaN = floatx80_is_nan( a ); 345129203Scognet aIsSignalingNaN = floatx80_is_signaling_nan( a ); 346129203Scognet bIsNaN = floatx80_is_nan( b ); 347129203Scognet bIsSignalingNaN = floatx80_is_signaling_nan( b ); 348129203Scognet a.low |= LIT64( 0xC000000000000000 ); 349129203Scognet b.low |= LIT64( 0xC000000000000000 ); 350129203Scognet if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 351129203Scognet if ( aIsNaN ) { 352129203Scognet return ( aIsSignalingNaN & bIsNaN ) ? b : a; 353129203Scognet } 354129203Scognet else { 355129203Scognet return b; 356129203Scognet } 357129203Scognet 358129203Scognet} 359129203Scognet 360129203Scognet#endif 361129203Scognet 362129203Scognet#ifdef FLOAT128 363129203Scognet 364129203Scognet/* 365129203Scognet------------------------------------------------------------------------------- 366129203ScognetThe pattern for a default generated quadruple-precision NaN. The `high' and 367129203Scognet`low' values hold the most- and least-significant bits, respectively. 368129203Scognet------------------------------------------------------------------------------- 369129203Scognet*/ 370129203Scognet#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF ) 371129203Scognet#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 372129203Scognet 373129203Scognet/* 374129203Scognet------------------------------------------------------------------------------- 375129203ScognetReturns 1 if the quadruple-precision floating-point value `a' is a NaN; 376129203Scognetotherwise returns 0. 377129203Scognet------------------------------------------------------------------------------- 378129203Scognet*/ 379129203Scognetflag float128_is_nan( float128 a ) 380129203Scognet{ 381129203Scognet 382129203Scognet return 383129203Scognet ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) 384129203Scognet && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); 385129203Scognet 386129203Scognet} 387129203Scognet 388129203Scognet/* 389129203Scognet------------------------------------------------------------------------------- 390129203ScognetReturns 1 if the quadruple-precision floating-point value `a' is a 391129203Scognetsignaling NaN; otherwise returns 0. 392129203Scognet------------------------------------------------------------------------------- 393129203Scognet*/ 394129203Scognetflag float128_is_signaling_nan( float128 a ) 395129203Scognet{ 396129203Scognet 397129203Scognet return 398129203Scognet ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) 399129203Scognet && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); 400129203Scognet 401129203Scognet} 402129203Scognet 403129203Scognet/* 404129203Scognet------------------------------------------------------------------------------- 405129203ScognetReturns the result of converting the quadruple-precision floating-point NaN 406129203Scognet`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 407129203Scognetexception is raised. 408129203Scognet------------------------------------------------------------------------------- 409129203Scognet*/ 410129203Scognetstatic commonNaNT float128ToCommonNaN( float128 a ) 411129203Scognet{ 412129203Scognet commonNaNT z; 413129203Scognet 414129203Scognet if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 415129203Scognet z.sign = a.high>>63; 416129203Scognet shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); 417129203Scognet return z; 418129203Scognet 419129203Scognet} 420129203Scognet 421129203Scognet/* 422129203Scognet------------------------------------------------------------------------------- 423129203ScognetReturns the result of converting the canonical NaN `a' to the quadruple- 424129203Scognetprecision floating-point format. 425129203Scognet------------------------------------------------------------------------------- 426129203Scognet*/ 427129203Scognetstatic float128 commonNaNToFloat128( commonNaNT a ) 428129203Scognet{ 429129203Scognet float128 z; 430129203Scognet 431129203Scognet shift128Right( a.high, a.low, 16, &z.high, &z.low ); 432129203Scognet z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); 433129203Scognet return z; 434129203Scognet 435129203Scognet} 436129203Scognet 437129203Scognet/* 438129203Scognet------------------------------------------------------------------------------- 439129203ScognetTakes two quadruple-precision floating-point values `a' and `b', one of 440129203Scognetwhich is a NaN, and returns the appropriate NaN result. If either `a' or 441129203Scognet`b' is a signaling NaN, the invalid exception is raised. 442129203Scognet------------------------------------------------------------------------------- 443129203Scognet*/ 444129203Scognetstatic float128 propagateFloat128NaN( float128 a, float128 b ) 445129203Scognet{ 446129203Scognet flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 447129203Scognet 448129203Scognet aIsNaN = float128_is_nan( a ); 449129203Scognet aIsSignalingNaN = float128_is_signaling_nan( a ); 450129203Scognet bIsNaN = float128_is_nan( b ); 451129203Scognet bIsSignalingNaN = float128_is_signaling_nan( b ); 452129203Scognet a.high |= LIT64( 0x0000800000000000 ); 453129203Scognet b.high |= LIT64( 0x0000800000000000 ); 454129203Scognet if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 455129203Scognet if ( aIsNaN ) { 456129203Scognet return ( aIsSignalingNaN & bIsNaN ) ? b : a; 457129203Scognet } 458129203Scognet else { 459129203Scognet return b; 460129203Scognet } 461129203Scognet 462129203Scognet} 463129203Scognet 464129203Scognet#endif 465129203Scognet 466