summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.cpp4
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpdouble.cpp41
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpsingle.cpp42
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
623static u32 vfp_double_ftouiz(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) 631static 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
629static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) 637static 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
700static u32 vfp_double_ftosiz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 715static 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
706static struct op fops_ext[] = { 721static 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
647static u32 vfp_single_ftouiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 659static 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
652static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 664static 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
726static u32 vfp_single_ftosiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 742static 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
731static struct op fops_ext[] = { 747static struct op fops_ext[] = {