aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/math-emu
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/math-emu')
-rw-r--r--arch/powerpc/math-emu/Makefile2
-rw-r--r--arch/powerpc/math-emu/math_efp.c65
2 files changed, 61 insertions, 6 deletions
diff --git a/arch/powerpc/math-emu/Makefile b/arch/powerpc/math-emu/Makefile
index 0c16ab947f1f..7d1dba0d57f9 100644
--- a/arch/powerpc/math-emu/Makefile
+++ b/arch/powerpc/math-emu/Makefile
@@ -15,4 +15,4 @@ obj-$(CONFIG_SPE) += math_efp.o
15CFLAGS_fabs.o = -fno-builtin-fabs 15CFLAGS_fabs.o = -fno-builtin-fabs
16CFLAGS_math.o = -fno-builtin-fabs 16CFLAGS_math.o = -fno-builtin-fabs
17 17
18EXTRA_CFLAGS = -I. -Iinclude/math-emu -w 18ccflags-y = -I. -Iinclude/math-emu -w
diff --git a/arch/powerpc/math-emu/math_efp.c b/arch/powerpc/math-emu/math_efp.c
index 41f4ef30e480..62279200d965 100644
--- a/arch/powerpc/math-emu/math_efp.c
+++ b/arch/powerpc/math-emu/math_efp.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * arch/powerpc/math-emu/math_efp.c 2 * arch/powerpc/math-emu/math_efp.c
3 * 3 *
4 * Copyright (C) 2006-2008 Freescale Semiconductor, Inc. All rights reserved. 4 * Copyright (C) 2006-2008, 2010 Freescale Semiconductor, Inc.
5 * 5 *
6 * Author: Ebony Zhu, <ebony.zhu@freescale.com> 6 * Author: Ebony Zhu, <ebony.zhu@freescale.com>
7 * Yu Liu, <yu.liu@freescale.com> 7 * Yu Liu, <yu.liu@freescale.com>
@@ -104,6 +104,8 @@
104#define FP_EX_MASK (FP_EX_INEXACT | FP_EX_INVALID | FP_EX_DIVZERO | \ 104#define FP_EX_MASK (FP_EX_INEXACT | FP_EX_INVALID | FP_EX_DIVZERO | \
105 FP_EX_UNDERFLOW | FP_EX_OVERFLOW) 105 FP_EX_UNDERFLOW | FP_EX_OVERFLOW)
106 106
107static int have_e500_cpu_a005_erratum;
108
107union dw_union { 109union dw_union {
108 u64 dp[1]; 110 u64 dp[1];
109 u32 wp[2]; 111 u32 wp[2];
@@ -320,7 +322,8 @@ int do_spe_mathemu(struct pt_regs *regs)
320 } else { 322 } else {
321 _FP_ROUND_ZERO(1, SB); 323 _FP_ROUND_ZERO(1, SB);
322 } 324 }
323 FP_TO_INT_S(vc.wp[1], SB, 32, ((func & 0x3) != 0)); 325 FP_TO_INT_S(vc.wp[1], SB, 32,
326 (((func & 0x3) != 0) || SB_s));
324 goto update_regs; 327 goto update_regs;
325 328
326 default: 329 default:
@@ -458,7 +461,8 @@ cmp_s:
458 } else { 461 } else {
459 _FP_ROUND_ZERO(2, DB); 462 _FP_ROUND_ZERO(2, DB);
460 } 463 }
461 FP_TO_INT_D(vc.wp[1], DB, 32, ((func & 0x3) != 0)); 464 FP_TO_INT_D(vc.wp[1], DB, 32,
465 (((func & 0x3) != 0) || DB_s));
462 goto update_regs; 466 goto update_regs;
463 467
464 default: 468 default:
@@ -589,8 +593,10 @@ cmp_d:
589 _FP_ROUND_ZERO(1, SB0); 593 _FP_ROUND_ZERO(1, SB0);
590 _FP_ROUND_ZERO(1, SB1); 594 _FP_ROUND_ZERO(1, SB1);
591 } 595 }
592 FP_TO_INT_S(vc.wp[0], SB0, 32, ((func & 0x3) != 0)); 596 FP_TO_INT_S(vc.wp[0], SB0, 32,
593 FP_TO_INT_S(vc.wp[1], SB1, 32, ((func & 0x3) != 0)); 597 (((func & 0x3) != 0) || SB0_s));
598 FP_TO_INT_S(vc.wp[1], SB1, 32,
599 (((func & 0x3) != 0) || SB1_s));
594 goto update_regs; 600 goto update_regs;
595 601
596 default: 602 default:
@@ -652,6 +658,15 @@ update_regs:
652 return 0; 658 return 0;
653 659
654illegal: 660illegal:
661 if (have_e500_cpu_a005_erratum) {
662 /* according to e500 cpu a005 erratum, reissue efp inst */
663 regs->nip -= 4;
664#ifdef DEBUG
665 printk(KERN_DEBUG "re-issue efp inst: %08lx\n", speinsn);
666#endif
667 return 0;
668 }
669
655 printk(KERN_ERR "\nOoops! IEEE-754 compliance handler encountered un-supported instruction.\ninst code: %08lx\n", speinsn); 670 printk(KERN_ERR "\nOoops! IEEE-754 compliance handler encountered un-supported instruction.\ninst code: %08lx\n", speinsn);
656 return -ENOSYS; 671 return -ENOSYS;
657} 672}
@@ -718,3 +733,43 @@ int speround_handler(struct pt_regs *regs)
718 733
719 return 0; 734 return 0;
720} 735}
736
737int __init spe_mathemu_init(void)
738{
739 u32 pvr, maj, min;
740
741 pvr = mfspr(SPRN_PVR);
742
743 if ((PVR_VER(pvr) == PVR_VER_E500V1) ||
744 (PVR_VER(pvr) == PVR_VER_E500V2)) {
745 maj = PVR_MAJ(pvr);
746 min = PVR_MIN(pvr);
747
748 /*
749 * E500 revision below 1.1, 2.3, 3.1, 4.1, 5.1
750 * need cpu a005 errata workaround
751 */
752 switch (maj) {
753 case 1:
754 if (min < 1)
755 have_e500_cpu_a005_erratum = 1;
756 break;
757 case 2:
758 if (min < 3)
759 have_e500_cpu_a005_erratum = 1;
760 break;
761 case 3:
762 case 4:
763 case 5:
764 if (min < 1)
765 have_e500_cpu_a005_erratum = 1;
766 break;
767 default:
768 break;
769 }
770 }
771
772 return 0;
773}
774
775module_init(spe_mathemu_init);