|
54 | 54 | #define SIGNBIT 0x80000000L
|
55 | 55 | #define HIDDEN (1L << 23L)
|
56 | 56 | #define SIGN(fp) ((fp) & SIGNBIT)
|
| 57 | +#define EXPMASK 0xFFL |
57 | 58 | #define EXP(fp) (((fp) >> 23L) & 0xFF)
|
58 | 59 | #define MANT(fp) (((fp) & 0x7FFFFFL) | HIDDEN)
|
59 | 60 | #define PACK(s,e,m) ((s) | ((e) << 23L) | (m))
|
@@ -262,6 +263,9 @@ __extendsfdf2 (float a1)
|
262 | 263 | mant &= ~HIDDEN;
|
263 | 264 | }
|
264 | 265 | exp = exp - EXCESS + EXCESSD;
|
| 266 | + /* Handle inf and NaN */ |
| 267 | + if (exp == EXPMASK - EXCESS + EXCESSD) |
| 268 | + exp = EXPDMASK; |
265 | 269 | dl.l.upper |= exp << 20;
|
266 | 270 | dl.l.upper |= mant >> 3;
|
267 | 271 | dl.l.lower = mant << 29;
|
@@ -295,40 +299,52 @@ __truncdfsf2 (double a1)
|
295 | 299 | /* shift double mantissa 6 bits so we can round */
|
296 | 300 | sticky |= mant & ((1 << 6) - 1);
|
297 | 301 | mant >>= 6;
|
298 |
| - |
299 |
| - /* Check for underflow and denormals. */ |
300 |
| - if (exp <= 0) |
| 302 | + if (exp == EXPDMASK - EXCESSD + EXCESS) |
| 303 | + { |
| 304 | + exp = EXPMASK; |
| 305 | + mant = mant >> 1 | (mant & 1) | !!sticky; |
| 306 | + } |
| 307 | + else |
301 | 308 | {
|
302 |
| - if (exp < -24) |
| 309 | + /* Check for underflow and denormals. */ |
| 310 | + if (exp <= 0) |
303 | 311 | {
|
304 |
| - sticky |= mant; |
305 |
| - mant = 0; |
| 312 | + if (exp < -24) |
| 313 | + { |
| 314 | + sticky |= mant; |
| 315 | + mant = 0; |
| 316 | + } |
| 317 | + else |
| 318 | + { |
| 319 | + sticky |= mant & ((1 << (1 - exp)) - 1); |
| 320 | + mant >>= 1 - exp; |
| 321 | + } |
| 322 | + exp = 0; |
306 | 323 | }
|
307 |
| - else |
| 324 | + |
| 325 | + /* now round */ |
| 326 | + shift = 1; |
| 327 | + if ((mant & 1) && (sticky || (mant & 2))) |
308 | 328 | {
|
309 |
| - sticky |= mant & ((1 << (1 - exp)) - 1); |
310 |
| - mant >>= 1 - exp; |
311 |
| - } |
312 |
| - exp = 0; |
313 |
| - } |
314 |
| - |
315 |
| - /* now round */ |
316 |
| - shift = 1; |
317 |
| - if ((mant & 1) && (sticky || (mant & 2))) |
318 |
| - { |
319 |
| - int rounding = exp ? 2 : 1; |
| 329 | + int rounding = exp ? 2 : 1; |
320 | 330 |
|
321 |
| - mant += 1; |
| 331 | + mant += 1; |
322 | 332 |
|
323 |
| - /* did the round overflow? */ |
324 |
| - if (mant >= (HIDDEN << rounding)) |
| 333 | + /* did the round overflow? */ |
| 334 | + if (mant >= (HIDDEN << rounding)) |
| 335 | + { |
| 336 | + exp++; |
| 337 | + shift = rounding; |
| 338 | + } |
| 339 | + } |
| 340 | + /* shift down */ |
| 341 | + mant >>= shift; |
| 342 | + if (exp >= EXPMASK) |
325 | 343 | {
|
326 |
| - exp++; |
327 |
| - shift = rounding; |
| 344 | + exp = EXPMASK; |
| 345 | + mant = 0; |
328 | 346 | }
|
329 | 347 | }
|
330 |
| - /* shift down */ |
331 |
| - mant >>= shift; |
332 | 348 |
|
333 | 349 | mant &= ~HIDDEN;
|
334 | 350 |
|
@@ -432,8 +448,31 @@ __extenddfxf2 (double d)
|
432 | 448 | }
|
433 | 449 |
|
434 | 450 | exp = EXPD (dl) - EXCESSD + EXCESSX;
|
435 |
| - ldl.l.upper |= exp << 16; |
| 451 | + dl.l.upper &= MANTDMASK; |
436 | 452 | ldl.l.middle = HIDDENX;
|
| 453 | + |
| 454 | + /* Recover from a denorm. */ |
| 455 | + if (exp == -EXCESSD + EXCESSX) |
| 456 | + { |
| 457 | + exp++; |
| 458 | + while ((dl.l.upper & HIDDEND) == 0) |
| 459 | + { |
| 460 | + exp--; |
| 461 | + dl.l.upper = (dl.l.upper << 1) | (dl.l.lower >> 31); |
| 462 | + dl.l.lower = dl.l.lower << 1; |
| 463 | + } |
| 464 | + } |
| 465 | + |
| 466 | + /* Handle inf and NaN */ |
| 467 | + else if (exp == EXPDMASK - EXCESSD + EXCESSX) |
| 468 | + { |
| 469 | + exp = EXPXMASK; |
| 470 | + /* No hidden one bit for INF */ |
| 471 | + if (dl.l.upper == 0 && dl.l.lower == 0) |
| 472 | + ldl.l.middle = 0; |
| 473 | + } |
| 474 | + |
| 475 | + ldl.l.upper |= exp << 16; |
437 | 476 | /* 31-20: # mantissa bits in ldl.l.middle - # mantissa bits in dl.l.upper */
|
438 | 477 | ldl.l.middle |= (dl.l.upper & MANTDMASK) << (31 - 20);
|
439 | 478 | /* 1+20: explicit-integer-bit + # mantissa bits in dl.l.upper */
|
@@ -464,9 +503,38 @@ __truncxfdf2 (long double ld)
|
464 | 503 | }
|
465 | 504 |
|
466 | 505 | exp = EXPX (ldl) - EXCESSX + EXCESSD;
|
467 |
| - /* ??? quick and dirty: keep `exp' sane */ |
468 |
| - if (exp >= EXPDMASK) |
469 |
| - exp = EXPDMASK - 1; |
| 506 | + /* Check for underflow and denormals. */ |
| 507 | + if (exp <= 0) |
| 508 | + { |
| 509 | + if (exp < -53) |
| 510 | + { |
| 511 | + ldl.l.middle = 0; |
| 512 | + ldl.l.lower = 0; |
| 513 | + } |
| 514 | + else if (exp < -30) |
| 515 | + { |
| 516 | + ldl.l.lower = (ldl.l.middle & MANTXMASK) >> ((1 - exp) - 32); |
| 517 | + ldl.l.middle &= ~MANTXMASK; |
| 518 | + } |
| 519 | + else |
| 520 | + { |
| 521 | + ldl.l.lower >>= 1 - exp; |
| 522 | + ldl.l.lower |= (ldl.l.middle & MANTXMASK) << (32 - (1 - exp)); |
| 523 | + ldl.l.middle = (ldl.l.middle & ~MANTXMASK) | (ldl.l.middle & MANTXMASK >> (1 - exp)); |
| 524 | + } |
| 525 | + exp = 0; |
| 526 | + } |
| 527 | + else if (exp == EXPXMASK - EXCESSX + EXCESSD) |
| 528 | + { |
| 529 | + exp = EXPDMASK; |
| 530 | + ldl.l.middle |= ldl.l.lower; |
| 531 | + } |
| 532 | + else if (exp >= EXPDMASK) |
| 533 | + { |
| 534 | + exp = EXPDMASK; |
| 535 | + ldl.l.middle = 0; |
| 536 | + ldl.l.lower = 0; |
| 537 | + } |
470 | 538 | dl.l.upper |= exp << (32 - (EXPDBITS + 1));
|
471 | 539 | /* +1-1: add one for sign bit, but take one off for explicit-integer-bit */
|
472 | 540 | dl.l.upper |= (ldl.l.middle & MANTXMASK) >> (EXPDBITS + 1 - 1);
|
@@ -511,10 +579,40 @@ __floatunsixf (unsigned long l)
|
511 | 579 |
|
512 | 580 | /* convert a long double to an int */
|
513 | 581 | long
|
514 |
| -__fixxfsi (long double ld) |
| 582 | +__fixxfsi (long double a) |
515 | 583 | {
|
516 |
| - long foo = __fixdfsi ((double) ld); |
517 |
| - return foo; |
| 584 | + union long_double_long ldl; |
| 585 | + long exp; |
| 586 | + long l; |
| 587 | + |
| 588 | + ldl.ld = a; |
| 589 | + |
| 590 | + exp = EXPX(ldl); |
| 591 | + if (exp == 0 && ldl.l.middle == 0 && ldl.l.lower == 0) |
| 592 | + return 0; |
| 593 | + |
| 594 | + exp = exp - EXCESSX - 64; |
| 595 | + |
| 596 | + if (exp > 0) |
| 597 | + { |
| 598 | + /* Return largest integer. */ |
| 599 | + return SIGNX (ldl) ? 0x80000000L : 0x7fffffffL; |
| 600 | + } |
| 601 | + |
| 602 | + if (exp <= -64) |
| 603 | + return 0; |
| 604 | + |
| 605 | + if (exp <= -32) |
| 606 | + { |
| 607 | + ldl.l.lower = ldl.l.middle >> (-exp - 32); |
| 608 | + } |
| 609 | + else if (exp < 0) |
| 610 | + { |
| 611 | + ldl.l.lower = ldl.l.lower >> -exp; |
| 612 | + ldl.l.lower |= ldl.l.middle << (32 + exp); |
| 613 | + } |
| 614 | + |
| 615 | + return SIGNX(ldl) ? -ldl.l.lower : ldl.l.lower; |
518 | 616 | }
|
519 | 617 |
|
520 | 618 | /* The remaining provide crude math support by working in double precision. */
|
|
0 commit comments