diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_dec.cpp | 4 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/vfp/vfpdouble.cpp | 41 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/vfp/vfpsingle.cpp | 42 |
3 files changed, 61 insertions, 26 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.cpp b/src/core/arm/dyncom/arm_dyncom_dec.cpp index 8cd6755cb..247d379e3 100644 --- a/src/core/arm/dyncom/arm_dyncom_dec.cpp +++ b/src/core/arm/dyncom/arm_dyncom_dec.cpp | |||
| @@ -422,6 +422,10 @@ ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) { | |||
| 422 | n = arm_instruction[i].attribute_value; | 422 | n = arm_instruction[i].attribute_value; |
| 423 | base = 0; | 423 | base = 0; |
| 424 | 424 | ||
| 425 | // 3DS has no VFP3 support | ||
| 426 | if (arm_instruction[i].version == ARMVFP3) | ||
| 427 | continue; | ||
| 428 | |||
| 425 | while (n) { | 429 | while (n) { |
| 426 | if (arm_instruction[i].content[base + 1] == 31 && arm_instruction[i].content[base] == 0) { | 430 | if (arm_instruction[i].content[base + 1] == 31 && arm_instruction[i].content[base] == 0) { |
| 427 | // clrex | 431 | // clrex |
diff --git a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp index 580e60c85..1d5641810 100644 --- a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp | |||
| @@ -568,7 +568,7 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 | |||
| 568 | if (vdm.exponent >= 1023 + 32) { | 568 | if (vdm.exponent >= 1023 + 32) { |
| 569 | d = vdm.sign ? 0 : 0xffffffff; | 569 | d = vdm.sign ? 0 : 0xffffffff; |
| 570 | exceptions = FPSCR_IOC; | 570 | exceptions = FPSCR_IOC; |
| 571 | } else if (vdm.exponent >= 1023 - 1) { | 571 | } else if (vdm.exponent >= 1023) { |
| 572 | int shift = 1023 + 63 - vdm.exponent; | 572 | int shift = 1023 + 63 - vdm.exponent; |
| 573 | u64 rem, incr = 0; | 573 | u64 rem, incr = 0; |
| 574 | 574 | ||
| @@ -603,12 +603,20 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 | |||
| 603 | } else { | 603 | } else { |
| 604 | d = 0; | 604 | d = 0; |
| 605 | if (vdm.exponent | vdm.significand) { | 605 | if (vdm.exponent | vdm.significand) { |
| 606 | exceptions |= FPSCR_IXC; | 606 | if (rmode == FPSCR_ROUND_NEAREST) { |
| 607 | if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0) | 607 | if (vdm.exponent >= 1022) { |
| 608 | d = vdm.sign ? 0 : 1; | ||
| 609 | exceptions |= vdm.sign ? FPSCR_IOC : FPSCR_IXC; | ||
| 610 | } else { | ||
| 611 | exceptions |= FPSCR_IXC; | ||
| 612 | } | ||
| 613 | } else if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0) { | ||
| 608 | d = 1; | 614 | d = 1; |
| 609 | else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) { | 615 | exceptions |= FPSCR_IXC; |
| 610 | d = 0; | 616 | } else if (rmode == FPSCR_ROUND_MINUSINF) { |
| 611 | exceptions |= FPSCR_IOC; | 617 | exceptions |= vdm.sign ? FPSCR_IOC : FPSCR_IXC; |
| 618 | } else { | ||
| 619 | exceptions |= FPSCR_IXC; | ||
| 612 | } | 620 | } |
| 613 | } | 621 | } |
| 614 | } | 622 | } |
| @@ -623,7 +631,7 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 | |||
| 623 | static u32 vfp_double_ftouiz(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) | 631 | static u32 vfp_double_ftouiz(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) |
| 624 | { | 632 | { |
| 625 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); | 633 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); |
| 626 | return vfp_double_ftoui(state, sd, unused, dm, FPSCR_ROUND_TOZERO); | 634 | return vfp_double_ftoui(state, sd, unused, dm, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); |
| 627 | } | 635 | } |
| 628 | 636 | ||
| 629 | static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) | 637 | static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) |
| @@ -647,12 +655,12 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 | |||
| 647 | if (tm & VFP_NAN) { | 655 | if (tm & VFP_NAN) { |
| 648 | d = 0; | 656 | d = 0; |
| 649 | exceptions |= FPSCR_IOC; | 657 | exceptions |= FPSCR_IOC; |
| 650 | } else if (vdm.exponent >= 1023 + 32) { | 658 | } else if (vdm.exponent >= 1023 + 31) { |
| 651 | d = 0x7fffffff; | 659 | d = 0x7fffffff; |
| 652 | if (vdm.sign) | 660 | if (vdm.sign) |
| 653 | d = ~d; | 661 | d = ~d; |
| 654 | exceptions |= FPSCR_IOC; | 662 | exceptions |= FPSCR_IOC; |
| 655 | } else if (vdm.exponent >= 1023 - 1) { | 663 | } else if (vdm.exponent >= 1023) { |
| 656 | int shift = 1023 + 63 - vdm.exponent; /* 58 */ | 664 | int shift = 1023 + 63 - vdm.exponent; /* 58 */ |
| 657 | u64 rem, incr = 0; | 665 | u64 rem, incr = 0; |
| 658 | 666 | ||
| @@ -683,10 +691,17 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 | |||
| 683 | d = 0; | 691 | d = 0; |
| 684 | if (vdm.exponent | vdm.significand) { | 692 | if (vdm.exponent | vdm.significand) { |
| 685 | exceptions |= FPSCR_IXC; | 693 | exceptions |= FPSCR_IXC; |
| 686 | if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0) | 694 | if (rmode == FPSCR_ROUND_NEAREST) { |
| 695 | if (vdm.exponent >= 1022) { | ||
| 696 | d = vdm.sign ? 0xffffffff : 1; | ||
| 697 | } else { | ||
| 698 | d = 0; | ||
| 699 | } | ||
| 700 | } else if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0) { | ||
| 687 | d = 1; | 701 | d = 1; |
| 688 | else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) | 702 | } else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) { |
| 689 | d = -1; | 703 | d = 0xffffffff; |
| 704 | } | ||
| 690 | } | 705 | } |
| 691 | } | 706 | } |
| 692 | 707 | ||
| @@ -700,7 +715,7 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 | |||
| 700 | static u32 vfp_double_ftosiz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) | 715 | static u32 vfp_double_ftosiz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) |
| 701 | { | 716 | { |
| 702 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); | 717 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); |
| 703 | return vfp_double_ftosi(state, dd, unused, dm, FPSCR_ROUND_TOZERO); | 718 | return vfp_double_ftosi(state, dd, unused, dm, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); |
| 704 | } | 719 | } |
| 705 | 720 | ||
| 706 | static struct op fops_ext[] = { | 721 | static struct op fops_ext[] = { |
diff --git a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp index 23e0cdf26..60264f9b3 100644 --- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp | |||
| @@ -600,7 +600,11 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f | |||
| 600 | * 2^0 <= m < 2^32-2^8 | 600 | * 2^0 <= m < 2^32-2^8 |
| 601 | */ | 601 | */ |
| 602 | d = (vsm.significand << 1) >> shift; | 602 | d = (vsm.significand << 1) >> shift; |
| 603 | rem = vsm.significand << (33 - shift); | 603 | if (shift > 0) { |
| 604 | rem = (vsm.significand << 1) << (32 - shift); | ||
| 605 | } else { | ||
| 606 | rem = 0; | ||
| 607 | } | ||
| 604 | 608 | ||
| 605 | if (rmode == FPSCR_ROUND_NEAREST) { | 609 | if (rmode == FPSCR_ROUND_NEAREST) { |
| 606 | incr = 0x80000000; | 610 | incr = 0x80000000; |
| @@ -627,12 +631,20 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f | |||
| 627 | } else { | 631 | } else { |
| 628 | d = 0; | 632 | d = 0; |
| 629 | if (vsm.exponent | vsm.significand) { | 633 | if (vsm.exponent | vsm.significand) { |
| 630 | exceptions |= FPSCR_IXC; | 634 | if (rmode == FPSCR_ROUND_NEAREST) { |
| 631 | if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0) | 635 | if (vsm.exponent >= 126) { |
| 636 | d = vsm.sign ? 0 : 1; | ||
| 637 | exceptions |= vsm.sign ? FPSCR_IOC : FPSCR_IXC; | ||
| 638 | } else { | ||
| 639 | exceptions |= FPSCR_IXC; | ||
| 640 | } | ||
| 641 | } else if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0) { | ||
| 632 | d = 1; | 642 | d = 1; |
| 633 | else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) { | 643 | exceptions |= FPSCR_IXC; |
| 634 | d = 0; | 644 | } else if (rmode == FPSCR_ROUND_MINUSINF) { |
| 635 | exceptions |= FPSCR_IOC; | 645 | exceptions |= vsm.sign ? FPSCR_IOC : FPSCR_IXC; |
| 646 | } else { | ||
| 647 | exceptions |= FPSCR_IXC; | ||
| 636 | } | 648 | } |
| 637 | } | 649 | } |
| 638 | } | 650 | } |
| @@ -646,7 +658,7 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f | |||
| 646 | 658 | ||
| 647 | static u32 vfp_single_ftouiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) | 659 | static u32 vfp_single_ftouiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) |
| 648 | { | 660 | { |
| 649 | return vfp_single_ftoui(state, sd, unused, m, FPSCR_ROUND_TOZERO); | 661 | return vfp_single_ftoui(state, sd, unused, m, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); |
| 650 | } | 662 | } |
| 651 | 663 | ||
| 652 | static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) | 664 | static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) |
| @@ -669,7 +681,7 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f | |||
| 669 | if (tm & VFP_NAN) { | 681 | if (tm & VFP_NAN) { |
| 670 | d = 0; | 682 | d = 0; |
| 671 | exceptions |= FPSCR_IOC; | 683 | exceptions |= FPSCR_IOC; |
| 672 | } else if (vsm.exponent >= 127 + 32) { | 684 | } else if (vsm.exponent >= 127 + 31) { |
| 673 | /* | 685 | /* |
| 674 | * m >= 2^31-2^7: invalid | 686 | * m >= 2^31-2^7: invalid |
| 675 | */ | 687 | */ |
| @@ -683,7 +695,7 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f | |||
| 683 | 695 | ||
| 684 | /* 2^0 <= m <= 2^31-2^7 */ | 696 | /* 2^0 <= m <= 2^31-2^7 */ |
| 685 | d = (vsm.significand << 1) >> shift; | 697 | d = (vsm.significand << 1) >> shift; |
| 686 | rem = vsm.significand << (33 - shift); | 698 | rem = (vsm.significand << 1) << (32 - shift); |
| 687 | 699 | ||
| 688 | if (rmode == FPSCR_ROUND_NEAREST) { | 700 | if (rmode == FPSCR_ROUND_NEAREST) { |
| 689 | incr = 0x80000000; | 701 | incr = 0x80000000; |
| @@ -709,10 +721,14 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f | |||
| 709 | d = 0; | 721 | d = 0; |
| 710 | if (vsm.exponent | vsm.significand) { | 722 | if (vsm.exponent | vsm.significand) { |
| 711 | exceptions |= FPSCR_IXC; | 723 | exceptions |= FPSCR_IXC; |
| 712 | if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0) | 724 | if (rmode == FPSCR_ROUND_NEAREST) { |
| 725 | if (vsm.exponent >= 126) | ||
| 726 | d = vsm.sign ? 0xffffffff : 1; | ||
| 727 | } else if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0) { | ||
| 713 | d = 1; | 728 | d = 1; |
| 714 | else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) | 729 | } else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) { |
| 715 | d = -1; | 730 | d = 0xffffffff; |
| 731 | } | ||
| 716 | } | 732 | } |
| 717 | } | 733 | } |
| 718 | 734 | ||
| @@ -725,7 +741,7 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f | |||
| 725 | 741 | ||
| 726 | static u32 vfp_single_ftosiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) | 742 | static u32 vfp_single_ftosiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) |
| 727 | { | 743 | { |
| 728 | return vfp_single_ftosi(state, sd, unused, m, FPSCR_ROUND_TOZERO); | 744 | return vfp_single_ftosi(state, sd, unused, m, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); |
| 729 | } | 745 | } |
| 730 | 746 | ||
| 731 | static struct op fops_ext[] = { | 747 | static struct op fops_ext[] = { |