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