Commit 9a819377d80f99a4293fd753dd1e90e6cbd618d2
1 parent
b12363e1
target-ppc: fix fcmp{o,u} instructions
The instructions are specified to update the condition register even if an error is to be signaled because of NaN input. Signed-off-by: Nathan Froyd <froydnj@codesourcery.com> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6034 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
41 additions
and
31 deletions
target-ppc/helper.h
| @@ -63,8 +63,8 @@ DEF_HELPER_1(fpscr_setbit, void, i32) | @@ -63,8 +63,8 @@ DEF_HELPER_1(fpscr_setbit, void, i32) | ||
| 63 | DEF_HELPER_1(float64_to_float32, i32, i64) | 63 | DEF_HELPER_1(float64_to_float32, i32, i64) |
| 64 | DEF_HELPER_1(float32_to_float64, i64, i32) | 64 | DEF_HELPER_1(float32_to_float64, i64, i32) |
| 65 | 65 | ||
| 66 | -DEF_HELPER_2(fcmpo, i32, i64, i64) | ||
| 67 | -DEF_HELPER_2(fcmpu, i32, i64, i64) | 66 | +DEF_HELPER_3(fcmpo, void, i64, i64, i32) |
| 67 | +DEF_HELPER_3(fcmpu, void, i64, i64, i32) | ||
| 68 | 68 | ||
| 69 | DEF_HELPER_1(fctiw, i64, i64) | 69 | DEF_HELPER_1(fctiw, i64, i64) |
| 70 | DEF_HELPER_1(fctiwz, i64, i64) | 70 | DEF_HELPER_1(fctiwz, i64, i64) |
target-ppc/op_helper.c
| @@ -1620,32 +1620,36 @@ uint64_t helper_fsel (uint64_t arg1, uint64_t arg2, uint64_t arg3) | @@ -1620,32 +1620,36 @@ uint64_t helper_fsel (uint64_t arg1, uint64_t arg2, uint64_t arg3) | ||
| 1620 | return arg3; | 1620 | return arg3; |
| 1621 | } | 1621 | } |
| 1622 | 1622 | ||
| 1623 | -uint32_t helper_fcmpu (uint64_t arg1, uint64_t arg2) | 1623 | +void helper_fcmpu (uint64_t arg1, uint64_t arg2, uint32_t crfD) |
| 1624 | { | 1624 | { |
| 1625 | CPU_DoubleU farg1, farg2; | 1625 | CPU_DoubleU farg1, farg2; |
| 1626 | uint32_t ret = 0; | 1626 | uint32_t ret = 0; |
| 1627 | farg1.ll = arg1; | 1627 | farg1.ll = arg1; |
| 1628 | farg2.ll = arg2; | 1628 | farg2.ll = arg2; |
| 1629 | 1629 | ||
| 1630 | - if (unlikely(float64_is_signaling_nan(farg1.d) || | ||
| 1631 | - float64_is_signaling_nan(farg2.d))) { | ||
| 1632 | - /* sNaN comparison */ | ||
| 1633 | - fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN); | 1630 | + if (unlikely(float64_is_nan(farg1.d) || |
| 1631 | + float64_is_nan(farg2.d))) { | ||
| 1632 | + ret = 0x01UL; | ||
| 1633 | + } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) { | ||
| 1634 | + ret = 0x08UL; | ||
| 1635 | + } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) { | ||
| 1636 | + ret = 0x04UL; | ||
| 1634 | } else { | 1637 | } else { |
| 1635 | - if (float64_lt(farg1.d, farg2.d, &env->fp_status)) { | ||
| 1636 | - ret = 0x08UL; | ||
| 1637 | - } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) { | ||
| 1638 | - ret = 0x04UL; | ||
| 1639 | - } else { | ||
| 1640 | - ret = 0x02UL; | ||
| 1641 | - } | 1638 | + ret = 0x02UL; |
| 1642 | } | 1639 | } |
| 1640 | + | ||
| 1643 | env->fpscr &= ~(0x0F << FPSCR_FPRF); | 1641 | env->fpscr &= ~(0x0F << FPSCR_FPRF); |
| 1644 | env->fpscr |= ret << FPSCR_FPRF; | 1642 | env->fpscr |= ret << FPSCR_FPRF; |
| 1645 | - return ret; | 1643 | + env->crf[crfD] = ret; |
| 1644 | + if (unlikely(ret == 0x01UL | ||
| 1645 | + && (float64_is_signaling_nan(farg1.d) || | ||
| 1646 | + float64_is_signaling_nan(farg2.d)))) { | ||
| 1647 | + /* sNaN comparison */ | ||
| 1648 | + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN); | ||
| 1649 | + } | ||
| 1646 | } | 1650 | } |
| 1647 | 1651 | ||
| 1648 | -uint32_t helper_fcmpo (uint64_t arg1, uint64_t arg2) | 1652 | +void helper_fcmpo (uint64_t arg1, uint64_t arg2, uint32_t crfD) |
| 1649 | { | 1653 | { |
| 1650 | CPU_DoubleU farg1, farg2; | 1654 | CPU_DoubleU farg1, farg2; |
| 1651 | uint32_t ret = 0; | 1655 | uint32_t ret = 0; |
| @@ -1654,6 +1658,19 @@ uint32_t helper_fcmpo (uint64_t arg1, uint64_t arg2) | @@ -1654,6 +1658,19 @@ uint32_t helper_fcmpo (uint64_t arg1, uint64_t arg2) | ||
| 1654 | 1658 | ||
| 1655 | if (unlikely(float64_is_nan(farg1.d) || | 1659 | if (unlikely(float64_is_nan(farg1.d) || |
| 1656 | float64_is_nan(farg2.d))) { | 1660 | float64_is_nan(farg2.d))) { |
| 1661 | + ret = 0x01UL; | ||
| 1662 | + } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) { | ||
| 1663 | + ret = 0x08UL; | ||
| 1664 | + } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) { | ||
| 1665 | + ret = 0x04UL; | ||
| 1666 | + } else { | ||
| 1667 | + ret = 0x02UL; | ||
| 1668 | + } | ||
| 1669 | + | ||
| 1670 | + env->fpscr &= ~(0x0F << FPSCR_FPRF); | ||
| 1671 | + env->fpscr |= ret << FPSCR_FPRF; | ||
| 1672 | + env->crf[crfD] = ret; | ||
| 1673 | + if (unlikely (ret == 0x01UL)) { | ||
| 1657 | if (float64_is_signaling_nan(farg1.d) || | 1674 | if (float64_is_signaling_nan(farg1.d) || |
| 1658 | float64_is_signaling_nan(farg2.d)) { | 1675 | float64_is_signaling_nan(farg2.d)) { |
| 1659 | /* sNaN comparison */ | 1676 | /* sNaN comparison */ |
| @@ -1663,18 +1680,7 @@ uint32_t helper_fcmpo (uint64_t arg1, uint64_t arg2) | @@ -1663,18 +1680,7 @@ uint32_t helper_fcmpo (uint64_t arg1, uint64_t arg2) | ||
| 1663 | /* qNaN comparison */ | 1680 | /* qNaN comparison */ |
| 1664 | fload_invalid_op_excp(POWERPC_EXCP_FP_VXVC); | 1681 | fload_invalid_op_excp(POWERPC_EXCP_FP_VXVC); |
| 1665 | } | 1682 | } |
| 1666 | - } else { | ||
| 1667 | - if (float64_lt(farg1.d, farg2.d, &env->fp_status)) { | ||
| 1668 | - ret = 0x08UL; | ||
| 1669 | - } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) { | ||
| 1670 | - ret = 0x04UL; | ||
| 1671 | - } else { | ||
| 1672 | - ret = 0x02UL; | ||
| 1673 | - } | ||
| 1674 | } | 1683 | } |
| 1675 | - env->fpscr &= ~(0x0F << FPSCR_FPRF); | ||
| 1676 | - env->fpscr |= ret << FPSCR_FPRF; | ||
| 1677 | - return ret; | ||
| 1678 | } | 1684 | } |
| 1679 | 1685 | ||
| 1680 | #if !defined (CONFIG_USER_ONLY) | 1686 | #if !defined (CONFIG_USER_ONLY) |
target-ppc/translate.c
| @@ -2249,26 +2249,30 @@ GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT); | @@ -2249,26 +2249,30 @@ GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT); | ||
| 2249 | /* fcmpo */ | 2249 | /* fcmpo */ |
| 2250 | GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT) | 2250 | GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT) |
| 2251 | { | 2251 | { |
| 2252 | + TCGv crf; | ||
| 2252 | if (unlikely(!ctx->fpu_enabled)) { | 2253 | if (unlikely(!ctx->fpu_enabled)) { |
| 2253 | gen_exception(ctx, POWERPC_EXCP_FPU); | 2254 | gen_exception(ctx, POWERPC_EXCP_FPU); |
| 2254 | return; | 2255 | return; |
| 2255 | } | 2256 | } |
| 2256 | gen_reset_fpstatus(); | 2257 | gen_reset_fpstatus(); |
| 2257 | - gen_helper_fcmpo(cpu_crf[crfD(ctx->opcode)], | ||
| 2258 | - cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); | 2258 | + crf = tcg_const_i32(crfD(ctx->opcode)); |
| 2259 | + gen_helper_fcmpo(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf); | ||
| 2260 | + tcg_temp_free(crf); | ||
| 2259 | gen_helper_float_check_status(); | 2261 | gen_helper_float_check_status(); |
| 2260 | } | 2262 | } |
| 2261 | 2263 | ||
| 2262 | /* fcmpu */ | 2264 | /* fcmpu */ |
| 2263 | GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT) | 2265 | GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT) |
| 2264 | { | 2266 | { |
| 2267 | + TCGv crf; | ||
| 2265 | if (unlikely(!ctx->fpu_enabled)) { | 2268 | if (unlikely(!ctx->fpu_enabled)) { |
| 2266 | gen_exception(ctx, POWERPC_EXCP_FPU); | 2269 | gen_exception(ctx, POWERPC_EXCP_FPU); |
| 2267 | return; | 2270 | return; |
| 2268 | } | 2271 | } |
| 2269 | gen_reset_fpstatus(); | 2272 | gen_reset_fpstatus(); |
| 2270 | - gen_helper_fcmpu(cpu_crf[crfD(ctx->opcode)], | ||
| 2271 | - cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); | 2273 | + crf = tcg_const_i32(crfD(ctx->opcode)); |
| 2274 | + gen_helper_fcmpu(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf); | ||
| 2275 | + tcg_temp_free(crf); | ||
| 2272 | gen_helper_float_check_status(); | 2276 | gen_helper_float_check_status(); |
| 2273 | } | 2277 | } |
| 2274 | 2278 |