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 |