Commit e864cabdc0a38bb598ddcf88b264896dc6f3e3b2

Authored by j_mayer
1 parent a7222580

PowerPC bugfixes:

- must clear carry bit when doing addic with a zero immediate value
- fix missing RETURN in micro-operation that would lead to random failures
  and crashes
- add USE_PRECISE_EMULATION compilation-time option to choose between
  getting exact floating point results and fast but less accurate computation.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2526 c046a42c-6fe2-441c-8c8c-71466251a162
target-ppc/exec.h
@@ -27,6 +27,10 @@ @@ -27,6 +27,10 @@
27 #include "cpu.h" 27 #include "cpu.h"
28 #include "exec-all.h" 28 #include "exec-all.h"
29 29
  30 +/* For normal operations, precise emulation should not be needed */
  31 +//#define USE_PRECISE_EMULATION 1
  32 +#define USE_PRECISE_EMULATION 0
  33 +
30 register struct CPUPPCState *env asm(AREG0); 34 register struct CPUPPCState *env asm(AREG0);
31 #if TARGET_LONG_BITS > HOST_LONG_BITS 35 #if TARGET_LONG_BITS > HOST_LONG_BITS
32 /* no registers can be used */ 36 /* no registers can be used */
target-ppc/op.c
@@ -261,10 +261,15 @@ PPC_OP(load_xer_cr) @@ -261,10 +261,15 @@ PPC_OP(load_xer_cr)
261 RETURN(); 261 RETURN();
262 } 262 }
263 263
264 -PPC_OP(clear_xer_cr) 264 +PPC_OP(clear_xer_ov)
265 { 265 {
266 xer_so = 0; 266 xer_so = 0;
267 xer_ov = 0; 267 xer_ov = 0;
  268 + RETURN();
  269 +}
  270 +
  271 +PPC_OP(clear_xer_ca)
  272 +{
268 xer_ca = 0; 273 xer_ca = 0;
269 RETURN(); 274 RETURN();
270 } 275 }
@@ -714,6 +719,7 @@ void OPPROTO op_check_addo (void) @@ -714,6 +719,7 @@ void OPPROTO op_check_addo (void)
714 xer_so = 1; 719 xer_so = 1;
715 xer_ov = 1; 720 xer_ov = 1;
716 } 721 }
  722 + RETURN();
717 } 723 }
718 724
719 #if defined(TARGET_PPC64) 725 #if defined(TARGET_PPC64)
@@ -726,6 +732,7 @@ void OPPROTO op_check_addo_64 (void) @@ -726,6 +732,7 @@ void OPPROTO op_check_addo_64 (void)
726 xer_so = 1; 732 xer_so = 1;
727 xer_ov = 1; 733 xer_ov = 1;
728 } 734 }
  735 + RETURN();
729 } 736 }
730 #endif 737 #endif
731 738
@@ -1643,16 +1650,24 @@ PPC_OP(fsel) @@ -1643,16 +1650,24 @@ PPC_OP(fsel)
1643 /* fmadd - fmadd. */ 1650 /* fmadd - fmadd. */
1644 PPC_OP(fmadd) 1651 PPC_OP(fmadd)
1645 { 1652 {
  1653 +#if USE_PRECISE_EMULATION
  1654 + do_fmadd();
  1655 +#else
1646 FT0 = float64_mul(FT0, FT1, &env->fp_status); 1656 FT0 = float64_mul(FT0, FT1, &env->fp_status);
1647 FT0 = float64_add(FT0, FT2, &env->fp_status); 1657 FT0 = float64_add(FT0, FT2, &env->fp_status);
  1658 +#endif
1648 RETURN(); 1659 RETURN();
1649 } 1660 }
1650 1661
1651 /* fmsub - fmsub. */ 1662 /* fmsub - fmsub. */
1652 PPC_OP(fmsub) 1663 PPC_OP(fmsub)
1653 { 1664 {
  1665 +#if USE_PRECISE_EMULATION
  1666 + do_fmsub();
  1667 +#else
1654 FT0 = float64_mul(FT0, FT1, &env->fp_status); 1668 FT0 = float64_mul(FT0, FT1, &env->fp_status);
1655 FT0 = float64_sub(FT0, FT2, &env->fp_status); 1669 FT0 = float64_sub(FT0, FT2, &env->fp_status);
  1670 +#endif
1656 RETURN(); 1671 RETURN();
1657 } 1672 }
1658 1673
@@ -2378,6 +2393,7 @@ void OPPROTO op_store_booke_tsr (void) @@ -2378,6 +2393,7 @@ void OPPROTO op_store_booke_tsr (void)
2378 void OPPROTO op_splatw_T1_64 (void) 2393 void OPPROTO op_splatw_T1_64 (void)
2379 { 2394 {
2380 T1_64 = (T1_64 << 32) | (T1_64 & 0x00000000FFFFFFFFULL); 2395 T1_64 = (T1_64 << 32) | (T1_64 & 0x00000000FFFFFFFFULL);
  2396 + RETURN();
2381 } 2397 }
2382 2398
2383 void OPPROTO op_splatwi_T0_64 (void) 2399 void OPPROTO op_splatwi_T0_64 (void)
@@ -2385,6 +2401,7 @@ void OPPROTO op_splatwi_T0_64 (void) @@ -2385,6 +2401,7 @@ void OPPROTO op_splatwi_T0_64 (void)
2385 uint64_t tmp = PARAM1; 2401 uint64_t tmp = PARAM1;
2386 2402
2387 T0_64 = (tmp << 32) | tmp; 2403 T0_64 = (tmp << 32) | tmp;
  2404 + RETURN();
