Commit 7c58044c0ab79f11604f71aa04b4691baacef886

Authored by j_mayer
1 parent a32ff1ad

Fix PowerPC FPSCR update and floating-point exception generation

in most useful cases.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3458 c046a42c-6fe2-441c-8c8c-71466251a162
darwin-user/main.c
@@ -224,11 +224,6 @@ void cpu_loop(CPUPPCState *env) @@ -224,11 +224,6 @@ void cpu_loop(CPUPPCState *env)
224 case POWERPC_EXCP_FP: 224 case POWERPC_EXCP_FP:
225 EXCP_DUMP(env, "Floating point program exception\n"); 225 EXCP_DUMP(env, "Floating point program exception\n");
226 /* Set FX */ 226 /* Set FX */
227 - env->fpscr[7] |= 0x8;  
228 - /* Finally, update FEX */  
229 - if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &  
230 - ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))  
231 - env->fpscr[7] |= 0x4;  
232 info.si_signo = SIGFPE; 227 info.si_signo = SIGFPE;
233 info.si_errno = 0; 228 info.si_errno = 0;
234 switch (env->error_code & 0xF) { 229 switch (env->error_code & 0xF) {
@@ -248,7 +243,7 @@ void cpu_loop(CPUPPCState *env) @@ -248,7 +243,7 @@ void cpu_loop(CPUPPCState *env)
248 case POWERPC_EXCP_FP_VXSOFT: 243 case POWERPC_EXCP_FP_VXSOFT:
249 info.si_code = FPE_FLTINV; 244 info.si_code = FPE_FLTINV;
250 break; 245 break;
251 - case POWERPC_EXCP_FP_VXNAN: 246 + case POWERPC_EXCP_FP_VXSNAN:
252 case POWERPC_EXCP_FP_VXISI: 247 case POWERPC_EXCP_FP_VXISI:
253 case POWERPC_EXCP_FP_VXIDI: 248 case POWERPC_EXCP_FP_VXIDI:
254 case POWERPC_EXCP_FP_VXIMZ: 249 case POWERPC_EXCP_FP_VXIMZ:
linux-user/main.c
@@ -829,12 +829,6 @@ void cpu_loop(CPUPPCState *env) @@ -829,12 +829,6 @@ void cpu_loop(CPUPPCState *env)
829 switch (env->error_code & ~0xF) { 829 switch (env->error_code & ~0xF) {
830 case POWERPC_EXCP_FP: 830 case POWERPC_EXCP_FP:
831 EXCP_DUMP(env, "Floating point program exception\n"); 831 EXCP_DUMP(env, "Floating point program exception\n");
832 - /* Set FX */  
833 - env->fpscr[7] |= 0x8;  
834 - /* Finally, update FEX */  
835 - if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &  
836 - ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))  
837 - env->fpscr[7] |= 0x4;  
838 info.si_signo = TARGET_SIGFPE; 832 info.si_signo = TARGET_SIGFPE;
839 info.si_errno = 0; 833 info.si_errno = 0;
840 switch (env->error_code & 0xF) { 834 switch (env->error_code & 0xF) {
@@ -854,7 +848,7 @@ void cpu_loop(CPUPPCState *env) @@ -854,7 +848,7 @@ void cpu_loop(CPUPPCState *env)
854 case POWERPC_EXCP_FP_VXSOFT: 848 case POWERPC_EXCP_FP_VXSOFT:
855 info.si_code = TARGET_FPE_FLTINV; 849 info.si_code = TARGET_FPE_FLTINV;
856 break; 850 break;
857 - case POWERPC_EXCP_FP_VXNAN: 851 + case POWERPC_EXCP_FP_VXSNAN:
858 case POWERPC_EXCP_FP_VXISI: 852 case POWERPC_EXCP_FP_VXISI:
859 case POWERPC_EXCP_FP_VXIDI: 853 case POWERPC_EXCP_FP_VXIDI:
860 case POWERPC_EXCP_FP_VXIMZ: 854 case POWERPC_EXCP_FP_VXIMZ:
target-ppc/cpu.h
@@ -239,7 +239,7 @@ enum { @@ -239,7 +239,7 @@ enum {
239 POWERPC_EXCP_FP_UX = 0x02, /* FP underflow */ 239 POWERPC_EXCP_FP_UX = 0x02, /* FP underflow */
240 POWERPC_EXCP_FP_ZX = 0x03, /* FP divide by zero */ 240 POWERPC_EXCP_FP_ZX = 0x03, /* FP divide by zero */
241 POWERPC_EXCP_FP_XX = 0x04, /* FP inexact */ 241 POWERPC_EXCP_FP_XX = 0x04, /* FP inexact */
242 - POWERPC_EXCP_FP_VXNAN = 0x05, /* FP invalid SNaN op */ 242 + POWERPC_EXCP_FP_VXSNAN = 0x05, /* FP invalid SNaN op */
243 POWERPC_EXCP_FP_VXISI = 0x06, /* FP invalid infinite subtraction */ 243 POWERPC_EXCP_FP_VXISI = 0x06, /* FP invalid infinite subtraction */
244 POWERPC_EXCP_FP_VXIDI = 0x07, /* FP invalid infinite divide */ 244 POWERPC_EXCP_FP_VXIDI = 0x07, /* FP invalid infinite divide */
245 POWERPC_EXCP_FP_VXZDZ = 0x08, /* FP invalid zero divide */ 245 POWERPC_EXCP_FP_VXZDZ = 0x08, /* FP invalid zero divide */
@@ -433,14 +433,84 @@ enum { @@ -433,14 +433,84 @@ enum {
433 POWERPC_FLAG_PMM = 0x00000400, 433 POWERPC_FLAG_PMM = 0x00000400,
434 }; 434 };
435 435
  436 +/*****************************************************************************/
  437 +/* Floating point status and control register */
  438 +#define FPSCR_FX 31 /* Floating-point exception summary */
  439 +#define FPSCR_FEX 30 /* Floating-point enabled exception summary */
  440 +#define FPSCR_VX 29 /* Floating-point invalid operation exception summ. */
  441 +#define FPSCR_OX 28 /* Floating-point overflow exception */
  442 +#define FPSCR_UX 27 /* Floating-point underflow exception */
  443 +#define FPSCR_ZX 26 /* Floating-point zero divide exception */
  444 +#define FPSCR_XX 25 /* Floating-point inexact exception */
  445 +#define FPSCR_VXSNAN 24 /* Floating-point invalid operation exception (sNan) */
  446 +#define FPSCR_VXISI 23 /* Floating-point invalid operation exception (inf) */
  447 +#define FPSCR_VXIDI 22 /* Floating-point invalid operation exception (inf) */
  448 +#define FPSCR_VXZDZ 21 /* Floating-point invalid operation exception (zero) */
  449 +#define FPSCR_VXIMZ 20 /* Floating-point invalid operation exception (inf) */
  450 +#define FPSCR_VXVC 19 /* Floating-point invalid operation exception (comp) */
  451 +#define FPSCR_FR 18 /* Floating-point fraction rounded */
  452 +#define FPSCR_FI 17 /* Floating-point fraction inexact */
  453 +#define FPSCR_C 16 /* Floating-point result class descriptor */
  454 +#define FPSCR_FL 15 /* Floating-point less than or negative */
  455 +#define FPSCR_FG 14 /* Floating-point greater than or negative */
  456 +#define FPSCR_FE 13 /* Floating-point equal or zero */
  457 +#define FPSCR_FU 12 /* Floating-point unordered or NaN */
  458 +#define FPSCR_FPCC 12 /* Floating-point condition code */
  459 +#define FPSCR_FPRF 12 /* Floating-point result flags */
  460 +#define FPSCR_VXSOFT 10 /* Floating-point invalid operation exception (soft) */
  461 +#define FPSCR_VXSQRT 9 /* Floating-point invalid operation exception (sqrt) */
  462 +#define FPSCR_VXCVI 8 /* Floating-point invalid operation exception (int) */
  463 +#define FPSCR_VE 7 /* Floating-point invalid operation exception enable */
  464 +#define FPSCR_OE 6 /* Floating-point overflow exception enable */
  465 +#define FPSCR_UE 5 /* Floating-point undeflow exception enable */
  466 +#define FPSCR_ZE 4 /* Floating-point zero divide exception enable */
  467 +#define FPSCR_XE 3 /* Floating-point inexact exception enable */
  468 +#define FPSCR_NI 2 /* Floating-point non-IEEE mode */
  469 +#define FPSCR_RN1 1
  470 +#define FPSCR_RN 0 /* Floating-point rounding control */
  471 +#define fpscr_fex (((env->fpscr) >> FPSCR_FEX) & 0x1)
  472 +#define fpscr_vx (((env->fpscr) >> FPSCR_VX) & 0x1)
  473 +#define fpscr_ox (((env->fpscr) >> FPSCR_OX) & 0x1)
  474 +#define fpscr_ux (((env->fpscr) >> FPSCR_UX) & 0x1)
  475 +#define fpscr_zx (((env->fpscr) >> FPSCR_ZX) & 0x1)
  476 +#define fpscr_xx (((env->fpscr) >> FPSCR_XX) & 0x1)
  477 +#define fpscr_vxsnan (((env->fpscr) >> FPSCR_VXSNAN) & 0x1)
  478 +#define fpscr_vxisi (((env->fpscr) >> FPSCR_VXISI) & 0x1)
  479 +#define fpscr_vxidi (((env->fpscr) >> FPSCR_VXIDI) & 0x1)
  480 +#define fpscr_vxzdz (((env->fpscr) >> FPSCR_VXZDZ) & 0x1)
  481 +#define fpscr_vximz (((env->fpscr) >> FPSCR_VXIMZ) & 0x1)
  482 +#define fpscr_vxvc (((env->fpscr) >> FPSCR_VXVC) & 0x1)
  483 +#define fpscr_fpcc (((env->fpscr) >> FPSCR_FPCC) & 0xF)
  484 +#define fpscr_vxsoft (((env->fpscr) >> FPSCR_VXSOFT) & 0x1)
  485 +#define fpscr_vxsqrt (((env->fpscr) >> FPSCR_VXSQRT) & 0x1)
  486 +#define fpscr_vxcvi (((env->fpscr) >> FPSCR_VXCVI) & 0x1)
  487 +#define fpscr_ve (((env->fpscr) >> FPSCR_VE) & 0x1)
  488 +#define fpscr_oe (((env->fpscr) >> FPSCR_OE) & 0x1)
  489 +#define fpscr_ue (((env->fpscr) >> FPSCR_UE) & 0x1)
  490 +#define fpscr_ze (((env->fpscr) >> FPSCR_ZE) & 0x1)
  491 +#define fpscr_xe (((env->fpscr) >> FPSCR_XE) & 0x1)
  492 +#define fpscr_ni (((env->fpscr) >> FPSCR_NI) & 0x1)
  493 +#define fpscr_rn (((env->fpscr) >> FPSCR_RN) & 0x3)
  494 +/* Invalid operation exception summary */
  495 +#define fpscr_ix ((env->fpscr) & ((1 << FPSCR_VXSNAN) | (1 << FPSCR_VXISI) | \
  496 + (1 << FPSCR_VXIDI) | (1 << FPSCR_VXZDZ) | \
  497 + (1 << FPSCR_VXIMZ) | (1 << FPSCR_VXVC) | \
  498 + (1 << FPSCR_VXSOFT) | (1 << FPSCR_VXSQRT) | \
  499 + (1 << FPSCR_VXCVI)))
  500 +/* exception summary */
  501 +#define fpscr_ex (((env->fpscr) >> FPSCR_XX) & 0x1F)
  502 +/* enabled exception summary */
  503 +#define fpscr_eex (((env->fpscr) >> FPSCR_XX) & ((env->fpscr) >> FPSCR_XE) & \
  504 + 0x1F)
  505 +
  506 +/*****************************************************************************/
  507 +/* The whole PowerPC CPU context */
436 #if defined(TARGET_PPC64H) 508 #if defined(TARGET_PPC64H)
437 #define NB_MMU_MODES 3 509 #define NB_MMU_MODES 3
438 #else 510 #else
439 #define NB_MMU_MODES 2 511 #define NB_MMU_MODES 2
440 #endif 512 #endif
441 513
442 -/*****************************************************************************/  
443 -/* The whole PowerPC CPU context */  
444 struct CPUPPCState { 514 struct CPUPPCState {
445 /* First are the most commonly used resources 515 /* First are the most commonly used resources
446 * during translated code execution 516 * during translated code execution
@@ -482,7 +552,7 @@ struct CPUPPCState { @@ -482,7 +552,7 @@ struct CPUPPCState {
482 /* floating point registers */ 552 /* floating point registers */
483 float64 fpr[32]; 553 float64 fpr[32];
484 /* floating point status and control register */ 554 /* floating point status and control register */
485 - uint8_t fpscr[8]; 555 + uint32_t fpscr;
486 556
487 CPU_COMMON 557 CPU_COMMON
488 558
target-ppc/helper.c
@@ -2130,6 +2130,8 @@ static always_inline void powerpc_excp (CPUState *env, @@ -2130,6 +2130,8 @@ static always_inline void powerpc_excp (CPUState *env,
2130 fprintf(logfile, "Ignore floating point exception\n"); 2130 fprintf(logfile, "Ignore floating point exception\n");
2131 } 2131 }
2132 #endif 2132 #endif
  2133 + env->exception_index = POWERPC_EXCP_NONE;
  2134 + env->error_code = 0;
2133 return; 2135 return;
2134 } 2136 }
2135 new_msr &= ~((target_ulong)1 << MSR_RI); 2137 new_msr &= ~((target_ulong)1 << MSR_RI);
@@ -2138,12 +2140,6 @@ static always_inline void powerpc_excp (CPUState *env, @@ -2138,12 +2140,6 @@ static always_inline void powerpc_excp (CPUState *env,
2138 new_msr |= (target_ulong)1 << MSR_HV; 2140 new_msr |= (target_ulong)1 << MSR_HV;
2139 #endif 2141 #endif
2140 msr |= 0x00100000; 2142 msr |= 0x00100000;
2141 - /* Set FX */  
2142 - env->fpscr[7] |= 0x8;  
2143 - /* Finally, update FEX */  
2144 - if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &  
2145 - ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))  
2146 - env->fpscr[7] |= 0x4;  
2147 if (msr_fe0 != msr_fe1) { 2143 if (msr_fe0 != msr_fe1) {
2148 msr |= 0x00010000; 2144 msr |= 0x00010000;
2149 goto store_current; 2145 goto store_current;
@@ -2199,8 +2195,11 @@ static always_inline void powerpc_excp (CPUState *env, @@ -2199,8 +2195,11 @@ static always_inline void powerpc_excp (CPUState *env,
2199 /* XXX: To be removed */ 2195 /* XXX: To be removed */
2200 if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b && 2196 if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b &&
2201 env->osi_call) { 2197 env->osi_call) {
2202 - if (env->osi_call(env) != 0) 2198 + if (env->osi_call(env) != 0) {
  2199 + env->exception_index = POWERPC_EXCP_NONE;
  2200 + env->error_code = 0;
2203 return; 2201 return;
  2202 + }
2204 } 2203 }
2205 if (loglevel & CPU_LOG_INT) { 2204 if (loglevel & CPU_LOG_INT) {
2206 dump_syscall(env); 2205 dump_syscall(env);
target-ppc/op.c
@@ -135,13 +135,6 @@ void OPPROTO op_set_Rc0 (void) @@ -135,13 +135,6 @@ void OPPROTO op_set_Rc0 (void)
135 RETURN(); 135 RETURN();
136 } 136 }
137 137
138 -/* Set Rc1 (for floating point arithmetic) */  
139 -void OPPROTO op_set_Rc1 (void)  
140 -{  
141 - env->crf[1] = env->fpscr[7];  
142 - RETURN();  
143 -}  
144 -  
145 /* Constants load */ 138 /* Constants load */
146 void OPPROTO op_reset_T0 (void) 139 void OPPROTO op_reset_T0 (void)
147 { 140 {
@@ -552,21 +545,108 @@ void OPPROTO op_store_dbatl (void) @@ -552,21 +545,108 @@ void OPPROTO op_store_dbatl (void)
552 #endif /* !defined(CONFIG_USER_ONLY) */ 545 #endif /* !defined(CONFIG_USER_ONLY) */
553 546
554 /* FPSCR */ 547 /* FPSCR */
555 -void OPPROTO op_load_fpscr (void) 548 +#ifdef CONFIG_SOFTFLOAT
  549 +void OPPROTO op_reset_fpstatus (void)
556 { 550 {
557 - do_load_fpscr(); 551 + env->fp_status.float_exception_flags = 0;
558 RETURN(); 552 RETURN();
559 } 553 }
  554 +#endif
560 555
561 -void OPPROTO op_store_fpscr (void) 556 +void OPPROTO op_compute_fprf (void)
562 { 557 {
563 - do_store_fpscr(PARAM1); 558 + do_compute_fprf(PARAM1);
564 RETURN(); 559 RETURN();
565 } 560 }
566 561
567 -void OPPROTO op_reset_scrfx (void) 562 +#ifdef CONFIG_SOFTFLOAT
  563 +void OPPROTO op_float_check_status (void)
568 { 564 {
569 - env->fpscr[7] &= ~0x8; 565 + do_float_check_status();
  566 + RETURN();
  567 +}
  568 +#else
  569 +void OPPROTO op_float_check_status (void)
  570 +{
  571 + if (env->exception_index == POWERPC_EXCP_PROGRAM &&
  572 + (env->error_code & POWERPC_EXCP_FP)) {
  573 + /* Differred floating-point exception after target FPR update */
  574 + if (msr_fe0 != 0 || msr_fe1 != 0)
  575 + do_raise_exception_err(env->exception_index, env->error_code);
  576 + }
  577 + RETURN();
  578 +}
  579 +#endif
  580 +
  581 +#if defined(WORDS_BIGENDIAN)
  582 +#define WORD0 0
  583 +#define WORD1 1
  584 +#else
  585 +#define WORD0 1
  586 +#define WORD1 0
  587 +#endif
  588 +void OPPROTO op_load_fpscr_FT0 (void)
  589 +{
  590 + /* The 32 MSB of the target fpr are undefined.
  591 + * They'll be zero...
  592 + */
  593 + union {
  594 + float64 d;
  595 + struct {
  596 + uint32_t u[2];
  597 + } s;
  598 + } u;
  599 +
  600 + u.s.u[WORD0] = 0;
  601 + u.s.u[WORD1] = env->fpscr;
  602 + FT0 = u.d;
  603 + RETURN();
  604 +}
  605 +
  606 +void OPPROTO op_set_FT0 (void)
  607 +{
  608 + union {
  609 + float64 d;
  610 + struct {
  611 + uint32_t u[2];
  612 + } s;
  613 + } u;
  614 +
  615 + u.s.u[WORD0] = 0;
  616 + u.s.u[WORD1] = PARAM1;
  617 + FT0 = u.d;
  618 + RETURN();
  619 +}
  620 +#undef WORD0
  621 +#undef WORD1
  622 +
  623 +void OPPROTO op_load_fpscr_T0 (void)
  624 +{
  625 + T0 = (env->fpscr >> PARAM1) & 0xF;
  626 + RETURN();
  627 +}
  628 +
  629 +void OPPROTO op_load_fpcc (void)
  630 +{
  631 + T0 = fpscr_fpcc;
  632 + RETURN();
  633 +}
  634 +
  635 +void OPPROTO op_fpscr_resetbit (void)
  636 +{
  637 + env->fpscr &= PARAM1;
  638 + RETURN();
  639 +}
  640 +
  641 +void OPPROTO op_fpscr_setbit (void)
  642 +{
  643 + do_fpscr_setbit(PARAM1);
  644 + RETURN();
  645 +}
  646 +
  647 +void OPPROTO op_store_fpscr (void)
  648 +{
  649 + do_store_fpscr(PARAM1);
570 RETURN(); 650 RETURN();
571 } 651 }
572 652
@@ -1702,28 +1782,44 @@ void OPPROTO op_srli_T1_64 (void) @@ -1702,28 +1782,44 @@ void OPPROTO op_srli_T1_64 (void)
1702 /* fadd - fadd. */ 1782 /* fadd - fadd. */
1703 void OPPROTO op_fadd (void) 1783 void OPPROTO op_fadd (void)
1704 { 1784 {
  1785 +#if USE_PRECISE_EMULATION
  1786 + do_fadd();
  1787 +#else
1705 FT0 = float64_add(FT0, FT1, &env->fp_status); 1788 FT0 = float64_add(FT0, FT1, &env->fp_status);
  1789 +#endif
1706 RETURN(); 1790 RETURN();
1707 } 1791 }
1708 1792
1709 /* fsub - fsub. */ 1793 /* fsub - fsub. */
1710 void OPPROTO op_fsub (void) 1794 void OPPROTO op_fsub (void)
1711 { 1795 {
  1796 +#if USE_PRECISE_EMULATION
  1797 + do_fsub();
  1798 +#else
1712 FT0 = float64_sub(FT0, FT1, &env->fp_status); 1799 FT0 = float64_sub(FT0, FT1, &env->fp_status);
  1800 +#endif
1713 RETURN(); 1801 RETURN();
1714 } 1802 }
1715 1803
1716 /* fmul - fmul. */ 1804 /* fmul - fmul. */
1717 void OPPROTO op_fmul (void) 1805 void OPPROTO op_fmul (void)
1718 { 1806 {
  1807 +#if USE_PRECISE_EMULATION
  1808 + do_fmul();
  1809 +#else
1719 FT0 = float64_mul(FT0, FT1, &env->fp_status); 1810 FT0 = float64_mul(FT0, FT1, &env->fp_status);
  1811 +#endif
1720 RETURN(); 1812 RETURN();
1721 } 1813 }
1722 1814
1723 /* fdiv - fdiv. */ 1815 /* fdiv - fdiv. */
1724 void OPPROTO op_fdiv (void) 1816 void OPPROTO op_fdiv (void)
1725 { 1817 {
  1818 +#if USE_PRECISE_EMULATION
  1819 + do_fdiv();
  1820 +#else
1726 FT0 = float64_div(FT0, FT1, &env->fp_status); 1821 FT0 = float64_div(FT0, FT1, &env->fp_status);
  1822 +#endif
1727 RETURN(); 1823 RETURN();
1728 } 1824 }
1729 1825
@@ -1805,7 +1901,11 @@ void OPPROTO op_fnmsub (void) @@ -1805,7 +1901,11 @@ void OPPROTO op_fnmsub (void)
1805 /* frsp - frsp. */ 1901 /* frsp - frsp. */
1806 void OPPROTO op_frsp (void) 1902 void OPPROTO op_frsp (void)
1807 { 1903 {
  1904 +#if USE_PRECISE_EMULATION
  1905 + do_frsp();
  1906 +#else
1808 FT0 = float64_to_float32(FT0, &env->fp_status); 1907 FT0 = float64_to_float32(FT0, &env->fp_status);
  1908 +#endif
1809 RETURN(); 1909 RETURN();
1810 } 1910 }
1811 1911
target-ppc/op_helper.c
@@ -51,14 +51,6 @@ void do_raise_exception_err (uint32_t exception, int error_code) @@ -51,14 +51,6 @@ void do_raise_exception_err (uint32_t exception, int error_code)
51 #if 0 51 #if 0
52 printf("Raise exception %3x code : %d\n", exception, error_code); 52 printf("Raise exception %3x code : %d\n", exception, error_code);
53 #endif 53 #endif
54 - switch (exception) {  
55 - case POWERPC_EXCP_PROGRAM:  
56 - if (error_code == POWERPC_EXCP_FP && msr_fe0 == 0 && msr_fe1 == 0)  
57 - return;  
58 - break;  
59 - default:  
60 - break;  
61 - }  
62 env->exception_index = exception; 54 env->exception_index = exception;
63 env->error_code = error_code; 55 env->error_code = error_code;
64 cpu_loop_exit(); 56 cpu_loop_exit();
@@ -107,77 +99,6 @@ void do_store_pri (int prio) @@ -107,77 +99,6 @@ void do_store_pri (int prio)
107 } 99 }
108 #endif 100 #endif
109 101
110 -void do_load_fpscr (void)  
111 -{  
112 - /* The 32 MSB of the target fpr are undefined.  
113 - * They'll be zero...  
114 - */  
115 - union {  
116 - float64 d;  
117 - struct {  
118 - uint32_t u[2];  
119 - } s;  
120 - } u;  
121 - int i;  
122 -  
123 -#if defined(WORDS_BIGENDIAN)  
124 -#define WORD0 0  
125 -#define WORD1 1  
126 -#else  
127 -#define WORD0 1  
128 -#define WORD1 0  
129 -#endif  
130 - u.s.u[WORD0] = 0;  
131 - u.s.u[WORD1] = 0;  
132 - for (i = 0; i < 8; i++)  
133 - u.s.u[WORD1] |= env->fpscr[i] << (4 * i);  
134 - FT0 = u.d;  
135 -}  
136 -  
137 -void do_store_fpscr (uint32_t mask)  
138 -{  
139 - /*  
140 - * We use only the 32 LSB of the incoming fpr  
141 - */  
142 - union {  
143 - double d;  
144 - struct {  
145 - uint32_t u[2];  
146 - } s;  
147 - } u;  
148 - int i, rnd_type;  
149 -  
150 - u.d = FT0;  
151 - if (mask & 0x80)  
152 - env->fpscr[0] = (env->fpscr[0] & 0x9) | ((u.s.u[WORD1] >> 28) & ~0x9);  
153 - for (i = 1; i < 7; i++) {  
154 - if (mask & (1 << (7 - i)))  
155 - env->fpscr[i] = (u.s.u[WORD1] >> (4 * (7 - i))) & 0xF;  
156 - }  
157 - /* TODO: update FEX & VX */  
158 - /* Set rounding mode */  
159 - switch (env->fpscr[0] & 0x3) {  
160 - case 0:  
161 - /* Best approximation (round to nearest) */  
162 - rnd_type = float_round_nearest_even;  
163 - break;  
164 - case 1:  
165 - /* Smaller magnitude (round toward zero) */  
166 - rnd_type = float_round_to_zero;  
167 - break;  
168 - case 2:  
169 - /* Round toward +infinite */  
170 - rnd_type = float_round_up;  
171 - break;  
172 - default:  
173 - case 3:  
174 - /* Round toward -infinite */  
175 - rnd_type = float_round_down;  
176 - break;  
177 - }  
178 - set_float_rounding_mode(rnd_type, &env->fp_status);  
179 -}  
180 -  
181 target_ulong ppc_load_dump_spr (int sprn) 102 target_ulong ppc_load_dump_spr (int sprn)
182 { 103 {
183 if (loglevel != 0) { 104 if (loglevel != 0) {
@@ -553,6 +474,538 @@ void do_popcntb_64 (void) @@ -553,6 +474,538 @@ void do_popcntb_64 (void)
553 474
554 /*****************************************************************************/ 475 /*****************************************************************************/
555 /* Floating point operations helpers */ 476 /* Floating point operations helpers */
  477 +static inline int fpisneg (float64 f)
  478 +{
  479 + union {
  480 + float64 f;
  481 + uint64_t u;
  482 + } u;
  483 +
  484 + u.f = f;
  485 +
  486 + return u.u >> 63 != 0;
  487 +}
  488 +
  489 +static inline int isden (float f)
  490 +{
  491 + union {
  492 + float64 f;
  493 + uint64_t u;
  494 + } u;
  495 +
  496 + u.f = f;
  497 +
  498 + return ((u.u >> 52) & 0x7FF) == 0;
  499 +}
  500 +
  501 +static inline int iszero (float64 f)
  502 +{
  503 + union {
  504 + float64 f;
  505 + uint64_t u;
  506 + } u;
  507 +
  508 + u.f = f;
  509 +
  510 + return (u.u & ~0x8000000000000000ULL) == 0;
  511 +}
  512 +
  513 +static inline int isinfinity (float64 f)
  514 +{
  515 + union {
  516 + float64 f;
  517 + uint64_t u;
  518 + } u;
  519 +
  520 + u.f = f;
  521 +
  522 + return ((u.u >> 51) & 0x3FF) == 0x3FF &&
  523 + (u.u & 0x000FFFFFFFFFFFFFULL) == 0;
  524 +}
  525 +
  526 +void do_compute_fprf (int set_fprf)
  527 +{
  528 + int isneg;
  529 +
  530 + isneg = fpisneg(FT0);
  531 + if (unlikely(float64_is_nan(FT0))) {
  532 + if (float64_is_signaling_nan(FT0)) {
  533 + /* Signaling NaN: flags are undefined */
  534 + T0 = 0x00;
  535 + } else {
  536 + /* Quiet NaN */
  537 + T0 = 0x11;
  538 + }
  539 + } else if (unlikely(isinfinity(FT0))) {
  540 + /* +/- infinity */
  541 + if (isneg)
  542 + T0 = 0x09;
  543 + else
  544 + T0 = 0x05;
  545 + } else {
  546 + if (iszero(FT0)) {
  547 + /* +/- zero */
  548 + if (isneg)
  549 + T0 = 0x12;
  550 + else
  551 + T0 = 0x02;
  552 + } else {
  553 + if (isden(FT0)) {
  554 + /* Denormalized numbers */
  555 + T0 = 0x10;
  556 + } else {
  557 + /* Normalized numbers */
  558 + T0 = 0x00;
  559 + }
  560 + if (isneg) {
  561 + T0 |= 0x08;
  562 + } else {
  563 + T0 |= 0x04;
  564 + }
  565 + }
  566 + }
  567 + if (set_fprf) {
  568 + /* We update FPSCR_FPRF */
  569 + env->fpscr &= ~(0x1F << FPSCR_FPRF);
  570 + env->fpscr |= T0 << FPSCR_FPRF;
  571 + }
  572 + /* We just need fpcc to update Rc1 */
  573 + T0 &= 0xF;
  574 +}
  575 +
  576 +/* Floating-point invalid operations exception */
  577 +static always_inline void fload_invalid_op_excp (int op)
  578 +{
  579 + int ve;
  580 +
  581 + ve = fpscr_ve;
  582 + if (op & POWERPC_EXCP_FP_VXSNAN) {
  583 + /* Operation on signaling NaN */
  584 + env->fpscr |= 1 << FPSCR_VXSNAN;
  585 + }
  586 + if (op & POWERPC_EXCP_FP_VXSOFT) {
  587 + /* Software-defined condition */
  588 + env->fpscr |= 1 << FPSCR_VXSOFT;
  589 + }
  590 + switch (op & ~(POWERPC_EXCP_FP_VXSOFT | POWERPC_EXCP_FP_VXSNAN)) {
  591 + case POWERPC_EXCP_FP_VXISI:
  592 + /* Magnitude subtraction of infinities */
  593 + env->fpscr |= 1 << FPSCR_VXISI;
  594 + goto update_arith;
  595 + case POWERPC_EXCP_FP_VXIDI:
  596 + /* Division of infinity by infinity */
  597 + env->fpscr |= 1 << FPSCR_VXIDI;
  598 + goto update_arith;
  599 + case POWERPC_EXCP_FP_VXZDZ:
  600 + /* Division of zero by zero */
  601 + env->fpscr |= 1 << FPSCR_VXZDZ;
  602 + goto update_arith;
  603 + case POWERPC_EXCP_FP_VXIMZ:
  604 + /* Multiplication of zero by infinity */
  605 + env->fpscr |= 1 << FPSCR_VXIMZ;
  606 + goto update_arith;
  607 + case POWERPC_EXCP_FP_VXVC:
  608 + /* Ordered comparison of NaN */
  609 + env->fpscr |= 1 << FPSCR_VXVC;
  610 + env->fpscr &= ~(0xF << FPSCR_FPCC);
  611 + env->fpscr |= 0x11 << FPSCR_FPCC;
  612 + /* We must update the target FPR before raising the exception */
  613 + if (ve != 0) {
  614 + env->exception_index = POWERPC_EXCP_PROGRAM;
  615 + env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_VXVC;
  616 + /* Update the floating-point enabled exception summary */
  617 + env->fpscr |= 1 << FPSCR_FEX;
  618 + /* Exception is differed */
  619 + ve = 0;
  620 + }
  621 + break;
  622 + case POWERPC_EXCP_FP_VXSQRT:
  623 + /* Square root of a negative number */
  624 + env->fpscr |= 1 << FPSCR_VXSQRT;
  625 + update_arith:
  626 + env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
  627 + if (ve == 0) {
  628 + /* Set the result to quiet NaN */
  629 + FT0 = (uint64_t)-1;
  630 + env->fpscr &= ~(0xF << FPSCR_FPCC);
  631 + env->fpscr |= 0x11 << FPSCR_FPCC;
  632 + }
  633 + break;
  634 + case POWERPC_EXCP_FP_VXCVI:
  635 + /* Invalid conversion */
  636 + env->fpscr |= 1 << FPSCR_VXCVI;
  637 + env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
  638 + if (ve == 0) {
  639 + /* Set the result to quiet NaN */
  640 + FT0 = (uint64_t)-1;
  641 + env->fpscr &= ~(0xF << FPSCR_FPCC);
  642 + env->fpscr |= 0x11 << FPSCR_FPCC;
  643 + }
  644 + break;
  645 + }
  646 + /* Update the floating-point invalid operation summary */
  647 + env->fpscr |= 1 << FPSCR_VX;
  648 + /* Update the floating-point exception summary */
  649 + env->fpscr |= 1 << FPSCR_FX;
  650 + if (ve != 0) {
  651 + /* Update the floating-point enabled exception summary */
  652 + env->fpscr |= 1 << FPSCR_FEX;
  653 + if (msr_fe0 != 0 || msr_fe1 != 0)
  654 + do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_FP | op);
  655 + }
  656 +}
  657 +
  658 +static always_inline void float_zero_divide_excp (void)
  659 +{
  660 + union {
  661 + float64 f;
  662 + uint64_t u;
  663 + } u0, u1;
  664 +
  665 +
  666 + env->fpscr |= 1 << FPSCR_ZX;
  667 + env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
  668 + /* Update the floating-point exception summary */
  669 + env->fpscr |= 1 << FPSCR_FX;
  670 + if (fpscr_ze != 0) {
  671 + /* Update the floating-point enabled exception summary */
  672 + env->fpscr |= 1 << FPSCR_FEX;
  673 + if (msr_fe0 != 0 || msr_fe1 != 0) {
  674 + do_raise_exception_err(POWERPC_EXCP_PROGRAM,
  675 + POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX);
  676 + }
  677 + } else {
  678 + /* Set the result to infinity */
  679 + u0.f = FT0;
  680 + u1.f = FT1;
  681 + u0.u = ((u0.u ^ u1.u) & 0x8000000000000000ULL);
  682 + u0.u |= 0x3FFULL << 51;
  683 + FT0 = u0.f;
  684 + }
  685 +}
  686 +
  687 +static always_inline void float_overflow_excp (void)
  688 +{
  689 + env->fpscr |= 1 << FPSCR_OX;
  690 + /* Update the floating-point exception summary */
  691 + env->fpscr |= 1 << FPSCR_FX;
  692 + if (fpscr_oe != 0) {
  693 + /* XXX: should adjust the result */
  694 + /* Update the floating-point enabled exception summary */
  695 + env->fpscr |= 1 << FPSCR_FEX;
  696 + /* We must update the target FPR before raising the exception */
  697 + env->exception_index = POWERPC_EXCP_PROGRAM;
  698 + env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
  699 + } else {
  700 + env->fpscr |= 1 << FPSCR_XX;
  701 + env->fpscr |= 1 << FPSCR_FI;
  702 + }
  703 +}
  704 +
  705 +static always_inline void float_underflow_excp (void)
  706 +{
  707 + env->fpscr |= 1 << FPSCR_UX;
  708 + /* Update the floating-point exception summary */
  709 + env->fpscr |= 1 << FPSCR_FX;
  710 + if (fpscr_ue != 0) {
  711 + /* XXX: should adjust the result */
  712 + /* Update the floating-point enabled exception summary */
  713 + env->fpscr |= 1 << FPSCR_FEX;
  714 + /* We must update the target FPR before raising the exception */
  715 + env->exception_index = POWERPC_EXCP_PROGRAM;
  716 + env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
  717 + }
  718 +}
  719 +
  720 +static always_inline void float_inexact_excp (void)
  721 +{
  722 + env->fpscr |= 1 << FPSCR_XX;
  723 + /* Update the floating-point exception summary */
  724 + env->fpscr |= 1 << FPSCR_FX;
  725 + if (fpscr_xe != 0) {
  726 + /* Update the floating-point enabled exception summary */
  727 + env->fpscr |= 1 << FPSCR_FEX;
  728 + /* We must update the target FPR before raising the exception */
  729 + env->exception_index = POWERPC_EXCP_PROGRAM;
  730 + env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
  731 + }
  732 +}
  733 +
  734 +static always_inline void fpscr_set_rounding_mode (void)
  735 +{
  736 + int rnd_type;
  737 +
  738 + /* Set rounding mode */
  739 + switch (fpscr_rn) {
  740 + case 0:
  741 + /* Best approximation (round to nearest) */
  742 + rnd_type = float_round_nearest_even;
  743 + break;
  744 + case 1:
  745 + /* Smaller magnitude (round toward zero) */
  746 + rnd_type = float_round_to_zero;
  747 + break;
  748 + case 2:
  749 + /* Round toward +infinite */
  750 + rnd_type = float_round_up;
  751 + break;
  752 + default:
  753 + case 3:
  754 + /* Round toward -infinite */
  755 + rnd_type = float_round_down;
  756 + break;
  757 + }
  758 + set_float_rounding_mode(rnd_type, &env->fp_status);
  759 +}
  760 +
  761 +void do_fpscr_setbit (int bit)
  762 +{
  763 + int prev;
  764 +
  765 + prev = (env->fpscr >> bit) & 1;
  766 + env->fpscr |= 1 << bit;
  767 + if (prev == 0) {
  768 + switch (bit) {
  769 + case FPSCR_VX:
  770 + env->fpscr |= 1 << FPSCR_FX;
  771 + if (fpscr_ve)
  772 + goto raise_ve;
  773 + case FPSCR_OX:
  774 + env->fpscr |= 1 << FPSCR_FX;
  775 + if (fpscr_oe)
  776 + goto raise_oe;
  777 + break;
  778 + case FPSCR_UX:
  779 + env->fpscr |= 1 << FPSCR_FX;
  780 + if (fpscr_ue)
  781 + goto raise_ue;
  782 + break;
  783 + case FPSCR_ZX:
  784 + env->fpscr |= 1 << FPSCR_FX;
  785 + if (fpscr_ze)
  786 + goto raise_ze;
  787 + break;
  788 + case FPSCR_XX:
  789 + env->fpscr |= 1 << FPSCR_FX;
  790 + if (fpscr_xe)
  791 + goto raise_xe;
  792 + break;
  793 + case FPSCR_VXSNAN:
  794 + case FPSCR_VXISI:
  795 + case FPSCR_VXIDI:
  796 + case FPSCR_VXZDZ:
  797 + case FPSCR_VXIMZ:
  798 + case FPSCR_VXVC:
  799 + case FPSCR_VXSOFT:
  800 + case FPSCR_VXSQRT:
  801 + case FPSCR_VXCVI:
  802 + env->fpscr |= 1 << FPSCR_VX;
  803 + env->fpscr |= 1 << FPSCR_FX;
  804 + if (fpscr_ve != 0)
  805 + goto raise_ve;
  806 + break;
  807 + case FPSCR_VE:
  808 + if (fpscr_vx != 0) {
  809 + raise_ve:
  810 + env->error_code = POWERPC_EXCP_FP;
  811 + if (fpscr_vxsnan)
  812 + env->error_code |= POWERPC_EXCP_FP_VXSNAN;
  813 + if (fpscr_vxisi)
  814 + env->error_code |= POWERPC_EXCP_FP_VXISI;
  815 + if (fpscr_vxidi)
  816 + env->error_code |= POWERPC_EXCP_FP_VXIDI;
  817 + if (fpscr_vxzdz)
  818 + env->error_code |= POWERPC_EXCP_FP_VXZDZ;
  819 + if (fpscr_vximz)
  820 + env->error_code |= POWERPC_EXCP_FP_VXIMZ;
  821 + if (fpscr_vxvc)
  822 + env->error_code |= POWERPC_EXCP_FP_VXVC;
  823 + if (fpscr_vxsoft)
  824 + env->error_code |= POWERPC_EXCP_FP_VXSOFT;
  825 + if (fpscr_vxsqrt)
  826 + env->error_code |= POWERPC_EXCP_FP_VXSQRT;
  827 + if (fpscr_vxcvi)
  828 + env->error_code |= POWERPC_EXCP_FP_VXCVI;
  829 + goto raise_excp;
  830 + }
  831 + break;
  832 + case FPSCR_OE:
  833 + if (fpscr_ox != 0) {
  834 + raise_oe:
  835 + env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
  836 + goto raise_excp;
  837 + }
  838 + break;
  839 + case FPSCR_UE:
  840 + if (fpscr_ux != 0) {
  841 + raise_ue:
  842 + env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
  843 + goto raise_excp;
  844 + }
  845 + break;
  846 + case FPSCR_ZE:
  847 + if (fpscr_zx != 0) {
  848 + raise_ze:
  849 + env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX;
  850 + goto raise_excp;
  851 + }
  852 + break;
  853 + case FPSCR_XE:
  854 + if (fpscr_xx != 0) {
  855 + raise_xe:
  856 + env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
  857 + goto raise_excp;
  858 + }
  859 + break;
  860 + case FPSCR_RN1:
  861 + case FPSCR_RN:
  862 + fpscr_set_rounding_mode();
  863 + break;
  864 + default:
  865 + break;
  866 + raise_excp:
  867 + /* Update the floating-point enabled exception summary */
  868 + env->fpscr |= 1 << FPSCR_FEX;
  869 + /* We have to update Rc1 before raising the exception */
  870 + env->exception_index = POWERPC_EXCP_PROGRAM;
  871 + break;
  872 + }
  873 + }
  874 +}
  875 +
  876 +#if defined(WORDS_BIGENDIAN)
  877 +#define WORD0 0
  878 +#define WORD1 1
  879 +#else
  880 +#define WORD0 1
  881 +#define WORD1 0
  882 +#endif
  883 +void do_store_fpscr (uint32_t mask)
  884 +{
  885 + /*
  886 + * We use only the 32 LSB of the incoming fpr
  887 + */
  888 + union {
  889 + double d;
  890 + struct {
  891 + uint32_t u[2];
  892 + } s;
  893 + } u;
  894 + uint32_t prev, new;
  895 + int i;
  896 +
  897 + u.d = FT0;
  898 + prev = env->fpscr;
  899 + new = u.s.u[WORD1];
  900 + new &= ~0x90000000;
  901 + new |= prev & 0x90000000;
  902 + for (i = 0; i < 7; i++) {
  903 + if (mask & (1 << i)) {
  904 + env->fpscr &= ~(0xF << (4 * i));
  905 + env->fpscr |= new & (0xF << (4 * i));
  906 + }
  907 + }
  908 + /* Update VX and FEX */
  909 + if (fpscr_ix != 0)
  910 + env->fpscr |= 1 << FPSCR_VX;
  911 + if ((fpscr_ex & fpscr_eex) != 0) {
  912 + env->fpscr |= 1 << FPSCR_FEX;
  913 + env->exception_index = POWERPC_EXCP_PROGRAM;
  914 + /* XXX: we should compute it properly */
  915 + env->error_code = POWERPC_EXCP_FP;
  916 + }
  917 + fpscr_set_rounding_mode();
  918 +}
  919 +#undef WORD0
  920 +#undef WORD1
  921 +
  922 +#ifdef CONFIG_SOFTFLOAT
  923 +void do_float_check_status (void)
  924 +{
  925 + if (env->exception_index == POWERPC_EXCP_PROGRAM &&
  926 + (env->error_code & POWERPC_EXCP_FP)) {
  927 + /* Differred floating-point exception after target FPR update */
  928 + if (msr_fe0 != 0 || msr_fe1 != 0)
  929 + do_raise_exception_err(env->exception_index, env->error_code);
  930 + } else if (env->fp_status.float_exception_flags & float_flag_overflow) {
  931 + float_overflow_excp();
  932 + } else if (env->fp_status.float_exception_flags & float_flag_underflow) {
  933 + float_underflow_excp();
  934 + } else if (env->fp_status.float_exception_flags & float_flag_inexact) {
  935 + float_inexact_excp();
  936 + }
  937 +}
  938 +#endif
  939 +
  940 +#if USE_PRECISE_EMULATION
  941 +void do_fadd (void)
  942 +{
  943 + if (unlikely(float64_is_signaling_nan(FT0) ||
  944 + float64_is_signaling_nan(FT1))) {
  945 + /* sNaN addition */
  946 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
  947 + } else if (likely(isfinite(FT0) || isfinite(FT1) ||
  948 + fpisneg(FT0) == fpisneg(FT1))) {
  949 + FT0 = float64_add(FT0, FT1, &env->fp_status);
  950 + } else {
  951 + /* Magnitude subtraction of infinities */
  952 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
  953 + }
  954 +}
  955 +
  956 +void do_fsub (void)
  957 +{
  958 + if (unlikely(float64_is_signaling_nan(FT0) ||
  959 + float64_is_signaling_nan(FT1))) {
  960 + /* sNaN subtraction */
  961 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
  962 + } else if (likely(isfinite(FT0) || isfinite(FT1) ||
  963 + fpisneg(FT0) != fpisneg(FT1))) {
  964 + FT0 = float64_sub(FT0, FT1, &env->fp_status);
  965 + } else {
  966 + /* Magnitude subtraction of infinities */
  967 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
  968 + }
  969 +}
  970 +
  971 +void do_fmul (void)
  972 +{
  973 + if (unlikely(float64_is_signaling_nan(FT0) ||
  974 + float64_is_signaling_nan(FT1))) {
  975 + /* sNaN multiplication */
  976 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
  977 + } else if (unlikely((ifinf(FT0) && iszero(FT1)) ||
  978 + (inzero(FT0) && isinfinity(FT1)))) {
  979 + /* Multiplication of zero by infinity */
  980 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
  981 + } else {
  982 + FT0 = float64_mul(FT0, FT1, &env->fp_status);
  983 + }
  984 +}
  985 +
  986 +void do_fdiv (void)
  987 +{
  988 + if (unlikely(float64_is_signaling_nan(FT0) ||
  989 + float64_is_signaling_nan(FT1))) {
  990 + /* sNaN division */
  991 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
  992 + } else if (unlikely(isinfinity(FT0) && isinfinity(FT1))) {
  993 + /* Division of infinity by infinity */
  994 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXIDI);
  995 + } else if (unlikely(iszero(FT1))) {
  996 + if (iszero(FT0)) {
  997 + /* Division of zero by zero */
  998 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ);
  999 + } else {
  1000 + /* Division by zero */
  1001 + float_zero_divide_excp();
  1002 + }
  1003 + } else {
  1004 + FT0 = float64_div(FT0, FT1, &env->fp_status);
  1005 + }
  1006 +}
  1007 +#endif /* USE_PRECISE_EMULATION */
  1008 +
556 void do_fctiw (void) 1009 void do_fctiw (void)
557 { 1010 {
558 union { 1011 union {
@@ -560,14 +1013,22 @@ void do_fctiw (void) @@ -560,14 +1013,22 @@ void do_fctiw (void)
560 uint64_t i; 1013 uint64_t i;
561 } p; 1014 } p;
562 1015
563 - p.i = float64_to_int32(FT0, &env->fp_status); 1016 + if (unlikely(float64_is_signaling_nan(FT0))) {
  1017 + /* sNaN conversion */
  1018 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
  1019 + } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
  1020 + /* qNan / infinity conversion */
  1021 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
  1022 + } else {
  1023 + p.i = float64_to_int32(FT0, &env->fp_status);
564 #if USE_PRECISE_EMULATION 1024 #if USE_PRECISE_EMULATION
565 - /* XXX: higher bits are not supposed to be significant.  
566 - * to make tests easier, return the same as a real PowerPC 750 (aka G3)  
567 - */  
568 - p.i |= 0xFFF80000ULL << 32; 1025 + /* XXX: higher bits are not supposed to be significant.
  1026 + * to make tests easier, return the same as a real PowerPC 750
  1027 + */
  1028 + p.i |= 0xFFF80000ULL << 32;
569 #endif 1029 #endif
570 - FT0 = p.d; 1030 + FT0 = p.d;
  1031 + }
571 } 1032 }
572 1033
573 void do_fctiwz (void) 1034 void do_fctiwz (void)
@@ -577,14 +1038,22 @@ void do_fctiwz (void) @@ -577,14 +1038,22 @@ void do_fctiwz (void)
577 uint64_t i; 1038 uint64_t i;
578 } p; 1039 } p;
579 1040
580 - p.i = float64_to_int32_round_to_zero(FT0, &env->fp_status); 1041 + if (unlikely(float64_is_signaling_nan(FT0))) {
  1042 + /* sNaN conversion */
  1043 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
  1044 + } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
  1045 + /* qNan / infinity conversion */
  1046 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
  1047 + } else {
  1048 + p.i = float64_to_int32_round_to_zero(FT0, &env->fp_status);
581 #if USE_PRECISE_EMULATION 1049 #if USE_PRECISE_EMULATION
582 - /* XXX: higher bits are not supposed to be significant.  
583 - * to make tests easier, return the same as a real PowerPC 750 (aka G3)  
584 - */  
585 - p.i |= 0xFFF80000ULL << 32; 1050 + /* XXX: higher bits are not supposed to be significant.
  1051 + * to make tests easier, return the same as a real PowerPC 750
  1052 + */
  1053 + p.i |= 0xFFF80000ULL << 32;
586 #endif 1054 #endif
587 - FT0 = p.d; 1055 + FT0 = p.d;
  1056 + }
588 } 1057 }
589 1058
590 #if defined(TARGET_PPC64) 1059 #if defined(TARGET_PPC64)
@@ -606,8 +1075,16 @@ void do_fctid (void) @@ -606,8 +1075,16 @@ void do_fctid (void)
606 uint64_t i; 1075 uint64_t i;
607 } p; 1076 } p;
608 1077
609 - p.i = float64_to_int64(FT0, &env->fp_status);  
610 - FT0 = p.d; 1078 + if (unlikely(float64_is_signaling_nan(FT0))) {
  1079 + /* sNaN conversion */
  1080 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
  1081 + } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
  1082 + /* qNan / infinity conversion */
  1083 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
  1084 + } else {
  1085 + p.i = float64_to_int64(FT0, &env->fp_status);
  1086 + FT0 = p.d;
  1087 + }
