1
0
Fork 1
forked from suyu/suyu

Merge pull request #1568 from JayFoxRox/fix-printf

Fix ftoi and disable VFPv3
This commit is contained in:
Mat M 2016-05-26 19:03:00 -04:00
commit 031a9c57bb
3 changed files with 61 additions and 26 deletions

View file

@ -422,6 +422,10 @@ ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) {
n = arm_instruction[i].attribute_value; n = arm_instruction[i].attribute_value;
base = 0; base = 0;
// 3DS has no VFP3 support
if (arm_instruction[i].version == ARMVFP3)
continue;
while (n) { while (n) {
if (arm_instruction[i].content[base + 1] == 31 && arm_instruction[i].content[base] == 0) { if (arm_instruction[i].content[base + 1] == 31 && arm_instruction[i].content[base] == 0) {
// clrex // clrex

View file

@ -568,7 +568,7 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32
if (vdm.exponent >= 1023 + 32) { if (vdm.exponent >= 1023 + 32) {
d = vdm.sign ? 0 : 0xffffffff; d = vdm.sign ? 0 : 0xffffffff;
exceptions = FPSCR_IOC; exceptions = FPSCR_IOC;
} else if (vdm.exponent >= 1023 - 1) { } else if (vdm.exponent >= 1023) {
int shift = 1023 + 63 - vdm.exponent; int shift = 1023 + 63 - vdm.exponent;
u64 rem, incr = 0; u64 rem, incr = 0;
@ -603,12 +603,20 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32
} else { } else {
d = 0; d = 0;
if (vdm.exponent | vdm.significand) { if (vdm.exponent | vdm.significand) {
exceptions |= FPSCR_IXC; if (rmode == FPSCR_ROUND_NEAREST) {
if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0) 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; d = 1;
else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) { exceptions |= FPSCR_IXC;
d = 0; } else if (rmode == FPSCR_ROUND_MINUSINF) {
exceptions |= FPSCR_IOC; exceptions |= vdm.sign ? FPSCR_IOC : FPSCR_IXC;
} else {
exceptions |= FPSCR_IXC;
} }
} }
} }
@ -623,7 +631,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) static u32 vfp_double_ftouiz(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
{ {
LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); 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) 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
if (tm & VFP_NAN) { if (tm & VFP_NAN) {
d = 0; d = 0;
exceptions |= FPSCR_IOC; exceptions |= FPSCR_IOC;
} else if (vdm.exponent >= 1023 + 32) { } else if (vdm.exponent >= 1023 + 31) {
d = 0x7fffffff; d = 0x7fffffff;
if (vdm.sign) if (vdm.sign)
d = ~d; d = ~d;
exceptions |= FPSCR_IOC; exceptions |= FPSCR_IOC;
} else if (vdm.exponent >= 1023 - 1) { } else if (vdm.exponent >= 1023) {
int shift = 1023 + 63 - vdm.exponent; /* 58 */ int shift = 1023 + 63 - vdm.exponent; /* 58 */
u64 rem, incr = 0; u64 rem, incr = 0;
@ -683,10 +691,17 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32
d = 0; d = 0;
if (vdm.exponent | vdm.significand) { if (vdm.exponent | vdm.significand) {
exceptions |= FPSCR_IXC; 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; d = 1;
else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) } else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) {
d = -1; d = 0xffffffff;
}
} }
} }
@ -700,7 +715,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) static u32 vfp_double_ftosiz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
{ {
LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); 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[] = { static struct op fops_ext[] = {

View file

@ -600,7 +600,11 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f
* 2^0 <= m < 2^32-2^8 * 2^0 <= m < 2^32-2^8
*/ */
d = (vsm.significand << 1) >> shift; 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) { if (rmode == FPSCR_ROUND_NEAREST) {
incr = 0x80000000; incr = 0x80000000;
@ -627,12 +631,20 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f
} else { } else {
d = 0; d = 0;
if (vsm.exponent | vsm.significand) { if (vsm.exponent | vsm.significand) {
exceptions |= FPSCR_IXC; if (rmode == FPSCR_ROUND_NEAREST) {
if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0) 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; d = 1;
else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) { exceptions |= FPSCR_IXC;
d = 0; } else if (rmode == FPSCR_ROUND_MINUSINF) {
exceptions |= FPSCR_IOC; exceptions |= vsm.sign ? FPSCR_IOC : FPSCR_IXC;
} else {
exceptions |= FPSCR_IXC;
} }
} }
} }
@ -646,7 +658,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) 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) 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
if (tm & VFP_NAN) { if (tm & VFP_NAN) {
d = 0; d = 0;
exceptions |= FPSCR_IOC; exceptions |= FPSCR_IOC;
} else if (vsm.exponent >= 127 + 32) { } else if (vsm.exponent >= 127 + 31) {
/* /*
* m >= 2^31-2^7: invalid * m >= 2^31-2^7: invalid
*/ */
@ -683,7 +695,7 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f
/* 2^0 <= m <= 2^31-2^7 */ /* 2^0 <= m <= 2^31-2^7 */
d = (vsm.significand << 1) >> shift; d = (vsm.significand << 1) >> shift;
rem = vsm.significand << (33 - shift); rem = (vsm.significand << 1) << (32 - shift);
if (rmode == FPSCR_ROUND_NEAREST) { if (rmode == FPSCR_ROUND_NEAREST) {
incr = 0x80000000; incr = 0x80000000;
@ -709,10 +721,14 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f
d = 0; d = 0;
if (vsm.exponent | vsm.significand) { if (vsm.exponent | vsm.significand) {
exceptions |= FPSCR_IXC; 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; d = 1;
else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) } else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) {
d = -1; d = 0xffffffff;
}
} }
} }
@ -725,7 +741,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) 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[] = { static struct op fops_ext[] = {