2388 } 2405 }
2389 2406
2390 void OPPROTO op_splatwi_T1_64 (void) 2407 void OPPROTO op_splatwi_T1_64 (void)
@@ -2392,6 +2409,7 @@ void OPPROTO op_splatwi_T1_64 (void) @@ -2392,6 +2409,7 @@ void OPPROTO op_splatwi_T1_64 (void)
2392 uint64_t tmp = PARAM1; 2409 uint64_t tmp = PARAM1;
2393 2410
2394 T1_64 = (tmp << 32) | tmp; 2411 T1_64 = (tmp << 32) | tmp;
  2412 + RETURN();
2395 } 2413 }
2396 2414
2397 void OPPROTO op_extsh_T1_64 (void) 2415 void OPPROTO op_extsh_T1_64 (void)
target-ppc/op_helper.c
@@ -615,11 +615,13 @@ void do_fctiw (void) @@ -615,11 +615,13 @@ void do_fctiw (void)
615 uint64_t i; 615 uint64_t i;
616 } p; 616 } p;
617 617
  618 + p.i = float64_to_int32(FT0, &env->fp_status);
  619 +#if USE_PRECISE_EMULATION
618 /* XXX: higher bits are not supposed to be significant. 620 /* XXX: higher bits are not supposed to be significant.
619 * to make tests easier, return the same as a real PowerPC 750 (aka G3) 621 * to make tests easier, return the same as a real PowerPC 750 (aka G3)
620 */ 622 */
621 - p.i = float64_to_int32(FT0, &env->fp_status);  
622 p.i |= 0xFFF80000ULL << 32; 623 p.i |= 0xFFF80000ULL << 32;
  624 +#endif
623 FT0 = p.d; 625 FT0 = p.d;
624 } 626 }
625 627
@@ -630,26 +632,96 @@ void do_fctiwz (void) @@ -630,26 +632,96 @@ void do_fctiwz (void)
630 uint64_t i; 632 uint64_t i;
631 } p; 633 } p;
632 634
  635 + p.i = float64_to_int32_round_to_zero(FT0, &env->fp_status);
  636 +#if USE_PRECISE_EMULATION
633 /* XXX: higher bits are not supposed to be significant. 637 /* XXX: higher bits are not supposed to be significant.
634 * to make tests easier, return the same as a real PowerPC 750 (aka G3) 638 * to make tests easier, return the same as a real PowerPC 750 (aka G3)
635 */ 639 */
636 - p.i = float64_to_int32_round_to_zero(FT0, &env->fp_status);  
637 p.i |= 0xFFF80000ULL << 32; 640 p.i |= 0xFFF80000ULL << 32;
  641 +#endif
638 FT0 = p.d; 642 FT0 = p.d;
639 } 643 }
640 644
  645 +#if USE_PRECISE_EMULATION
  646 +void do_fmadd (void)
  647 +{
  648 +#ifdef FLOAT128
  649 + float128 ft0_128, ft1_128;
  650 +
  651 + ft0_128 = float64_to_float128(FT0, &env->fp_status);
  652 + ft1_128 = float64_to_float128(FT1, &env->fp_status);
  653 + ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
  654 + ft1_128 = float64_to_float128(FT2, &env->fp_status);
  655 + ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
  656 + FT0 = float128_to_float64(ft0_128, &env->fp_status);
  657 +#else
  658 + /* This is OK on x86 hosts */
  659 + FT0 = (FT0 * FT1) + FT2;
  660 +#endif
  661 +}
  662 +
  663 +void do_fmsub (void)
  664 +{
  665 +#ifdef FLOAT128
  666 + float128 ft0_128, ft1_128;
  667 +
  668 + ft0_128 = float64_to_float128(FT0, &env->fp_status);
  669 + ft1_128 = float64_to_float128(FT1, &env->fp_status);
  670 + ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
  671 + ft1_128 = float64_to_float128(FT2, &env->fp_status);
  672 + ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
  673 + FT0 = float128_to_float64(ft0_128, &env->fp_status);
  674 +#else
  675 + /* This is OK on x86 hosts */
  676 + FT0 = (FT0 * FT1) - FT2;
  677 +#endif
  678 +}
  679 +#endif /* USE_PRECISE_EMULATION */
  680 +