611 } 1088 }
612 1089
613 void do_fctidz (void) 1090 void do_fctidz (void)
@@ -617,20 +1094,34 @@ void do_fctidz (void) @@ -617,20 +1094,34 @@ void do_fctidz (void)
617 uint64_t i; 1094 uint64_t i;
618 } p; 1095 } p;
619 1096
620 - p.i = float64_to_int64_round_to_zero(FT0, &env->fp_status);  
621 - FT0 = p.d; 1097 + if (unlikely(float64_is_signaling_nan(FT0))) {
  1098 + /* sNaN conversion */
  1099 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
  1100 + } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
  1101 + /* qNan / infinity conversion */
  1102 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
  1103 + } else {
  1104 + p.i = float64_to_int64_round_to_zero(FT0, &env->fp_status);
  1105 + FT0 = p.d;
  1106 + }
622 } 1107 }
623 1108
624 #endif 1109 #endif
625 1110
626 static always_inline void do_fri (int rounding_mode) 1111 static always_inline void do_fri (int rounding_mode)
627 { 1112 {
628 - int curmode;  
629 -  
630 - curmode = env->fp_status.float_rounding_mode;  
631 - set_float_rounding_mode(rounding_mode, &env->fp_status);  
632 - FT0 = float64_round_to_int(FT0, &env->fp_status);  
633 - set_float_rounding_mode(curmode, &env->fp_status); 1113 + if (unlikely(float64_is_signaling_nan(FT0))) {
  1114 + /* sNaN round */
  1115 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
  1116 + } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
  1117 + /* qNan / infinity round */
  1118 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
  1119 + } else {
  1120 + set_float_rounding_mode(rounding_mode, &env->fp_status);
  1121 + FT0 = float64_round_to_int(FT0, &env->fp_status);
  1122 + /* Restore rounding mode from FPSCR */
  1123 + fpscr_set_rounding_mode();
  1124 + }
634 } 1125 }
635 1126
636 void do_frin (void) 1127 void do_frin (void)
@@ -656,90 +1147,142 @@ void do_frim (void) @@ -656,90 +1147,142 @@ void do_frim (void)
656 #if USE_PRECISE_EMULATION 1147 #if USE_PRECISE_EMULATION
657 void do_fmadd (void) 1148 void do_fmadd (void)
658 { 1149 {
  1150 + if (unlikely(float64_is_signaling_nan(FT0) ||
  1151 + float64_is_signaling_nan(FT1) ||
  1152 + float64_is_signaling_nan(FT2))) {
  1153 + /* sNaN operation */
  1154 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
  1155 + } else {
659 #ifdef FLOAT128 1156 #ifdef FLOAT128
660 - float128 ft0_128, ft1_128;  
661 -  
662 - ft0_128 = float64_to_float128(FT0, &env->fp_status);  
663 - ft1_128 = float64_to_float128(FT1, &env->fp_status);  
664 - ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);  
665 - ft1_128 = float64_to_float128(FT2, &env->fp_status);  
666 - ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);  
667 - FT0 = float128_to_float64(ft0_128, &env->fp_status); 1157 + /* This is the way the PowerPC specification defines it */
  1158 + float128 ft0_128, ft1_128;
  1159 +
  1160 + ft0_128 = float64_to_float128(FT0, &env->fp_status);
  1161 + ft1_128 = float64_to_float128(FT1, &env->fp_status);
  1162 + ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
  1163 + ft1_128 = float64_to_float128(FT2, &env->fp_status);
  1164 + ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
  1165 + FT0 = float128_to_float64(ft0_128, &env->fp_status);
668 #else 1166 #else
669 - /* This is OK on x86 hosts */  
670 - FT0 = (FT0 * FT1) + FT2; 1167 + /* This is OK on x86 hosts */
  1168 + FT0 = (FT0 * FT1) + FT2;
671 #endif 1169 #endif
  1170 + }
