linux/arch/mn10300/mm/misalignment.c
<<
>>
Prefs
   1/* MN10300 Misalignment fixup handler
   2 *
   3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
   4 * Written by David Howells (dhowells@redhat.com)
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public Licence
   8 * as published by the Free Software Foundation; either version
   9 * 2 of the Licence, or (at your option) any later version.
  10 */
  11#include <linux/module.h>
  12#include <linux/sched.h>
  13#include <linux/kernel.h>
  14#include <linux/string.h>
  15#include <linux/errno.h>
  16#include <linux/ptrace.h>
  17#include <linux/timer.h>
  18#include <linux/mm.h>
  19#include <linux/smp.h>
  20#include <linux/init.h>
  21#include <linux/delay.h>
  22#include <linux/spinlock.h>
  23#include <linux/interrupt.h>
  24#include <linux/pci.h>
  25#include <asm/processor.h>
  26#include <asm/system.h>
  27#include <asm/uaccess.h>
  28#include <asm/io.h>
  29#include <asm/atomic.h>
  30#include <asm/smp.h>
  31#include <asm/pgalloc.h>
  32#include <asm/cpu-regs.h>
  33#include <asm/busctl-regs.h>
  34#include <asm/fpu.h>
  35#include <asm/gdb-stub.h>
  36#include <asm/asm-offsets.h>
  37
  38#if 0
  39#define kdebug(FMT, ...) printk(KERN_DEBUG "MISALIGN: "FMT"\n", ##__VA_ARGS__)
  40#else
  41#define kdebug(FMT, ...) do {} while (0)
  42#endif
  43
  44static int misalignment_addr(unsigned long *registers, unsigned long sp,
  45                             unsigned params, unsigned opcode,
  46                             unsigned long disp,
  47                             void **_address, unsigned long **_postinc,
  48                             unsigned long *_inc);
  49
  50static int misalignment_reg(unsigned long *registers, unsigned params,
  51                            unsigned opcode, unsigned long disp,
  52                            unsigned long **_register);
  53
  54static void misalignment_MOV_Lcc(struct pt_regs *regs, uint32_t opcode);
  55
  56static const unsigned Dreg_index[] = {
  57        REG_D0 >> 2, REG_D1 >> 2, REG_D2 >> 2, REG_D3 >> 2
  58};
  59
  60static const unsigned Areg_index[] = {
  61        REG_A0 >> 2, REG_A1 >> 2, REG_A2 >> 2, REG_A3 >> 2
  62};
  63
  64static const unsigned Rreg_index[] = {
  65        REG_E0 >> 2, REG_E1 >> 2, REG_E2 >> 2, REG_E3 >> 2,
  66        REG_E4 >> 2, REG_E5 >> 2, REG_E6 >> 2, REG_E7 >> 2,
  67        REG_A0 >> 2, REG_A1 >> 2, REG_A2 >> 2, REG_A3 >> 2,
  68        REG_D0 >> 2, REG_D1 >> 2, REG_D2 >> 2, REG_D3 >> 2
  69};
  70
  71enum format_id {
  72        FMT_S0,
  73        FMT_S1,
  74        FMT_S2,
  75        FMT_S4,
  76        FMT_D0,
  77        FMT_D1,
  78        FMT_D2,
  79        FMT_D4,
  80        FMT_D6,
  81        FMT_D7,
  82        FMT_D8,
  83        FMT_D9,
  84        FMT_D10,
  85};
  86
  87static const struct {
  88        u_int8_t opsz, dispsz;
  89} format_tbl[16] = {
  90        [FMT_S0]        = { 8,  0       },
  91        [FMT_S1]        = { 8,  8       },
  92        [FMT_S2]        = { 8,  16      },
  93        [FMT_S4]        = { 8,  32      },
  94        [FMT_D0]        = { 16, 0       },
  95        [FMT_D1]        = { 16, 8       },
  96        [FMT_D2]        = { 16, 16      },
  97        [FMT_D4]        = { 16, 32      },
  98        [FMT_D6]        = { 24, 0       },
  99        [FMT_D7]        = { 24, 8       },
 100        [FMT_D8]        = { 24, 24      },
 101        [FMT_D9]        = { 24, 32      },
 102        [FMT_D10]       = { 32, 0       },
 103};
 104
 105enum value_id {
 106        DM0,            /* data reg in opcode in bits 0-1 */
 107        DM1,            /* data reg in opcode in bits 2-3 */
 108        DM2,            /* data reg in opcode in bits 4-5 */
 109        AM0,            /* addr reg in opcode in bits 0-1 */
 110        AM1,            /* addr reg in opcode in bits 2-3 */
 111        AM2,            /* addr reg in opcode in bits 4-5 */
 112        RM0,            /* reg in opcode in bits 0-3 */
 113        RM1,            /* reg in opcode in bits 2-5 */
 114        RM2,            /* reg in opcode in bits 4-7 */
 115        RM4,            /* reg in opcode in bits 8-11 */
 116        RM6,            /* reg in opcode in bits 12-15 */
 117
 118        RD0,            /* reg in displacement in bits 0-3 */
 119        RD2,            /* reg in displacement in bits 4-7 */
 120
 121        SP,             /* stack pointer */
 122
 123        SD8,            /* 8-bit signed displacement */
 124        SD16,           /* 16-bit signed displacement */
 125        SD24,           /* 24-bit signed displacement */
 126        SIMM4_2,        /* 4-bit signed displacement in opcode bits 4-7 */
 127        SIMM8,          /* 8-bit signed immediate */
 128        IMM8,           /* 8-bit unsigned immediate */
 129        IMM16,          /* 16-bit unsigned immediate */
 130        IMM24,          /* 24-bit unsigned immediate */
 131        IMM32,          /* 32-bit unsigned immediate */
 132        IMM32_HIGH8,    /* 32-bit unsigned immediate, LSB in opcode */
 133
 134        IMM32_MEM,      /* 32-bit unsigned displacement */
 135        IMM32_HIGH8_MEM, /* 32-bit unsigned displacement, LSB in opcode */
 136
 137        DN0     = DM0,
 138        DN1     = DM1,
 139        DN2     = DM2,
 140        AN0     = AM0,
 141        AN1     = AM1,
 142        AN2     = AM2,
 143        RN0     = RM0,
 144        RN1     = RM1,
 145        RN2     = RM2,
 146        RN4     = RM4,
 147        RN6     = RM6,
 148        DI      = DM1,
 149        RI      = RM2,
 150
 151};
 152
 153struct mn10300_opcode {
 154        const char      name[8];
 155        u_int32_t       opcode;
 156        u_int32_t       opmask;
 157        unsigned        exclusion;
 158
 159        enum format_id  format;
 160
 161        unsigned        cpu_mask;
 162#define AM33    330
 163
 164        unsigned        params[2];
 165#define MEM(ADDR)               (0x80000000 | (ADDR))
 166#define MEM2(ADDR1, ADDR2)      (0x80000000 | (ADDR1) << 8 | (ADDR2))
 167#define MEMINC(ADDR)            (0x81000000 | (ADDR))
 168#define MEMINC2(ADDR, INC)      (0x81000000 | (ADDR) << 8 | (INC))
 169};
 170
 171/* LIBOPCODES EXCERPT
 172   Assemble Matsushita MN10300 instructions.
 173   Copyright 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
 174
 175   This program is free software; you can redistribute it and/or modify
 176   it under the terms of the GNU General Public Licence as published by
 177   the Free Software Foundation; either version 2 of the Licence, or
 178   (at your option) any later version.
 179
 180   This program is distributed in the hope that it will be useful,
 181   but WITHOUT ANY WARRANTY; without even the implied warranty of
 182   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 183   GNU General Public Licence for more details.
 184
 185   You should have received a copy of the GNU General Public Licence
 186   along with this program; if not, write to the Free Software
 187   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 188*/
 189static const struct mn10300_opcode mn10300_opcodes[] = {
 190{ "mov",        0x4200,      0xf300,      0,    FMT_S1, 0,      {DM1, MEM2(IMM8, SP)}},
 191{ "mov",        0x4300,      0xf300,      0,    FMT_S1, 0,      {AM1, MEM2(IMM8, SP)}},
 192{ "mov",        0x5800,      0xfc00,      0,    FMT_S1, 0,      {MEM2(IMM8, SP), DN0}},
 193{ "mov",        0x5c00,      0xfc00,      0,    FMT_S1, 0,      {MEM2(IMM8, SP), AN0}},
 194{ "mov",        0x60,        0xf0,        0,    FMT_S0, 0,      {DM1, MEM(AN0)}},
 195{ "mov",        0x70,        0xf0,        0,    FMT_S0, 0,      {MEM(AM0), DN1}},
 196{ "mov",        0xf000,      0xfff0,      0,    FMT_D0, 0,      {MEM(AM0), AN1}},
 197{ "mov",        0xf010,      0xfff0,      0,    FMT_D0, 0,      {AM1, MEM(AN0)}},
 198{ "mov",        0xf300,      0xffc0,      0,    FMT_D0, 0,      {MEM2(DI, AM0), DN2}},
 199{ "mov",        0xf340,      0xffc0,      0,    FMT_D0, 0,      {DM2, MEM2(DI, AN0)}},
 200{ "mov",        0xf380,      0xffc0,      0,    FMT_D0, 0,      {MEM2(DI, AM0), AN2}},
 201{ "mov",        0xf3c0,      0xffc0,      0,    FMT_D0, 0,      {AM2, MEM2(DI, AN0)}},
 202{ "mov",        0xf80000,    0xfff000,    0,    FMT_D1, 0,      {MEM2(SD8, AM0), DN1}},
 203{ "mov",        0xf81000,    0xfff000,    0,    FMT_D1, 0,      {DM1, MEM2(SD8, AN0)}},
 204{ "mov",        0xf82000,    0xfff000,    0,    FMT_D1, 0,      {MEM2(SD8,AM0), AN1}},
 205{ "mov",        0xf83000,    0xfff000,    0,    FMT_D1, 0,      {AM1, MEM2(SD8, AN0)}},
 206{ "mov",        0xf90a00,    0xffff00,    0,    FMT_D6, AM33,   {MEM(RM0), RN2}},
 207{ "mov",        0xf91a00,    0xffff00,    0,    FMT_D6, AM33,   {RM2, MEM(RN0)}},
 208{ "mov",        0xf96a00,    0xffff00,    0x12, FMT_D6, AM33,   {MEMINC(RM0), RN2}},
 209{ "mov",        0xf97a00,    0xffff00,    0,    FMT_D6, AM33,   {RM2, MEMINC(RN0)}},
 210{ "mov",        0xfa000000,  0xfff00000,  0,    FMT_D2, 0,      {MEM2(SD16, AM0), DN1}},
 211{ "mov",        0xfa100000,  0xfff00000,  0,    FMT_D2, 0,      {DM1, MEM2(SD16, AN0)}},
 212{ "mov",        0xfa200000,  0xfff00000,  0,    FMT_D2, 0,      {MEM2(SD16, AM0), AN1}},
 213{ "mov",        0xfa300000,  0xfff00000,  0,    FMT_D2, 0,      {AM1, MEM2(SD16, AN0)}},
 214{ "mov",        0xfa900000,  0xfff30000,  0,    FMT_D2, 0,      {AM1, MEM2(IMM16, SP)}},
 215{ "mov",        0xfa910000,  0xfff30000,  0,    FMT_D2, 0,      {DM1, MEM2(IMM16, SP)}},
 216{ "mov",        0xfab00000,  0xfffc0000,  0,    FMT_D2, 0,      {MEM2(IMM16, SP), AN0}},
 217{ "mov",        0xfab40000,  0xfffc0000,  0,    FMT_D2, 0,      {MEM2(IMM16, SP), DN0}},
 218{ "mov",        0xfb0a0000,  0xffff0000,  0,    FMT_D7, AM33,   {MEM2(SD8, RM0), RN2}},
 219{ "mov",        0xfb1a0000,  0xffff0000,  0,    FMT_D7, AM33,   {RM2, MEM2(SD8, RN0)}},
 220{ "mov",        0xfb6a0000,  0xffff0000,  0x22, FMT_D7, AM33,   {MEMINC2 (RM0, SIMM8), RN2}},
 221{ "mov",        0xfb7a0000,  0xffff0000,  0,    FMT_D7, AM33,   {RM2, MEMINC2 (RN0, SIMM8)}},
 222{ "mov",        0xfb8a0000,  0xffff0f00,  0,    FMT_D7, AM33,   {MEM2(IMM8, SP), RN2}},
 223{ "mov",        0xfb8e0000,  0xffff000f,  0,    FMT_D7, AM33,   {MEM2(RI, RM0), RD2}},
 224{ "mov",        0xfb9a0000,  0xffff0f00,  0,    FMT_D7, AM33,   {RM2, MEM2(IMM8, SP)}},
 225{ "mov",        0xfb9e0000,  0xffff000f,  0,    FMT_D7, AM33,   {RD2, MEM2(RI, RN0)}},
 226{ "mov",        0xfc000000,  0xfff00000,  0,    FMT_D4, 0,      {MEM2(IMM32,AM0), DN1}},
 227{ "mov",        0xfc100000,  0xfff00000,  0,    FMT_D4, 0,      {DM1, MEM2(IMM32,AN0)}},
 228{ "mov",        0xfc200000,  0xfff00000,  0,    FMT_D4, 0,      {MEM2(IMM32,AM0), AN1}},
 229{ "mov",        0xfc300000,  0xfff00000,  0,    FMT_D4, 0,      {AM1, MEM2(IMM32,AN0)}},
 230{ "mov",        0xfc800000,  0xfff30000,  0,    FMT_D4, 0,      {AM1, MEM(IMM32_MEM)}},
 231{ "mov",        0xfc810000,  0xfff30000,  0,    FMT_D4, 0,      {DM1, MEM(IMM32_MEM)}},
 232{ "mov",        0xfc900000,  0xfff30000,  0,    FMT_D4, 0,      {AM1, MEM2(IMM32, SP)}},
 233{ "mov",        0xfc910000,  0xfff30000,  0,    FMT_D4, 0,      {DM1, MEM2(IMM32, SP)}},
 234{ "mov",        0xfca00000,  0xfffc0000,  0,    FMT_D4, 0,      {MEM(IMM32_MEM), AN0}},
 235{ "mov",        0xfca40000,  0xfffc0000,  0,    FMT_D4, 0,      {MEM(IMM32_MEM), DN0}},
 236{ "mov",        0xfcb00000,  0xfffc0000,  0,    FMT_D4, 0,      {MEM2(IMM32, SP), AN0}},
 237{ "mov",        0xfcb40000,  0xfffc0000,  0,    FMT_D4, 0,      {MEM2(IMM32, SP), DN0}},
 238{ "mov",        0xfd0a0000,  0xffff0000,  0,    FMT_D8, AM33,   {MEM2(SD24, RM0), RN2}},
 239{ "mov",        0xfd1a0000,  0xffff0000,  0,    FMT_D8, AM33,   {RM2, MEM2(SD24, RN0)}},
 240{ "mov",        0xfd6a0000,  0xffff0000,  0x22, FMT_D8, AM33,   {MEMINC2 (RM0, IMM24), RN2}},
 241{ "mov",        0xfd7a0000,  0xffff0000,  0,    FMT_D8, AM33,   {RM2, MEMINC2 (RN0, IMM24)}},
 242{ "mov",        0xfd8a0000,  0xffff0f00,  0,    FMT_D8, AM33,   {MEM2(IMM24, SP), RN2}},
 243{ "mov",        0xfd9a0000,  0xffff0f00,  0,    FMT_D8, AM33,   {RM2, MEM2(IMM24, SP)}},
 244{ "mov",        0xfe0a0000,  0xffff0000,  0,    FMT_D9, AM33,   {MEM2(IMM32_HIGH8,RM0), RN2}},
 245{ "mov",        0xfe0a0000,  0xffff0000,  0,    FMT_D9, AM33,   {MEM2(IMM32_HIGH8,RM0), RN2}},
 246{ "mov",        0xfe0e0000,  0xffff0f00,  0,    FMT_D9, AM33,   {MEM(IMM32_HIGH8_MEM), RN2}},
 247{ "mov",        0xfe1a0000,  0xffff0000,  0,    FMT_D9, AM33,   {RM2, MEM2(IMM32_HIGH8, RN0)}},
 248{ "mov",        0xfe1a0000,  0xffff0000,  0,    FMT_D9, AM33,   {RM2, MEM2(IMM32_HIGH8, RN0)}},
 249{ "mov",        0xfe1e0000,  0xffff0f00,  0,    FMT_D9, AM33,   {RM2, MEM(IMM32_HIGH8_MEM)}},
 250{ "mov",        0xfe6a0000,  0xffff0000,  0x22, FMT_D9, AM33,   {MEMINC2 (RM0, IMM32_HIGH8), RN2}},
 251{ "mov",        0xfe7a0000,  0xffff0000,  0,    FMT_D9, AM33,   {RN2, MEMINC2 (RM0, IMM32_HIGH8)}},
 252{ "mov",        0xfe8a0000,  0xffff0f00,  0,    FMT_D9, AM33,   {MEM2(IMM32_HIGH8, SP), RN2}},
 253{ "mov",        0xfe9a0000,  0xffff0f00,  0,    FMT_D9, AM33,   {RM2, MEM2(IMM32_HIGH8, SP)}},
 254
 255{ "movhu",      0xf060,      0xfff0,      0,    FMT_D0, 0,      {MEM(AM0), DN1}},
 256{ "movhu",      0xf070,      0xfff0,      0,    FMT_D0, 0,      {DM1, MEM(AN0)}},
 257{ "movhu",      0xf480,      0xffc0,      0,    FMT_D0, 0,      {MEM2(DI, AM0), DN2}},
 258{ "movhu",      0xf4c0,      0xffc0,      0,    FMT_D0, 0,      {DM2, MEM2(DI, AN0)}},
 259{ "movhu",      0xf86000,    0xfff000,    0,    FMT_D1, 0,      {MEM2(SD8, AM0), DN1}},
 260{ "movhu",      0xf87000,    0xfff000,    0,    FMT_D1, 0,      {DM1, MEM2(SD8, AN0)}},
 261{ "movhu",      0xf89300,    0xfff300,    0,    FMT_D1, 0,      {DM1, MEM2(IMM8, SP)}},
 262{ "movhu",      0xf8bc00,    0xfffc00,    0,    FMT_D1, 0,      {MEM2(IMM8, SP), DN0}},
 263{ "movhu",      0xf94a00,    0xffff00,    0,    FMT_D6, AM33,   {MEM(RM0), RN2}},
 264{ "movhu",      0xf95a00,    0xffff00,    0,    FMT_D6, AM33,   {RM2, MEM(RN0)}},
 265{ "movhu",      0xf9ea00,    0xffff00,    0x12, FMT_D6, AM33,   {MEMINC(RM0), RN2}},
 266{ "movhu",      0xf9fa00,    0xffff00,    0,    FMT_D6, AM33,   {RM2, MEMINC(RN0)}},
 267{ "movhu",      0xfa600000,  0xfff00000,  0,    FMT_D2, 0,      {MEM2(SD16, AM0), DN1}},
 268{ "movhu",      0xfa700000,  0xfff00000,  0,    FMT_D2, 0,      {DM1, MEM2(SD16, AN0)}},
 269{ "movhu",      0xfa930000,  0xfff30000,  0,    FMT_D2, 0,      {DM1, MEM2(IMM16, SP)}},
 270{ "movhu",      0xfabc0000,  0xfffc0000,  0,    FMT_D2, 0,      {MEM2(IMM16, SP), DN0}},
 271{ "movhu",      0xfb4a0000,  0xffff0000,  0,    FMT_D7, AM33,   {MEM2(SD8, RM0), RN2}},
 272{ "movhu",      0xfb5a0000,  0xffff0000,  0,    FMT_D7, AM33,   {RM2, MEM2(SD8, RN0)}},
 273{ "movhu",      0xfbca0000,  0xffff0f00,  0,    FMT_D7, AM33,   {MEM2(IMM8, SP), RN2}},
 274{ "movhu",      0xfbce0000,  0xffff000f,  0,    FMT_D7, AM33,   {MEM2(RI, RM0), RD2}},
 275{ "movhu",      0xfbda0000,  0xffff0f00,  0,    FMT_D7, AM33,   {RM2, MEM2(IMM8, SP)}},
 276{ "movhu",      0xfbde0000,  0xffff000f,  0,    FMT_D7, AM33,   {RD2, MEM2(RI, RN0)}},
 277{ "movhu",      0xfbea0000,  0xffff0000,  0x22, FMT_D7, AM33,   {MEMINC2 (RM0, SIMM8), RN2}},
 278{ "movhu",      0xfbfa0000,  0xffff0000,  0,    FMT_D7, AM33,   {RM2, MEMINC2 (RN0, SIMM8)}},
 279{ "movhu",      0xfc600000,  0xfff00000,  0,    FMT_D4, 0,      {MEM2(IMM32,AM0), DN1}},
 280{ "movhu",      0xfc700000,  0xfff00000,  0,    FMT_D4, 0,      {DM1, MEM2(IMM32,AN0)}},
 281{ "movhu",      0xfc830000,  0xfff30000,  0,    FMT_D4, 0,      {DM1, MEM(IMM32_MEM)}},
 282{ "movhu",      0xfc930000,  0xfff30000,  0,    FMT_D4, 0,      {DM1, MEM2(IMM32, SP)}},
 283{ "movhu",      0xfcac0000,  0xfffc0000,  0,    FMT_D4, 0,      {MEM(IMM32_MEM), DN0}},
 284{ "movhu",      0xfcbc0000,  0xfffc0000,  0,    FMT_D4, 0,      {MEM2(IMM32, SP), DN0}},
 285{ "movhu",      0xfd4a0000,  0xffff0000,  0,    FMT_D8, AM33,   {MEM2(SD24, RM0), RN2}},
 286{ "movhu",      0xfd5a0000,  0xffff0000,  0,    FMT_D8, AM33,   {RM2, MEM2(SD24, RN0)}},
 287{ "movhu",      0xfdca0000,  0xffff0f00,  0,    FMT_D8, AM33,   {MEM2(IMM24, SP), RN2}},
 288{ "movhu",      0xfdda0000,  0xffff0f00,  0,    FMT_D8, AM33,   {RM2, MEM2(IMM24, SP)}},
 289{ "movhu",      0xfdea0000,  0xffff0000,  0x22, FMT_D8, AM33,   {MEMINC2 (RM0, IMM24), RN2}},
 290{ "movhu",      0xfdfa0000,  0xffff0000,  0,    FMT_D8, AM33,   {RM2, MEMINC2 (RN0, IMM24)}},
 291{ "movhu",      0xfe4a0000,  0xffff0000,  0,    FMT_D9, AM33,   {MEM2(IMM32_HIGH8,RM0), RN2}},
 292{ "movhu",      0xfe4e0000,  0xffff0f00,  0,    FMT_D9, AM33,   {MEM(IMM32_HIGH8_MEM), RN2}},
 293{ "movhu",      0xfe5a0000,  0xffff0000,  0,    FMT_D9, AM33,   {RM2, MEM2(IMM32_HIGH8, RN0)}},
 294{ "movhu",      0xfe5e0000,  0xffff0f00,  0,    FMT_D9, AM33,   {RM2, MEM(IMM32_HIGH8_MEM)}},
 295{ "movhu",      0xfeca0000,  0xffff0f00,  0,    FMT_D9, AM33,   {MEM2(IMM32_HIGH8, SP), RN2}},
 296{ "movhu",      0xfeda0000,  0xffff0f00,  0,    FMT_D9, AM33,   {RM2, MEM2(IMM32_HIGH8, SP)}},
 297{ "movhu",      0xfeea0000,  0xffff0000,  0x22, FMT_D9, AM33,   {MEMINC2 (RM0, IMM32_HIGH8), RN2}},
 298{ "movhu",      0xfefa0000,  0xffff0000,  0,    FMT_D9, AM33,   {RN2, MEMINC2 (RM0, IMM32_HIGH8)}},
 299
 300{ "mov_llt",    0xf7e00000,  0xffff000f,  0x22, FMT_D10, AM33,   {MEMINC2 (RN4,SIMM4_2), RM6}},
 301{ "mov_lgt",    0xf7e00001,  0xffff000f,  0x22, FMT_D10, AM33,   {MEMINC2 (RN4,SIMM4_2), RM6}},
 302{ "mov_lge",    0xf7e00002,  0xffff000f,  0x22, FMT_D10, AM33,   {MEMINC2 (RN4,SIMM4_2), RM6}},
 303{ "mov_lle",    0xf7e00003,  0xffff000f,  0x22, FMT_D10, AM33,   {MEMINC2 (RN4,SIMM4_2), RM6}},
 304{ "mov_lcs",    0xf7e00004,  0xffff000f,  0x22, FMT_D10, AM33,   {MEMINC2 (RN4,SIMM4_2), RM6}},
 305{ "mov_lhi",    0xf7e00005,  0xffff000f,  0x22, FMT_D10, AM33,   {MEMINC2 (RN4,SIMM4_2), RM6}},
 306{ "mov_lcc",    0xf7e00006,  0xffff000f,  0x22, FMT_D10, AM33,   {MEMINC2 (RN4,SIMM4_2), RM6}},
 307{ "mov_lls",    0xf7e00007,  0xffff000f,  0x22, FMT_D10, AM33,   {MEMINC2 (RN4,SIMM4_2), RM6}},
 308{ "mov_leq",    0xf7e00008,  0xffff000f,  0x22, FMT_D10, AM33,   {MEMINC2 (RN4,SIMM4_2), RM6}},
 309{ "mov_lne",    0xf7e00009,  0xffff000f,  0x22, FMT_D10, AM33,   {MEMINC2 (RN4,SIMM4_2), RM6}},
 310{ "mov_lra",    0xf7e0000a,  0xffff000f,  0x22, FMT_D10, AM33,   {MEMINC2 (RN4,SIMM4_2), RM6}},
 311
 312{ "", 0, 0, 0, 0, 0, {0}},
 313};
 314
 315/*
 316 * fix up misalignment problems where possible
 317 */
 318asmlinkage void misalignment(struct pt_regs *regs, enum exception_code code)
 319{
 320        const struct exception_table_entry *fixup;
 321        const struct mn10300_opcode *pop;
 322        unsigned long *registers = (unsigned long *) regs;
 323        unsigned long data, *store, *postinc, disp, inc, sp;
 324        mm_segment_t seg;
 325        siginfo_t info;
 326        uint32_t opcode, noc, xo, xm;
 327        uint8_t *pc, byte, datasz;
 328        void *address;
 329        unsigned tmp, npop, dispsz, loop;
 330
 331        /* we don't fix up userspace misalignment faults */
 332        if (user_mode(regs))
 333                goto bus_error;
 334
 335        sp = (unsigned long) regs + sizeof(*regs);
 336
 337        kdebug("==>misalignment({pc=%lx,sp=%lx})", regs->pc, sp);
 338
 339        if (regs->epsw & EPSW_IE)
 340                asm volatile("or %0,epsw" : : "i"(EPSW_IE));
 341
 342        seg = get_fs();
 343        set_fs(KERNEL_DS);
 344
 345        fixup = search_exception_tables(regs->pc);
 346
 347        /* first thing to do is to match the opcode */
 348        pc = (u_int8_t *) regs->pc;
 349
 350        if (__get_user(byte, pc) != 0)
 351                goto fetch_error;
 352        opcode = byte;
 353        noc = 8;
 354
 355        for (pop = mn10300_opcodes; pop->name[0]; pop++) {
 356                npop = ilog2(pop->opcode | pop->opmask);
 357                if (npop <= 0 || npop > 31)
 358                        continue;
 359                npop = (npop + 8) & ~7;
 360
 361        got_more_bits:
 362                if (npop == noc) {
 363                        if ((opcode & pop->opmask) == pop->opcode)
 364                                goto found_opcode;
 365                } else if (npop > noc) {
 366                        xo = pop->opcode >> (npop - noc);
 367                        xm = pop->opmask >> (npop - noc);
 368
 369                        if ((opcode & xm) != xo)
 370                                continue;
 371
 372                        /* we've got a partial match (an exact match on the
 373                         * first N bytes), so we need to get some more data */
 374                        pc++;
 375                        if (__get_user(byte, pc) != 0)
 376                                goto fetch_error;
 377                        opcode = opcode << 8 | byte;
 378                        noc += 8;
 379                        goto got_more_bits;
 380                } else {
 381                        /* there's already been a partial match as long as the
 382                         * complete match we're now considering, so this one
 383                         * should't match */
 384                        continue;
 385                }
 386        }
 387
 388        /* didn't manage to find a fixup */
 389        printk(KERN_CRIT "MISALIGN: %lx: unsupported instruction %x\n",
 390               regs->pc, opcode);
 391
 392failed:
 393        set_fs(seg);
 394        if (die_if_no_fixup("misalignment error", regs, code))
 395                return;
 396
 397bus_error:
 398        info.si_signo   = SIGBUS;
 399        info.si_errno   = 0;
 400        info.si_code    = BUS_ADRALN;
 401        info.si_addr    = (void *) regs->pc;
 402        force_sig_info(SIGBUS, &info, current);
 403        return;
 404
 405        /* error reading opcodes */
 406fetch_error:
 407        printk(KERN_CRIT
 408               "MISALIGN: %p: fault whilst reading instruction data\n",
 409               pc);
 410        goto failed;
 411
 412bad_addr_mode:
 413        printk(KERN_CRIT
 414               "MISALIGN: %lx: unsupported addressing mode %x\n",
 415               regs->pc, opcode);
 416        goto failed;
 417
 418bad_reg_mode:
 419        printk(KERN_CRIT
 420               "MISALIGN: %lx: unsupported register mode %x\n",
 421               regs->pc, opcode);
 422        goto failed;
 423
 424unsupported_instruction:
 425        printk(KERN_CRIT
 426               "MISALIGN: %lx: unsupported instruction %x (%s)\n",
 427               regs->pc, opcode, pop->name);
 428        goto failed;
 429
 430transfer_failed:
 431        set_fs(seg);
 432        if (fixup) {
 433                regs->pc = fixup->fixup;
 434                return;
 435        }
 436        if (die_if_no_fixup("misalignment fixup", regs, code))
 437                return;
 438
 439        info.si_signo   = SIGSEGV;
 440        info.si_errno   = 0;
 441        info.si_code    = 0;
 442        info.si_addr    = (void *) regs->pc;
 443        force_sig_info(SIGSEGV, &info, current);
 444        return;
 445
 446        /* we matched the opcode */
 447found_opcode:
 448        kdebug("%lx: %x==%x { %x, %x }",
 449               regs->pc, opcode, pop->opcode, pop->params[0], pop->params[1]);
 450
 451        tmp = format_tbl[pop->format].opsz;
 452        BUG_ON(tmp > noc); /* match was less complete than it ought to have been */
 453
 454        if (tmp < noc) {
 455                tmp = noc - tmp;
 456                opcode >>= tmp;
 457                pc -= tmp >> 3;
 458        }
 459
 460        /* grab the extra displacement (note it's LSB first) */
 461        disp = 0;
 462        dispsz = format_tbl[pop->format].dispsz;
 463        for (loop = 0; loop < dispsz; loop += 8) {
 464                pc++;
 465                if (__get_user(byte, pc) != 0)
 466                        goto fetch_error;
 467                disp |= byte << loop;
 468                kdebug("{%p} disp[%02x]=%02x", pc, loop, byte);
 469        }
 470
 471        kdebug("disp=%lx", disp);
 472
 473        set_fs(KERNEL_XDS);
 474        if (fixup)
 475                set_fs(seg);
 476
 477        tmp = (pop->params[0] ^ pop->params[1]) & 0x80000000;
 478        if (!tmp) {
 479                printk(KERN_CRIT
 480                       "MISALIGN: %lx: insn not move to/from memory %x\n",
 481                       regs->pc, opcode);
 482                goto failed;
 483        }
 484
 485        /* determine the data transfer size of the move */
 486        if (pop->name[3] == 0 || /* "mov" */
 487            pop->name[4] == 'l') /* mov_lcc */
 488                inc = datasz = 4;
 489        else if (pop->name[3] == 'h') /* movhu */
 490                inc = datasz = 2;
 491        else
 492                goto unsupported_instruction;
 493
 494        if (pop->params[0] & 0x80000000) {
 495                /* move memory to register */
 496                if (!misalignment_addr(registers, sp,
 497                                       pop->params[0], opcode, disp,
 498                                       &address, &postinc, &inc))
 499                        goto bad_addr_mode;
 500
 501                if (!misalignment_reg(registers, pop->params[1], opcode, disp,
 502                                      &store))
 503                        goto bad_reg_mode;
 504
 505                kdebug("mov%u (%p),DARn", datasz, address);
 506                if (copy_from_user(&data, (void *) address, datasz) != 0)
 507                        goto transfer_failed;
 508                if (pop->params[0] & 0x1000000) {
 509                        kdebug("inc=%lx", inc);
 510                        *postinc += inc;
 511                }
 512
 513                *store = data;
 514                kdebug("loaded %lx", data);
 515        } else {
 516                /* move register to memory */
 517                if (!misalignment_reg(registers, pop->params[0], opcode, disp,
 518                                      &store))
 519                        goto bad_reg_mode;
 520
 521                if (!misalignment_addr(registers, sp,
 522                                       pop->params[1], opcode, disp,
 523                                       &address, &postinc, &inc))
 524                        goto bad_addr_mode;
 525
 526                data = *store;
 527
 528                kdebug("mov%u %lx,(%p)", datasz, data, address);
 529                if (copy_to_user((void *) address, &data, datasz) != 0)
 530                        goto transfer_failed;
 531                if (pop->params[1] & 0x1000000)
 532                        *postinc += inc;
 533        }
 534
 535        tmp = format_tbl[pop->format].opsz + format_tbl[pop->format].dispsz;
 536        regs->pc += tmp >> 3;
 537
 538        /* handle MOV_Lcc, which are currently the only FMT_D10 insns that
 539         * access memory */
 540        if (pop->format == FMT_D10)
 541                misalignment_MOV_Lcc(regs, opcode);
 542
 543        set_fs(seg);
 544}
 545
 546/*
 547 * determine the address that was being accessed
 548 */
 549static int misalignment_addr(unsigned long *registers, unsigned long sp,
 550                             unsigned params, unsigned opcode,
 551                             unsigned long disp,
 552                             void **_address, unsigned long **_postinc,
 553                             unsigned long *_inc)
 554{
 555        unsigned long *postinc = NULL, address = 0, tmp;
 556
 557        if (!(params & 0x1000000)) {
 558                kdebug("noinc");
 559                *_inc = 0;
 560                _inc = NULL;
 561        }
 562
 563        params &= 0x00ffffff;
 564
 565        do {
 566                switch (params & 0xff) {
 567                case DM0:
 568                        postinc = &registers[Dreg_index[opcode & 0x03]];
 569                        address += *postinc;
 570                        break;
 571                case DM1:
 572                        postinc = &registers[Dreg_index[opcode >> 2 & 0x03]];
 573                        address += *postinc;
 574                        break;
 575                case DM2:
 576                        postinc = &registers[Dreg_index[opcode >> 4 & 0x03]];
 577                        address += *postinc;
 578                        break;
 579                case AM0:
 580                        postinc = &registers[Areg_index[opcode & 0x03]];
 581                        address += *postinc;
 582                        break;
 583                case AM1:
 584                        postinc = &registers[Areg_index[opcode >> 2 & 0x03]];
 585                        address += *postinc;
 586                        break;
 587                case AM2:
 588                        postinc = &registers[Areg_index[opcode >> 4 & 0x03]];
 589                        address += *postinc;
 590                        break;
 591                case RM0:
 592                        postinc = &registers[Rreg_index[opcode & 0x0f]];
 593                        address += *postinc;
 594                        break;
 595                case RM1:
 596                        postinc = &registers[Rreg_index[opcode >> 2 & 0x0f]];
 597                        address += *postinc;
 598                        break;
 599                case RM2:
 600                        postinc = &registers[Rreg_index[opcode >> 4 & 0x0f]];
 601                        address += *postinc;
 602                        break;
 603                case RM4:
 604                        postinc = &registers[Rreg_index[opcode >> 8 & 0x0f]];
 605                        address += *postinc;
 606                        break;
 607                case RM6:
 608                        postinc = &registers[Rreg_index[opcode >> 12 & 0x0f]];
 609                        address += *postinc;
 610                        break;
 611                case RD0:
 612                        postinc = &registers[Rreg_index[disp & 0x0f]];
 613                        address += *postinc;
 614                        break;
 615                case RD2:
 616                        postinc = &registers[Rreg_index[disp >> 4 & 0x0f]];
 617                        address += *postinc;
 618                        break;
 619                case SP:
 620                        address += sp;
 621                        break;
 622
 623                        /* displacements are either to be added to the address
 624                         * before use, or, in the case of post-inc addressing,
 625                         * to be added into the base register after use */
 626                case SD8:
 627                case SIMM8:
 628                        disp = (long) (int8_t) (disp & 0xff);
 629                        goto displace_or_inc;
 630                case SD16:
 631                        disp = (long) (int16_t) (disp & 0xffff);
 632                        goto displace_or_inc;
 633                case SD24:
 634                        tmp = disp << 8;
 635                        asm("asr 8,%0" : "=r"(tmp) : "0"(tmp) : "cc");
 636                        disp = (long) tmp;
 637                        goto displace_or_inc;
 638                case SIMM4_2:
 639                        tmp = opcode >> 4 & 0x0f;
 640                        tmp <<= 28;
 641                        asm("asr 28,%0" : "=r"(tmp) : "0"(tmp) : "cc");
 642                        disp = (long) tmp;
 643                        goto displace_or_inc;
 644                case IMM8:
 645                        disp &= 0x000000ff;
 646                        goto displace_or_inc;
 647                case IMM16:
 648                        disp &= 0x0000ffff;
 649                        goto displace_or_inc;
 650                case IMM24:
 651                        disp &= 0x00ffffff;
 652                        goto displace_or_inc;
 653                case IMM32:
 654                case IMM32_MEM:
 655                case IMM32_HIGH8:
 656                case IMM32_HIGH8_MEM:
 657                displace_or_inc:
 658                        kdebug("%s %lx", _inc ? "incr" : "disp", disp);
 659                        if (!_inc)
 660                                address += disp;
 661                        else
 662                                *_inc = disp;
 663                        break;
 664                default:
 665                        BUG();
 666                        return 0;
 667                }
 668        } while ((params >>= 8));
 669
 670        *_address = (void *) address;
 671        *_postinc = postinc;
 672        return 1;
 673}
 674
 675/*
 676 * determine the register that is acting as source/dest
 677 */
 678static int misalignment_reg(unsigned long *registers, unsigned params,
 679                            unsigned opcode, unsigned long disp,
 680                            unsigned long **_register)
 681{
 682        params &= 0x7fffffff;
 683
 684        if (params & 0xffffff00)
 685                return 0;
 686
 687        switch (params & 0xff) {
 688        case DM0:
 689                *_register = &registers[Dreg_index[opcode & 0x03]];
 690                break;
 691        case DM1:
 692                *_register = &registers[Dreg_index[opcode >> 2 & 0x03]];
 693                break;
 694        case DM2:
 695                *_register = &registers[Dreg_index[opcode >> 4 & 0x03]];
 696                break;
 697        case AM0:
 698                *_register = &registers[Areg_index[opcode & 0x03]];
 699                break;
 700        case AM1:
 701                *_register = &registers[Areg_index[opcode >> 2 & 0x03]];
 702                break;
 703        case AM2:
 704                *_register = &registers[Areg_index[opcode >> 4 & 0x03]];
 705                break;
 706        case RM0:
 707                *_register = &registers[Rreg_index[opcode & 0x0f]];
 708                break;
 709        case RM1:
 710                *_register = &registers[Rreg_index[opcode >> 2 & 0x0f]];
 711                break;
 712        case RM2:
 713                *_register = &registers[Rreg_index[opcode >> 4 & 0x0f]];
 714                break;
 715        case RM4:
 716                *_register = &registers[Rreg_index[opcode >> 8 & 0x0f]];
 717                break;
 718        case RM6:
 719                *_register = &registers[Rreg_index[opcode >> 12 & 0x0f]];
 720                break;
 721        case RD0:
 722                *_register = &registers[Rreg_index[disp & 0x0f]];
 723                break;
 724        case RD2:
 725                *_register = &registers[Rreg_index[disp >> 4 & 0x0f]];
 726                break;
 727        case SP:
 728                *_register = &registers[REG_SP >> 2];
 729                break;
 730
 731        default:
 732                BUG();
 733                return 0;
 734        }
 735
 736        return 1;
 737}
 738
 739/*
 740 * handle the conditional loop part of the move-and-loop instructions
 741 */
 742static void misalignment_MOV_Lcc(struct pt_regs *regs, uint32_t opcode)
 743{
 744        unsigned long epsw = regs->epsw;
 745        unsigned long NxorV;
 746
 747        kdebug("MOV_Lcc %x [flags=%lx]", opcode, epsw & 0xf);
 748
 749        /* calculate N^V and shift onto the same bit position as Z */
 750        NxorV = ((epsw >> 3) ^ epsw >> 1) & 1;
 751
 752        switch (opcode & 0xf) {
 753        case 0x0: /* MOV_LLT: N^V */
 754                if (NxorV)
 755                        goto take_the_loop;
 756                return;
 757        case 0x1: /* MOV_LGT: ~(Z or (N^V))*/
 758                if (!((epsw & EPSW_FLAG_Z) | NxorV))
 759                        goto take_the_loop;
 760                return;
 761        case 0x2: /* MOV_LGE: ~(N^V) */
 762                if (!NxorV)
 763                        goto take_the_loop;
 764                return;
 765        case 0x3: /* MOV_LLE: Z or (N^V) */
 766                if ((epsw & EPSW_FLAG_Z) | NxorV)
 767                        goto take_the_loop;
 768                return;
 769
 770        case 0x4: /* MOV_LCS: C */
 771                if (epsw & EPSW_FLAG_C)
 772                        goto take_the_loop;
 773                return;
 774        case 0x5: /* MOV_LHI: ~(C or Z) */
 775                if (!(epsw & (EPSW_FLAG_C | EPSW_FLAG_Z)))
 776                        goto take_the_loop;
 777                return;
 778        case 0x6: /* MOV_LCC: ~C */
 779                if (!(epsw & EPSW_FLAG_C))
 780                        goto take_the_loop;
 781                return;
 782        case 0x7: /* MOV_LLS: C or Z */
 783                if (epsw & (EPSW_FLAG_C | EPSW_FLAG_Z))
 784                        goto take_the_loop;
 785                return;
 786
 787        case 0x8: /* MOV_LEQ: Z */
 788                if (epsw & EPSW_FLAG_Z)
 789                        goto take_the_loop;
 790                return;
 791        case 0x9: /* MOV_LNE: ~Z */
 792                if (!(epsw & EPSW_FLAG_Z))
 793                        goto take_the_loop;
 794                return;
 795        case 0xa: /* MOV_LRA: always */
 796                goto take_the_loop;
 797
 798        default:
 799                BUG();
 800        }
 801
 802take_the_loop:
 803        /* wind the PC back to just after the SETLB insn */
 804        kdebug("loop LAR=%lx", regs->lar);
 805        regs->pc = regs->lar - 4;
 806}
 807
 808/*
 809 * misalignment handler tests
 810 */
 811#ifdef CONFIG_TEST_MISALIGNMENT_HANDLER
 812static u8 __initdata testbuf[512] __attribute__((aligned(16))) = {
 813        [257] = 0x11,
 814        [258] = 0x22,
 815        [259] = 0x33,
 816        [260] = 0x44,
 817};
 818
 819#define ASSERTCMP(X, OP, Y)                                             \
 820do {                                                                    \
 821        if (unlikely(!((X) OP (Y)))) {                                  \
 822                printk(KERN_ERR "\n");                                  \
 823                printk(KERN_ERR "MISALIGN: Assertion failed at line %u\n", \
 824                       __LINE__);                                       \
 825                printk(KERN_ERR "0x%lx " #OP " 0x%lx is false\n",       \
 826                       (unsigned long)(X), (unsigned long)(Y));         \
 827                BUG();                                                  \
 828        }                                                               \
 829} while(0)
 830
 831static int __init test_misalignment(void)
 832{
 833        register void *r asm("e0");
 834        register u32 y asm("e1");
 835        void *p = testbuf, *q;
 836        u32 tmp, tmp2, x;
 837
 838        printk(KERN_NOTICE "==>test_misalignment() [testbuf=%p]\n", p);
 839        p++;
 840
 841        printk(KERN_NOTICE "___ MOV (Am),Dn ___\n");
 842        q = p + 256;
 843        asm volatile("mov       (%0),%1" : "+a"(q), "=d"(x));
 844        ASSERTCMP(q, ==, p + 256);
 845        ASSERTCMP(x, ==, 0x44332211);
 846
 847        printk(KERN_NOTICE "___ MOV (256,Am),Dn ___\n");
 848        q = p;
 849        asm volatile("mov       (256,%0),%1" : "+a"(q), "=d"(x));
 850        ASSERTCMP(q, ==, p);
 851        ASSERTCMP(x, ==, 0x44332211);
 852
 853        printk(KERN_NOTICE "___ MOV (Di,Am),Dn ___\n");
 854        tmp = 256;
 855        q = p;
 856        asm volatile("mov       (%2,%0),%1" : "+a"(q), "=d"(x), "+d"(tmp));
 857        ASSERTCMP(q, ==, p);
 858        ASSERTCMP(x, ==, 0x44332211);
 859        ASSERTCMP(tmp, ==, 256);
 860
 861        printk(KERN_NOTICE "___ MOV (256,Rm),Rn ___\n");
 862        r = p;
 863        asm volatile("mov       (256,%0),%1" : "+r"(r), "=r"(y));
 864        ASSERTCMP(r, ==, p);
 865        ASSERTCMP(y, ==, 0x44332211);
 866
 867        printk(KERN_NOTICE "___ MOV (Rm+),Rn ___\n");
 868        r = p + 256;
 869        asm volatile("mov       (%0+),%1" : "+r"(r), "=r"(y));
 870        ASSERTCMP(r, ==, p + 256 + 4);
 871        ASSERTCMP(y, ==, 0x44332211);
 872
 873        printk(KERN_NOTICE "___ MOV (Rm+,8),Rn ___\n");
 874        r = p + 256;
 875        asm volatile("mov       (%0+,8),%1" : "+r"(r), "=r"(y));
 876        ASSERTCMP(r, ==, p + 256 + 8);
 877        ASSERTCMP(y, ==, 0x44332211);
 878
 879        printk(KERN_NOTICE "___ MOV (7,SP),Rn ___\n");
 880        asm volatile(
 881                "add    -16,sp          \n"
 882                "mov    +0x11,%0        \n"
 883                "movbu  %0,(7,sp)       \n"
 884                "mov    +0x22,%0        \n"
 885                "movbu  %0,(8,sp)       \n"
 886                "mov    +0x33,%0        \n"
 887                "movbu  %0,(9,sp)       \n"
 888                "mov    +0x44,%0        \n"
 889                "movbu  %0,(10,sp)      \n"
 890                "mov    (7,sp),%1       \n"
 891                "add    +16,sp          \n"
 892                : "+a"(q), "=d"(x));
 893        ASSERTCMP(x, ==, 0x44332211);
 894
 895        printk(KERN_NOTICE "___ MOV (259,SP),Rn ___\n");
 896        asm volatile(
 897                "add    -264,sp         \n"
 898                "mov    +0x11,%0        \n"
 899                "movbu  %0,(259,sp)     \n"
 900                "mov    +0x22,%0        \n"
 901                "movbu  %0,(260,sp)     \n"
 902                "mov    +0x33,%0        \n"
 903                "movbu  %0,(261,sp)     \n"
 904                "mov    +0x55,%0        \n"
 905                "movbu  %0,(262,sp)     \n"
 906                "mov    (259,sp),%1     \n"
 907                "add    +264,sp         \n"
 908                : "+d"(tmp), "=d"(x));
 909        ASSERTCMP(x, ==, 0x55332211);
 910
 911        printk(KERN_NOTICE "___ MOV (260,SP),Rn ___\n");
 912        asm volatile(
 913                "add    -264,sp         \n"
 914                "mov    +0x11,%0        \n"
 915                "movbu  %0,(260,sp)     \n"
 916                "mov    +0x22,%0        \n"
 917                "movbu  %0,(261,sp)     \n"
 918                "mov    +0x33,%0        \n"
 919                "movbu  %0,(262,sp)     \n"
 920                "mov    +0x55,%0        \n"
 921                "movbu  %0,(263,sp)     \n"
 922                "mov    (260,sp),%1     \n"
 923                "add    +264,sp         \n"
 924                : "+d"(tmp), "=d"(x));
 925        ASSERTCMP(x, ==, 0x55332211);
 926
 927
 928        printk(KERN_NOTICE "___ MOV_LNE ___\n");
 929        tmp = 1;
 930        tmp2 = 2;
 931        q = p + 256;
 932        asm volatile(
 933                "setlb                  \n"
 934                "mov    %2,%3           \n"
 935                "mov    %1,%2           \n"
 936                "cmp    +0,%1           \n"
 937                "mov_lne        (%0+,4),%1"
 938                : "+r"(q), "+d"(tmp), "+d"(tmp2), "=d"(x)
 939                :
 940                : "cc");
 941        ASSERTCMP(q, ==, p + 256 + 12);
 942        ASSERTCMP(x, ==, 0x44332211);
 943
 944        printk(KERN_NOTICE "___ MOV in SETLB ___\n");
 945        tmp = 1;
 946        tmp2 = 2;
 947        q = p + 256;
 948        asm volatile(
 949                "setlb                  \n"
 950                "mov    %1,%3           \n"
 951                "mov    (%0+),%1        \n"
 952                "cmp    +0,%1           \n"
 953                "lne                    "
 954                : "+a"(q), "+d"(tmp), "+d"(tmp2), "=d"(x)
 955                :
 956                : "cc");
 957
 958        ASSERTCMP(q, ==, p + 256 + 8);
 959        ASSERTCMP(x, ==, 0x44332211);
 960
 961        printk(KERN_NOTICE "<==test_misalignment()\n");
 962        return 0;
 963}
 964
 965arch_initcall(test_misalignment);
 966
 967#endif /* CONFIG_TEST_MISALIGNMENT_HANDLER */
 968