641 void do_fnmadd (void) 681 void do_fnmadd (void)
642 { 682 {
  683 +#if USE_PRECISE_EMULATION
  684 +#ifdef FLOAT128
  685 + float128 ft0_128, ft1_128;
  686 +
  687 + ft0_128 = float64_to_float128(FT0, &env->fp_status);
  688 + ft1_128 = float64_to_float128(FT1, &env->fp_status);
  689 + ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
  690 + ft1_128 = float64_to_float128(FT2, &env->fp_status);
  691 + ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
  692 + FT0 = float128_to_float64(ft0_128, &env->fp_status);
  693 +#else
  694 + /* This is OK on x86 hosts */
  695 + FT0 = (FT0 * FT1) + FT2;
  696 +#endif
  697 +#else
643 FT0 = float64_mul(FT0, FT1, &env->fp_status); 698 FT0 = float64_mul(FT0, FT1, &env->fp_status);
644 FT0 = float64_add(FT0, FT2, &env->fp_status); 699 FT0 = float64_add(FT0, FT2, &env->fp_status);
  700 +#endif
645 if (likely(!isnan(FT0))) 701 if (likely(!isnan(FT0)))
646 FT0 = float64_chs(FT0); 702 FT0 = float64_chs(FT0);
647 } 703 }
648 704
649 void do_fnmsub (void) 705 void do_fnmsub (void)
650 { 706 {
  707 +#if USE_PRECISE_EMULATION
  708 +#ifdef FLOAT128
  709 + float128 ft0_128, ft1_128;
  710 +
  711 + ft0_128 = float64_to_float128(FT0, &env->fp_status);
  712 + ft1_128 = float64_to_float128(FT1, &env->fp_status);
  713 + ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
  714 + ft1_128 = float64_to_float128(FT2, &env->fp_status);
  715 + ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
  716 + FT0 = float128_to_float64(ft0_128, &env->fp_status);
  717 +#else
  718 + /* This is OK on x86 hosts */
  719 + FT0 = (FT0 * FT1) - FT2;
  720 +#endif
  721 +#else
651 FT0 = float64_mul(FT0, FT1, &env->fp_status); 722 FT0 = float64_mul(FT0, FT1, &env->fp_status);
652 FT0 = float64_sub(FT0, FT2, &env->fp_status); 723 FT0 = float64_sub(FT0, FT2, &env->fp_status);
  724 +#endif
653 if (likely(!isnan(FT0))) 725 if (likely(!isnan(FT0)))
654 FT0 = float64_chs(FT0); 726 FT0 = float64_chs(FT0);
655 } 727 }
@@ -667,7 +739,12 @@ void do_fres (void) @@ -667,7 +739,12 @@ void do_fres (void)
667 } p; 739 } p;
668 740
669 if (likely(isnormal(FT0))) { 741 if (likely(isnormal(FT0))) {
  742 +#if USE_PRECISE_EMULATION
  743 + FT0 = float64_div(1.0, FT0, &env->fp_status);
  744 + FT0 = float64_to_float32(FT0, &env->fp_status);
  745 +#else
670 FT0 = float32_div(1.0, FT0, &env->fp_status); 746 FT0 = float32_div(1.0, FT0, &env->fp_status);
  747 +#endif
671 } else { 748 } else {
672 p.d = FT0; 749 p.d = FT0;
673 if (p.i == 0x8000000000000000ULL) { 750 if (p.i == 0x8000000000000000ULL) {
target-ppc/op_helper.h
@@ -93,6 +93,10 @@ void do_fsqrt (void); @@ -93,6 +93,10 @@ void do_fsqrt (void);
93 void do_fres (void); 93 void do_fres (void);
94 void do_frsqrte (void); 94 void do_frsqrte (void);
95 void do_fsel (void); 95 void do_fsel (void);
  96 +#if USE_PRECISE_EMULATION
  97 +void do_fmadd (void);
  98 +void do_fmsub (void);
  99 +#endif
96 void do_fnmadd (void); 100 void do_fnmadd (void);
97 void do_fnmsub (void); 101 void do_fnmsub (void);
98 void do_fctiw (void); 102 void do_fctiw (void);
target-ppc/translate.c
@@ -781,6 +781,8 @@ GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) @@ -781,6 +781,8 @@ GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
781 else 781 else
782 #endif 782 #endif
783 gen_op_check_addc(); 783 gen_op_check_addc();
  784 + } else {
  785 + gen_op_clear_xer_ca();
784 } 786 }
785 gen_op_store_T0_gpr(rD(ctx->opcode)); 787 gen_op_store_T0_gpr(rD(ctx->opcode));
786 } 788 }
@@ -2804,7 +2806,8 @@ GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC) @@ -2804,7 +2806,8 @@ GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
2804 { 2806 {
2805 gen_op_load_xer_cr(); 2807 gen_op_load_xer_cr();
2806 gen_op_store_T0_crf(crfD(ctx->opcode)); 2808 gen_op_store_T0_crf(crfD(ctx->opcode));
2807 - gen_op_clear_xer_cr(); 2809 + gen_op_clear_xer_ov();
  2810 + gen_op_clear_xer_ca();
2808 } 2811 }
2809 2812
2810 /* mfcr */ 2813 /* mfcr */