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