672 } 1171 }
673 1172
674 void do_fmsub (void) 1173 void do_fmsub (void)
675 { 1174 {
  1175 + if (unlikely(float64_is_signaling_nan(FT0) ||
  1176 + float64_is_signaling_nan(FT1) ||
  1177 + float64_is_signaling_nan(FT2))) {
  1178 + /* sNaN operation */
  1179 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
  1180 + } else {
676 #ifdef FLOAT128 1181 #ifdef FLOAT128
677 - float128 ft0_128, ft1_128;  
678 -  
679 - ft0_128 = float64_to_float128(FT0, &env->fp_status);  
680 - ft1_128 = float64_to_float128(FT1, &env->fp_status);  
681 - ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);  
682 - ft1_128 = float64_to_float128(FT2, &env->fp_status);  
683 - ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);  
684 - FT0 = float128_to_float64(ft0_128, &env->fp_status); 1182 + /* This is the way the PowerPC specification defines it */
  1183 + float128 ft0_128, ft1_128;
  1184 +
  1185 + ft0_128 = float64_to_float128(FT0, &env->fp_status);
  1186 + ft1_128 = float64_to_float128(FT1, &env->fp_status);
  1187 + ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
  1188 + ft1_128 = float64_to_float128(FT2, &env->fp_status);
  1189 + ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
  1190 + FT0 = float128_to_float64(ft0_128, &env->fp_status);
685 #else 1191 #else
686 - /* This is OK on x86 hosts */  
687 - FT0 = (FT0 * FT1) - FT2; 1192 + /* This is OK on x86 hosts */
  1193 + FT0 = (FT0 * FT1) - FT2;
688 #endif 1194 #endif
  1195 + }
