22 #include <linux/types.h>
24 #include <asm/uaccess.h>
27 #define FP_EX_BOOKE_E500_SPE
28 #include <asm/sfp-machine.h>
47 #define EFSCMPGT 0x2cc
48 #define EFSCMPLT 0x2cd
49 #define EFSCMPEQ 0x2ce
56 #define EFSCTUIZ 0x2d8
57 #define EFSCTSIZ 0x2da
62 #define EVFSNABS 0x285
66 #define EVFSCMPGT 0x28c
67 #define EVFSCMPLT 0x28d
68 #define EVFSCMPEQ 0x28e
69 #define EVFSCTUI 0x294
70 #define EVFSCTSI 0x295
71 #define EVFSCTUF 0x296
72 #define EVFSCTSF 0x297
73 #define EVFSCTUIZ 0x298
74 #define EVFSCTSIZ 0x29a
83 #define EFDCTUIDZ 0x2ea
84 #define EFDCTSIDZ 0x2eb
85 #define EFDCMPGT 0x2ec
86 #define EFDCMPLT 0x2ed
87 #define EFDCMPEQ 0x2ee
93 #define EFDCTUIZ 0x2f8
94 #define EFDCTSIZ 0x2fa
102 #define SIGN_BIT_S (1UL << 31)
103 #define SIGN_BIT_D (1ULL << 63)
104 #define FP_EX_MASK (FP_EX_INEXACT | FP_EX_INVALID | FP_EX_DIVZERO | \
105 FP_EX_UNDERFLOW | FP_EX_OVERFLOW)
107 static int have_e500_cpu_a005_erratum;
114 static unsigned long insn_type(
unsigned long speinsn)
118 switch (speinsn & 0x7ff) {
189 if ((speinsn >> 26) !=
EFAPU)
192 type = insn_type(speinsn);
196 func = speinsn & 0x7ff;
197 fc = (speinsn >> 21) & 0x1f;
198 fa = (speinsn >> 16) & 0x1f;
199 fb = (speinsn >> 11) & 0x1f;
200 src = (speinsn >> 5) & 0x7;
232 pr_debug(
"SA: %ld %08lx %ld (%ld)\n", SA_s, SA_f, SA_e, SA_c);
233 pr_debug(
"SB: %ld %08lx %ld (%ld)\n", SB_s, SB_f, SB_e, SB_c);
278 if (!((vb.
wp[1] >> 23) == 0xff && ((vb.
wp[1] & 0x7fffff) > 0))) {
280 if (((vb.
wp[1] >> 23) & 0xff) == 0) {
283 }
else if ((vb.
wp[1] >> 31) == 0) {
286 0x7fffffff : 0xffffffff;
301 pr_debug(
"DB: %ld %08lx %08lx %ld (%ld)\n",
302 DB_s, DB_f1, DB_f0, DB_e, DB_c);
318 (((func & 0x3) != 0) || SB_s));
327 pr_debug(
"SR: %ld %08lx %ld (%ld)\n", SR_s, SR_f, SR_e, SR_c);
359 pr_debug(
"DA: %ld %08lx %08lx %ld (%ld)\n",
360 DA_s, DA_f1, DA_f0, DA_e, DA_c);
361 pr_debug(
"DB: %ld %08lx %08lx %ld (%ld)\n",
362 DB_s, DB_f1, DB_f0, DB_e, DB_c);
407 if (!((vb.
wp[0] >> 20) == 0x7ff &&
408 ((vb.
wp[0] & 0xfffff) > 0 || (vb.
wp[1] > 0)))) {
410 if (((vb.
wp[0] >> 20) & 0x7ff) == 0) {
413 }
else if ((vb.
wp[0] >> 31) == 0) {
416 0x7fffffff : 0xffffffff;
431 pr_debug(
"SB: %ld %08lx %ld (%ld)\n",
432 SB_s, SB_f, SB_e, SB_c);
454 (((func & 0x3) != 0) || DB_s));
463 pr_debug(
"DR: %ld %08lx %08lx %ld (%ld)\n",
464 DR_s, DR_f1, DR_f0, DR_e, DR_c);
502 pr_debug(
"SA0: %ld %08lx %ld (%ld)\n",
503 SA0_s, SA0_f, SA0_e, SA0_c);
504 pr_debug(
"SA1: %ld %08lx %ld (%ld)\n",
505 SA1_s, SA1_f, SA1_e, SA1_c);
506 pr_debug(
"SB0: %ld %08lx %ld (%ld)\n",
507 SB0_s, SB0_f, SB0_e, SB0_c);
508 pr_debug(
"SB1: %ld %08lx %ld (%ld)\n",
509 SB1_s, SB1_f, SB1_e, SB1_c);
560 __asm__ __volatile__ (
"mtspr 512, %4\n"
563 :
"=r" (vc.
wp[0]),
"=r" (vc.
wp[1])
564 :
"r" (vb.
wp[0]),
"r" (vb.
wp[1]),
"r" (0));
568 __asm__ __volatile__ (
"mtspr 512, %4\n"
571 :
"=r" (vc.
wp[0]),
"=r" (vc.
wp[1])
572 :
"r" (vb.
wp[0]),
"r" (vb.
wp[1]),
"r" (0));
587 (((func & 0x3) != 0) || SB0_s));
589 (((func & 0x3) != 0) || SB1_s));
598 pr_debug(
"SR0: %ld %08lx %ld (%ld)\n",
599 SR0_s, SR0_f, SR0_e, SR0_c);
600 pr_debug(
"SR1: %ld %08lx %ld (%ld)\n",
601 SR1_s, SR1_f, SR1_e, SR1_c);
617 ch = (IR0 == cmp) ? 1 : 0;
618 cl = (IR1 == cmp) ? 1 : 0;
619 IR = (ch << 3) | (cl << 2) | ((ch |
cl) << 1) |
629 regs->
ccr &= ~(15 << ((7 - ((speinsn >> 23) & 0x7)) << 2));
630 regs->
ccr |= (IR << ((7 - ((speinsn >> 23) & 0x7)) << 2));
641 pr_debug(
"cur exceptions = %08x spefscr = %08lx\n",
650 if (have_e500_cpu_a005_erratum) {
653 pr_debug(
"re-issue efp inst: %08lx\n", speinsn);
657 printk(
KERN_ERR "\nOoops! IEEE-754 compliance handler encountered un-supported instruction.\ninst code: %08lx\n", speinsn);
665 unsigned long speinsn,
type,
fc;
669 if ((speinsn >> 26) != 4)
672 type = insn_type(speinsn & 0x7ff);
682 fc = (speinsn >> 21) & 0x1f;
688 pr_debug(
"round fgpr: %08x %08x\n", fgpr.
wp[0], fgpr.
wp[1]);
690 switch ((speinsn >> 5) & 0x7) {
697 if (!s_lo) fgpr.
wp[1]++;
699 if (s_lo) fgpr.
wp[1]++;
705 if (!s_hi) fgpr.
dp[0]++;
707 if (s_hi) fgpr.
dp[0]++;
713 if (!s_lo) fgpr.
wp[1]++;
714 if (!s_hi) fgpr.
wp[0]++;
716 if (s_lo) fgpr.
wp[1]++;
717 if (s_hi) fgpr.
wp[0]++;
728 pr_debug(
" to fgpr: %08x %08x\n", fgpr.
wp[0], fgpr.
wp[1]);
739 if ((
PVR_VER(pvr) == PVR_VER_E500V1) ||
740 (
PVR_VER(pvr) == PVR_VER_E500V2)) {
751 have_e500_cpu_a005_erratum = 1;
755 have_e500_cpu_a005_erratum = 1;
761 have_e500_cpu_a005_erratum = 1;