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,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