689 } 1196 }
690 #endif /* USE_PRECISE_EMULATION */ 1197 #endif /* USE_PRECISE_EMULATION */
691 1198
692 void do_fnmadd (void) 1199 void do_fnmadd (void)
693 { 1200 {
  1201 + if (unlikely(float64_is_signaling_nan(FT0) ||
  1202 + float64_is_signaling_nan(FT1) ||
  1203 + float64_is_signaling_nan(FT2))) {
  1204 + /* sNaN operation */
  1205 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
  1206 + } else {
694 #if USE_PRECISE_EMULATION 1207 #if USE_PRECISE_EMULATION
695 #ifdef FLOAT128 1208 #ifdef FLOAT128
696 - float128 ft0_128, ft1_128;  
697 -  
698 - ft0_128 = float64_to_float128(FT0, &env->fp_status);  
699 - ft1_128 = float64_to_float128(FT1, &env->fp_status);  
700 - ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);  
701 - ft1_128 = float64_to_float128(FT2, &env->fp_status);  
702 - ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);  
703 - FT0 = float128_to_float64(ft0_128, &env->fp_status); 1209 + /* This is the way the PowerPC specification defines it */
  1210 + float128 ft0_128, ft1_128;
  1211 +
  1212 + ft0_128 = float64_to_float128(FT0, &env->fp_status);
  1213 + ft1_128 = float64_to_float128(FT1, &env->fp_status);
  1214 + ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
  1215 + ft1_128 = float64_to_float128(FT2, &env->fp_status);
  1216 + ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
  1217 + FT0 = float128_to_float64(ft0_128, &env->fp_status);
704 #else 1218 #else
705 - /* This is OK on x86 hosts */  
706 - FT0 = (FT0 * FT1) + FT2; 1219 + /* This is OK on x86 hosts */
  1220 + FT0 = (FT0 * FT1) + FT2;
707 #endif 1221 #endif
708 #else 1222 #else
709 - FT0 = float64_mul(FT0, FT1, &env->fp_status);  
710 - FT0 = float64_add(FT0, FT2, &env->fp_status); 1223 + FT0 = float64_mul(FT0, FT1, &env->fp_status);
  1224 + FT0 = float64_add(FT0, FT2, &env->fp_status);
711 #endif 1225 #endif
712 - if (likely(!isnan(FT0)))  
713 - FT0 = float64_chs(FT0); 1226 + if (likely(!isnan(FT0)))
  1227 + FT0 = float64_chs(FT0);
  1228 + }
