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