1 2/* 3=============================================================================== 4 5This C source file is part of TestFloat, Release 2a, a package of programs 6for testing the correctness of floating-point arithmetic complying to the 7IEC/IEEE Standard for Floating-Point. 8 9Written by John R. Hauser. More information is available through the Web 10page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. 11 12THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort 13has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT 14TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO 15PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY 16AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. 17 18Derivative works are acceptable, even for commercial purposes, so long as 19(1) they include prominent notice that the work is derivative, and (2) they 20include prominent notice akin to these four paragraphs for those parts of 21this code that are retained. 22 23=============================================================================== 24*/ 25 26int8 slow_float_rounding_mode; 27int8 slow_float_exception_flags; 28int8 slow_float_detect_tininess; 29#ifdef FLOATX80 30int8 slow_floatx80_rounding_precision; 31#endif 32 33typedef struct { 34 bits64 a0, a1; 35} bits128X; 36 37typedef struct { 38 flag isNaN; 39 flag isInf; 40 flag isZero; 41 flag sign; 42 int32 exp; 43 bits128X sig; 44} floatX; 45 46static const floatX floatXNaN = { TRUE, FALSE, FALSE, FALSE, 0, { 0, 0 } }; 47static const floatX floatXPositiveZero = 48 { FALSE, FALSE, TRUE, FALSE, 0, { 0, 0 } }; 49static const floatX floatXNegativeZero = 50 { FALSE, FALSE, TRUE, TRUE, 0, { 0, 0 } }; 51 52static bits128X shortShift128Left( bits128X a, int8 shiftCount ) 53{ 54 int8 negShiftCount; 55 56 negShiftCount = ( - shiftCount & 63 ); 57 a.a0 = ( a.a0<<shiftCount ) | ( a.a1>>negShiftCount ); 58 a.a1 <<= shiftCount; 59 return a; 60 61} 62 63static bits128X shortShift128RightJamming( bits128X a, int8 shiftCount ) 64{ 65 int8 negShiftCount; 66 bits64 extra; 67 68 negShiftCount = ( - shiftCount & 63 ); 69 extra = a.a1<<negShiftCount; 70 a.a1 = ( a.a0<<negShiftCount ) | ( a.a1>>shiftCount ) | ( extra != 0 ); 71 a.a0 >>= shiftCount; 72 return a; 73 74} 75 76static bits128X neg128( bits128X a ) 77{ 78 79 if ( a.a1 == 0 ) { 80 a.a0 = - a.a0; 81 } 82 else { 83 a.a1 = - a.a1; 84 a.a0 = ~ a.a0; 85 } 86 return a; 87 88} 89 90static bits128X add128( bits128X a, bits128X b ) 91{ 92 93 a.a1 += b.a1; 94 a.a0 += b.a0 + ( a.a1 < b.a1 ); 95 return a; 96 97} 98 99static flag eq128( bits128X a, bits128X b ) 100{ 101 102 return ( a.a0 == b.a0 ) && ( a.a1 == b.a1 ); 103 104} 105 106static flag le128( bits128X a, bits128X b ) 107{ 108 109 return ( a.a0 < b.a0 ) || ( ( a.a0 == b.a0 ) && ( a.a1 <= b.a1 ) ); 110 111} 112 113static flag lt128( bits128X a, bits128X b ) 114{ 115 116 return ( a.a0 < b.a0 ) || ( ( a.a0 == b.a0 ) && ( a.a1 < b.a1 ) ); 117 118} 119 120static floatX roundFloatXTo24( flag isTiny, floatX zx ) 121{ 122 bits32 roundBits; 123 124 zx.sig.a0 |= ( zx.sig.a1 != 0 ); 125 zx.sig.a1 = 0; 126 roundBits = zx.sig.a0 & 0xFFFFFFFF; 127 zx.sig.a0 -= roundBits; 128 if ( roundBits ) { 129 slow_float_exception_flags |= float_flag_inexact; 130 if ( isTiny ) slow_float_exception_flags |= float_flag_underflow; 131 switch ( slow_float_rounding_mode ) { 132 case float_round_nearest_even: 133 if ( roundBits < 0x80000000 ) goto noIncrement; 134 if ( ( roundBits == 0x80000000 ) 135 && ! ( zx.sig.a0 & LIT64( 0x100000000 ) ) ) { 136 goto noIncrement; 137 } 138 break; 139 case float_round_to_zero: 140 goto noIncrement; 141 case float_round_down: 142 if ( ! zx.sign ) goto noIncrement; 143 break; 144 case float_round_up: 145 if ( zx.sign ) goto noIncrement; 146 break; 147 } 148 zx.sig.a0 += LIT64( 0x100000000 ); 149 if ( zx.sig.a0 == LIT64( 0x0100000000000000 ) ) { 150 zx.sig.a0 = LIT64( 0x0080000000000000 ); 151 ++zx.exp; 152 } 153 } 154 noIncrement: 155 return zx; 156 157} 158 159static floatX roundFloatXTo53( flag isTiny, floatX zx ) 160{ 161 int8 roundBits; 162 163 zx.sig.a0 |= ( zx.sig.a1 != 0 ); 164 zx.sig.a1 = 0; 165 roundBits = zx.sig.a0 & 7; 166 zx.sig.a0 -= roundBits; 167 if ( roundBits ) { 168 slow_float_exception_flags |= float_flag_inexact; 169 if ( isTiny ) slow_float_exception_flags |= float_flag_underflow; 170 switch ( slow_float_rounding_mode ) { 171 case float_round_nearest_even: 172 if ( roundBits < 4 ) goto noIncrement; 173 if ( ( roundBits == 4 ) && ! ( zx.sig.a0 & 8 ) ) goto noIncrement; 174 break; 175 case float_round_to_zero: 176 goto noIncrement; 177 case float_round_down: 178 if ( ! zx.sign ) goto noIncrement; 179 break; 180 case float_round_up: 181 if ( zx.sign ) goto noIncrement; 182 break; 183 } 184 zx.sig.a0 += 8; 185 if ( zx.sig.a0 == LIT64( 0x0100000000000000 ) ) { 186 zx.sig.a0 = LIT64( 0x0080000000000000 ); 187 ++zx.exp; 188 } 189 } 190 noIncrement: 191 return zx; 192 193} 194 195static floatX roundFloatXTo64( flag isTiny, floatX zx ) 196{ 197 int64 roundBits; 198 199 roundBits = zx.sig.a1 & LIT64( 0x00FFFFFFFFFFFFFF ); 200 zx.sig.a1 -= roundBits; 201 if ( roundBits ) { 202 slow_float_exception_flags |= float_flag_inexact; 203 if ( isTiny ) slow_float_exception_flags |= float_flag_underflow; 204 switch ( slow_float_rounding_mode ) { 205 case float_round_nearest_even: 206 if ( roundBits < LIT64( 0x0080000000000000 ) ) goto noIncrement; 207 if ( ( roundBits == LIT64( 0x0080000000000000 ) ) 208 && ! ( zx.sig.a1 & LIT64( 0x0100000000000000 ) ) ) { 209 goto noIncrement; 210 } 211 break; 212 case float_round_to_zero: 213 goto noIncrement; 214 case float_round_down: 215 if ( ! zx.sign ) goto noIncrement; 216 break; 217 case float_round_up: 218 if ( zx.sign ) goto noIncrement; 219 break; 220 } 221 zx.sig.a1 += LIT64( 0x0100000000000000 ); 222 zx.sig.a0 += ( zx.sig.a1 == 0 ); 223 if ( zx.sig.a0 == LIT64( 0x0100000000000000 ) ) { 224 zx.sig.a0 = LIT64( 0x0080000000000000 ); 225 ++zx.exp; 226 } 227 } 228 noIncrement: 229 return zx; 230 231} 232 233static floatX roundFloatXTo113( flag isTiny, floatX zx ) 234{ 235 int8 roundBits; 236 237 roundBits = zx.sig.a1 & 0x7F; 238 zx.sig.a1 -= roundBits; 239 if ( roundBits ) { 240 slow_float_exception_flags |= float_flag_inexact; 241 if ( isTiny ) slow_float_exception_flags |= float_flag_underflow; 242 switch ( slow_float_rounding_mode ) { 243 case float_round_nearest_even: 244 if ( roundBits < 0x40 ) goto noIncrement; 245 if ( ( roundBits == 0x40 ) 246 && ! ( zx.sig.a1 & 0x80 ) ) goto noIncrement; 247 break; 248 case float_round_to_zero: 249 goto noIncrement; 250 case float_round_down: 251 if ( ! zx.sign ) goto noIncrement; 252 break; 253 case float_round_up: 254 if ( zx.sign ) goto noIncrement; 255 break; 256 } 257 zx.sig.a1 += 0x80; 258 zx.sig.a0 += ( zx.sig.a1 == 0 ); 259 if ( zx.sig.a0 == LIT64( 0x0100000000000000 ) ) { 260 zx.sig.a0 = LIT64( 0x0080000000000000 ); 261 ++zx.exp; 262 } 263 } 264 noIncrement: 265 return zx; 266 267} 268 269static floatX int32ToFloatX( int32 a ) 270{ 271 floatX ax; 272 273 ax.isNaN = FALSE; 274 ax.isInf = FALSE; 275 ax.sign = ( a < 0 ); 276 ax.sig.a1 = 0; 277 ax.sig.a0 = ax.sign ? - (bits64) a : a; 278 if ( a == 0 ) { 279 ax.isZero = TRUE; 280 return ax; 281 } 282 ax.isZero = FALSE; 283 ax.sig.a0 <<= 24; 284 ax.exp = 31; 285 while ( ax.sig.a0 < LIT64( 0x0080000000000000 ) ) { 286 ax.sig.a0 <<= 1; 287 --ax.exp; 288 } 289 return ax; 290 291} 292 293static int32 floatXToInt32( floatX ax ) 294{ 295 int8 savedExceptionFlags; 296 int32 shiftCount; 297 int32 z; 298 299 if ( ax.isInf || ax.isNaN ) { 300 slow_float_exception_flags |= float_flag_invalid; 301 return ( ax.isInf & ax.sign ) ? (sbits32) 0x80000000 : 0x7FFFFFFF; 302 } 303 if ( ax.isZero ) return 0; 304 savedExceptionFlags = slow_float_exception_flags; 305 shiftCount = 52 - ax.exp; 306 if ( 56 < shiftCount ) { 307 ax.sig.a1 = 1; 308 ax.sig.a0 = 0; 309 } 310 else { 311 while ( 0 < shiftCount ) { 312 ax.sig = shortShift128RightJamming( ax.sig, 1 ); 313 --shiftCount; 314 } 315 } 316 ax = roundFloatXTo53( FALSE, ax ); 317 ax.sig = shortShift128RightJamming( ax.sig, 3 ); 318 z = ax.sig.a0; 319 if ( ax.sign ) z = - z; 320 if ( ( shiftCount < 0 ) 321 || ( ax.sig.a0>>32 ) 322 || ( ( z != 0 ) && ( ( ax.sign ^ ( z < 0 ) ) != 0 ) ) 323 ) { 324 slow_float_exception_flags = savedExceptionFlags | float_flag_invalid; 325 return ax.sign ? (sbits32) 0x80000000 : 0x7FFFFFFF; 326 } 327 return z; 328 329} 330 331static floatX int64ToFloatX( int64 a ) 332{ 333 uint64 absA; 334 floatX ax; 335 336 ax.isNaN = FALSE; 337 ax.isInf = FALSE; 338 ax.sign = ( a < 0 ); 339 ax.sig.a1 = ax.sign ? - a : a; 340 ax.sig.a0 = 0; 341 if ( a == 0 ) { 342 ax.isZero = TRUE; 343 return ax; 344 } 345 ax.isZero = FALSE; 346 ax.sig = shortShift128Left( ax.sig, 56 ); 347 ax.exp = 63; 348 while ( ax.sig.a0 < LIT64( 0x0080000000000000 ) ) { 349 ax.sig = shortShift128Left( ax.sig, 1 ); 350 --ax.exp; 351 } 352 return ax; 353 354} 355 356static int64 floatXToInt64( floatX ax ) 357{ 358 int8 savedExceptionFlags; 359 int32 shiftCount; 360 int64 z; 361 362 if ( ax.isInf || ax.isNaN ) { 363 slow_float_exception_flags |= float_flag_invalid; 364 return 365 ( ax.isInf & ax.sign ) ? (sbits64) LIT64( 0x8000000000000000 ) 366 : LIT64( 0x7FFFFFFFFFFFFFFF ); 367 } 368 if ( ax.isZero ) return 0; 369 savedExceptionFlags = slow_float_exception_flags; 370 shiftCount = 112 - ax.exp; 371 if ( 116 < shiftCount ) { 372 ax.sig.a1 = 1; 373 ax.sig.a0 = 0; 374 } 375 else { 376 while ( 0 < shiftCount ) { 377 ax.sig = shortShift128RightJamming( ax.sig, 1 ); 378 --shiftCount; 379 } 380 } 381 ax = roundFloatXTo113( FALSE, ax ); 382 ax.sig = shortShift128RightJamming( ax.sig, 7 ); 383 z = ax.sig.a1; 384 if ( ax.sign ) z = - z; 385 if ( ( shiftCount < 0 ) 386 || ax.sig.a0 387 || ( ( z != 0 ) && ( ( ax.sign ^ ( z < 0 ) ) != 0 ) ) 388 ) { 389 slow_float_exception_flags = savedExceptionFlags | float_flag_invalid; 390 return 391 ax.sign ? (sbits64) LIT64( 0x8000000000000000 ) 392 : LIT64( 0x7FFFFFFFFFFFFFFF ); 393 } 394 return z; 395 396} 397 398static floatX float32ToFloatX( float32 a ) 399{ 400 int16 expField; 401 floatX ax; 402 403 ax.isNaN = FALSE; 404 ax.isInf = FALSE; 405 ax.isZero = FALSE; 406 ax.sign = ( ( a & 0x80000000 ) != 0 ); 407 expField = ( a>>23 ) & 0xFF; 408 ax.sig.a1 = 0; 409 ax.sig.a0 = a & 0x007FFFFF; 410 ax.sig.a0 <<= 32; 411 if ( expField == 0 ) { 412 if ( ax.sig.a0 == 0 ) { 413 ax.isZero = TRUE; 414 } 415 else { 416 expField = 1 - 0x7F; 417 do { 418 ax.sig.a0 <<= 1; 419 --expField; 420 } while ( ax.sig.a0 < LIT64( 0x0080000000000000 ) ); 421 ax.exp = expField; 422 } 423 } 424 else if ( expField == 0xFF ) { 425 if ( ax.sig.a0 == 0 ) { 426 ax.isInf = TRUE; 427 } 428 else { 429 ax.isNaN = TRUE; 430 } 431 } 432 else { 433 ax.sig.a0 |= LIT64( 0x0080000000000000 ); 434 ax.exp = expField - 0x7F; 435 } 436 return ax; 437 438} 439 440static float32 floatXToFloat32( floatX zx ) 441{ 442 floatX savedZ; 443 flag isTiny; 444 int32 expField; 445 float32 z; 446 447 if ( zx.isZero ) return zx.sign ? 0x80000000 : 0; 448 if ( zx.isInf ) return zx.sign ? 0xFF800000 : 0x7F800000; 449 if ( zx.isNaN ) return 0xFFFFFFFF; 450 while ( LIT64( 0x0100000000000000 ) <= zx.sig.a0 ) { 451 zx.sig = shortShift128RightJamming( zx.sig, 1 ); 452 ++zx.exp; 453 } 454 while ( zx.sig.a0 < LIT64( 0x0080000000000000 ) ) { 455 zx.sig = shortShift128Left( zx.sig, 1 ); 456 --zx.exp; 457 } 458 savedZ = zx; 459 isTiny = 460 ( slow_float_detect_tininess == float_tininess_before_rounding ) 461 && ( zx.exp + 0x7F <= 0 ); 462 zx = roundFloatXTo24( isTiny, zx ); 463 expField = zx.exp + 0x7F; 464 if ( 0xFF <= expField ) { 465 slow_float_exception_flags |= 466 float_flag_overflow | float_flag_inexact; 467 if ( zx.sign ) { 468 switch ( slow_float_rounding_mode ) { 469 case float_round_nearest_even: 470 case float_round_down: 471 z = 0xFF800000; 472 break; 473 case float_round_to_zero: 474 case float_round_up: 475 z = 0xFF7FFFFF; 476 break; 477 } 478 } 479 else { 480 switch ( slow_float_rounding_mode ) { 481 case float_round_nearest_even: 482 case float_round_up: 483 z = 0x7F800000; 484 break; 485 case float_round_to_zero: 486 case float_round_down: 487 z = 0x7F7FFFFF; 488 break; 489 } 490 } 491 return z; 492 } 493 if ( expField <= 0 ) { 494 isTiny = TRUE; 495 zx = savedZ; 496 expField = zx.exp + 0x7F; 497 if ( expField < -27 ) { 498 zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 ); 499 zx.sig.a0 = 0; 500 } 501 else { 502 while ( expField <= 0 ) { 503 zx.sig = shortShift128RightJamming( zx.sig, 1 ); 504 ++expField; 505 } 506 } 507 zx = roundFloatXTo24( isTiny, zx ); 508 expField = ( LIT64( 0x0080000000000000 ) <= zx.sig.a0 ) ? 1 : 0; 509 } 510 z = expField; 511 z <<= 23; 512 if ( zx.sign ) z |= 0x80000000; 513 z |= ( zx.sig.a0>>32 ) & 0x007FFFFF; 514 return z; 515 516} 517 518static floatX float64ToFloatX( float64 a ) 519{ 520 int16 expField; 521 floatX ax; 522 523 ax.isNaN = FALSE; 524 ax.isInf = FALSE; 525 ax.isZero = FALSE; 526 ax.sign = ( ( a & LIT64( 0x8000000000000000 ) ) != 0 ); 527 expField = ( a>>52 ) & 0x7FF; 528 ax.sig.a1 = 0; 529 ax.sig.a0 = a & LIT64( 0x000FFFFFFFFFFFFF ); 530 if ( expField == 0 ) { 531 if ( ax.sig.a0 == 0 ) { 532 ax.isZero = TRUE; 533 } 534 else { 535 expField = 1 - 0x3FF; 536 do { 537 ax.sig.a0 <<= 1; 538 --expField; 539 } while ( ax.sig.a0 < LIT64( 0x0010000000000000 ) ); 540 ax.exp = expField; 541 } 542 } 543 else if ( expField == 0x7FF ) { 544 if ( ax.sig.a0 == 0 ) { 545 ax.isInf = TRUE; 546 } 547 else { 548 ax.isNaN = TRUE; 549 } 550 } 551 else { 552 ax.exp = expField - 0x3FF; 553 ax.sig.a0 |= LIT64( 0x0010000000000000 ); 554 } 555 ax.sig.a0 <<= 3; 556 return ax; 557 558} 559 560static float64 floatXToFloat64( floatX zx ) 561{ 562 floatX savedZ; 563 flag isTiny; 564 int32 expField; 565 float64 z; 566 567 if ( zx.isZero ) return zx.sign ? LIT64( 0x8000000000000000 ) : 0; 568 if ( zx.isInf ) { 569 return 570 zx.sign ? LIT64( 0xFFF0000000000000 ) 571 : LIT64( 0x7FF0000000000000 ); 572 } 573 if ( zx.isNaN ) return LIT64( 0xFFFFFFFFFFFFFFFF ); 574 while ( LIT64( 0x0100000000000000 ) <= zx.sig.a0 ) { 575 zx.sig = shortShift128RightJamming( zx.sig, 1 ); 576 ++zx.exp; 577 } 578 while ( zx.sig.a0 < LIT64( 0x0080000000000000 ) ) { 579 zx.sig = shortShift128Left( zx.sig, 1 ); 580 --zx.exp; 581 } 582 savedZ = zx; 583 isTiny = 584 ( slow_float_detect_tininess == float_tininess_before_rounding ) 585 && ( zx.exp + 0x3FF <= 0 ); 586 zx = roundFloatXTo53( isTiny, zx ); 587 expField = zx.exp + 0x3FF; 588 if ( 0x7FF <= expField ) { 589 slow_float_exception_flags |= 590 float_flag_overflow | float_flag_inexact; 591 if ( zx.sign ) { 592 switch ( slow_float_rounding_mode ) { 593 case float_round_nearest_even: 594 case float_round_down: 595 z = LIT64( 0xFFF0000000000000 ); 596 break; 597 case float_round_to_zero: 598 case float_round_up: 599 z = LIT64( 0xFFEFFFFFFFFFFFFF ); 600 break; 601 } 602 } 603 else { 604 switch ( slow_float_rounding_mode ) { 605 case float_round_nearest_even: 606 case float_round_up: 607 z = LIT64( 0x7FF0000000000000 ); 608 break; 609 case float_round_to_zero: 610 case float_round_down: 611 z = LIT64( 0x7FEFFFFFFFFFFFFF ); 612 break; 613 } 614 } 615 return z; 616 } 617 if ( expField <= 0 ) { 618 isTiny = TRUE; 619 zx = savedZ; 620 expField = zx.exp + 0x3FF; 621 if ( expField < -56 ) { 622 zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 ); 623 zx.sig.a0 = 0; 624 } 625 else { 626 while ( expField <= 0 ) { 627 zx.sig = shortShift128RightJamming( zx.sig, 1 ); 628 ++expField; 629 } 630 } 631 zx = roundFloatXTo53( isTiny, zx ); 632 expField = ( LIT64( 0x0080000000000000 ) <= zx.sig.a0 ) ? 1 : 0; 633 } 634 zx.sig.a0 >>= 3; 635 z = expField; 636 z <<= 52; 637 if ( zx.sign ) z |= LIT64( 0x8000000000000000 ); 638 z |= zx.sig.a0 & LIT64( 0x000FFFFFFFFFFFFF ); 639 return z; 640 641} 642 643#ifdef FLOATX80 644 645static floatX floatx80ToFloatX( floatx80 a ) 646{ 647 int32 expField; 648 floatX ax; 649 650 ax.isNaN = FALSE; 651 ax.isInf = FALSE; 652 ax.isZero = FALSE; 653 ax.sign = ( ( a.high & 0x8000 ) != 0 ); 654 expField = a.high & 0x7FFF; 655 ax.sig.a1 = a.low; 656 ax.sig.a0 = 0; 657 if ( expField == 0 ) { 658 if ( ax.sig.a1 == 0 ) { 659 ax.isZero = TRUE; 660 } 661 else { 662 expField = 1 - 0x3FFF; 663 while ( ax.sig.a1 < LIT64( 0x8000000000000000 ) ) { 664 ax.sig.a1 <<= 1; 665 --expField; 666 } 667 ax.exp = expField; 668 } 669 } 670 else if ( expField == 0x7FFF ) { 671 if ( ( ax.sig.a1 & LIT64( 0x7FFFFFFFFFFFFFFF ) ) == 0 ) { 672 ax.isInf = TRUE; 673 } 674 else { 675 ax.isNaN = TRUE; 676 } 677 } 678 else { 679 ax.exp = expField - 0x3FFF; 680 } 681 ax.sig = shortShift128Left( ax.sig, 56 ); 682 return ax; 683 684} 685 686static floatx80 floatXToFloatx80( floatX zx ) 687{ 688 floatX savedZ; 689 flag isTiny; 690 int32 expField; 691 floatx80 z; 692 693 if ( zx.isZero ) { 694 z.low = 0; 695 z.high = zx.sign ? 0x8000 : 0; 696 return z; 697 } 698 if ( zx.isInf ) { 699 z.low = LIT64( 0x8000000000000000 ); 700 z.high = zx.sign ? 0xFFFF : 0x7FFF; 701 return z; 702 } 703 if ( zx.isNaN ) { 704 z.low = LIT64( 0xFFFFFFFFFFFFFFFF ); 705 z.high = 0xFFFF; 706 return z; 707 } 708 while ( LIT64( 0x0100000000000000 ) <= zx.sig.a0 ) { 709 zx.sig = shortShift128RightJamming( zx.sig, 1 ); 710 ++zx.exp; 711 } 712 while ( zx.sig.a0 < LIT64( 0x0080000000000000 ) ) { 713 zx.sig = shortShift128Left( zx.sig, 1 ); 714 --zx.exp; 715 } 716 savedZ = zx; 717 isTiny = 718 ( slow_float_detect_tininess == float_tininess_before_rounding ) 719 && ( zx.exp + 0x3FFF <= 0 ); 720 switch ( slow_floatx80_rounding_precision ) { 721 case 32: 722 zx = roundFloatXTo24( isTiny, zx ); 723 break; 724 case 64: 725 zx = roundFloatXTo53( isTiny, zx ); 726 break; 727 default: 728 zx = roundFloatXTo64( isTiny, zx ); 729 break; 730 } 731 expField = zx.exp + 0x3FFF; 732 if ( 0x7FFF <= expField ) { 733 slow_float_exception_flags |= 734 float_flag_overflow | float_flag_inexact; 735 if ( zx.sign ) { 736 switch ( slow_float_rounding_mode ) { 737 case float_round_nearest_even: 738 case float_round_down: 739 z.low = LIT64( 0x8000000000000000 ); 740 z.high = 0xFFFF; 741 break; 742 case float_round_to_zero: 743 case float_round_up: 744 switch ( slow_floatx80_rounding_precision ) { 745 case 32: 746 z.low = LIT64( 0xFFFFFF0000000000 ); 747 break; 748 case 64: 749 z.low = LIT64( 0xFFFFFFFFFFFFF800 ); 750 break; 751 default: 752 z.low = LIT64( 0xFFFFFFFFFFFFFFFF ); 753 break; 754 } 755 z.high = 0xFFFE; 756 break; 757 } 758 } 759 else { 760 switch ( slow_float_rounding_mode ) { 761 case float_round_nearest_even: 762 case float_round_up: 763 z.low = LIT64( 0x8000000000000000 ); 764 z.high = 0x7FFF; 765 break; 766 case float_round_to_zero: 767 case float_round_down: 768 switch ( slow_floatx80_rounding_precision ) { 769 case 32: 770 z.low = LIT64( 0xFFFFFF0000000000 ); 771 break; 772 case 64: 773 z.low = LIT64( 0xFFFFFFFFFFFFF800 ); 774 break; 775 default: 776 z.low = LIT64( 0xFFFFFFFFFFFFFFFF ); 777 break; 778 } 779 z.high = 0x7FFE; 780 break; 781 } 782 } 783 return z; 784 } 785 if ( expField <= 0 ) { 786 isTiny = TRUE; 787 zx = savedZ; 788 expField = zx.exp + 0x3FFF; 789 if ( expField < -70 ) { 790 zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 ); 791 zx.sig.a0 = 0; 792 } 793 else { 794 while ( expField <= 0 ) { 795 zx.sig = shortShift128RightJamming( zx.sig, 1 ); 796 ++expField; 797 } 798 } 799 switch ( slow_floatx80_rounding_precision ) { 800 case 32: 801 zx = roundFloatXTo24( isTiny, zx ); 802 break; 803 case 64: 804 zx = roundFloatXTo53( isTiny, zx ); 805 break; 806 default: 807 zx = roundFloatXTo64( isTiny, zx ); 808 break; 809 } 810 expField = ( LIT64( 0x0080000000000000 ) <= zx.sig.a0 ) ? 1 : 0; 811 } 812 zx.sig = shortShift128RightJamming( zx.sig, 56 ); 813 z.low = zx.sig.a1; 814 z.high = expField; 815 if ( zx.sign ) z.high |= 0x8000; 816 return z; 817 818} 819 820#endif 821 822#ifdef FLOAT128 823 824static floatX float128ToFloatX( float128 a ) 825{ 826 int32 expField; 827 floatX ax; 828 829 ax.isNaN = FALSE; 830 ax.isInf = FALSE; 831 ax.isZero = FALSE; 832 ax.sign = ( ( a.high & LIT64( 0x8000000000000000 ) ) != 0 ); 833 expField = ( a.high>>48 ) & 0x7FFF; 834 ax.sig.a1 = a.low; 835 ax.sig.a0 = a.high & LIT64( 0x0000FFFFFFFFFFFF ); 836 if ( expField == 0 ) { 837 if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) { 838 ax.isZero = TRUE; 839 } 840 else { 841 expField = 1 - 0x3FFF; 842 do { 843 ax.sig = shortShift128Left( ax.sig, 1 ); 844 --expField; 845 } while ( ax.sig.a0 < LIT64( 0x0001000000000000 ) ); 846 ax.exp = expField; 847 } 848 } 849 else if ( expField == 0x7FFF ) { 850 if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) { 851 ax.isInf = TRUE; 852 } 853 else { 854 ax.isNaN = TRUE; 855 } 856 } 857 else { 858 ax.exp = expField - 0x3FFF; 859 ax.sig.a0 |= LIT64( 0x0001000000000000 ); 860 } 861 ax.sig = shortShift128Left( ax.sig, 7 ); 862 return ax; 863 864} 865 866static float128 floatXToFloat128( floatX zx ) 867{ 868 floatX savedZ; 869 flag isTiny; 870 int32 expField; 871 float128 z; 872 873 if ( zx.isZero ) { 874 z.low = 0; 875 z.high = zx.sign ? LIT64( 0x8000000000000000 ) : 0; 876 return z; 877 } 878 if ( zx.isInf ) { 879 z.low = 0; 880 z.high = 881 zx.sign ? LIT64( 0xFFFF000000000000 ) 882 : LIT64( 0x7FFF000000000000 ); 883 return z; 884 } 885 if ( zx.isNaN ) { 886 z.high = z.low = LIT64( 0xFFFFFFFFFFFFFFFF ); 887 return z; 888 } 889 while ( LIT64( 0x0100000000000000 ) <= zx.sig.a0 ) { 890 zx.sig = shortShift128RightJamming( zx.sig, 1 ); 891 ++zx.exp; 892 } 893 while ( zx.sig.a0 < LIT64( 0x0080000000000000 ) ) { 894 zx.sig = shortShift128Left( zx.sig, 1 ); 895 --zx.exp; 896 } 897 savedZ = zx; 898 isTiny = 899 ( slow_float_detect_tininess == float_tininess_before_rounding ) 900 && ( zx.exp + 0x3FFF <= 0 ); 901 zx = roundFloatXTo113( isTiny, zx ); 902 expField = zx.exp + 0x3FFF; 903 if ( 0x7FFF <= expField ) { 904 slow_float_exception_flags |= 905 float_flag_overflow | float_flag_inexact; 906 if ( zx.sign ) { 907 switch ( slow_float_rounding_mode ) { 908 case float_round_nearest_even: 909 case float_round_down: 910 z.low = 0; 911 z.high = LIT64( 0xFFFF000000000000 ); 912 break; 913 case float_round_to_zero: 914 case float_round_up: 915 z.low = LIT64( 0xFFFFFFFFFFFFFFFF ); 916 z.high = LIT64( 0xFFFEFFFFFFFFFFFF ); 917 break; 918 } 919 } 920 else { 921 switch ( slow_float_rounding_mode ) { 922 case float_round_nearest_even: 923 case float_round_up: 924 z.low = 0; 925 z.high = LIT64( 0x7FFF000000000000 ); 926 break; 927 case float_round_to_zero: 928 case float_round_down: 929 z.low = LIT64( 0xFFFFFFFFFFFFFFFF ); 930 z.high = LIT64( 0x7FFEFFFFFFFFFFFF ); 931 break; 932 } 933 } 934 return z; 935 } 936 if ( expField <= 0 ) { 937 isTiny = TRUE; 938 zx = savedZ; 939 expField = zx.exp + 0x3FFF; 940 if ( expField < -120 ) { 941 zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 ); 942 zx.sig.a0 = 0; 943 } 944 else { 945 while ( expField <= 0 ) { 946 zx.sig = shortShift128RightJamming( zx.sig, 1 ); 947 ++expField; 948 } 949 } 950 zx = roundFloatXTo113( isTiny, zx ); 951 expField = ( LIT64( 0x0080000000000000 ) <= zx.sig.a0 ) ? 1 : 0; 952 } 953 zx.sig = shortShift128RightJamming( zx.sig, 7 ); 954 z.low = zx.sig.a1; 955 z.high = expField; 956 z.high <<= 48; 957 if ( zx.sign ) z.high |= LIT64( 0x8000000000000000 ); 958 z.high |= zx.sig.a0 & LIT64( 0x0000FFFFFFFFFFFF ); 959 return z; 960 961} 962 963#endif 964 965static floatX floatXInvalid( void ) 966{ 967 968 slow_float_exception_flags |= float_flag_invalid; 969 return floatXNaN; 970 971} 972 973static floatX floatXRoundToInt( floatX ax ) 974{ 975 int32 shiftCount, i; 976 977 if ( ax.isNaN || ax.isInf ) return ax; 978 shiftCount = 112 - ax.exp; 979 if ( shiftCount <= 0 ) return ax; 980 if ( 119 < shiftCount ) { 981 ax.exp = 112; 982 ax.sig.a1 = ! ax.isZero; 983 ax.sig.a0 = 0; 984 } 985 else { 986 while ( 0 < shiftCount ) { 987 ax.sig = shortShift128RightJamming( ax.sig, 1 ); 988 ++ax.exp; 989 --shiftCount; 990 } 991 } 992 ax = roundFloatXTo113( FALSE, ax ); 993 if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) ax.isZero = TRUE; 994 return ax; 995 996} 997 998static floatX floatXAdd( floatX ax, floatX bx ) 999{ 1000 int32 expDiff; 1001 floatX zx; 1002 1003 if ( ax.isNaN ) return ax; 1004 if ( bx.isNaN ) return bx; 1005 if ( ax.isInf && bx.isInf ) { 1006 if ( ax.sign == bx.sign ) return ax; 1007 return floatXInvalid(); 1008 } 1009 if ( ax.isInf ) return ax; 1010 if ( bx.isInf ) return bx; 1011 if ( ax.isZero && bx.isZero ) { 1012 if ( ax.sign == bx.sign ) return ax; 1013 goto completeCancellation; 1014 } 1015 if ( ( ax.sign != bx.sign ) 1016 && ( ax.exp == bx.exp ) 1017 && eq128( ax.sig, bx.sig ) 1018 ) { 1019 completeCancellation: 1020 return 1021 ( slow_float_rounding_mode == float_round_down ) ? 1022 floatXNegativeZero 1023 : floatXPositiveZero; 1024 } 1025 if ( ax.isZero ) return bx; 1026 if ( bx.isZero ) return ax; 1027 expDiff = ax.exp - bx.exp; 1028 if ( expDiff < 0 ) { 1029 zx = ax; 1030 zx.exp = bx.exp; 1031 if ( expDiff < -120 ) { 1032 zx.sig.a1 = 1; 1033 zx.sig.a0 = 0; 1034 } 1035 else { 1036 while ( expDiff < 0 ) { 1037 zx.sig = shortShift128RightJamming( zx.sig, 1 ); 1038 ++expDiff; 1039 } 1040 } 1041 if ( ax.sign != bx.sign ) zx.sig = neg128( zx.sig ); 1042 zx.sign = bx.sign; 1043 zx.sig = add128( zx.sig, bx.sig ); 1044 } 1045 else { 1046 zx = bx; 1047 zx.exp = ax.exp; 1048 if ( 120 < expDiff ) { 1049 zx.sig.a1 = 1; 1050 zx.sig.a0 = 0; 1051 } 1052 else { 1053 while ( 0 < expDiff ) { 1054 zx.sig = shortShift128RightJamming( zx.sig, 1 ); 1055 --expDiff; 1056 } 1057 } 1058 if ( ax.sign != bx.sign ) zx.sig = neg128( zx.sig ); 1059 zx.sign = ax.sign; 1060 zx.sig = add128( zx.sig, ax.sig ); 1061 } 1062 if ( zx.sig.a0 & LIT64( 0x8000000000000000 ) ) { 1063 zx.sig = neg128( zx.sig ); 1064 zx.sign = ! zx.sign; 1065 } 1066 return zx; 1067 1068} 1069 1070static floatX floatXMul( floatX ax, floatX bx ) 1071{ 1072 int8 bitNum; 1073 floatX zx; 1074 1075 if ( ax.isNaN ) return ax; 1076 if ( bx.isNaN ) return bx; 1077 if ( ax.isInf ) { 1078 if ( bx.isZero ) return floatXInvalid(); 1079 if ( bx.sign ) ax.sign = ! ax.sign; 1080 return ax; 1081 } 1082 if ( bx.isInf ) { 1083 if ( ax.isZero ) return floatXInvalid(); 1084 if ( ax.sign ) bx.sign = ! bx.sign; 1085 return bx; 1086 } 1087 zx = ax; 1088 zx.sign ^= bx.sign; 1089 if ( ax.isZero || bx.isZero ) { 1090 return zx.sign ? floatXNegativeZero : floatXPositiveZero; 1091 } 1092 zx.exp += bx.exp + 1; 1093 zx.sig.a1 = 0; 1094 zx.sig.a0 = 0; 1095 for ( bitNum = 0; bitNum < 119; ++bitNum ) { 1096 if ( bx.sig.a1 & 2 ) zx.sig = add128( zx.sig, ax.sig ); 1097 bx.sig = shortShift128RightJamming( bx.sig, 1 ); 1098 zx.sig = shortShift128RightJamming( zx.sig, 1 ); 1099 } 1100 return zx; 1101 1102} 1103 1104static floatX floatXDiv( floatX ax, floatX bx ) 1105{ 1106 bits128X negBSig; 1107 int8 bitNum; 1108 floatX zx; 1109 1110 if ( ax.isNaN ) return ax; 1111 if ( bx.isNaN ) return bx; 1112 if ( ax.isInf ) { 1113 if ( bx.isInf ) return floatXInvalid(); 1114 if ( bx.sign ) ax.sign = ! ax.sign; 1115 return ax; 1116 } 1117 if ( bx.isZero ) { 1118 if ( ax.isZero ) return floatXInvalid(); 1119 slow_float_exception_flags |= float_flag_divbyzero; 1120 if ( ax.sign ) bx.sign = ! bx.sign; 1121 bx.isZero = FALSE; 1122 bx.isInf = TRUE; 1123 return bx; 1124 } 1125 zx = ax; 1126 zx.sign ^= bx.sign; 1127 if ( ax.isZero || bx.isInf ) { 1128 return zx.sign ? floatXNegativeZero : floatXPositiveZero; 1129 } 1130 zx.exp -= bx.exp + 1; 1131 zx.sig.a1 = 0; 1132 zx.sig.a0 = 0; 1133 negBSig = neg128( bx.sig ); 1134 for ( bitNum = 0; bitNum < 120; ++bitNum ) { 1135 if ( le128( bx.sig, ax.sig ) ) { 1136 zx.sig.a1 |= 1; 1137 ax.sig = add128( ax.sig, negBSig ); 1138 } 1139 ax.sig = shortShift128Left( ax.sig, 1 ); 1140 zx.sig = shortShift128Left( zx.sig, 1 ); 1141 } 1142 if ( ax.sig.a0 || ax.sig.a1 ) zx.sig.a1 |= 1; 1143 return zx; 1144 1145} 1146 1147static floatX floatXRem( floatX ax, floatX bx ) 1148{ 1149 bits128X negBSig; 1150 flag lastQuotientBit; 1151 bits128X savedASig; 1152 1153 if ( ax.isNaN ) return ax; 1154 if ( bx.isNaN ) return bx; 1155 if ( ax.isInf || bx.isZero ) return floatXInvalid(); 1156 if ( ax.isZero || bx.isInf ) return ax; 1157 --bx.exp; 1158 if ( ax.exp < bx.exp ) return ax; 1159 bx.sig = shortShift128Left( bx.sig, 1 ); 1160 negBSig = neg128( bx.sig ); 1161 while ( bx.exp < ax.exp ) { 1162 if ( le128( bx.sig, ax.sig ) ) ax.sig = add128( ax.sig, negBSig ); 1163 ax.sig = shortShift128Left( ax.sig, 1 ); 1164 --ax.exp; 1165 } 1166 lastQuotientBit = le128( bx.sig, ax.sig ); 1167 if ( lastQuotientBit ) ax.sig = add128( ax.sig, negBSig ); 1168 savedASig = ax.sig; 1169 ax.sig = neg128( add128( ax.sig, negBSig ) ); 1170 if ( lt128( ax.sig, savedASig ) ) { 1171 ax.sign = ! ax.sign; 1172 } 1173 else if ( lt128( savedASig, ax.sig ) ) { 1174 ax.sig = savedASig; 1175 } 1176 else { 1177 if ( lastQuotientBit ) { 1178 ax.sign = ! ax.sign; 1179 } 1180 else { 1181 ax.sig = savedASig; 1182 } 1183 } 1184 if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) ax.isZero = TRUE; 1185 return ax; 1186 1187} 1188 1189static floatX floatXSqrt( floatX ax ) 1190{ 1191 int8 bitNum; 1192 bits128X bitSig, savedASig; 1193 floatX zx; 1194 1195 if ( ax.isNaN || ax.isZero ) return ax; 1196 if ( ax.sign ) return floatXInvalid(); 1197 if ( ax.isInf ) return ax; 1198 zx = ax; 1199 zx.exp >>= 1; 1200 if ( ( ax.exp & 1 ) == 0 ) ax.sig = shortShift128RightJamming( ax.sig, 1 ); 1201 zx.sig.a1 = 0; 1202 zx.sig.a0 = 0; 1203 bitSig.a1 = 0; 1204 bitSig.a0 = LIT64( 0x0080000000000000 ); 1205 for ( bitNum = 0; bitNum < 120; ++bitNum ) { 1206 savedASig = ax.sig; 1207 ax.sig = add128( ax.sig, neg128( zx.sig ) ); 1208 ax.sig = shortShift128Left( ax.sig, 1 ); 1209 ax.sig = add128( ax.sig, neg128( bitSig ) ); 1210 if ( ax.sig.a0 & LIT64( 0x8000000000000000 ) ) { 1211 ax.sig = shortShift128Left( savedASig, 1 ); 1212 } 1213 else { 1214 zx.sig.a1 |= bitSig.a1; 1215 zx.sig.a0 |= bitSig.a0; 1216 } 1217 bitSig = shortShift128RightJamming( bitSig, 1 ); 1218 } 1219 if ( ax.sig.a0 || ax.sig.a1 ) zx.sig.a1 |= 1; 1220 return zx; 1221 1222} 1223 1224static flag floatXEq( floatX ax, floatX bx ) 1225{ 1226 1227 if ( ax.isNaN || bx.isNaN ) return FALSE; 1228 if ( ax.isZero && bx.isZero ) return TRUE; 1229 if ( ax.sign != bx.sign ) return FALSE; 1230 if ( ax.isInf || bx.isInf ) return ax.isInf && bx.isInf; 1231 return ( ax.exp == bx.exp ) && eq128( ax.sig, bx.sig ); 1232 1233} 1234 1235static flag floatXLe( floatX ax, floatX bx ) 1236{ 1237 1238 if ( ax.isNaN || bx.isNaN ) return FALSE; 1239 if ( ax.isZero && bx.isZero ) return TRUE; 1240 if ( ax.sign != bx.sign ) return ax.sign; 1241 if ( ax.sign ) { 1242 if ( ax.isInf || bx.isZero ) return TRUE; 1243 if ( bx.isInf || ax.isZero ) return FALSE; 1244 if ( bx.exp < ax.exp ) return TRUE; 1245 if ( ax.exp < bx.exp ) return FALSE; 1246 return le128( bx.sig, ax.sig ); 1247 } 1248 else { 1249 if ( bx.isInf || ax.isZero ) return TRUE; 1250 if ( ax.isInf || bx.isZero ) return FALSE; 1251 if ( ax.exp < bx.exp ) return TRUE; 1252 if ( bx.exp < ax.exp ) return FALSE; 1253 return le128( ax.sig, bx.sig ); 1254 } 1255 1256} 1257 1258static flag floatXLt( floatX ax, floatX bx ) 1259{ 1260 1261 if ( ax.isNaN || bx.isNaN ) return FALSE; 1262 if ( ax.isZero && bx.isZero ) return FALSE; 1263 if ( ax.sign != bx.sign ) return ax.sign; 1264 if ( ax.isInf && bx.isInf ) return FALSE; 1265 if ( ax.sign ) { 1266 if ( ax.isInf || bx.isZero ) return TRUE; 1267 if ( bx.isInf || ax.isZero ) return FALSE; 1268 if ( bx.exp < ax.exp ) return TRUE; 1269 if ( ax.exp < bx.exp ) return FALSE; 1270 return lt128( bx.sig, ax.sig ); 1271 } 1272 else { 1273 if ( bx.isInf || ax.isZero ) return TRUE; 1274 if ( ax.isInf || bx.isZero ) return FALSE; 1275 if ( ax.exp < bx.exp ) return TRUE; 1276 if ( bx.exp < ax.exp ) return FALSE; 1277 return lt128( ax.sig, bx.sig ); 1278 } 1279 1280} 1281 1282float32 slow_int32_to_float32( int32 a ) 1283{ 1284 1285 return floatXToFloat32( int32ToFloatX( a ) ); 1286 1287} 1288 1289float64 slow_int32_to_float64( int32 a ) 1290{ 1291 1292 return floatXToFloat64( int32ToFloatX( a ) ); 1293 1294} 1295 1296#ifdef FLOATX80 1297 1298floatx80 slow_int32_to_floatx80( int32 a ) 1299{ 1300 1301 return floatXToFloatx80( int32ToFloatX( a ) ); 1302 1303} 1304 1305#endif 1306 1307#ifdef FLOAT128 1308 1309float128 slow_int32_to_float128( int32 a ) 1310{ 1311 1312 return floatXToFloat128( int32ToFloatX( a ) ); 1313 1314} 1315 1316#endif 1317 1318float32 slow_int64_to_float32( int64 a ) 1319{ 1320 1321 return floatXToFloat32( int64ToFloatX( a ) ); 1322 1323} 1324 1325float64 slow_int64_to_float64( int64 a ) 1326{ 1327 1328 return floatXToFloat64( int64ToFloatX( a ) ); 1329 1330} 1331 1332#ifdef FLOATX80 1333 1334floatx80 slow_int64_to_floatx80( int64 a ) 1335{ 1336 1337 return floatXToFloatx80( int64ToFloatX( a ) ); 1338 1339} 1340 1341#endif 1342 1343#ifdef FLOAT128 1344 1345float128 slow_int64_to_float128( int64 a ) 1346{ 1347 1348 return floatXToFloat128( int64ToFloatX( a ) ); 1349 1350} 1351 1352#endif 1353 1354int32 slow_float32_to_int32( float32 a ) 1355{ 1356 1357 return floatXToInt32( float32ToFloatX( a ) ); 1358 1359} 1360 1361int32 slow_float32_to_int32_round_to_zero( float32 a ) 1362{ 1363 int8 savedRoundingMode; 1364 int32 z; 1365 1366 savedRoundingMode = slow_float_rounding_mode; 1367 slow_float_rounding_mode = float_round_to_zero; 1368 z = floatXToInt32( float32ToFloatX( a ) ); 1369 slow_float_rounding_mode = savedRoundingMode; 1370 return z; 1371 1372} 1373 1374int64 slow_float32_to_int64( float32 a ) 1375{ 1376 1377 return floatXToInt64( float32ToFloatX( a ) ); 1378 1379} 1380 1381int64 slow_float32_to_int64_round_to_zero( float32 a ) 1382{ 1383 int8 savedRoundingMode; 1384 int64 z; 1385 1386 savedRoundingMode = slow_float_rounding_mode; 1387 slow_float_rounding_mode = float_round_to_zero; 1388 z = floatXToInt64( float32ToFloatX( a ) ); 1389 slow_float_rounding_mode = savedRoundingMode; 1390 return z; 1391 1392} 1393 1394float64 slow_float32_to_float64( float32 a ) 1395{ 1396 1397 return floatXToFloat64( float32ToFloatX( a ) ); 1398 1399} 1400 1401#ifdef FLOATX80 1402 1403floatx80 slow_float32_to_floatx80( float32 a ) 1404{ 1405 1406 return floatXToFloatx80( float32ToFloatX( a ) ); 1407 1408} 1409 1410#endif 1411 1412#ifdef FLOAT128 1413 1414float128 slow_float32_to_float128( float32 a ) 1415{ 1416 1417 return floatXToFloat128( float32ToFloatX( a ) ); 1418 1419} 1420 1421#endif 1422 1423float32 slow_float32_round_to_int( float32 a ) 1424{ 1425 1426 return floatXToFloat32( floatXRoundToInt( float32ToFloatX( a ) ) ); 1427 1428} 1429 1430float32 slow_float32_add( float32 a, float32 b ) 1431{ 1432 1433 return 1434 floatXToFloat32( 1435 floatXAdd( float32ToFloatX( a ), float32ToFloatX( b ) ) ); 1436 1437} 1438 1439float32 slow_float32_sub( float32 a, float32 b ) 1440{ 1441 1442 b ^= 0x80000000; 1443 return 1444 floatXToFloat32( 1445 floatXAdd( float32ToFloatX( a ), float32ToFloatX( b ) ) ); 1446 1447} 1448 1449float32 slow_float32_mul( float32 a, float32 b ) 1450{ 1451 1452 return 1453 floatXToFloat32( 1454 floatXMul( float32ToFloatX( a ), float32ToFloatX( b ) ) ); 1455 1456} 1457 1458float32 slow_float32_div( float32 a, float32 b ) 1459{ 1460 1461 return 1462 floatXToFloat32( 1463 floatXDiv( float32ToFloatX( a ), float32ToFloatX( b ) ) ); 1464 1465} 1466 1467float32 slow_float32_rem( float32 a, float32 b ) 1468{ 1469 1470 return 1471 floatXToFloat32( 1472 floatXRem( float32ToFloatX( a ), float32ToFloatX( b ) ) ); 1473 1474} 1475 1476float32 slow_float32_sqrt( float32 a ) 1477{ 1478 1479 return floatXToFloat32( floatXSqrt( float32ToFloatX( a ) ) ); 1480 1481} 1482 1483flag slow_float32_eq( float32 a, float32 b ) 1484{ 1485 1486 return floatXEq( float32ToFloatX( a ), float32ToFloatX( b ) ); 1487 1488} 1489 1490flag slow_float32_le( float32 a, float32 b ) 1491{ 1492 floatX ax, bx; 1493 1494 ax = float32ToFloatX( a ); 1495 bx = float32ToFloatX( b ); 1496 if ( ax.isNaN || bx.isNaN ) { 1497 slow_float_exception_flags |= float_flag_invalid; 1498 } 1499 return floatXLe( ax, bx ); 1500 1501} 1502 1503flag slow_float32_lt( float32 a, float32 b ) 1504{ 1505 floatX ax, bx; 1506 1507 ax = float32ToFloatX( a ); 1508 bx = float32ToFloatX( b ); 1509 if ( ax.isNaN || bx.isNaN ) { 1510 slow_float_exception_flags |= float_flag_invalid; 1511 } 1512 return floatXLt( ax, bx ); 1513 1514} 1515 1516flag slow_float32_eq_signaling( float32 a, float32 b ) 1517{ 1518 floatX ax, bx; 1519 1520 ax = float32ToFloatX( a ); 1521 bx = float32ToFloatX( b ); 1522 if ( ax.isNaN || bx.isNaN ) { 1523 slow_float_exception_flags |= float_flag_invalid; 1524 } 1525 return floatXEq( ax, bx ); 1526 1527} 1528 1529flag slow_float32_le_quiet( float32 a, float32 b ) 1530{ 1531 1532 return floatXLe( float32ToFloatX( a ), float32ToFloatX( b ) ); 1533 1534} 1535 1536flag slow_float32_lt_quiet( float32 a, float32 b ) 1537{ 1538 1539 return floatXLt( float32ToFloatX( a ), float32ToFloatX( b ) ); 1540 1541} 1542 1543int32 slow_float64_to_int32( float64 a ) 1544{ 1545 1546 return floatXToInt32( float64ToFloatX( a ) ); 1547 1548} 1549 1550int32 slow_float64_to_int32_round_to_zero( float64 a ) 1551{ 1552 int8 savedRoundingMode; 1553 int32 z; 1554 1555 savedRoundingMode = slow_float_rounding_mode; 1556 slow_float_rounding_mode = float_round_to_zero; 1557 z = floatXToInt32( float64ToFloatX( a ) ); 1558 slow_float_rounding_mode = savedRoundingMode; 1559 return z; 1560 1561} 1562 1563int64 slow_float64_to_int64( float64 a ) 1564{ 1565 1566 return floatXToInt64( float64ToFloatX( a ) ); 1567 1568} 1569 1570int64 slow_float64_to_int64_round_to_zero( float64 a ) 1571{ 1572 int8 savedRoundingMode; 1573 int64 z; 1574 1575 savedRoundingMode = slow_float_rounding_mode; 1576 slow_float_rounding_mode = float_round_to_zero; 1577 z = floatXToInt64( float64ToFloatX( a ) ); 1578 slow_float_rounding_mode = savedRoundingMode; 1579 return z; 1580 1581} 1582 1583float32 slow_float64_to_float32( float64 a ) 1584{ 1585 1586 return floatXToFloat32( float64ToFloatX( a ) ); 1587 1588} 1589 1590#ifdef FLOATX80 1591 1592floatx80 slow_float64_to_floatx80( float64 a ) 1593{ 1594 1595 return floatXToFloatx80( float64ToFloatX( a ) ); 1596 1597} 1598 1599#endif 1600 1601#ifdef FLOAT128 1602 1603float128 slow_float64_to_float128( float64 a ) 1604{ 1605 1606 return floatXToFloat128( float64ToFloatX( a ) ); 1607 1608} 1609 1610#endif 1611 1612float64 slow_float64_round_to_int( float64 a ) 1613{ 1614 1615 return floatXToFloat64( floatXRoundToInt( float64ToFloatX( a ) ) ); 1616 1617} 1618 1619float64 slow_float64_add( float64 a, float64 b ) 1620{ 1621 1622 return 1623 floatXToFloat64( 1624 floatXAdd( float64ToFloatX( a ), float64ToFloatX( b ) ) ); 1625 1626} 1627 1628float64 slow_float64_sub( float64 a, float64 b ) 1629{ 1630 1631 b ^= LIT64( 0x8000000000000000 ); 1632 return 1633 floatXToFloat64( 1634 floatXAdd( float64ToFloatX( a ), float64ToFloatX( b ) ) ); 1635 1636} 1637 1638float64 slow_float64_mul( float64 a, float64 b ) 1639{ 1640 1641 return 1642 floatXToFloat64( 1643 floatXMul( float64ToFloatX( a ), float64ToFloatX( b ) ) ); 1644 1645} 1646 1647float64 slow_float64_div( float64 a, float64 b ) 1648{ 1649 1650 return 1651 floatXToFloat64( 1652 floatXDiv( float64ToFloatX( a ), float64ToFloatX( b ) ) ); 1653 1654} 1655 1656float64 slow_float64_rem( float64 a, float64 b ) 1657{ 1658 1659 return 1660 floatXToFloat64( 1661 floatXRem( float64ToFloatX( a ), float64ToFloatX( b ) ) ); 1662 1663} 1664 1665float64 slow_float64_sqrt( float64 a ) 1666{ 1667 1668 return floatXToFloat64( floatXSqrt( float64ToFloatX( a ) ) ); 1669 1670} 1671 1672flag slow_float64_eq( float64 a, float64 b ) 1673{ 1674 1675 return floatXEq( float64ToFloatX( a ), float64ToFloatX( b ) ); 1676 1677} 1678 1679flag slow_float64_le( float64 a, float64 b ) 1680{ 1681 floatX ax, bx; 1682 1683 ax = float64ToFloatX( a ); 1684 bx = float64ToFloatX( b ); 1685 if ( ax.isNaN || bx.isNaN ) { 1686 slow_float_exception_flags |= float_flag_invalid; 1687 } 1688 return floatXLe( ax, bx ); 1689 1690} 1691 1692flag slow_float64_lt( float64 a, float64 b ) 1693{ 1694 floatX ax, bx; 1695 1696 ax = float64ToFloatX( a ); 1697 bx = float64ToFloatX( b ); 1698 if ( ax.isNaN || bx.isNaN ) { 1699 slow_float_exception_flags |= float_flag_invalid; 1700 } 1701 return floatXLt( ax, bx ); 1702 1703} 1704 1705flag slow_float64_eq_signaling( float64 a, float64 b ) 1706{ 1707 floatX ax, bx; 1708 1709 ax = float64ToFloatX( a ); 1710 bx = float64ToFloatX( b ); 1711 if ( ax.isNaN || bx.isNaN ) { 1712 slow_float_exception_flags |= float_flag_invalid; 1713 } 1714 return floatXEq( ax, bx ); 1715 1716} 1717 1718flag slow_float64_le_quiet( float64 a, float64 b ) 1719{ 1720 1721 return floatXLe( float64ToFloatX( a ), float64ToFloatX( b ) ); 1722 1723} 1724 1725flag slow_float64_lt_quiet( float64 a, float64 b ) 1726{ 1727 1728 return floatXLt( float64ToFloatX( a ), float64ToFloatX( b ) ); 1729 1730} 1731 1732#ifdef FLOATX80 1733 1734int32 slow_floatx80_to_int32( floatx80 a ) 1735{ 1736 1737 return floatXToInt32( floatx80ToFloatX( a ) ); 1738 1739} 1740 1741int32 slow_floatx80_to_int32_round_to_zero( floatx80 a ) 1742{ 1743 int8 savedRoundingMode; 1744 int32 z; 1745 1746 savedRoundingMode = slow_float_rounding_mode; 1747 slow_float_rounding_mode = float_round_to_zero; 1748 z = floatXToInt32( floatx80ToFloatX( a ) ); 1749 slow_float_rounding_mode = savedRoundingMode; 1750 return z; 1751 1752} 1753 1754int64 slow_floatx80_to_int64( floatx80 a ) 1755{ 1756 1757 return floatXToInt64( floatx80ToFloatX( a ) ); 1758 1759} 1760 1761int64 slow_floatx80_to_int64_round_to_zero( floatx80 a ) 1762{ 1763 int8 savedRoundingMode; 1764 int64 z; 1765 1766 savedRoundingMode = slow_float_rounding_mode; 1767 slow_float_rounding_mode = float_round_to_zero; 1768 z = floatXToInt64( floatx80ToFloatX( a ) ); 1769 slow_float_rounding_mode = savedRoundingMode; 1770 return z; 1771 1772} 1773 1774float32 slow_floatx80_to_float32( floatx80 a ) 1775{ 1776 1777 return floatXToFloat32( floatx80ToFloatX( a ) ); 1778 1779} 1780 1781float64 slow_floatx80_to_float64( floatx80 a ) 1782{ 1783 1784 return floatXToFloat64( floatx80ToFloatX( a ) ); 1785 1786} 1787 1788#ifdef FLOAT128 1789 1790float128 slow_floatx80_to_float128( floatx80 a ) 1791{ 1792 1793 return floatXToFloat128( floatx80ToFloatX( a ) ); 1794 1795} 1796 1797#endif 1798 1799floatx80 slow_floatx80_round_to_int( floatx80 a ) 1800{ 1801 1802 return floatXToFloatx80( floatXRoundToInt( floatx80ToFloatX( a ) ) ); 1803 1804} 1805 1806floatx80 slow_floatx80_add( floatx80 a, floatx80 b ) 1807{ 1808 1809 return 1810 floatXToFloatx80( 1811 floatXAdd( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ) ); 1812 1813} 1814 1815floatx80 slow_floatx80_sub( floatx80 a, floatx80 b ) 1816{ 1817 1818 b.high ^= 0x8000; 1819 return 1820 floatXToFloatx80( 1821 floatXAdd( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ) ); 1822 1823} 1824 1825floatx80 slow_floatx80_mul( floatx80 a, floatx80 b ) 1826{ 1827 1828 return 1829 floatXToFloatx80( 1830 floatXMul( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ) ); 1831 1832} 1833 1834floatx80 slow_floatx80_div( floatx80 a, floatx80 b ) 1835{ 1836 1837 return 1838 floatXToFloatx80( 1839 floatXDiv( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ) ); 1840 1841} 1842 1843floatx80 slow_floatx80_rem( floatx80 a, floatx80 b ) 1844{ 1845 1846 return 1847 floatXToFloatx80( 1848 floatXRem( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ) ); 1849 1850} 1851 1852floatx80 slow_floatx80_sqrt( floatx80 a ) 1853{ 1854 1855 return floatXToFloatx80( floatXSqrt( floatx80ToFloatX( a ) ) ); 1856 1857} 1858 1859flag slow_floatx80_eq( floatx80 a, floatx80 b ) 1860{ 1861 1862 return floatXEq( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ); 1863 1864} 1865 1866flag slow_floatx80_le( floatx80 a, floatx80 b ) 1867{ 1868 floatX ax, bx; 1869 1870 ax = floatx80ToFloatX( a ); 1871 bx = floatx80ToFloatX( b ); 1872 if ( ax.isNaN || bx.isNaN ) { 1873 slow_float_exception_flags |= float_flag_invalid; 1874 } 1875 return floatXLe( ax, bx ); 1876 1877} 1878 1879flag slow_floatx80_lt( floatx80 a, floatx80 b ) 1880{ 1881 floatX ax, bx; 1882 1883 ax = floatx80ToFloatX( a ); 1884 bx = floatx80ToFloatX( b ); 1885 if ( ax.isNaN || bx.isNaN ) { 1886 slow_float_exception_flags |= float_flag_invalid; 1887 } 1888 return floatXLt( ax, bx ); 1889 1890} 1891 1892flag slow_floatx80_eq_signaling( floatx80 a, floatx80 b ) 1893{ 1894 floatX ax, bx; 1895 1896 ax = floatx80ToFloatX( a ); 1897 bx = floatx80ToFloatX( b ); 1898 if ( ax.isNaN || bx.isNaN ) { 1899 slow_float_exception_flags |= float_flag_invalid; 1900 } 1901 return floatXEq( ax, bx ); 1902 1903} 1904 1905flag slow_floatx80_le_quiet( floatx80 a, floatx80 b ) 1906{ 1907 1908 return floatXLe( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ); 1909 1910} 1911 1912flag slow_floatx80_lt_quiet( floatx80 a, floatx80 b ) 1913{ 1914 1915 return floatXLt( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ); 1916 1917} 1918 1919#endif 1920 1921#ifdef FLOAT128 1922 1923int32 slow_float128_to_int32( float128 a ) 1924{ 1925 1926 return floatXToInt32( float128ToFloatX( a ) ); 1927 1928} 1929 1930int32 slow_float128_to_int32_round_to_zero( float128 a ) 1931{ 1932 int8 savedRoundingMode; 1933 int32 z; 1934 1935 savedRoundingMode = slow_float_rounding_mode; 1936 slow_float_rounding_mode = float_round_to_zero; 1937 z = floatXToInt32( float128ToFloatX( a ) ); 1938 slow_float_rounding_mode = savedRoundingMode; 1939 return z; 1940 1941} 1942 1943int64 slow_float128_to_int64( float128 a ) 1944{ 1945 1946 return floatXToInt64( float128ToFloatX( a ) ); 1947 1948} 1949 1950int64 slow_float128_to_int64_round_to_zero( float128 a ) 1951{ 1952 int8 savedRoundingMode; 1953 int64 z; 1954 1955 savedRoundingMode = slow_float_rounding_mode; 1956 slow_float_rounding_mode = float_round_to_zero; 1957 z = floatXToInt64( float128ToFloatX( a ) ); 1958 slow_float_rounding_mode = savedRoundingMode; 1959 return z; 1960 1961} 1962 1963float32 slow_float128_to_float32( float128 a ) 1964{ 1965 1966 return floatXToFloat32( float128ToFloatX( a ) ); 1967 1968} 1969 1970float64 slow_float128_to_float64( float128 a ) 1971{ 1972 1973 return floatXToFloat64( float128ToFloatX( a ) ); 1974 1975} 1976 1977#ifdef FLOATX80 1978 1979floatx80 slow_float128_to_floatx80( float128 a ) 1980{ 1981 1982 return floatXToFloatx80( float128ToFloatX( a ) ); 1983 1984} 1985 1986#endif 1987 1988float128 slow_float128_round_to_int( float128 a ) 1989{ 1990 1991 return floatXToFloat128( floatXRoundToInt( float128ToFloatX( a ) ) ); 1992 1993} 1994 1995float128 slow_float128_add( float128 a, float128 b ) 1996{ 1997 1998 return 1999 floatXToFloat128( 2000 floatXAdd( float128ToFloatX( a ), float128ToFloatX( b ) ) ); 2001 2002} 2003 2004float128 slow_float128_sub( float128 a, float128 b ) 2005{ 2006 2007 b.high ^= LIT64( 0x8000000000000000 ); 2008 return 2009 floatXToFloat128( 2010 floatXAdd( float128ToFloatX( a ), float128ToFloatX( b ) ) ); 2011 2012} 2013 2014float128 slow_float128_mul( float128 a, float128 b ) 2015{ 2016 2017 return 2018 floatXToFloat128( 2019 floatXMul( float128ToFloatX( a ), float128ToFloatX( b ) ) ); 2020 2021} 2022 2023float128 slow_float128_div( float128 a, float128 b ) 2024{ 2025 2026 return 2027 floatXToFloat128( 2028 floatXDiv( float128ToFloatX( a ), float128ToFloatX( b ) ) ); 2029 2030} 2031 2032float128 slow_float128_rem( float128 a, float128 b ) 2033{ 2034 2035 return 2036 floatXToFloat128( 2037 floatXRem( float128ToFloatX( a ), float128ToFloatX( b ) ) ); 2038 2039} 2040 2041float128 slow_float128_sqrt( float128 a ) 2042{ 2043 2044 return floatXToFloat128( floatXSqrt( float128ToFloatX( a ) ) ); 2045 2046} 2047 2048flag slow_float128_eq( float128 a, float128 b ) 2049{ 2050 2051 return floatXEq( float128ToFloatX( a ), float128ToFloatX( b ) ); 2052 2053} 2054 2055flag slow_float128_le( float128 a, float128 b ) 2056{ 2057 floatX ax, bx; 2058 2059 ax = float128ToFloatX( a ); 2060 bx = float128ToFloatX( b ); 2061 if ( ax.isNaN || bx.isNaN ) { 2062 slow_float_exception_flags |= float_flag_invalid; 2063 } 2064 return floatXLe( ax, bx ); 2065 2066} 2067 2068flag slow_float128_lt( float128 a, float128 b ) 2069{ 2070 floatX ax, bx; 2071 2072 ax = float128ToFloatX( a ); 2073 bx = float128ToFloatX( b ); 2074 if ( ax.isNaN || bx.isNaN ) { 2075 slow_float_exception_flags |= float_flag_invalid; 2076 } 2077 return floatXLt( ax, bx ); 2078 2079} 2080 2081flag slow_float128_eq_signaling( float128 a, float128 b ) 2082{ 2083 floatX ax, bx; 2084 2085 ax = float128ToFloatX( a ); 2086 bx = float128ToFloatX( b ); 2087 if ( ax.isNaN || bx.isNaN ) { 2088 slow_float_exception_flags |= float_flag_invalid; 2089 } 2090 return floatXEq( ax, bx ); 2091 2092} 2093 2094flag slow_float128_le_quiet( float128 a, float128 b ) 2095{ 2096 2097 return floatXLe( float128ToFloatX( a ), float128ToFloatX( b ) ); 2098 2099} 2100 2101flag slow_float128_lt_quiet( float128 a, float128 b ) 2102{ 2103 2104 return floatXLt( float128ToFloatX( a ), float128ToFloatX( b ) ); 2105 2106} 2107 2108#endif 2109 2110