aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/math-emu/math_efp.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/arch/powerpc/math-emu/math_efp.c b/arch/powerpc/math-emu/math_efp.c
index 59835c625dc6..ecdf35d8cb00 100644
--- a/arch/powerpc/math-emu/math_efp.c
+++ b/arch/powerpc/math-emu/math_efp.c
@@ -680,7 +680,8 @@ int speround_handler(struct pt_regs *regs)
680{ 680{
681 union dw_union fgpr; 681 union dw_union fgpr;
682 int s_lo, s_hi; 682 int s_lo, s_hi;
683 unsigned long speinsn, type, fc; 683 int lo_inexact, hi_inexact;
684 unsigned long speinsn, type, fc, fptype;
684 685
685 if (get_user(speinsn, (unsigned int __user *) regs->nip)) 686 if (get_user(speinsn, (unsigned int __user *) regs->nip))
686 return -EFAULT; 687 return -EFAULT;
@@ -693,8 +694,12 @@ int speround_handler(struct pt_regs *regs)
693 __FPU_FPSCR = mfspr(SPRN_SPEFSCR); 694 __FPU_FPSCR = mfspr(SPRN_SPEFSCR);
694 pr_debug("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR); 695 pr_debug("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR);
695 696
697 fptype = (speinsn >> 5) & 0x7;
698
696 /* No need to round if the result is exact */ 699 /* No need to round if the result is exact */
697 if (!(__FPU_FPSCR & FP_EX_INEXACT)) 700 lo_inexact = __FPU_FPSCR & (SPEFSCR_FG | SPEFSCR_FX);
701 hi_inexact = __FPU_FPSCR & (SPEFSCR_FGH | SPEFSCR_FXH);
702 if (!(lo_inexact || (hi_inexact && fptype == VCT)))
698 return 0; 703 return 0;
699 704
700 fc = (speinsn >> 21) & 0x1f; 705 fc = (speinsn >> 21) & 0x1f;
@@ -705,7 +710,7 @@ int speround_handler(struct pt_regs *regs)
705 710
706 pr_debug("round fgpr: %08x %08x\n", fgpr.wp[0], fgpr.wp[1]); 711 pr_debug("round fgpr: %08x %08x\n", fgpr.wp[0], fgpr.wp[1]);
707 712
708 switch ((speinsn >> 5) & 0x7) { 713 switch (fptype) {
709 /* Since SPE instructions on E500 core can handle round to nearest 714 /* Since SPE instructions on E500 core can handle round to nearest
710 * and round toward zero with IEEE-754 complied, we just need 715 * and round toward zero with IEEE-754 complied, we just need
711 * to handle round toward +Inf and round toward -Inf by software. 716 * to handle round toward +Inf and round toward -Inf by software.
@@ -728,11 +733,15 @@ int speround_handler(struct pt_regs *regs)
728 733
729 case VCT: 734 case VCT:
730 if (FP_ROUNDMODE == FP_RND_PINF) { 735 if (FP_ROUNDMODE == FP_RND_PINF) {
731 if (!s_lo) fgpr.wp[1]++; /* Z_low > 0, choose Z1 */ 736 if (lo_inexact && !s_lo)
732 if (!s_hi) fgpr.wp[0]++; /* Z_high word > 0, choose Z1 */ 737 fgpr.wp[1]++; /* Z_low > 0, choose Z1 */
738 if (hi_inexact && !s_hi)
739 fgpr.wp[0]++; /* Z_high word > 0, choose Z1 */
733 } else { /* round to -Inf */ 740 } else { /* round to -Inf */
734 if (s_lo) fgpr.wp[1]++; /* Z_low < 0, choose Z2 */ 741 if (lo_inexact && s_lo)
735 if (s_hi) fgpr.wp[0]++; /* Z_high < 0, choose Z2 */ 742 fgpr.wp[1]++; /* Z_low < 0, choose Z2 */
743 if (hi_inexact && s_hi)
744 fgpr.wp[0]++; /* Z_high < 0, choose Z2 */
736 } 745 }
737 break; 746 break;
738 747