From 1643786c04738d1dab9604e98cc1d815a2ca027b Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sun, 15 May 2016 16:32:42 +0200 Subject: [PATCH 1/3] Disable VFP3 instructions --- src/core/arm/dyncom/arm_dyncom_dec.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/arm/dyncom/arm_dyncom_dec.cpp b/src/core/arm/dyncom/arm_dyncom_dec.cpp index 8cd6755cb3..247d379e3c 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) { n = arm_instruction[i].attribute_value; base = 0; + // 3DS has no VFP3 support + if (arm_instruction[i].version == ARMVFP3) + continue; + while (n) { if (arm_instruction[i].content[base + 1] == 31 && arm_instruction[i].content[base] == 0) { // clrex From 6fe0cb671df9daf29314be9cbe754606f8cb1ed1 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 16 May 2016 10:47:01 +0200 Subject: [PATCH 2/3] Respect fpscr in ftoiz --- src/core/arm/skyeye_common/vfp/vfpdouble.cpp | 4 ++-- src/core/arm/skyeye_common/vfp/vfpsingle.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp index 45914d4792..5215d48eb3 100644 --- a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp @@ -615,7 +615,7 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 static u32 vfp_double_ftouiz(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) { LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - return vfp_double_ftoui(state, sd, unused, dm, FPSCR_ROUND_TOZERO); + return vfp_double_ftoui(state, sd, unused, dm, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); } static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) @@ -692,7 +692,7 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 static u32 vfp_double_ftosiz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) { LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - return vfp_double_ftosi(state, dd, unused, dm, FPSCR_ROUND_TOZERO); + return vfp_double_ftosi(state, dd, unused, dm, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); } 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 e47ad2760a..e15a957165 100644 --- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp @@ -638,7 +638,7 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f static u32 vfp_single_ftouiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) { - return vfp_single_ftoui(state, sd, unused, m, FPSCR_ROUND_TOZERO); + return vfp_single_ftoui(state, sd, unused, m, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); } static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) @@ -717,7 +717,7 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f static u32 vfp_single_ftosiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) { - return vfp_single_ftosi(state, sd, unused, m, FPSCR_ROUND_TOZERO); + return vfp_single_ftosi(state, sd, unused, m, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); } static struct op fops_ext[] = { From 501d0bc5edd9091c7c831a710e6ebff9839fad36 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sun, 15 May 2016 16:33:36 +0200 Subject: [PATCH 3/3] Fix ftoi behaviour --- src/core/arm/skyeye_common/vfp/vfpdouble.cpp | 37 +++++++++++++------ src/core/arm/skyeye_common/vfp/vfpsingle.cpp | 38 ++++++++++++++------ 2 files changed, 53 insertions(+), 22 deletions(-) diff --git a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp index 5215d48eb3..a2a625abc0 100644 --- a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp @@ -560,7 +560,7 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 if (vdm.exponent >= 1023 + 32) { d = vdm.sign ? 0 : 0xffffffff; exceptions = FPSCR_IOC; - } else if (vdm.exponent >= 1023 - 1) { + } else if (vdm.exponent >= 1023) { int shift = 1023 + 63 - vdm.exponent; u64 rem, incr = 0; @@ -595,12 +595,20 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 } else { d = 0; if (vdm.exponent | vdm.significand) { - exceptions |= FPSCR_IXC; - if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0) + if (rmode == FPSCR_ROUND_NEAREST) { + if (vdm.exponent >= 1022) { + d = vdm.sign ? 0 : 1; + exceptions |= vdm.sign ? FPSCR_IOC : FPSCR_IXC; + } else { + exceptions |= FPSCR_IXC; + } + } else if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0) { d = 1; - else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) { - d = 0; - exceptions |= FPSCR_IOC; + exceptions |= FPSCR_IXC; + } else if (rmode == FPSCR_ROUND_MINUSINF) { + exceptions |= vdm.sign ? FPSCR_IOC : FPSCR_IXC; + } else { + exceptions |= FPSCR_IXC; } } } @@ -639,12 +647,12 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 if (tm & VFP_NAN) { d = 0; exceptions |= FPSCR_IOC; - } else if (vdm.exponent >= 1023 + 32) { + } else if (vdm.exponent >= 1023 + 31) { d = 0x7fffffff; if (vdm.sign) d = ~d; exceptions |= FPSCR_IOC; - } else if (vdm.exponent >= 1023 - 1) { + } else if (vdm.exponent >= 1023) { int shift = 1023 + 63 - vdm.exponent; /* 58 */ u64 rem, incr = 0; @@ -675,10 +683,17 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 d = 0; if (vdm.exponent | vdm.significand) { exceptions |= FPSCR_IXC; - if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0) + if (rmode == FPSCR_ROUND_NEAREST) { + if (vdm.exponent >= 1022) { + d = vdm.sign ? 0xffffffff : 1; + } else { + d = 0; + } + } else if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0) { d = 1; - else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) - d = -1; + } else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) { + d = 0xffffffff; + } } } diff --git a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp index e15a957165..6f6e0ca316 100644 --- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp @@ -592,7 +592,11 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f * 2^0 <= m < 2^32-2^8 */ d = (vsm.significand << 1) >> shift; - rem = vsm.significand << (33 - shift); + if (shift > 0) { + rem = (vsm.significand << 1) << (32 - shift); + } else { + rem = 0; + } if (rmode == FPSCR_ROUND_NEAREST) { incr = 0x80000000; @@ -619,12 +623,20 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f } else { d = 0; if (vsm.exponent | vsm.significand) { - exceptions |= FPSCR_IXC; - if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0) + if (rmode == FPSCR_ROUND_NEAREST) { + if (vsm.exponent >= 126) { + d = vsm.sign ? 0 : 1; + exceptions |= vsm.sign ? FPSCR_IOC : FPSCR_IXC; + } else { + exceptions |= FPSCR_IXC; + } + } else if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0) { d = 1; - else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) { - d = 0; - exceptions |= FPSCR_IOC; + exceptions |= FPSCR_IXC; + } else if (rmode == FPSCR_ROUND_MINUSINF) { + exceptions |= vsm.sign ? FPSCR_IOC : FPSCR_IXC; + } else { + exceptions |= FPSCR_IXC; } } } @@ -661,7 +673,7 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f if (tm & VFP_NAN) { d = 0; exceptions |= FPSCR_IOC; - } else if (vsm.exponent >= 127 + 32) { + } else if (vsm.exponent >= 127 + 31) { /* * m >= 2^31-2^7: invalid */ @@ -675,7 +687,7 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f /* 2^0 <= m <= 2^31-2^7 */ d = (vsm.significand << 1) >> shift; - rem = vsm.significand << (33 - shift); + rem = (vsm.significand << 1) << (32 - shift); if (rmode == FPSCR_ROUND_NEAREST) { incr = 0x80000000; @@ -701,10 +713,14 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f d = 0; if (vsm.exponent | vsm.significand) { exceptions |= FPSCR_IXC; - if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0) + if (rmode == FPSCR_ROUND_NEAREST) { + if (vsm.exponent >= 126) + d = vsm.sign ? 0xffffffff : 1; + } else if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0) { d = 1; - else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) - d = -1; + } else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) { + d = 0xffffffff; + } } }