diff options
Diffstat (limited to 'src/core/arm/skyeye_common/vfp/vfpsingle.cpp')
-rw-r--r-- | src/core/arm/skyeye_common/vfp/vfpsingle.cpp | 42 |
1 files changed, 29 insertions, 13 deletions
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 * 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; @@ -627,12 +631,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; } } } @@ -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) { - 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) @@ -669,7 +681,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 */ @@ -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 */ d = (vsm.significand << 1) >> shift; - rem = vsm.significand << (33 - shift); + rem = (vsm.significand << 1) << (32 - shift); if (rmode == FPSCR_ROUND_NEAREST) { incr = 0x80000000; @@ -709,10 +721,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; + } } } @@ -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) { - 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[] = { |