]> git.hungrycats.org Git - linux/commitdiff
PPC32: Update the alignment exception handler for POWER4 processors
authorPaul Mackerras <paulus@samba.org>
Sat, 6 Sep 2003 07:54:39 +0000 (17:54 +1000)
committerPaul Mackerras <paulus@samba.org>
Sat, 6 Sep 2003 07:54:39 +0000 (17:54 +1000)
arch/ppc/kernel/align.c

index ed5a13ca643f611e5a9a0c8626b3b48bbfaefaa1..d942c318675df3628ff4d817bb7cbd8a016a7446 100644 (file)
@@ -21,11 +21,11 @@ struct aligninfo {
        unsigned char flags;
 };
 
-#if defined(CONFIG_4xx)
+#if defined(CONFIG_4xx) || defined(CONFIG_POWER4)
 #define        OPCD(inst)      (((inst) & 0xFC000000) >> 26)
 #define        RS(inst)        (((inst) & 0x03E00000) >> 21)
 #define        RA(inst)        (((inst) & 0x001F0000) >> 16)
-#define        IS_DFORM(code)  ((code) >= 32 && (code) <= 55)
+#define        IS_XFORM(code)  ((code) == 31)
 #endif
 
 #define INVALID        { 0, 0 }
@@ -61,9 +61,9 @@ static struct aligninfo aligninfo[128] = {
        { 4, ST+F+S },          /* 00 0 1010: stfs */
        { 8, ST+F },            /* 00 0 1011: stfd */
        INVALID,                /* 00 0 1100 */
-       INVALID,                /* 00 0 1101 */
+       INVALID,                /* 00 0 1101: ld/ldu/lwa */
        INVALID,                /* 00 0 1110 */
-       INVALID,                /* 00 0 1111 */
+       INVALID,                /* 00 0 1111: std/stdu */
        { 4, LD+U },            /* 00 1 0000: lwzu */
        INVALID,                /* 00 1 0001 */
        { 4, ST+U },            /* 00 1 0010: stwu */
@@ -80,12 +80,12 @@ static struct aligninfo aligninfo[128] = {
        INVALID,                /* 00 1 1101 */
        INVALID,                /* 00 1 1110 */
        INVALID,                /* 00 1 1111 */
-       INVALID,                /* 01 0 0000 */
+       INVALID,                /* 01 0 0000: ldx */
        INVALID,                /* 01 0 0001 */
-       INVALID,                /* 01 0 0010 */
+       INVALID,                /* 01 0 0010: stdx */
        INVALID,                /* 01 0 0011 */
        INVALID,                /* 01 0 0100 */
-       INVALID,                /* 01 0 0101: lwax?? */
+       INVALID,                /* 01 0 0101: lwax */
        INVALID,                /* 01 0 0110 */
        INVALID,                /* 01 0 0111 */
        { 0, LD+HARD },         /* 01 0 1000: lswx */
@@ -96,12 +96,12 @@ static struct aligninfo aligninfo[128] = {
        INVALID,                /* 01 0 1101 */
        INVALID,                /* 01 0 1110 */
        INVALID,                /* 01 0 1111 */
-       INVALID,                /* 01 1 0000 */
+       INVALID,                /* 01 1 0000: ldux */
        INVALID,                /* 01 1 0001 */
-       INVALID,                /* 01 1 0010 */
+       INVALID,                /* 01 1 0010: stdux */
        INVALID,                /* 01 1 0011 */
        INVALID,                /* 01 1 0100 */
-       INVALID,                /* 01 1 0101: lwaux?? */
+       INVALID,                /* 01 1 0101: lwaux */
        INVALID,                /* 01 1 0110 */
        INVALID,                /* 01 1 0111 */
        INVALID,                /* 01 1 1000 */
@@ -157,9 +157,9 @@ static struct aligninfo aligninfo[128] = {
        { 4, ST+F+S },          /* 11 0 1010: stfsx */
        { 8, ST+F },            /* 11 0 1011: stfdx */
        INVALID,                /* 11 0 1100 */
-       INVALID,                /* 11 0 1101 */
+       INVALID,                /* 11 0 1101: lmd */
        INVALID,                /* 11 0 1110 */
-       INVALID,                /* 11 0 1111 */
+       INVALID,                /* 11 0 1111: stmd */
        { 4, LD+U },            /* 11 1 0000: lwzux */
        INVALID,                /* 11 1 0001 */
        { 4, ST+U },            /* 11 1 0010: stwux */
@@ -184,7 +184,7 @@ int
 fix_alignment(struct pt_regs *regs)
 {
        int instr, nb, flags;
-#if defined(CONFIG_4xx)
+#if defined(CONFIG_4xx) || defined(CONFIG_POWER4)
        int opcode, f1, f2, f3;
 #endif
        int i, t;
@@ -199,9 +199,11 @@ fix_alignment(struct pt_regs *regs)
 
        CHECK_FULL_REGS(regs);
 
-#if defined(CONFIG_4xx)
+#if defined(CONFIG_4xx) || defined(CONFIG_POWER4)
        /* The 4xx-family processors have no DSISR register,
         * so we emulate it.
+        * The POWER4 has a DSISR register but doesn't set it on
+        * an alignment fault.  -- paulus
         */
 
        instr = *((unsigned int *)regs->nip);
@@ -209,7 +211,7 @@ fix_alignment(struct pt_regs *regs)
        reg = RS(instr);
        areg = RA(instr);
 
-       if (IS_DFORM(opcode)) {
+       if (!IS_XFORM(opcode)) {
                f1 = 0;
                f2 = (instr & 0x04000000) >> 26;
                f3 = (instr & 0x78000000) >> 27;