714 } 1229 }
715 1230
716 void do_fnmsub (void) 1231 void do_fnmsub (void)
717 { 1232 {
  1233 + if (unlikely(float64_is_signaling_nan(FT0) ||
  1234 + float64_is_signaling_nan(FT1) ||
  1235 + float64_is_signaling_nan(FT2))) {
  1236 + /* sNaN operation */
  1237 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
  1238 + } else {
718 #if USE_PRECISE_EMULATION 1239 #if USE_PRECISE_EMULATION
719 #ifdef FLOAT128 1240 #ifdef FLOAT128
720 - float128 ft0_128, ft1_128;  
721 -  
722 - ft0_128 = float64_to_float128(FT0, &env->fp_status);  
723 - ft1_128 = float64_to_float128(FT1, &env->fp_status);  
724 - ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);  
725 - ft1_128 = float64_to_float128(FT2, &env->fp_status);  
726 - ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);  
727 - FT0 = float128_to_float64(ft0_128, &env->fp_status); 1241 + /* This is the way the PowerPC specification defines it */
  1242 + float128 ft0_128, ft1_128;
  1243 +
  1244 + ft0_128 = float64_to_float128(FT0, &env->fp_status);
  1245 + ft1_128 = float64_to_float128(FT1, &env->fp_status);
  1246 + ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
  1247 + ft1_128 = float64_to_float128(FT2, &env->fp_status);
  1248 + ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
  1249 + FT0 = float128_to_float64(ft0_128, &env->fp_status);
728 #else 1250 #else
729 - /* This is OK on x86 hosts */  
730 - FT0 = (FT0 * FT1) - FT2; 1251 + /* This is OK on x86 hosts */
  1252 + FT0 = (FT0 * FT1) - FT2;
731 #endif 1253 #endif
732 #else 1254 #else
733 - FT0 = float64_mul(FT0, FT1, &env->fp_status);  
734 - FT0 = float64_sub(FT0, FT2, &env->fp_status); 1255 + FT0 = float64_mul(FT0, FT1, &env->fp_status);
  1256 + FT0 = float64_sub(FT0, FT2, &env->fp_status);
735 #endif 1257 #endif
736 - if (likely(!isnan(FT0)))  
737 - FT0 = float64_chs(FT0); 1258 + if (likely(!isnan(FT0)))
  1259 + FT0 = float64_chs(FT0);
  1260 + }
738 } 1261 }
739 1262
  1263 +#if USE_PRECISE_EMULATION
  1264 +void do_frsp (void)
  1265 +{
  1266 + if (unlikely(float64_is_signaling_nan(FT0))) {
  1267 + /* sNaN square root */
  1268 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
  1269 + } else {
  1270 + FT0 = float64_to_float32(FT0, &env->fp_status);
  1271 + }
  1272 +}
  1273 +#endif /* USE_PRECISE_EMULATION */
  1274 +
