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