Mercurial > flash_v2
comparison packages/hal/mips/arch/current/src/mipsfp.c @ 92:08ffab08d2ee ecos-sw-2000-05-26
Merge from eCos master repository on 2000-05-26-07:47:03-BST
| author | jlarmour |
|---|---|
| date | Fri, 26 May 2000 13:46:34 +0000 |
| parents | bf00f99aec69 |
| children | e0c0827131d1 |
comparison
equal
deleted
inserted
replaced
| 91:86f6a8b98920 | 92:08ffab08d2ee |
|---|---|
| 65 | 65 |
| 66 // The following types were taken from <sys/ieeefp.h> from libm. | 66 // The following types were taken from <sys/ieeefp.h> from libm. |
| 67 | 67 |
| 68 #if (CYG_BYTEORDER == CYG_MSBFIRST) // Big endian | 68 #if (CYG_BYTEORDER == CYG_MSBFIRST) // Big endian |
| 69 | 69 |
| 70 // Note: there do not seem to be any current machines which are Big Endian but | |
| 71 // have a mixed up double layout. | |
| 72 | |
| 73 typedef union | 70 typedef union |
| 74 { | 71 { |
| 75 cyg_int32 asi32[2]; | 72 cyg_int32 asi32[2]; |
| 76 | 73 |
| 77 cyg_int64 asi64; | 74 cyg_int64 asi64; |
| 78 | 75 |
| 79 double value; | 76 double value; |
| 80 | 77 |
| 81 struct | 78 struct |
| 82 { | 79 { |
| 80 #if (CYG_DOUBLE_BYTEORDER == CYG_MSBFIRST) | |
| 83 unsigned int sign : 1; | 81 unsigned int sign : 1; |
| 84 unsigned int exponent: 11; | 82 unsigned int exponent: 11; |
| 85 unsigned int fraction0:4; | 83 unsigned int fraction0:4; |
| 86 unsigned int fraction1:16; | 84 unsigned int fraction1:16; |
| 87 unsigned int fraction2:16; | 85 unsigned int fraction2:16; |
| 88 unsigned int fraction3:16; | 86 unsigned int fraction3:16; |
| 89 | 87 #else |
| 88 unsigned int fraction2:16; | |
| 89 unsigned int fraction3:16; | |
| 90 unsigned int sign : 1; | |
| 91 unsigned int exponent: 11; | |
| 92 unsigned int fraction0:4; | |
| 93 unsigned int fraction1:16; | |
| 94 #endif | |
| 90 } number; | 95 } number; |
| 91 | 96 |
| 92 struct | 97 struct |
| 93 { | 98 { |
| 99 #if (CYG_DOUBLE_BYTEORDER == CYG_MSBFIRST) | |
| 94 unsigned int sign : 1; | 100 unsigned int sign : 1; |
| 95 unsigned int exponent: 11; | 101 unsigned int exponent: 11; |
| 96 unsigned int quiet:1; | 102 unsigned int quiet:1; |
| 97 unsigned int function0:3; | 103 unsigned int function0:3; |
| 98 unsigned int function1:16; | 104 unsigned int function1:16; |
| 99 unsigned int function2:16; | 105 unsigned int function2:16; |
| 100 unsigned int function3:16; | 106 unsigned int function3:16; |
| 107 #else | |
| 108 unsigned int function2:16; | |
| 109 unsigned int function3:16; | |
| 110 unsigned int sign : 1; | |
| 111 unsigned int exponent: 11; | |
| 112 unsigned int quiet:1; | |
| 113 unsigned int function0:3; | |
| 114 unsigned int function1:16; | |
| 115 #endif | |
| 101 } nan; | 116 } nan; |
| 102 | 117 |
| 103 struct | 118 struct |
| 104 { | 119 { |
| 120 #if (CYG_DOUBLE_BYTEORDER == CYG_MSBFIRST) | |
| 105 cyg_uint32 msw; | 121 cyg_uint32 msw; |
| 106 cyg_uint32 lsw; | 122 cyg_uint32 lsw; |
| 123 #else | |
| 124 cyg_uint32 lsw; | |
| 125 cyg_uint32 msw; | |
| 126 #endif | |
| 107 } parts; | 127 } parts; |
| 108 | 128 |
| 109 | 129 |
| 110 } Cyg_libm_ieee_double_shape_type; | 130 } Cyg_libm_ieee_double_shape_type; |
| 111 | 131 |
| 282 } // reg2flt() | 302 } // reg2flt() |
| 283 | 303 |
| 284 static __inline__ void | 304 static __inline__ void |
| 285 flt2reg( Cyg_libm_ieee_float_shape_type *flt, CYG_HAL_FPU_REG *fpu_reg_p ) | 305 flt2reg( Cyg_libm_ieee_float_shape_type *flt, CYG_HAL_FPU_REG *fpu_reg_p ) |
| 286 { | 306 { |
| 287 *fpu_reg_p = flt->asi32; | 307 #if defined(CYGHWR_HAL_MIPS_FPU_32BIT) || (CYG_BYTEORDER == CYG_LSBFIRST) |
| 308 *(cyg_int32 *)fpu_reg_p = flt->asi32; | |
| 309 #else | |
| 310 *((cyg_int32 *)fpu_reg_p + 1) = flt->asi32; | |
| 311 # endif | |
| 288 } // flt2reg() | 312 } // flt2reg() |
| 313 | |
| 314 static __inline__ void | |
| 315 reg2dbl( CYG_HAL_FPU_REG *fpu_reg_p, Cyg_libm_ieee_double_shape_type *flt) | |
| 316 { | |
| 317 flt->asi64 = *(cyg_int64 *)fpu_reg_p; | |
| 318 } // reg2dbl() | |
| 319 | |
| 320 static __inline__ void | |
| 321 dbl2reg( Cyg_libm_ieee_double_shape_type *flt, CYG_HAL_FPU_REG *fpu_reg_p ) | |
| 322 { | |
| 323 *(cyg_uint64*)fpu_reg_p = flt->asi64; | |
| 324 } // dbl2reg() | |
| 325 | |
| 289 | 326 |
| 290 // This function returns non-zero if the exception has been handled | 327 // This function returns non-zero if the exception has been handled |
| 291 // successfully. | 328 // successfully. |
| 292 | 329 |
| 293 // FIXME: Arguably we should raise underflow exceptions in some of the cases | 330 // FIXME: Arguably we should raise underflow exceptions in some of the cases |
| 377 case DIV_INSN: | 414 case DIV_INSN: |
| 378 | 415 |
| 379 if (fp64bit) { | 416 if (fp64bit) { |
| 380 Cyg_libm_ieee_double_shape_type s1, s2; | 417 Cyg_libm_ieee_double_shape_type s1, s2; |
| 381 | 418 |
| 382 s1.asi64 = *srcreg1; | 419 reg2dbl( srcreg1, &s1 ); |
| 383 s2.asi64 = *srcreg2; | 420 reg2dbl( srcreg2, &s2 ); |
| 384 | 421 |
| 385 if ( issubnormal( s1 ) ) { // flush to 0 and restart | 422 if ( issubnormal( s1 ) ) { // flush to 0 and restart |
| 386 // but preserve sign | 423 // but preserve sign |
| 387 if (s1.number.sign) | 424 if (s1.number.sign) |
| 388 s1.value = -0.0; | 425 s1.value = -0.0; |
| 389 else | 426 else |
| 390 s1.value = 0.0; | 427 s1.value = 0.0; |
| 391 *srcreg1 = s1.asi64; | 428 dbl2reg( &s1, srcreg1 ); |
| 392 handled++; | 429 handled++; |
| 393 } | 430 } |
| 394 | 431 |
| 395 // We could try flushing both to 0 at the same time, but | 432 // We could try flushing both to 0 at the same time, but |
| 396 // that's inadvisable if both numbers are very small. | 433 // that's inadvisable if both numbers are very small. |
| 402 // but preserve sign | 439 // but preserve sign |
| 403 if (s2.number.sign) | 440 if (s2.number.sign) |
| 404 s2.value = -0.0; | 441 s2.value = -0.0; |
| 405 else | 442 else |
| 406 s2.value = 0.0; | 443 s2.value = 0.0; |
| 407 *srcreg2 = s2.asi64; | 444 dbl2reg( &s2, srcreg2 ); |
| 408 handled++; | 445 handled++; |
| 409 } | 446 } |
| 410 | 447 |
| 411 } else { // 32-bit | 448 } else { // 32-bit |
| 412 Cyg_libm_ieee_float_shape_type s1, s2; | 449 Cyg_libm_ieee_float_shape_type s1, s2; |
| 437 | 474 |
| 438 case SQRT_INSN: | 475 case SQRT_INSN: |
| 439 if ( fp64bit ) { | 476 if ( fp64bit ) { |
| 440 Cyg_libm_ieee_double_shape_type d, s; | 477 Cyg_libm_ieee_double_shape_type d, s; |
| 441 | 478 |
| 442 d.asi64 = *dstreg; | 479 reg2dbl( dstreg, &d ); |
| 443 s.asi64 = *srcreg1; | 480 reg2dbl( srcreg1, &s ); |
| 444 | 481 |
| 445 if ( issubnormal( s ) ) { // Sqrt of something tiny is 0 | 482 if ( issubnormal( s ) ) { // Sqrt of something tiny is 0 |
| 446 // if this is a delay slot, we can't restart properly | 483 // if this is a delay slot, we can't restart properly |
| 447 // so if it is subnormal, clear the source register instead | 484 // so if it is subnormal, clear the source register instead |
| 448 if ( delay_slot ) { | 485 if ( delay_slot ) { |
| 449 // but preserve sign | 486 // but preserve sign |
| 450 if (s.number.sign) | 487 if (s.number.sign) |
| 451 s.value = -0.0; | 488 s.value = -0.0; |
| 452 else | 489 else |
| 453 s.value = 0.0; | 490 s.value = 0.0; |
| 454 *srcreg1 = s.asi64; | 491 dbl2reg( &s, srcreg1 ); |
| 455 } else { | 492 } else { |
| 456 // but preserve sign | 493 // but preserve sign |
| 457 if (s.number.sign) | 494 if (s.number.sign) |
| 458 d.value = -0.0; | 495 d.value = -0.0; |
| 459 else | 496 else |
| 460 d.value = 0.0; | 497 d.value = 0.0; |
| 461 *dstreg = d.asi64; | 498 dbl2reg( &d, dstreg ); |
| 462 regs->pc += 4; // We've dealt with this so move on | 499 regs->pc += 4; // We've dealt with this so move on |
| 463 } | 500 } |
| 464 handled++; | 501 handled++; |
| 465 } | 502 } |
| 466 | 503 |
| 497 case ABS_INSN: | 534 case ABS_INSN: |
| 498 // We may as well do this right if we can | 535 // We may as well do this right if we can |
| 499 if ( fp64bit ) { | 536 if ( fp64bit ) { |
| 500 Cyg_libm_ieee_double_shape_type d, s; | 537 Cyg_libm_ieee_double_shape_type d, s; |
| 501 | 538 |
| 502 d.asi64 = *dstreg; | 539 reg2dbl( dstreg, &d ); |
| 503 s.asi64 = *srcreg1; | 540 reg2dbl( srcreg1, &s ); |
| 504 | 541 |
| 505 // if this is a delay slot, we can't restart properly | 542 // if this is a delay slot, we can't restart properly |
| 506 // so if it is subnormal, clear the source register instead | 543 // so if it is subnormal, clear the source register instead |
| 507 if ( delay_slot ) { | 544 if ( delay_slot ) { |
| 508 if ( issubnormal( s ) ) { | 545 if ( issubnormal( s ) ) { |
| 511 // register | 548 // register |
| 512 if (s.number.sign) | 549 if (s.number.sign) |
| 513 s.value = -0.0; | 550 s.value = -0.0; |
| 514 else | 551 else |
| 515 s.value = 0.0; | 552 s.value = 0.0; |
| 516 *srcreg1 = s.asi64; | 553 dbl2reg( &s, srcreg1 ); |
| 517 handled++; | 554 handled++; |
| 518 } | 555 } |
| 519 } else { | 556 } else { |
| 520 d.asi64 = s.asi64; | 557 d.asi64 = s.asi64; |
| 521 d.number.sign = 0; | 558 d.number.sign = 0; |
| 522 *dstreg = d.asi64; | 559 dbl2reg( &d, dstreg ); |
| 523 regs->pc += 4; | 560 regs->pc += 4; |
| 524 handled++; | 561 handled++; |
| 525 } | 562 } |
| 526 } else { // 32-bit | 563 } else { // 32-bit |
| 527 Cyg_libm_ieee_float_shape_type d, s; | 564 Cyg_libm_ieee_float_shape_type d, s; |
| 556 case MOV_INSN: | 593 case MOV_INSN: |
| 557 // We may as well do this right if we can | 594 // We may as well do this right if we can |
| 558 if ( fp64bit ) { | 595 if ( fp64bit ) { |
| 559 Cyg_libm_ieee_double_shape_type d, s; | 596 Cyg_libm_ieee_double_shape_type d, s; |
| 560 | 597 |
| 561 d.asi64 = *dstreg; | 598 reg2dbl( dstreg, &d ); |
| 562 s.asi64 = *srcreg1; | 599 reg2dbl( srcreg1, &s ); |
| 563 | 600 |
| 564 // if this is a delay slot, we can't restart properly | 601 // if this is a delay slot, we can't restart properly |
| 565 // so if it is subnormal, clear the source register instead | 602 // so if it is subnormal, clear the source register instead |
| 566 if ( delay_slot ) { | 603 if ( delay_slot ) { |
| 567 if ( issubnormal( s ) ) { | 604 if ( issubnormal( s ) ) { |
| 568 // but preserve sign | 605 // but preserve sign |
| 569 if (s.number.sign) | 606 if (s.number.sign) |
| 570 s.value = -0.0; | 607 s.value = -0.0; |
| 571 else | 608 else |
| 572 s.value = 0.0; | 609 s.value = 0.0; |
| 573 *srcreg1 = s.asi64; | 610 dbl2reg( &s, srcreg1 ); |
| 574 handled++; | 611 handled++; |
| 575 } | 612 } |
| 576 } else { | 613 } else { |
| 577 d.asi64 = s.asi64; | 614 d.asi64 = s.asi64; |
| 578 *dstreg = d.asi64; | 615 dbl2reg( &d, dstreg ); |
| 579 regs->pc += 4; | 616 regs->pc += 4; |
| 580 handled++; | 617 handled++; |
| 581 } | 618 } |
| 582 } else { // 32-bit | 619 } else { // 32-bit |
| 583 Cyg_libm_ieee_float_shape_type d, s; | 620 Cyg_libm_ieee_float_shape_type d, s; |
| 611 case NEG_INSN: | 648 case NEG_INSN: |
| 612 // We may as well do this right if we can | 649 // We may as well do this right if we can |
| 613 if ( fp64bit ) { | 650 if ( fp64bit ) { |
| 614 Cyg_libm_ieee_double_shape_type d, s; | 651 Cyg_libm_ieee_double_shape_type d, s; |
| 615 | 652 |
| 616 d.asi64 = *dstreg; | 653 reg2dbl( dstreg, &d ); |
| 617 s.asi64 = *srcreg1; | 654 reg2dbl( srcreg1, &s ); |
| 618 | 655 |
| 619 // if this is a delay slot, we can't restart properly | 656 // if this is a delay slot, we can't restart properly |
| 620 // so if it is subnormal, clear the source register instead | 657 // so if it is subnormal, clear the source register instead |
| 621 if ( delay_slot ) { | 658 if ( delay_slot ) { |
| 622 if ( issubnormal( s ) ) { | 659 if ( issubnormal( s ) ) { |
| 623 // but preserve sign | 660 // but preserve sign |
| 624 if (s.number.sign) | 661 if (s.number.sign) |
| 625 s.value = -0.0; | 662 s.value = -0.0; |
| 626 else | 663 else |
| 627 s.value = 0.0; | 664 s.value = 0.0; |
| 628 *srcreg1 = s.asi64; | 665 dbl2reg( &s, srcreg1 ); |
| 629 handled++; | 666 handled++; |
| 630 } | 667 } |
| 631 } else { | 668 } else { |
| 632 d.asi64 = s.asi64; | 669 d.asi64 = s.asi64; |
| 633 d.number.sign = s.number.sign ? 0 : 1; | 670 d.number.sign = s.number.sign ? 0 : 1; |
| 634 *dstreg = d.asi64; | 671 dbl2reg( &d, dstreg ); |
| 635 regs->pc += 4; | 672 regs->pc += 4; |
| 636 handled++; | 673 handled++; |
| 637 } | 674 } |
| 638 } else { // 32-bit | 675 } else { // 32-bit |
| 639 Cyg_libm_ieee_float_shape_type d, s; | 676 Cyg_libm_ieee_float_shape_type d, s; |
| 680 case CVTL_INSN: | 717 case CVTL_INSN: |
| 681 | 718 |
| 682 if ( fp64bit ) { | 719 if ( fp64bit ) { |
| 683 Cyg_libm_ieee_double_shape_type s; | 720 Cyg_libm_ieee_double_shape_type s; |
| 684 | 721 |
| 685 s.asi64 = *srcreg1; | 722 reg2dbl( srcreg1, &s ); |
| 686 | 723 |
| 687 // just try and 0 the source register if it is subnormal | 724 // just try and 0 the source register if it is subnormal |
| 688 if ( issubnormal( s ) ) { | 725 if ( issubnormal( s ) ) { |
| 689 // but preserve sign | 726 // but preserve sign |
| 690 if (s.number.sign) | 727 if (s.number.sign) |
| 691 s.value = -0.0; | 728 s.value = -0.0; |
| 692 else | 729 else |
| 693 s.value = 0.0; | 730 s.value = 0.0; |
| 694 *srcreg1 = s.asi64; | 731 dbl2reg( &s, srcreg1 ); |
| 695 handled++; | 732 handled++; |
| 696 } | 733 } |
| 697 } else { // 32-bit | 734 } else { // 32-bit |
| 698 Cyg_libm_ieee_float_shape_type s; | 735 Cyg_libm_ieee_float_shape_type s; |
| 699 | 736 |
| 716 // check for floating-point compare (C.cond.fmt) | 753 // check for floating-point compare (C.cond.fmt) |
| 717 if ( (insn & 0x30) == 0x30 ) { | 754 if ( (insn & 0x30) == 0x30 ) { |
| 718 if (fp64bit) { | 755 if (fp64bit) { |
| 719 Cyg_libm_ieee_double_shape_type s1, s2; | 756 Cyg_libm_ieee_double_shape_type s1, s2; |
| 720 | 757 |
| 721 s1.asi64 = *srcreg1; | 758 reg2dbl( srcreg1, &s1 ); |
| 722 s2.asi64 = *srcreg2; | 759 reg2dbl( srcreg2, &s2 ); |
| 723 | 760 |
| 724 if ( issubnormal( s1 ) ) { // flush to 0 and restart | 761 if ( issubnormal( s1 ) ) { // flush to 0 and restart |
| 725 // but preserve sign | 762 // but preserve sign |
| 726 if (s1.number.sign) | 763 if (s1.number.sign) |
| 727 s1.value = -0.0; | 764 s1.value = -0.0; |
| 728 else | 765 else |
| 729 s1.value = 0.0; | 766 s1.value = 0.0; |
| 730 *srcreg1 = s1.asi64; | 767 dbl2reg( &s1, srcreg1 ); |
| 731 handled++; | 768 handled++; |
| 732 } | 769 } |
| 733 | 770 |
| 734 if ( issubnormal( s2 ) ) { // flush to 0 and restart | 771 if ( issubnormal( s2 ) ) { // flush to 0 and restart |
| 735 // but preserve sign | 772 // but preserve sign |
| 736 if (s2.number.sign) | 773 if (s2.number.sign) |
| 737 s2.value = -0.0; | 774 s2.value = -0.0; |
| 738 else | 775 else |
| 739 s2.value = 0.0; | 776 s2.value = 0.0; |
| 740 *srcreg2 = s2.asi64; | 777 dbl2reg( &s2, srcreg2 ); |
| 741 handled++; | 778 handled++; |
| 742 } | 779 } |
| 743 | 780 |
| 744 } else { // 32-bit | 781 } else { // 32-bit |
| 745 Cyg_libm_ieee_float_shape_type s1, s2; | 782 Cyg_libm_ieee_float_shape_type s1, s2; |
