1/* $NetBSD: softfloat-specialize,v 1.3 2002/05/12 13:12:45 bjh21 Exp $ */ 2 3/* This is a derivative work. */ 4 5/* 6=============================================================================== 7 8This C source fragment is part of the SoftFloat IEC/IEEE Floating-point 9Arithmetic Package, Release 2a. 10 11Written by John R. Hauser. This work was made possible in part by the 12International Computer Science Institute, located at Suite 600, 1947 Center 13Street, Berkeley, California 94704. Funding was partially provided by the 14National Science Foundation under grant MIP-9311980. The original version 15of this code was written as part of a project to build a fixed-point vector 16processor in collaboration with the University of California at Berkeley, 17overseen by Profs. Nelson Morgan and John Wawrzynek. More information 18is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ 19arithmetic/SoftFloat.html'. 20 21THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort 22has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT 23TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO 24PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY 25AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. 26 27Derivative works are acceptable, even for commercial purposes, so long as 28(1) they include prominent notice that the work is derivative, and (2) they 29include prominent notice akin to these four paragraphs for those parts of 30this code that are retained. 31 32=============================================================================== 33*/ 34 35#include <signal.h> 36 37/* 38------------------------------------------------------------------------------- 39Underflow tininess-detection mode, statically initialized to default value. 40(The declaration in `softfloat.h' must match the `int8' type here.) 41------------------------------------------------------------------------------- 42*/ 43#ifdef SOFTFLOAT_FOR_GCC 44static 45#endif 46int8 float_detect_tininess = float_tininess_after_rounding; 47 48/* 49------------------------------------------------------------------------------- 50Raises the exceptions specified by `flags'. Floating-point traps can be 51defined here if desired. It is currently not possible for such a trap to 52substitute a result value. If traps are not implemented, this routine 53should be simply `float_exception_flags |= flags;'. 54------------------------------------------------------------------------------- 55*/ 56fp_except float_exception_mask = 0; 57void float_raise( fp_except flags ) 58{ 59 60 float_exception_flags |= flags; 61 62 if ( flags & float_exception_mask ) { 63 raise( SIGFPE ); 64 } 65} 66 67/* 68------------------------------------------------------------------------------- 69Internal canonical NaN format. 70------------------------------------------------------------------------------- 71*/ 72typedef struct { 73 flag sign; 74 bits64 high, low; 75} commonNaNT; 76 77/* 78------------------------------------------------------------------------------- 79The pattern for a default generated single-precision NaN. 80------------------------------------------------------------------------------- 81*/ 82#define float32_default_nan 0xFFFFFFFF 83 84/* 85------------------------------------------------------------------------------- 86Returns 1 if the single-precision floating-point value `a' is a NaN; 87otherwise returns 0. 88------------------------------------------------------------------------------- 89*/ 90#ifdef SOFTFLOAT_FOR_GCC 91static 92#endif 93flag float32_is_nan( float32 a ) 94{ 95 96 return ( 0xFF000000 < (bits32) ( a<<1 ) ); 97 98} 99 100/* 101------------------------------------------------------------------------------- 102Returns 1 if the single-precision floating-point value `a' is a signaling 103NaN; otherwise returns 0. 104------------------------------------------------------------------------------- 105*/ 106#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) 107static 108#endif 109flag float32_is_signaling_nan( float32 a ) 110{ 111 112 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); 113 114} 115 116/* 117------------------------------------------------------------------------------- 118Returns the result of converting the single-precision floating-point NaN 119`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 120exception is raised. 121------------------------------------------------------------------------------- 122*/ 123static commonNaNT float32ToCommonNaN( float32 a ) 124{ 125 commonNaNT z; 126 127 if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 128 z.sign = a>>31; 129 z.low = 0; 130 z.high = ( (bits64) a )<<41; 131 return z; 132 133} 134 135/* 136------------------------------------------------------------------------------- 137Returns the result of converting the canonical NaN `a' to the single- 138precision floating-point format. 139------------------------------------------------------------------------------- 140*/ 141static float32 commonNaNToFloat32( commonNaNT a ) 142{ 143 144 return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); 145 146} 147 148/* 149------------------------------------------------------------------------------- 150Takes two single-precision floating-point values `a' and `b', one of which 151is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 152signaling NaN, the invalid exception is raised. 153------------------------------------------------------------------------------- 154*/ 155static float32 propagateFloat32NaN( float32 a, float32 b ) 156{ 157 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 158 159 aIsNaN = float32_is_nan( a ); 160 aIsSignalingNaN = float32_is_signaling_nan( a ); 161 bIsNaN = float32_is_nan( b ); 162 bIsSignalingNaN = float32_is_signaling_nan( b ); 163 a |= 0x00400000; 164 b |= 0x00400000; 165 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 166 if ( aIsNaN ) { 167 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 168 } 169 else { 170 return b; 171 } 172 173} 174 175/* 176------------------------------------------------------------------------------- 177The pattern for a default generated double-precision NaN. 178------------------------------------------------------------------------------- 179*/ 180#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF ) 181 182/* 183------------------------------------------------------------------------------- 184Returns 1 if the double-precision floating-point value `a' is a NaN; 185otherwise returns 0. 186------------------------------------------------------------------------------- 187*/ 188#ifdef SOFTFLOAT_FOR_GCC 189static 190#endif 191flag float64_is_nan( float64 a ) 192{ 193 194 return ( LIT64( 0xFFE0000000000000 ) < 195 (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) ); 196 197} 198 199/* 200------------------------------------------------------------------------------- 201Returns 1 if the double-precision floating-point value `a' is a signaling 202NaN; otherwise returns 0. 203------------------------------------------------------------------------------- 204*/ 205#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) 206static 207#endif 208flag float64_is_signaling_nan( float64 a ) 209{ 210 211 return 212 ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE ) 213 && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) ); 214 215} 216 217/* 218------------------------------------------------------------------------------- 219Returns the result of converting the double-precision floating-point NaN 220`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 221exception is raised. 222------------------------------------------------------------------------------- 223*/ 224static commonNaNT float64ToCommonNaN( float64 a ) 225{ 226 commonNaNT z; 227 228 if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 229 z.sign = FLOAT64_DEMANGLE(a)>>63; 230 z.low = 0; 231 z.high = FLOAT64_DEMANGLE(a)<<12; 232 return z; 233 234} 235 236/* 237------------------------------------------------------------------------------- 238Returns the result of converting the canonical NaN `a' to the double- 239precision floating-point format. 240------------------------------------------------------------------------------- 241*/ 242static float64 commonNaNToFloat64( commonNaNT a ) 243{ 244 245 return FLOAT64_MANGLE( 246 ( ( (bits64) a.sign )<<63 ) 247 | LIT64( 0x7FF8000000000000 ) 248 | ( a.high>>12 ) ); 249 250} 251 252/* 253------------------------------------------------------------------------------- 254Takes two double-precision floating-point values `a' and `b', one of which 255is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 256signaling NaN, the invalid exception is raised. 257------------------------------------------------------------------------------- 258*/ 259static float64 propagateFloat64NaN( float64 a, float64 b ) 260{ 261 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 262 263 aIsNaN = float64_is_nan( a ); 264 aIsSignalingNaN = float64_is_signaling_nan( a ); 265 bIsNaN = float64_is_nan( b ); 266 bIsSignalingNaN = float64_is_signaling_nan( b ); 267 a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 )); 268 b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 )); 269 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 270 if ( aIsNaN ) { 271 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 272 } 273 else { 274 return b; 275 } 276 277} 278 279#ifdef FLOATX80 280 281/* 282------------------------------------------------------------------------------- 283The pattern for a default generated extended double-precision NaN. The 284`high' and `low' values hold the most- and least-significant bits, 285respectively. 286------------------------------------------------------------------------------- 287*/ 288#define floatx80_default_nan_high 0xFFFF 289#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 290 291/* 292------------------------------------------------------------------------------- 293Returns 1 if the extended double-precision floating-point value `a' is a 294NaN; otherwise returns 0. 295------------------------------------------------------------------------------- 296*/ 297flag floatx80_is_nan( floatx80 a ) 298{ 299 300 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); 301 302} 303 304/* 305------------------------------------------------------------------------------- 306Returns 1 if the extended double-precision floating-point value `a' is a 307signaling NaN; otherwise returns 0. 308------------------------------------------------------------------------------- 309*/ 310flag floatx80_is_signaling_nan( floatx80 a ) 311{ 312 bits64 aLow; 313 314 aLow = a.low & ~ LIT64( 0x4000000000000000 ); 315 return 316 ( ( a.high & 0x7FFF ) == 0x7FFF ) 317 && (bits64) ( aLow<<1 ) 318 && ( a.low == aLow ); 319 320} 321 322/* 323------------------------------------------------------------------------------- 324Returns the result of converting the extended double-precision floating- 325point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the 326invalid exception is raised. 327------------------------------------------------------------------------------- 328*/ 329static commonNaNT floatx80ToCommonNaN( floatx80 a ) 330{ 331 commonNaNT z; 332 333 if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 334 z.sign = a.high>>15; 335 z.low = 0; 336 z.high = a.low<<1; 337 return z; 338 339} 340 341/* 342------------------------------------------------------------------------------- 343Returns the result of converting the canonical NaN `a' to the extended 344double-precision floating-point format. 345------------------------------------------------------------------------------- 346*/ 347static floatx80 commonNaNToFloatx80( commonNaNT a ) 348{ 349 floatx80 z; 350 351 z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); 352 z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; 353 return z; 354 355} 356 357/* 358------------------------------------------------------------------------------- 359Takes two extended double-precision floating-point values `a' and `b', one 360of which is a NaN, and returns the appropriate NaN result. If either `a' or 361`b' is a signaling NaN, the invalid exception is raised. 362------------------------------------------------------------------------------- 363*/ 364static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) 365{ 366 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 367 368 aIsNaN = floatx80_is_nan( a ); 369 aIsSignalingNaN = floatx80_is_signaling_nan( a ); 370 bIsNaN = floatx80_is_nan( b ); 371 bIsSignalingNaN = floatx80_is_signaling_nan( b ); 372 a.low |= LIT64( 0xC000000000000000 ); 373 b.low |= LIT64( 0xC000000000000000 ); 374 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 375 if ( aIsNaN ) { 376 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 377 } 378 else { 379 return b; 380 } 381 382} 383 384#endif 385 386#ifdef FLOAT128 387 388/* 389------------------------------------------------------------------------------- 390The pattern for a default generated quadruple-precision NaN. The `high' and 391`low' values hold the most- and least-significant bits, respectively. 392------------------------------------------------------------------------------- 393*/ 394#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF ) 395#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 396 397/* 398------------------------------------------------------------------------------- 399Returns 1 if the quadruple-precision floating-point value `a' is a NaN; 400otherwise returns 0. 401------------------------------------------------------------------------------- 402*/ 403flag float128_is_nan( float128 a ) 404{ 405 406 return 407 ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) 408 && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); 409 410} 411 412/* 413------------------------------------------------------------------------------- 414Returns 1 if the quadruple-precision floating-point value `a' is a 415signaling NaN; otherwise returns 0. 416------------------------------------------------------------------------------- 417*/ 418flag float128_is_signaling_nan( float128 a ) 419{ 420 421 return 422 ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) 423 && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); 424 425} 426 427/* 428------------------------------------------------------------------------------- 429Returns the result of converting the quadruple-precision floating-point NaN 430`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 431exception is raised. 432------------------------------------------------------------------------------- 433*/ 434static commonNaNT float128ToCommonNaN( float128 a ) 435{ 436 commonNaNT z; 437 438 if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 439 z.sign = a.high>>63; 440 shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); 441 return z; 442 443} 444 445/* 446------------------------------------------------------------------------------- 447Returns the result of converting the canonical NaN `a' to the quadruple- 448precision floating-point format. 449------------------------------------------------------------------------------- 450*/ 451static float128 commonNaNToFloat128( commonNaNT a ) 452{ 453 float128 z; 454 455 shift128Right( a.high, a.low, 16, &z.high, &z.low ); 456 z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); 457 return z; 458 459} 460 461/* 462------------------------------------------------------------------------------- 463Takes two quadruple-precision floating-point values `a' and `b', one of 464which is a NaN, and returns the appropriate NaN result. If either `a' or 465`b' is a signaling NaN, the invalid exception is raised. 466------------------------------------------------------------------------------- 467*/ 468static float128 propagateFloat128NaN( float128 a, float128 b ) 469{ 470 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 471 472 aIsNaN = float128_is_nan( a ); 473 aIsSignalingNaN = float128_is_signaling_nan( a ); 474 bIsNaN = float128_is_nan( b ); 475 bIsSignalingNaN = float128_is_signaling_nan( b ); 476 a.high |= LIT64( 0x0000800000000000 ); 477 b.high |= LIT64( 0x0000800000000000 ); 478 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 479 if ( aIsNaN ) { 480 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 481 } 482 else { 483 return b; 484 } 485 486} 487 488#endif 489 490