1/* $NetBSD: softfloat-specialize,v 1.5 2011/03/04 11:48:58 martin 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#include <string.h> 37#include <unistd.h> 38 39/* 40------------------------------------------------------------------------------- 41Underflow tininess-detection mode, statically initialized to default value. 42(The declaration in `softfloat.h' must match the `int8' type here.) 43------------------------------------------------------------------------------- 44*/ 45#ifdef SOFTFLOAT_FOR_GCC 46static 47#endif 48int8 float_detect_tininess = float_tininess_after_rounding; 49 50/* 51------------------------------------------------------------------------------- 52Raises the exceptions specified by `flags'. Floating-point traps can be 53defined here if desired. It is currently not possible for such a trap to 54substitute a result value. If traps are not implemented, this routine 55should be simply `float_exception_flags |= flags;'. 56------------------------------------------------------------------------------- 57*/ 58#ifdef SOFTFLOAT_FOR_GCC 59#define float_exception_mask _softfloat_float_exception_mask 60#endif 61fp_except float_exception_mask = 0; 62void float_raise( fp_except flags ) 63{ 64 siginfo_t info; 65 66 float_exception_flags |= flags; 67 68 if ( flags & float_exception_mask ) { 69 memset(&info, 0, sizeof info); 70 info.si_signo = SIGFPE; 71 info.si_pid = getpid(); 72 info.si_uid = geteuid(); 73 if (flags & float_flag_underflow) 74 info.si_code = FPE_FLTUND; 75 else if (flags & float_flag_overflow) 76 info.si_code = FPE_FLTOVF; 77 else if (flags & float_flag_divbyzero) 78 info.si_code = FPE_FLTDIV; 79 else if (flags & float_flag_invalid) 80 info.si_code = FPE_FLTINV; 81 else if (flags & float_flag_inexact) 82 info.si_code = FPE_FLTRES; 83 sigqueueinfo(getpid(), &info); 84 } 85} 86#undef float_exception_mask 87 88/* 89------------------------------------------------------------------------------- 90Internal canonical NaN format. 91------------------------------------------------------------------------------- 92*/ 93typedef struct { 94 flag sign; 95 bits64 high, low; 96} commonNaNT; 97 98/* 99------------------------------------------------------------------------------- 100The pattern for a default generated single-precision NaN. 101------------------------------------------------------------------------------- 102*/ 103#define float32_default_nan 0xFFFFFFFF 104 105/* 106------------------------------------------------------------------------------- 107Returns 1 if the single-precision floating-point value `a' is a NaN; 108otherwise returns 0. 109------------------------------------------------------------------------------- 110*/ 111#ifdef SOFTFLOAT_FOR_GCC 112static 113#endif 114flag float32_is_nan( float32 a ) 115{ 116 117 return ( 0xFF000000 < (bits32) ( a<<1 ) ); 118 119} 120 121/* 122------------------------------------------------------------------------------- 123Returns 1 if the single-precision floating-point value `a' is a signaling 124NaN; otherwise returns 0. 125------------------------------------------------------------------------------- 126*/ 127#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \ 128 !defined(SOFTFLOAT_M68K_FOR_GCC) 129static 130#endif 131flag float32_is_signaling_nan( float32 a ) 132{ 133 134 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); 135 136} 137 138/* 139------------------------------------------------------------------------------- 140Returns the result of converting the single-precision floating-point NaN 141`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 142exception is raised. 143------------------------------------------------------------------------------- 144*/ 145static commonNaNT float32ToCommonNaN( float32 a ) 146{ 147 commonNaNT z; 148 149 if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 150 z.sign = a>>31; 151 z.low = 0; 152 z.high = ( (bits64) a )<<41; 153 return z; 154 155} 156 157/* 158------------------------------------------------------------------------------- 159Returns the result of converting the canonical NaN `a' to the single- 160precision floating-point format. 161------------------------------------------------------------------------------- 162*/ 163static float32 commonNaNToFloat32( commonNaNT a ) 164{ 165 166 return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); 167 168} 169 170/* 171------------------------------------------------------------------------------- 172Takes two single-precision floating-point values `a' and `b', one of which 173is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 174signaling NaN, the invalid exception is raised. 175------------------------------------------------------------------------------- 176*/ 177static float32 propagateFloat32NaN( float32 a, float32 b ) 178{ 179 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 180 181 aIsNaN = float32_is_nan( a ); 182 aIsSignalingNaN = float32_is_signaling_nan( a ); 183 bIsNaN = float32_is_nan( b ); 184 bIsSignalingNaN = float32_is_signaling_nan( b ); 185 a |= 0x00400000; 186 b |= 0x00400000; 187 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 188 if ( aIsNaN ) { 189 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 190 } 191 else { 192 return b; 193 } 194 195} 196 197/* 198------------------------------------------------------------------------------- 199The pattern for a default generated double-precision NaN. 200------------------------------------------------------------------------------- 201*/ 202#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF ) 203 204/* 205------------------------------------------------------------------------------- 206Returns 1 if the double-precision floating-point value `a' is a NaN; 207otherwise returns 0. 208------------------------------------------------------------------------------- 209*/ 210#ifdef SOFTFLOAT_FOR_GCC 211static 212#endif 213flag float64_is_nan( float64 a ) 214{ 215 216 return ( LIT64( 0xFFE0000000000000 ) < 217 (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) ); 218 219} 220 221/* 222------------------------------------------------------------------------------- 223Returns 1 if the double-precision floating-point value `a' is a signaling 224NaN; otherwise returns 0. 225------------------------------------------------------------------------------- 226*/ 227#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \ 228 !defined(SOFTFLOATM68K_FOR_GCC) 229static 230#endif 231flag float64_is_signaling_nan( float64 a ) 232{ 233 234 return 235 ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE ) 236 && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) ); 237 238} 239 240/* 241------------------------------------------------------------------------------- 242Returns the result of converting the double-precision floating-point NaN 243`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 244exception is raised. 245------------------------------------------------------------------------------- 246*/ 247static commonNaNT float64ToCommonNaN( float64 a ) 248{ 249 commonNaNT z; 250 251 if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 252 z.sign = FLOAT64_DEMANGLE(a)>>63; 253 z.low = 0; 254 z.high = FLOAT64_DEMANGLE(a)<<12; 255 return z; 256 257} 258 259/* 260------------------------------------------------------------------------------- 261Returns the result of converting the canonical NaN `a' to the double- 262precision floating-point format. 263------------------------------------------------------------------------------- 264*/ 265static float64 commonNaNToFloat64( commonNaNT a ) 266{ 267 268 return FLOAT64_MANGLE( 269 ( ( (bits64) a.sign )<<63 ) 270 | LIT64( 0x7FF8000000000000 ) 271 | ( a.high>>12 ) ); 272 273} 274 275/* 276------------------------------------------------------------------------------- 277Takes two double-precision floating-point values `a' and `b', one of which 278is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 279signaling NaN, the invalid exception is raised. 280------------------------------------------------------------------------------- 281*/ 282static float64 propagateFloat64NaN( float64 a, float64 b ) 283{ 284 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 285 286 aIsNaN = float64_is_nan( a ); 287 aIsSignalingNaN = float64_is_signaling_nan( a ); 288 bIsNaN = float64_is_nan( b ); 289 bIsSignalingNaN = float64_is_signaling_nan( b ); 290 a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 )); 291 b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 )); 292 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 293 if ( aIsNaN ) { 294 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 295 } 296 else { 297 return b; 298 } 299 300} 301 302#ifdef FLOATX80 303 304/* 305------------------------------------------------------------------------------- 306The pattern for a default generated extended double-precision NaN. The 307`high' and `low' values hold the most- and least-significant bits, 308respectively. 309------------------------------------------------------------------------------- 310*/ 311#define floatx80_default_nan_high 0xFFFF 312#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 313 314/* 315------------------------------------------------------------------------------- 316Returns 1 if the extended double-precision floating-point value `a' is a 317NaN; otherwise returns 0. 318------------------------------------------------------------------------------- 319*/ 320flag floatx80_is_nan( floatx80 a ) 321{ 322 323 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); 324 325} 326 327/* 328------------------------------------------------------------------------------- 329Returns 1 if the extended double-precision floating-point value `a' is a 330signaling NaN; otherwise returns 0. 331------------------------------------------------------------------------------- 332*/ 333flag floatx80_is_signaling_nan( floatx80 a ) 334{ 335 bits64 aLow; 336 337 aLow = a.low & ~ LIT64( 0x4000000000000000 ); 338 return 339 ( ( a.high & 0x7FFF ) == 0x7FFF ) 340 && (bits64) ( aLow<<1 ) 341 && ( a.low == aLow ); 342 343} 344 345/* 346------------------------------------------------------------------------------- 347Returns the result of converting the extended double-precision floating- 348point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the 349invalid exception is raised. 350------------------------------------------------------------------------------- 351*/ 352static commonNaNT floatx80ToCommonNaN( floatx80 a ) 353{ 354 commonNaNT z; 355 356 if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 357 z.sign = a.high>>15; 358 z.low = 0; 359 z.high = a.low<<1; 360 return z; 361 362} 363 364/* 365------------------------------------------------------------------------------- 366Returns the result of converting the canonical NaN `a' to the extended 367double-precision floating-point format. 368------------------------------------------------------------------------------- 369*/ 370static floatx80 commonNaNToFloatx80( commonNaNT a ) 371{ 372 floatx80 z; 373 374 z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); 375 z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; 376 return z; 377 378} 379 380/* 381------------------------------------------------------------------------------- 382Takes two extended double-precision floating-point values `a' and `b', one 383of which is a NaN, and returns the appropriate NaN result. If either `a' or 384`b' is a signaling NaN, the invalid exception is raised. 385------------------------------------------------------------------------------- 386*/ 387static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) 388{ 389 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 390 391 aIsNaN = floatx80_is_nan( a ); 392 aIsSignalingNaN = floatx80_is_signaling_nan( a ); 393 bIsNaN = floatx80_is_nan( b ); 394 bIsSignalingNaN = floatx80_is_signaling_nan( b ); 395 a.low |= LIT64( 0xC000000000000000 ); 396 b.low |= LIT64( 0xC000000000000000 ); 397 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 398 if ( aIsNaN ) { 399 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 400 } 401 else { 402 return b; 403 } 404 405} 406 407#endif 408 409#ifdef FLOAT128 410 411/* 412------------------------------------------------------------------------------- 413The pattern for a default generated quadruple-precision NaN. The `high' and 414`low' values hold the most- and least-significant bits, respectively. 415------------------------------------------------------------------------------- 416*/ 417#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF ) 418#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 419 420/* 421------------------------------------------------------------------------------- 422Returns 1 if the quadruple-precision floating-point value `a' is a NaN; 423otherwise returns 0. 424------------------------------------------------------------------------------- 425*/ 426flag float128_is_nan( float128 a ) 427{ 428 429 return 430 ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) 431 && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); 432 433} 434 435/* 436------------------------------------------------------------------------------- 437Returns 1 if the quadruple-precision floating-point value `a' is a 438signaling NaN; otherwise returns 0. 439------------------------------------------------------------------------------- 440*/ 441flag float128_is_signaling_nan( float128 a ) 442{ 443 444 return 445 ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) 446 && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); 447 448} 449 450/* 451------------------------------------------------------------------------------- 452Returns the result of converting the quadruple-precision floating-point NaN 453`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 454exception is raised. 455------------------------------------------------------------------------------- 456*/ 457static commonNaNT float128ToCommonNaN( float128 a ) 458{ 459 commonNaNT z; 460 461 if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 462 z.sign = a.high>>63; 463 shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); 464 return z; 465 466} 467 468/* 469------------------------------------------------------------------------------- 470Returns the result of converting the canonical NaN `a' to the quadruple- 471precision floating-point format. 472------------------------------------------------------------------------------- 473*/ 474static float128 commonNaNToFloat128( commonNaNT a ) 475{ 476 float128 z; 477 478 shift128Right( a.high, a.low, 16, &z.high, &z.low ); 479 z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); 480 return z; 481 482} 483 484/* 485------------------------------------------------------------------------------- 486Takes two quadruple-precision floating-point values `a' and `b', one of 487which is a NaN, and returns the appropriate NaN result. If either `a' or 488`b' is a signaling NaN, the invalid exception is raised. 489------------------------------------------------------------------------------- 490*/ 491static float128 propagateFloat128NaN( float128 a, float128 b ) 492{ 493 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 494 495 aIsNaN = float128_is_nan( a ); 496 aIsSignalingNaN = float128_is_signaling_nan( a ); 497 bIsNaN = float128_is_nan( b ); 498 bIsSignalingNaN = float128_is_signaling_nan( b ); 499 a.high |= LIT64( 0x0000800000000000 ); 500 b.high |= LIT64( 0x0000800000000000 ); 501 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 502 if ( aIsNaN ) { 503 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 504 } 505 else { 506 return b; 507 } 508 509} 510 511#endif 512 513