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