740 void do_fsqrt (void) 1275 void do_fsqrt (void)
741 { 1276 {
742 - FT0 = float64_sqrt(FT0, &env->fp_status); 1277 + if (unlikely(float64_is_signaling_nan(FT0))) {
  1278 + /* sNaN square root */
  1279 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
  1280 + } else if (unlikely(fpisneg(FT0) && !iszero(FT0))) {
  1281 + /* Square root of a negative nonzero number */
  1282 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
  1283 + } else {
  1284 + FT0 = float64_sqrt(FT0, &env->fp_status);
  1285 + }
743 } 1286 }
744 1287
745 void do_fre (void) 1288 void do_fre (void)
@@ -749,7 +1292,13 @@ void do_fre (void) @@ -749,7 +1292,13 @@ void do_fre (void)
749 uint64_t i; 1292 uint64_t i;
750 } p; 1293 } p;
751 1294
752 - if (likely(isnormal(FT0))) { 1295 + if (unlikely(float64_is_signaling_nan(FT0))) {
  1296 + /* sNaN reciprocal */
  1297 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
  1298 + } else if (unlikely(iszero(FT0))) {
  1299 + /* Zero reciprocal */
  1300 + float_zero_divide_excp();
  1301 + } else if (likely(isnormal(FT0))) {
753 FT0 = float64_div(1.0, FT0, &env->fp_status); 1302 FT0 = float64_div(1.0, FT0, &env->fp_status);
754 } else { 1303 } else {
755 p.d = FT0; 1304 p.d = FT0;
@@ -759,7 +1308,7 @@ void do_fre (void) @@ -759,7 +1308,7 @@ void do_fre (void)
759 p.i = 0x7FF0000000000000ULL; 1308 p.i = 0x7FF0000000000000ULL;
760 } else if (isnan(FT0)) { 1309 } else if (isnan(FT0)) {
761 p.i = 0x7FF8000000000000ULL; 1310 p.i = 0x7FF8000000000000ULL;
762 - } else if (FT0 < 0.0) { 1311 + } else if (fpisneg(FT0)) {
763 p.i = 0x8000000000000000ULL; 1312 p.i = 0x8000000000000000ULL;
764 } else { 1313 } else {
765 p.i = 0x0000000000000000ULL; 1314 p.i = 0x0000000000000000ULL;
@@ -775,7 +1324,13 @@ void do_fres (void) @@ -775,7 +1324,13 @@ void do_fres (void)
775 uint64_t i; 1324 uint64_t i;
776 } p; 1325 } p;
777 1326
778 - if (likely(isnormal(FT0))) { 1327 + if (unlikely(float64_is_signaling_nan(FT0))) {
  1328 + /* sNaN reciprocal */
  1329 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
  1330 + } else if (unlikely(iszero(FT0))) {
  1331 + /* Zero reciprocal */
  1332 + float_zero_divide_excp();
  1333 + } else if (likely(isnormal(FT0))) {
779 #if USE_PRECISE_EMULATION 1334 #if USE_PRECISE_EMULATION
780 FT0 = float64_div(1.0, FT0, &env->fp_status); 1335 FT0 = float64_div(1.0, FT0, &env->fp_status);
781 FT0 = float64_to_float32(FT0, &env->fp_status); 1336 FT0 = float64_to_float32(FT0, &env->fp_status);
@@ -790,7 +1345,7 @@ void do_fres (void) @@ -790,7 +1345,7 @@ void do_fres (void)
790 p.i = 0x7FF0000000000000ULL; 1345 p.i = 0x7FF0000000000000ULL;
791 } else if (isnan(FT0)) { 1346 } else if (isnan(FT0)) {
792 p.i = 0x7FF8000000000000ULL; 1347 p.i = 0x7FF8000000000000ULL;
793 - } else if (FT0 < 0.0) { 1348 + } else if (fpisneg(FT0)) {
794 p.i = 0x8000000000000000ULL; 1349 p.i = 0x8000000000000000ULL;
795 } else { 1350 } else {
796 p.i = 0x0000000000000000ULL; 1351 p.i = 0x0000000000000000ULL;
@@ -806,7 +1361,13 @@ void do_frsqrte (void) @@ -806,7 +1361,13 @@ void do_frsqrte (void)
806 uint64_t i; 1361 uint64_t i;
807 } p; 1362 } p;
808 1363
809 - if (likely(isnormal(FT0) && FT0 > 0.0)) { 1364 + if (unlikely(float64_is_signaling_nan(FT0))) {
  1365 + /* sNaN reciprocal square root */
  1366 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
  1367 + } else if (unlikely(fpisneg(FT0) && !iszero(FT0))) {
  1368 + /* Reciprocal square root of a negative nonzero number */
  1369 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
  1370 + } else if (likely(isnormal(FT0))) {
810 FT0 = float64_sqrt(FT0, &env->fp_status); 1371 FT0 = float64_sqrt(FT0, &env->fp_status);
811 FT0 = float32_div(1.0, FT0, &env->fp_status); 1372 FT0 = float32_div(1.0, FT0, &env->fp_status);
812 } else { 1373 } else {
@@ -816,9 +1377,8 @@ void do_frsqrte (void) @@ -816,9 +1377,8 @@ void do_frsqrte (void)
816 } else if (p.i == 0x0000000000000000ULL) { 1377 } else if (p.i == 0x0000000000000000ULL) {
817 p.i = 0x7FF0000000000000ULL; 1378 p.i = 0x7FF0000000000000ULL;
818 } else if (isnan(FT0)) { 1379 } else if (isnan(FT0)) {
819 - if (!(p.i & 0x0008000000000000ULL))  
820 - p.i |= 0x000FFFFFFFFFFFFFULL;  
821 - } else if (FT0 < 0) { 1380 + p.i |= 0x000FFFFFFFFFFFFFULL;
  1381 + } else if (fpisneg(FT0)) {
822 p.i = 0x7FF8000000000000ULL; 1382 p.i = 0x7FF8000000000000ULL;
823 } else { 1383 } else {
824 p.i = 0x0000000000000000ULL; 1384 p.i = 0x0000000000000000ULL;
@@ -829,7 +1389,7 @@ void do_frsqrte (void) @@ -829,7 +1389,7 @@ void do_frsqrte (void)
829 1389
830 void do_fsel (void) 1390 void do_fsel (void)
831 { 1391 {
832 - if (FT0 >= 0) 1392 + if (!fpisneg(FT0) || iszero(FT0))
833 FT0 = FT1; 1393 FT0 = FT1;
834 else 1394 else
835 FT0 = FT2; 1395 FT0 = FT2;
@@ -837,7 +1397,11 @@ void do_fsel (void) @@ -837,7 +1397,11 @@ void do_fsel (void)
837 1397
838 void do_fcmpu (void) 1398 void do_fcmpu (void)
839 { 1399 {
840 - if (likely(!isnan(FT0) && !isnan(FT1))) { 1400 + if (unlikely(float64_is_signaling_nan(FT0) ||
  1401 + float64_is_signaling_nan(FT1))) {
  1402 + /* sNaN comparison */
  1403 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
  1404 + } else {
841 if (float64_lt(FT0, FT1, &env->fp_status)) { 1405 if (float64_lt(FT0, FT1, &env->fp_status)) {
842 T0 = 0x08UL; 1406 T0 = 0x08UL;
843 } else if (!float64_le(FT0, FT1, &env->fp_status)) { 1407 } else if (!float64_le(FT0, FT1, &env->fp_status)) {
@@ -845,18 +1409,25 @@ void do_fcmpu (void) @@ -845,18 +1409,25 @@ void do_fcmpu (void)
845 } else { 1409 } else {
846 T0 = 0x02UL; 1410 T0 = 0x02UL;
847 } 1411 }
848 - } else {  
849 - T0 = 0x01UL;  
850 - env->fpscr[4] |= 0x1;  
851 - env->fpscr[6] |= 0x1;  
852 } 1412 }
853 - env->fpscr[3] = T0; 1413 + env->fpscr &= ~(0x0F << FPSCR_FPRF);
  1414 + env->fpscr |= T0 << FPSCR_FPRF;
854 } 1415 }
855 1416
856 void do_fcmpo (void) 1417 void do_fcmpo (void)
857 { 1418 {
858 - env->fpscr[4] &= ~0x1;  
859 - if (likely(!isnan(FT0) && !isnan(FT1))) { 1419 + if (unlikely(float64_is_nan(FT0) ||
  1420 + float64_is_nan(FT1))) {
  1421 + if (float64_is_signaling_nan(FT0) ||
  1422 + float64_is_signaling_nan(FT1)) {
  1423 + /* sNaN comparison */
  1424 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN |
  1425 + POWERPC_EXCP_FP_VXVC);
  1426 + } else {
  1427 + /* qNaN comparison */
  1428 + fload_invalid_op_excp(POWERPC_EXCP_FP_VXVC);
  1429 + }
  1430 + } else {
860 if (float64_lt(FT0, FT1, &env->fp_status)) { 1431 if (float64_lt(FT0, FT1, &env->fp_status)) {
861 T0 = 0x08UL; 1432 T0 = 0x08UL;
862 } else if (!float64_le(FT0, FT1, &env->fp_status)) { 1433 } else if (!float64_le(FT0, FT1, &env->fp_status)) {
@@ -864,19 +1435,9 @@ void do_fcmpo (void) @@ -864,19 +1435,9 @@ void do_fcmpo (void)
864 } else { 1435 } else {
865 T0 = 0x02UL; 1436 T0 = 0x02UL;
866 } 1437 }
867 - } else {  
868 - T0 = 0x01UL;  
869 - env->fpscr[4] |= 0x1;  
870 - if (!float64_is_signaling_nan(FT0) || !float64_is_signaling_nan(FT1)) {  
871 - /* Quiet NaN case */  
872 - env->fpscr[6] |= 0x1;  
873 - if (!(env->fpscr[1] & 0x8))  
874 - env->fpscr[4] |= 0x8;  
875 - } else {  
876 - env->fpscr[4] |= 0x8;  
877 - }  
878 } 1438 }
879 - env->fpscr[3] = T0; 1439 + env->fpscr &= ~(0x0F << FPSCR_FPRF);
  1440 + env->fpscr |= T0 << FPSCR_FPRF;
880 } 1441 }
881 1442
882 #if !defined (CONFIG_USER_ONLY) 1443 #if !defined (CONFIG_USER_ONLY)
target-ppc/op_helper.h
@@ -60,7 +60,7 @@ void do_store_cr (uint32_t mask); @@ -60,7 +60,7 @@ void do_store_cr (uint32_t mask);
60 #if defined(TARGET_PPC64) 60 #if defined(TARGET_PPC64)
61 void do_store_pri (int prio); 61 void do_store_pri (int prio);
62 #endif 62 #endif
63 -void do_load_fpscr (void); 63 +void do_fpscr_setbit (int bit);
64 void do_store_fpscr (uint32_t mask); 64 void do_store_fpscr (uint32_t mask);
65 target_ulong ppc_load_dump_spr (int sprn); 65 target_ulong ppc_load_dump_spr (int sprn);
66 void ppc_store_dump_spr (int sprn, target_ulong val); 66 void ppc_store_dump_spr (int sprn, target_ulong val);
@@ -94,6 +94,16 @@ void do_popcntb_64 (void); @@ -94,6 +94,16 @@ void do_popcntb_64 (void);
94 #endif 94 #endif
95 95
96 /* Floating-point arithmetic helpers */ 96 /* Floating-point arithmetic helpers */
  97 +void do_compute_fprf (int set_class);
  98 +#ifdef CONFIG_SOFTFLOAT
  99 +void do_float_check_status (void);
  100 +#endif
  101 +#if USE_PRECISE_EMULATION
  102 +void do_fadd (void);
  103 +void do_fsub (void);
  104 +void do_fmul (void);
  105 +void do_fdiv (void);
  106 +#endif
97 void do_fsqrt (void); 107 void do_fsqrt (void);
98 void do_fre (void); 108 void do_fre (void);
99 void do_fres (void); 109 void do_fres (void);
@@ -105,6 +115,9 @@ void do_fmsub (void); @@ -105,6 +115,9 @@ void do_fmsub (void);
105 #endif 115 #endif
106 void do_fnmadd (void); 116 void do_fnmadd (void);
107 void do_fnmsub (void); 117 void do_fnmsub (void);
  118 +#if USE_PRECISE_EMULATION
  119 +void do_frsp (void);
  120 +#endif
108 void do_fctiw (void); 121 void do_fctiw (void);
109 void do_fctiwz (void); 122 void do_fctiwz (void);
110 #if defined(TARGET_PPC64) 123 #if defined(TARGET_PPC64)
target-ppc/op_template.h
@@ -165,39 +165,6 @@ void OPPROTO glue(op_store_T1_crf_crf, REG) (void) @@ -165,39 +165,6 @@ void OPPROTO glue(op_store_T1_crf_crf, REG) (void)
165 RETURN(); 165 RETURN();
166 } 166 }
167 167
168 -/* Floating point condition and status register moves */  
169 -void OPPROTO glue(op_load_fpscr_T0_fpscr, REG) (void)  
170 -{  
171 - T0 = env->fpscr[REG];  
172 - RETURN();  
173 -}  
174 -  
175 -#if REG == 0  
176 -void OPPROTO glue(op_store_T0_fpscr_fpscr, REG) (void)  
177 -{  
178 - env->fpscr[REG] = (env->fpscr[REG] & 0x9) | (T0 & ~0x9);  
179 - RETURN();  
180 -}  
181 -  
182 -void OPPROTO glue(op_clear_fpscr_fpscr, REG) (void)  
183 -{  
184 - env->fpscr[REG] = (env->fpscr[REG] & 0x9);  
185 - RETURN();  
186 -}  
187 -#else  
188 -void OPPROTO glue(op_store_T0_fpscr_fpscr, REG) (void)  
189 -{  
190 - env->fpscr[REG] = T0;  
191 - RETURN();  
192 -}  
193 -  
194 -void OPPROTO glue(op_clear_fpscr_fpscr, REG) (void)  
195 -{  
196 - env->fpscr[REG] = 0x0;  
197 - RETURN();  
198 -}  
199 -#endif  
200 -  
201 #endif /* REG <= 7 */ 168 #endif /* REG <= 7 */
202 169
203 /* floating point registers moves */ 170 /* floating point registers moves */
target-ppc/translate.c
@@ -32,6 +32,7 @@ @@ -32,6 +32,7 @@
32 //#define PPC_DEBUG_DISAS 32 //#define PPC_DEBUG_DISAS
33 //#define DEBUG_MEMORY_ACCESSES 33 //#define DEBUG_MEMORY_ACCESSES
34 //#define DO_PPC_STATISTICS 34 //#define DO_PPC_STATISTICS
  35 +//#define OPTIMIZE_FPRF_UPDATE
35 36
36 /*****************************************************************************/ 37 /*****************************************************************************/
37 /* Code translation helpers */ 38 /* Code translation helpers */
@@ -50,6 +51,10 @@ enum { @@ -50,6 +51,10 @@ enum {
50 51
51 static uint16_t *gen_opc_ptr; 52 static uint16_t *gen_opc_ptr;
52 static uint32_t *gen_opparam_ptr; 53 static uint32_t *gen_opparam_ptr;
  54 +#if defined(OPTIMIZE_FPRF_UPDATE)
  55 +static uint16_t *gen_fprf_buf[OPC_BUF_SIZE];
  56 +static uint16_t **gen_fprf_ptr;
  57 +#endif
53 58
54 #include "gen-op.h" 59 #include "gen-op.h"
55 60
@@ -117,16 +122,6 @@ GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf); @@ -117,16 +122,6 @@ GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf);
117 GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf); 122 GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf);
118 GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf); 123 GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf);
119 124
120 -/* Floating point condition and status register moves */  
121 -GEN8(gen_op_load_fpscr_T0, gen_op_load_fpscr_T0_fpscr);  
122 -GEN8(gen_op_store_T0_fpscr, gen_op_store_T0_fpscr_fpscr);  
123 -GEN8(gen_op_clear_fpscr, gen_op_clear_fpscr_fpscr);  
124 -static always_inline void gen_op_store_T0_fpscri (int n, uint8_t param)  
125 -{  
126 - gen_op_set_T0(param);  
127 - gen_op_store_T0_fpscr(n);  
128 -}  
129 -  
130 /* General purpose registers moves */ 125 /* General purpose registers moves */
131 GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr); 126 GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
132 GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr); 127 GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
@@ -199,6 +194,44 @@ static always_inline void gen_set_Rc0 (DisasContext *ctx) @@ -199,6 +194,44 @@ static always_inline void gen_set_Rc0 (DisasContext *ctx)
199 gen_op_set_Rc0(); 194 gen_op_set_Rc0();
200 } 195 }
201 196
  197 +static always_inline void gen_reset_fpstatus (void)
  198 +{
  199 +#ifdef CONFIG_SOFTFLOAT
  200 + gen_op_reset_fpstatus();
  201 +#endif
  202 +}
  203 +
  204 +static always_inline void gen_compute_fprf (int set_fprf, int set_rc)
  205 +{
  206 + if (set_fprf != 0) {
  207 + /* This case might be optimized later */
  208 +#if defined(OPTIMIZE_FPRF_UPDATE)
  209 + *gen_fprf_ptr++ = gen_opc_ptr;
  210 +#endif
  211 + gen_op_compute_fprf(1);
  212 + if (unlikely(set_rc))
  213 + gen_op_store_T0_crf(1);
  214 + gen_op_float_check_status();
  215 + } else if (unlikely(set_rc)) {
  216 + /* We always need to compute fpcc */
  217 + gen_op_compute_fprf(0);
  218 + gen_op_store_T0_crf(1);
  219 + if (set_fprf)
  220 + gen_op_float_check_status();
  221 + }
  222 +}
  223 +
  224 +static always_inline void gen_optimize_fprf (void)
  225 +{
  226 +#if defined(OPTIMIZE_FPRF_UPDATE)
  227 + uint16_t **ptr;
  228 +
  229 + for (ptr = gen_fprf_buf; ptr != (gen_fprf_ptr - 1); ptr++)
  230 + *ptr = INDEX_op_nop1;
  231 + gen_fprf_ptr = gen_fprf_buf;
  232 +#endif
  233 +}
  234 +
