Commit 9a819377d80f99a4293fd753dd1e90e6cbd618d2

Authored by aurel32
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
target-ppc/helper.h
... ... @@ -63,8 +63,8 @@ DEF_HELPER_1(fpscr_setbit, void, i32)
63 63 DEF_HELPER_1(float64_to_float32, i32, i64)
64 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 69 DEF_HELPER_1(fctiw, i64, i64)
70 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 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 1625 CPU_DoubleU farg1, farg2;
1626 1626 uint32_t ret = 0;
1627 1627 farg1.ll = arg1;
1628 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 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 1641 env->fpscr &= ~(0x0F << FPSCR_FPRF);
1644 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 1654 CPU_DoubleU farg1, farg2;
1651 1655 uint32_t ret = 0;
... ... @@ -1654,6 +1658,19 @@ uint32_t helper_fcmpo (uint64_t arg1, uint64_t arg2)
1654 1658  
1655 1659 if (unlikely(float64_is_nan(farg1.d) ||
1656 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 1674 if (float64_is_signaling_nan(farg1.d) ||
1658 1675 float64_is_signaling_nan(farg2.d)) {
1659 1676 /* sNaN comparison */
... ... @@ -1663,18 +1680,7 @@ uint32_t helper_fcmpo (uint64_t arg1, uint64_t arg2)
1663 1680 /* qNaN comparison */
1664 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 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 2249 /* fcmpo */
2250 2250 GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
2251 2251 {
  2252 + TCGv crf;
2252 2253 if (unlikely(!ctx->fpu_enabled)) {
2253 2254 gen_exception(ctx, POWERPC_EXCP_FPU);
2254 2255 return;
2255 2256 }
2256 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 2261 gen_helper_float_check_status();
2260 2262 }
2261 2263  
2262 2264 /* fcmpu */
2263 2265 GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
2264 2266 {
  2267 + TCGv crf;
2265 2268 if (unlikely(!ctx->fpu_enabled)) {
2266 2269 gen_exception(ctx, POWERPC_EXCP_FPU);
2267 2270 return;
2268 2271 }
2269 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 2276 gen_helper_float_check_status();
2273 2277 }
2274 2278  
... ...