MN10300: Extract the displacement from an insn correctly in misalignment fixup
authorDavid Howells <dhowells@redhat.com>
Wed, 12 Nov 2008 15:35:14 +0000 (15:35 +0000)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 12 Nov 2008 18:41:17 +0000 (10:41 -0800)
Extract the displacement from an MN10300 instruction correctly in the
misalignment fixup handler.

The code should extract the displacement in LSB order, not MSB order.

Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
arch/mn10300/mm/misalignment.c

index ab03bac497cb041514639e937f1a022d7f603864..614c32b6325b52f3b167d0ca486b0d6b78fa85ad 100644 (file)
 #endif
 
 static int misalignment_addr(unsigned long *registers, unsigned params,
-                            unsigned opcode, unsigned disp,
+                            unsigned opcode, unsigned long disp,
                             void **_address, unsigned long **_postinc);
 
 static int misalignment_reg(unsigned long *registers, unsigned params,
-                           unsigned opcode, unsigned disp,
+                           unsigned opcode, unsigned long disp,
                            unsigned long **_register);
 
 static const unsigned Dreg_index[] = {
@@ -304,13 +304,13 @@ asmlinkage void misalignment(struct pt_regs *regs, enum exception_code code)
        const struct exception_table_entry *fixup;
        const struct mn10300_opcode *pop;
        unsigned long *registers = (unsigned long *) regs;
-       unsigned long data, *store, *postinc;
+       unsigned long data, *store, *postinc, disp;
        mm_segment_t seg;
        siginfo_t info;
-       uint32_t opcode, disp, noc, xo, xm;
+       uint32_t opcode, noc, xo, xm;
        uint8_t *pc, byte;
        void *address;
-       unsigned tmp, npop;
+       unsigned tmp, npop, dispsz, loop;
 
        kdebug("==>misalignment({pc=%lx})", regs->pc);
 
@@ -445,17 +445,17 @@ found_opcode:
 
        /* grab the extra displacement (note it's LSB first) */
        disp = 0;
-       tmp = format_tbl[pop->format].dispsz >> 3;
-       while (tmp > 0) {
-               tmp--;
-               disp <<= 8;
-
+       dispsz = format_tbl[pop->format].dispsz;
+       for (loop = 0; loop < dispsz; loop += 8) {
                pc++;
                if (__get_user(byte, pc) != 0)
                        goto fetch_error;
-               disp |= byte;
+               disp |= byte << loop;
+               kdebug("{%p} disp[%02x]=%02x", pc, loop, byte);
        }
 
+       kdebug("disp=%lx", disp);
+
        set_fs(KERNEL_XDS);
        if (fixup || regs->epsw & EPSW_nSL)
                set_fs(seg);
@@ -538,7 +538,7 @@ found_opcode:
  * determine the address that was being accessed
  */
 static int misalignment_addr(unsigned long *registers, unsigned params,
-                            unsigned opcode, unsigned disp,
+                            unsigned opcode, unsigned long disp,
                             void **_address, unsigned long **_postinc)
 {
        unsigned long *postinc = NULL, address = 0, tmp;
@@ -644,7 +644,7 @@ static int misalignment_addr(unsigned long *registers, unsigned params,
  * determine the register that is acting as source/dest
  */
 static int misalignment_reg(unsigned long *registers, unsigned params,
-                           unsigned opcode, unsigned disp,
+                           unsigned opcode, unsigned long disp,
                            unsigned long **_register)
 {
        params &= 0x7fffffff;