202 static always_inline void gen_update_nip (DisasContext *ctx, target_ulong nip) 235 static always_inline void gen_update_nip (DisasContext *ctx, target_ulong nip)
203 { 236 {
204 #if defined(TARGET_PPC64) 237 #if defined(TARGET_PPC64)
@@ -497,6 +530,8 @@ enum { @@ -497,6 +530,8 @@ enum {
497 PPC_CACHE_DCBZ = 0x0000400000000000ULL, 530 PPC_CACHE_DCBZ = 0x0000400000000000ULL,
498 /* dcbz instruction with tunable cache line size */ 531 /* dcbz instruction with tunable cache line size */
499 PPC_CACHE_DCBZT = 0x0000800000000000ULL, 532 PPC_CACHE_DCBZT = 0x0000800000000000ULL,
  533 + /* frsqrtes extension */
  534 + PPC_FLOAT_FRSQRTES = 0x0001000000000000ULL,
500 }; 535 };
501 536
502 /*****************************************************************************/ 537 /*****************************************************************************/
@@ -1656,124 +1691,127 @@ __GEN_LOGICAL2(srd, 0x1B, 0x10, PPC_64B); @@ -1656,124 +1691,127 @@ __GEN_LOGICAL2(srd, 0x1B, 0x10, PPC_64B);
1656 #endif 1691 #endif
1657 1692
1658 /*** Floating-Point arithmetic ***/ 1693 /*** Floating-Point arithmetic ***/
1659 -#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, type) \ 1694 +#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
1660 GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type) \ 1695 GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type) \
1661 { \ 1696 { \
1662 if (unlikely(!ctx->fpu_enabled)) { \ 1697 if (unlikely(!ctx->fpu_enabled)) { \
1663 GEN_EXCP_NO_FP(ctx); \ 1698 GEN_EXCP_NO_FP(ctx); \
1664 return; \ 1699 return; \
1665 } \ 1700 } \
1666 - gen_op_reset_scrfx(); \  
1667 gen_op_load_fpr_FT0(rA(ctx->opcode)); \ 1701 gen_op_load_fpr_FT0(rA(ctx->opcode)); \
1668 gen_op_load_fpr_FT1(rC(ctx->opcode)); \ 1702 gen_op_load_fpr_FT1(rC(ctx->opcode)); \
1669 gen_op_load_fpr_FT2(rB(ctx->opcode)); \ 1703 gen_op_load_fpr_FT2(rB(ctx->opcode)); \
  1704 + gen_reset_fpstatus(); \
1670 gen_op_f##op(); \ 1705 gen_op_f##op(); \
1671 if (isfloat) { \ 1706 if (isfloat) { \
1672 gen_op_frsp(); \ 1707 gen_op_frsp(); \
1673 } \ 1708 } \
1674 gen_op_store_FT0_fpr(rD(ctx->opcode)); \ 1709 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1675 - if (unlikely(Rc(ctx->opcode) != 0)) \  
1676 - gen_op_set_Rc1(); \ 1710 + gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1677 } 1711 }
1678 1712
1679 -#define GEN_FLOAT_ACB(name, op2, type) \  
1680 -_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, type); \  
1681 -_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, type); 1713 +#define GEN_FLOAT_ACB(name, op2, set_fprf, type) \
  1714 +_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type); \
  1715 +_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
1682 1716
1683 -#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat) \  
1684 -GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ 1717 +#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
  1718 +GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type) \
1685 { \ 1719 { \
1686 if (unlikely(!ctx->fpu_enabled)) { \ 1720 if (unlikely(!ctx->fpu_enabled)) { \
1687 GEN_EXCP_NO_FP(ctx); \ 1721 GEN_EXCP_NO_FP(ctx); \
1688 return; \ 1722 return; \
1689 } \ 1723 } \
1690 - gen_op_reset_scrfx(); \  
1691 gen_op_load_fpr_FT0(rA(ctx->opcode)); \ 1724 gen_op_load_fpr_FT0(rA(ctx->opcode)); \
1692 gen_op_load_fpr_FT1(rB(ctx->opcode)); \ 1725 gen_op_load_fpr_FT1(rB(ctx->opcode)); \
  1726 + gen_reset_fpstatus(); \
1693 gen_op_f##op(); \ 1727 gen_op_f##op(); \
1694 if (isfloat) { \ 1728 if (isfloat) { \
1695 gen_op_frsp(); \ 1729 gen_op_frsp(); \
1696 } \ 1730 } \
1697 gen_op_store_FT0_fpr(rD(ctx->opcode)); \ 1731 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1698 - if (unlikely(Rc(ctx->opcode) != 0)) \  
1699 - gen_op_set_Rc1(); \ 1732 + gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1700 } 1733 }
1701 -#define GEN_FLOAT_AB(name, op2, inval) \  
1702 -_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0); \  
1703 -_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1); 1734 +#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \
  1735 +_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
  1736 +_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
1704 1737
1705 -#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat) \  
1706 -GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ 1738 +#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type) \
  1739 +GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type) \
1707 { \ 1740 { \
1708 if (unlikely(!ctx->fpu_enabled)) { \ 1741 if (unlikely(!ctx->fpu_enabled)) { \
1709 GEN_EXCP_NO_FP(ctx); \ 1742 GEN_EXCP_NO_FP(ctx); \
1710 return; \ 1743 return; \
1711 } \ 1744 } \
1712 - gen_op_reset_scrfx(); \  
1713 gen_op_load_fpr_FT0(rA(ctx->opcode)); \ 1745 gen_op_load_fpr_FT0(rA(ctx->opcode)); \
1714 gen_op_load_fpr_FT1(rC(ctx->opcode)); \ 1746 gen_op_load_fpr_FT1(rC(ctx->opcode)); \
  1747 + gen_reset_fpstatus(); \
1715 gen_op_f##op(); \ 1748 gen_op_f##op(); \
1716 if (isfloat) { \ 1749 if (isfloat) { \
1717 gen_op_frsp(); \ 1750 gen_op_frsp(); \
1718 } \ 1751 } \
1719 gen_op_store_FT0_fpr(rD(ctx->opcode)); \ 1752 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1720 - if (unlikely(Rc(ctx->opcode) != 0)) \  
1721 - gen_op_set_Rc1(); \ 1753 + gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1722 } 1754 }
1723 -#define GEN_FLOAT_AC(name, op2, inval) \  
1724 -_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0); \  
1725 -_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1); 1755 +#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \
  1756 +_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
  1757 +_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
1726 1758
1727 -#define GEN_FLOAT_B(name, op2, op3, type) \ 1759 +#define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \
1728 GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type) \ 1760 GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type) \
1729 { \ 1761 { \
1730 if (unlikely(!ctx->fpu_enabled)) { \ 1762 if (unlikely(!ctx->fpu_enabled)) { \
1731 GEN_EXCP_NO_FP(ctx); \ 1763 GEN_EXCP_NO_FP(ctx); \
1732 return; \ 1764 return; \
1733 } \ 1765 } \
1734 - gen_op_reset_scrfx(); \  
1735 gen_op_load_fpr_FT0(rB(ctx->opcode)); \ 1766 gen_op_load_fpr_FT0(rB(ctx->opcode)); \
  1767 + gen_reset_fpstatus(); \
1736 gen_op_f##name(); \ 1768 gen_op_f##name(); \
1737 gen_op_store_FT0_fpr(rD(ctx->opcode)); \ 1769 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1738 - if (unlikely(Rc(ctx->opcode) != 0)) \  
1739 - gen_op_set_Rc1(); \ 1770 + gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1740 } 1771 }
1741 1772
1742 -#define GEN_FLOAT_BS(name, op1, op2, type) \ 1773 +#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
1743 GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type) \ 1774 GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type) \
1744 { \ 1775 { \
1745 if (unlikely(!ctx->fpu_enabled)) { \ 1776 if (unlikely(!ctx->fpu_enabled)) { \
1746 GEN_EXCP_NO_FP(ctx); \ 1777 GEN_EXCP_NO_FP(ctx); \
1747 return; \ 1778 return; \
1748 } \ 1779 } \
1749 - gen_op_reset_scrfx(); \  
1750 gen_op_load_fpr_FT0(rB(ctx->opcode)); \ 1780 gen_op_load_fpr_FT0(rB(ctx->opcode)); \
  1781 + gen_reset_fpstatus(); \
1751 gen_op_f##name(); \ 1782 gen_op_f##name(); \
1752 gen_op_store_FT0_fpr(rD(ctx->opcode)); \ 1783 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1753 - if (unlikely(Rc(ctx->opcode) != 0)) \  
1754 - gen_op_set_Rc1(); \ 1784 + gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1755 } 1785 }
1756 1786
1757 /* fadd - fadds */ 1787 /* fadd - fadds */
1758 -GEN_FLOAT_AB(add, 0x15, 0x000007C0); 1788 +GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
1759 /* fdiv - fdivs */ 1789 /* fdiv - fdivs */
1760 -GEN_FLOAT_AB(div, 0x12, 0x000007C0); 1790 +GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
1761 /* fmul - fmuls */ 1791 /* fmul - fmuls */
1762 -GEN_FLOAT_AC(mul, 0x19, 0x0000F800); 1792 +GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
1763 1793
1764 /* fre */ 1794 /* fre */
1765 -GEN_FLOAT_BS(re, 0x3F, 0x18, PPC_FLOAT_EXT); 1795 +GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
1766 1796
1767 /* fres */ 1797 /* fres */
1768 -GEN_FLOAT_BS(res, 0x3B, 0x18, PPC_FLOAT_FRES); 1798 +GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
1769 1799
1770 /* frsqrte */ 1800 /* frsqrte */
1771 -GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, PPC_FLOAT_FRSQRTE); 1801 +GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
  1802 +
  1803 +/* frsqrtes */
  1804 +static always_inline void gen_op_frsqrtes (void)
  1805 +{
  1806 + gen_op_frsqrte();
  1807 + gen_op_frsp();
  1808 +}
  1809 +GEN_FLOAT_BS(rsqrtes, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTES);
1772 1810
1773 /* fsel */ 1811 /* fsel */
1774 -_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, PPC_FLOAT_FSEL); 1812 +_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
1775 /* fsub - fsubs */ 1813 /* fsub - fsubs */
1776 -GEN_FLOAT_AB(sub, 0x14, 0x000007C0); 1814 +GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
1777 /* Optional: */ 1815 /* Optional: */
1778 /* fsqrt */ 1816 /* fsqrt */
1779 GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT) 1817 GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
@@ -1782,12 +1820,11 @@ GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT) @@ -1782,12 +1820,11 @@ GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
1782 GEN_EXCP_NO_FP(ctx); 1820 GEN_EXCP_NO_FP(ctx);
1783 return; 1821 return;
1784 } 1822 }
1785 - gen_op_reset_scrfx();  
1786 gen_op_load_fpr_FT0(rB(ctx->opcode)); 1823 gen_op_load_fpr_FT0(rB(ctx->opcode));
  1824 + gen_reset_fpstatus();
1787 gen_op_fsqrt(); 1825 gen_op_fsqrt();
1788 gen_op_store_FT0_fpr(rD(ctx->opcode)); 1826 gen_op_store_FT0_fpr(rD(ctx->opcode));
1789 - if (unlikely(Rc(ctx->opcode) != 0))  
1790 - gen_op_set_Rc1(); 1827 + gen_compute_fprf(1, Rc(ctx->opcode) != 0);
1791 } 1828 }
1792 1829
1793 GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT) 1830 GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
@@ -1796,49 +1833,48 @@ GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT) @@ -1796,49 +1833,48 @@ GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
1796 GEN_EXCP_NO_FP(ctx); 1833 GEN_EXCP_NO_FP(ctx);
1797 return; 1834 return;
1798 } 1835 }
1799 - gen_op_reset_scrfx();  
1800 gen_op_load_fpr_FT0(rB(ctx->opcode)); 1836 gen_op_load_fpr_FT0(rB(ctx->opcode));
  1837 + gen_reset_fpstatus();
1801 gen_op_fsqrt(); 1838 gen_op_fsqrt();
1802 gen_op_frsp(); 1839 gen_op_frsp();
1803 gen_op_store_FT0_fpr(rD(ctx->opcode)); 1840 gen_op_store_FT0_fpr(rD(ctx->opcode));
1804 - if (unlikely(Rc(ctx->opcode) != 0))  
1805 - gen_op_set_Rc1(); 1841 + gen_compute_fprf(1, Rc(ctx->opcode) != 0);
1806 } 1842 }
1807 1843
1808 /*** Floating-Point multiply-and-add ***/ 1844 /*** Floating-Point multiply-and-add ***/
1809 /* fmadd - fmadds */ 1845 /* fmadd - fmadds */
1810 -GEN_FLOAT_ACB(madd, 0x1D, PPC_FLOAT); 1846 +GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
1811 /* fmsub - fmsubs */ 1847 /* fmsub - fmsubs */
1812 -GEN_FLOAT_ACB(msub, 0x1C, PPC_FLOAT); 1848 +GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
1813 /* fnmadd - fnmadds */ 1849 /* fnmadd - fnmadds */
1814 -GEN_FLOAT_ACB(nmadd, 0x1F, PPC_FLOAT); 1850 +GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
1815 /* fnmsub - fnmsubs */ 1851 /* fnmsub - fnmsubs */
1816 -GEN_FLOAT_ACB(nmsub, 0x1E, PPC_FLOAT); 1852 +GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
1817 1853
1818 /*** Floating-Point round & convert ***/ 1854 /*** Floating-Point round & convert ***/
1819 /* fctiw */ 1855 /* fctiw */
1820 -GEN_FLOAT_B(ctiw, 0x0E, 0x00, PPC_FLOAT); 1856 +GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
1821 /* fctiwz */ 1857 /* fctiwz */
1822 -GEN_FLOAT_B(ctiwz, 0x0F, 0x00, PPC_FLOAT); 1858 +GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
1823 /* frsp */ 1859 /* frsp */
1824 -GEN_FLOAT_B(rsp, 0x0C, 0x00, PPC_FLOAT); 1860 +GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
1825 #if defined(TARGET_PPC64) 1861 #if defined(TARGET_PPC64)
1826 /* fcfid */ 1862 /* fcfid */
1827 -GEN_FLOAT_B(cfid, 0x0E, 0x1A, PPC_64B); 1863 +GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
1828 /* fctid */ 1864 /* fctid */
1829 -GEN_FLOAT_B(ctid, 0x0E, 0x19, PPC_64B); 1865 +GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
1830 /* fctidz */ 1866 /* fctidz */
1831 -GEN_FLOAT_B(ctidz, 0x0F, 0x19, PPC_64B); 1867 +GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
1832 #endif 1868 #endif
1833 1869
1834 /* frin */ 1870 /* frin */
1835 -GEN_FLOAT_B(rin, 0x08, 0x0C, PPC_FLOAT_EXT); 1871 +GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
1836 /* friz */ 1872 /* friz */
1837 -GEN_FLOAT_B(riz, 0x08, 0x0D, PPC_FLOAT_EXT); 1873 +GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
1838 /* frip */ 1874 /* frip */
1839 -GEN_FLOAT_B(rip, 0x08, 0x0E, PPC_FLOAT_EXT); 1875 +GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
1840 /* frim */ 1876 /* frim */
1841 -GEN_FLOAT_B(rim, 0x08, 0x0F, PPC_FLOAT_EXT); 1877 +GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
1842 1878
1843 /*** Floating-Point compare ***/ 1879 /*** Floating-Point compare ***/
1844 /* fcmpo */ 1880 /* fcmpo */
@@ -1848,11 +1884,12 @@ GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT) @@ -1848,11 +1884,12 @@ GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
1848 GEN_EXCP_NO_FP(ctx); 1884 GEN_EXCP_NO_FP(ctx);
1849 return; 1885 return;
1850 } 1886 }
1851 - gen_op_reset_scrfx();  
1852 gen_op_load_fpr_FT0(rA(ctx->opcode)); 1887 gen_op_load_fpr_FT0(rA(ctx->opcode));
1853 gen_op_load_fpr_FT1(rB(ctx->opcode)); 1888 gen_op_load_fpr_FT1(rB(ctx->opcode));
  1889 + gen_reset_fpstatus();
1854 gen_op_fcmpo(); 1890 gen_op_fcmpo();
1855 gen_op_store_T0_crf(crfD(ctx->opcode)); 1891 gen_op_store_T0_crf(crfD(ctx->opcode));
  1892 + gen_op_float_check_status();
1856 } 1893 }
1857 1894
1858 /* fcmpu */ 1895 /* fcmpu */
@@ -1862,47 +1899,54 @@ GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT) @@ -1862,47 +1899,54 @@ GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
1862 GEN_EXCP_NO_FP(ctx); 1899 GEN_EXCP_NO_FP(ctx);
1863 return; 1900 return;
1864 } 1901 }
1865 - gen_op_reset_scrfx();  
1866 gen_op_load_fpr_FT0(rA(ctx->opcode)); 1902 gen_op_load_fpr_FT0(rA(ctx->opcode));
1867 gen_op_load_fpr_FT1(rB(ctx->opcode)); 1903 gen_op_load_fpr_FT1(rB(ctx->opcode));
  1904 + gen_reset_fpstatus();
1868 gen_op_fcmpu(); 1905 gen_op_fcmpu();
1869 gen_op_store_T0_crf(crfD(ctx->opcode)); 1906 gen_op_store_T0_crf(crfD(ctx->opcode));
  1907 + gen_op_float_check_status();
1870 } 1908 }
1871 1909
1872 /*** Floating-point move ***/ 1910 /*** Floating-point move ***/
1873 /* fabs */ 1911 /* fabs */
1874 -GEN_FLOAT_B(abs, 0x08, 0x08, PPC_FLOAT); 1912 +/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
  1913 +GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
1875 1914
1876 /* fmr - fmr. */ 1915 /* fmr - fmr. */
  1916 +/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
1877 GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT) 1917 GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
1878 { 1918 {
1879 if (unlikely(!ctx->fpu_enabled)) { 1919 if (unlikely(!ctx->fpu_enabled)) {
1880 GEN_EXCP_NO_FP(ctx); 1920 GEN_EXCP_NO_FP(ctx);
1881 return; 1921 return;
1882 } 1922 }
1883 - gen_op_reset_scrfx();  
1884 gen_op_load_fpr_FT0(rB(ctx->opcode)); 1923 gen_op_load_fpr_FT0(rB(ctx->opcode));
1885 gen_op_store_FT0_fpr(rD(ctx->opcode)); 1924 gen_op_store_FT0_fpr(rD(ctx->opcode));
1886 - if (unlikely(Rc(ctx->opcode) != 0))  
1887 - gen_op_set_Rc1(); 1925 + gen_compute_fprf(0, Rc(ctx->opcode) != 0);
1888 } 1926 }
1889 1927
1890 /* fnabs */ 1928 /* fnabs */
1891 -GEN_FLOAT_B(nabs, 0x08, 0x04, PPC_FLOAT); 1929 +/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
  1930 +GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
1892 /* fneg */ 1931 /* fneg */
1893 -GEN_FLOAT_B(neg, 0x08, 0x01, PPC_FLOAT); 1932 +/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
  1933 +GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
1894 1934
1895 /*** Floating-Point status & ctrl register ***/ 1935 /*** Floating-Point status & ctrl register ***/
1896 /* mcrfs */ 1936 /* mcrfs */
1897 GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT) 1937 GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
1898 { 1938 {
  1939 + int bfa;
  1940 +
1899 if (unlikely(!ctx->fpu_enabled)) { 1941 if (unlikely(!ctx->fpu_enabled)) {
1900 GEN_EXCP_NO_FP(ctx); 1942 GEN_EXCP_NO_FP(ctx);
1901 return; 1943 return;
1902 } 1944 }
1903 - gen_op_load_fpscr_T0(crfS(ctx->opcode)); 1945 + gen_optimize_fprf();
  1946 + bfa = 4 * (7 - crfS(ctx->opcode));
  1947 + gen_op_load_fpscr_T0(bfa);
1904 gen_op_store_T0_crf(crfD(ctx->opcode)); 1948 gen_op_store_T0_crf(crfD(ctx->opcode));
1905 - gen_op_clear_fpscr(crfS(ctx->opcode)); 1949 + gen_op_fpscr_resetbit(~(0xF << bfa));
1906 } 1950 }
1907 1951
1908 /* mffs */ 1952 /* mffs */
@@ -1912,10 +1956,11 @@ GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT) @@ -1912,10 +1956,11 @@ GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
1912 GEN_EXCP_NO_FP(ctx); 1956 GEN_EXCP_NO_FP(ctx);
1913 return; 1957 return;
1914 } 1958 }
1915 - gen_op_load_fpscr(); 1959 + gen_optimize_fprf();
  1960 + gen_reset_fpstatus();
  1961 + gen_op_load_fpscr_FT0();
1916 gen_op_store_FT0_fpr(rD(ctx->opcode)); 1962 gen_op_store_FT0_fpr(rD(ctx->opcode));
1917 - if (unlikely(Rc(ctx->opcode) != 0))  
1918 - gen_op_set_Rc1(); 1963 + gen_compute_fprf(0, Rc(ctx->opcode) != 0);
1919 } 1964 }
1920 1965
1921 /* mtfsb0 */ 1966 /* mtfsb0 */
@@ -1927,12 +1972,15 @@ GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT) @@ -1927,12 +1972,15 @@ GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT)
1927 GEN_EXCP_NO_FP(ctx); 1972 GEN_EXCP_NO_FP(ctx);
1928 return; 1973 return;
1929 } 1974 }
1930 - crb = crbD(ctx->opcode) >> 2;  
1931 - gen_op_load_fpscr_T0(crb);  
1932 - gen_op_andi_T0(~(1 << (crbD(ctx->opcode) & 0x03)));  
1933 - gen_op_store_T0_fpscr(crb);  
1934 - if (unlikely(Rc(ctx->opcode) != 0))  
1935 - gen_op_set_Rc1(); 1975 + crb = 32 - (crbD(ctx->opcode) >> 2);
  1976 + gen_optimize_fprf();
  1977 + gen_reset_fpstatus();
  1978 + if (likely(crb != 30 && crb != 29))
  1979 + gen_op_fpscr_resetbit(~(1 << crb));
  1980 + if (unlikely(Rc(ctx->opcode) != 0)) {
  1981 + gen_op_load_fpcc();
  1982 + gen_op_set_Rc0();
  1983 + }
1936 } 1984 }
1937 1985
1938 /* mtfsb1 */ 1986 /* mtfsb1 */
@@ -1944,12 +1992,18 @@ GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT) @@ -1944,12 +1992,18 @@ GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
1944 GEN_EXCP_NO_FP(ctx); 1992 GEN_EXCP_NO_FP(ctx);
1945 return; 1993 return;
1946 } 1994 }
1947 - crb = crbD(ctx->opcode) >> 2;  
1948 - gen_op_load_fpscr_T0(crb);  
1949 - gen_op_ori(1 << (crbD(ctx->opcode) & 0x03));  
1950 - gen_op_store_T0_fpscr(crb);  
1951 - if (unlikely(Rc(ctx->opcode) != 0))  
1952 - gen_op_set_Rc1(); 1995 + crb = 32 - (crbD(ctx->opcode) >> 2);
  1996 + gen_optimize_fprf();
  1997 + gen_reset_fpstatus();
  1998 + /* XXX: we pretend we can only do IEEE floating-point computations */
  1999 + if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI))
  2000 + gen_op_fpscr_setbit(crb);
  2001 + if (unlikely(Rc(ctx->opcode) != 0)) {
  2002 + gen_op_load_fpcc();
  2003 + gen_op_set_Rc0();
  2004 + }
  2005 + /* We can raise a differed exception */
  2006 + gen_op_float_check_status();
1953 } 2007 }
1954 2008
1955 /* mtfsf */ 2009 /* mtfsf */
@@ -1959,22 +2013,39 @@ GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT) @@ -1959,22 +2013,39 @@ GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
1959 GEN_EXCP_NO_FP(ctx); 2013 GEN_EXCP_NO_FP(ctx);
1960 return; 2014 return;
1961 } 2015 }
  2016 + gen_optimize_fprf();
1962 gen_op_load_fpr_FT0(rB(ctx->opcode)); 2017 gen_op_load_fpr_FT0(rB(ctx->opcode));
  2018 + gen_reset_fpstatus();
1963 gen_op_store_fpscr(FM(ctx->opcode)); 2019 gen_op_store_fpscr(FM(ctx->opcode));
1964 - if (unlikely(Rc(ctx->opcode) != 0))  
1965 - gen_op_set_Rc1(); 2020 + if (unlikely(Rc(ctx->opcode) != 0)) {
  2021 + gen_op_load_fpcc();
  2022 + gen_op_set_Rc0();
  2023 + }
  2024 + /* We can raise a differed exception */
  2025 + gen_op_float_check_status();
1966 } 2026 }
1967 2027
1968 /* mtfsfi */ 2028 /* mtfsfi */
1969 GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT) 2029 GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
1970 { 2030 {
  2031 + int bf, sh;
  2032 +
1971 if (unlikely(!ctx->fpu_enabled)) { 2033 if (unlikely(!ctx->fpu_enabled)) {
1972 GEN_EXCP_NO_FP(ctx); 2034 GEN_EXCP_NO_FP(ctx);
1973 return; 2035 return;
1974 } 2036 }
1975 - gen_op_store_T0_fpscri(crbD(ctx->opcode) >> 2, FPIMM(ctx->opcode));  
1976 - if (unlikely(Rc(ctx->opcode) != 0))  
1977 - gen_op_set_Rc1(); 2037 + bf = crbD(ctx->opcode) >> 2;
  2038 + sh = 7 - bf;
  2039 + gen_optimize_fprf();
  2040 + gen_op_set_FT0(FPIMM(ctx->opcode) << (4 * sh));
  2041 + gen_reset_fpstatus();
  2042 + gen_op_store_fpscr(1 << sh);
  2043 + if (unlikely(Rc(ctx->opcode) != 0)) {
  2044 + gen_op_load_fpcc();
  2045 + gen_op_set_Rc0();
  2046 + }
  2047 + /* We can raise a differed exception */
  2048 + gen_op_float_check_status();
1978 } 2049 }
1979 2050
1980 /*** Addressing modes ***/ 2051 /*** Addressing modes ***/
@@ -6717,6 +6788,9 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, @@ -6717,6 +6788,9 @@ static always_inline int gen_intermediate_code_internal (CPUState *env,
6717 gen_opc_ptr = gen_opc_buf; 6788 gen_opc_ptr = gen_opc_buf;
6718 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; 6789 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6719 gen_opparam_ptr = gen_opparam_buf; 6790 gen_opparam_ptr = gen_opparam_buf;
  6791 +#if defined(OPTIMIZE_FPRF_UPDATE)
  6792 + gen_fprf_ptr = gen_fprf_buf;
  6793 +#endif
6720 nb_gen_labels = 0; 6794 nb_gen_labels = 0;
6721 ctx.nip = pc_start; 6795 ctx.nip = pc_start;
6722 ctx.tb = tb; 6796 ctx.tb = tb;