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        if (tmp > noc)
 453                BUG(); /* match was less complete than it ought to have been */
 454
 455        if (tmp < noc) {
 456                tmp = noc - tmp;
 457                opcode >>= tmp;
 458                pc -= tmp >> 3;
 459        }
 460
 461        /* grab the extra displacement (note it's LSB first) */
 462        disp = 0;
 463        dispsz = format_tbl[pop->format].dispsz;
 464        for (loop = 0; loop < dispsz; loop += 8) {
 465                pc++;
 466                if (__get_user(byte, pc) != 0)
 467                        goto fetch_error;
 468                disp |= byte << loop;
 469                kdebug("{%p} disp[%02x]=%02x", pc, loop, byte);
 470        }
 471
 472        kdebug("disp=%lx", disp);
 473
 474        set_fs(KERNEL_XDS);
 475        if (fixup)
 476                set_fs(seg);
 477
 478        tmp = (pop->params[0] ^ pop->params[1]) & 0x80000000;
 479        if (!tmp) {
 480                printk(KERN_CRIT
 481                       "MISALIGN: %lx: insn not move to/from memory %x\n",
 482                       regs->pc, opcode);
 483                goto failed;
 484        }
 485
 486        /* determine the data transfer size of the move */
 487        if (pop->name[3] == 0 || /* "mov" */
 488            pop->name[4] == 'l') /* mov_lcc */
 489                inc = datasz = 4;
 490        else if (pop->name[3] == 'h') /* movhu */
 491                inc = datasz = 2;
 492        else
 493                goto unsupported_instruction;
 494
 495        if (pop->params[0] & 0x80000000) {
 496                /* move memory to register */
 497                if (!misalignment_addr(registers, sp,
 498                                       pop->params[0], opcode, disp,
 499                                       &address, &postinc, &inc))
 500                        goto bad_addr_mode;
 501
 502                if (!misalignment_reg(registers, pop->params[1], opcode, disp,
 503                                      &store))
 504                        goto bad_reg_mode;
 505
 506                kdebug("mov%u (%p),DARn", datasz, address);
 507                if (copy_from_user(&data, (void *) address, datasz) != 0)
 508                        goto transfer_failed;
 509                if (pop->params[0] & 0x1000000) {
 510                        kdebug("inc=%lx", inc);
 511                        *postinc += inc;
 512                }
 513
 514                *store = data;
 515                kdebug("loaded %lx", data);
 516        } else {
 517                /* move register to memory */
 518                if (!misalignment_reg(registers, pop->params[0], opcode, disp,
 519                                      &store))
 520                        goto bad_reg_mode;
 521
 522                if (!misalignment_addr(registers, sp,
 523                                       pop->params[1], opcode, disp,
 524                                       &address, &postinc, &inc))
 525                        goto bad_addr_mode;
 526
 527                data = *store;
 528
 529                kdebug("mov%u %lx,(%p)", datasz, data, address);
 530                if (copy_to_user((void *) address, &data, datasz) != 0)
 531                        goto transfer_failed;
 532                if (pop->params[1] & 0x1000000)
 533                        *postinc += inc;
 534        }
 535
 536        tmp = format_tbl[pop->format].opsz + format_tbl[pop->format].dispsz;
 537        regs->pc += tmp >> 3;
 538
 539        /* handle MOV_Lcc, which are currently the only FMT_D10 insns that
 540         * access memory */
 541        if (pop->format == FMT_D10)
 542                misalignment_MOV_Lcc(regs, opcode);
 543
 544        set_fs(seg);
 545}
 546
 547/*
 548 * determine the address that was being accessed
 549 */
 550static int misalignment_addr(unsigned long *registers, unsigned long sp,
 551                             unsigned params, unsigned opcode,
 552                             unsigned long disp,
 553                             void **_address, unsigned long **_postinc,
 554                             unsigned long *_inc)
 555{
 556        unsigned long *postinc = NULL, address = 0, tmp;
 557
 558        if (!(params & 0x1000000)) {
 559                kdebug("noinc");
 560                *_inc = 0;
 561                _inc = NULL;
 562        }
 563
 564        params &= 0x00ffffff;
 565
 566        do {
 567                switch (params & 0xff) {
 568                case DM0:
 569                        postinc = &registers[Dreg_index[opcode & 0x03]];
 570                        address += *postinc;
 571                        break;
 572                case DM1:
 573                        postinc = &registers[Dreg_index[opcode >> 2 & 0x03]];
 574                        address += *postinc;
 575                        break;
 576                case DM2:
 577                        postinc = &registers[Dreg_index[opcode >> 4 & 0x03]];
 578                        address += *postinc;
 579                        break;
 580                case AM0:
 581                        postinc = &registers[Areg_index[opcode & 0x03]];
 582                        address += *postinc;
 583                        break;
 584                case AM1:
 585                        postinc = &registers[Areg_index[opcode >> 2 & 0x03]];
 586                        address += *postinc;
 587                        break;
 588                case AM2:
 589                        postinc = &registers[Areg_index[opcode >> 4 & 0x03]];
 590                        address += *postinc;
 591                        break;
 592                case RM0:
 593                        postinc = &registers[Rreg_index[opcode & 0x0f]];
 594                        address += *postinc;
 595                        break;
 596                case RM1:
 597                        postinc = &registers[Rreg_index[opcode >> 2 & 0x0f]];
 598                        address += *postinc;
 599                        break;
 600                case RM2:
 601                        postinc = &registers[Rreg_index[opcode >> 4 & 0x0f]];
 602                        address += *postinc;
 603                        break;
 604                case RM4:
 605                        postinc = &registers[Rreg_index[opcode >> 8 & 0x0f]];
 606                        address += *postinc;
 607                        break;
 608                case RM6:
 609                        postinc = &registers[Rreg_index[opcode >> 12 & 0x0f]];
 610                        address += *postinc;
 611                        break;
 612                case RD0:
 613                        postinc = &registers[Rreg_index[disp & 0x0f]];
 614                        address += *postinc;
 615                        break;
 616                case RD2:
 617                        postinc = &registers[Rreg_index[disp >> 4 & 0x0f]];
 618                        address += *postinc;
 619                        break;
 620                case SP:
 621                        address += sp;
 622                        break;
 623
 624                        /* displacements are either to be added to the address
 625                         * before use, or, in the case of post-inc addressing,
 626                         * to be added into the base register after use */
 627                case SD8:
 628                case SIMM8:
 629                        disp = (long) (int8_t) (disp & 0xff);
 630                        goto displace_or_inc;
 631                case SD16:
 632                        disp = (long) (int16_t) (disp & 0xffff);
 633                        goto displace_or_inc;
 634                case SD24:
 635                        tmp = disp << 8;
 636                        asm("asr 8,%0" : "=r"(tmp) : "0"(tmp));
 637                        disp = (long) tmp;
 638                        goto displace_or_inc;
 639                case SIMM4_2:
 640                        tmp = opcode >> 4 & 0x0f;
 641                        tmp <<= 28;
 642                        asm("asr 28,%0" : "=r"(tmp) : "0"(tmp));
 643                        disp = (long) tmp;
 644                        goto displace_or_inc;
 645                case IMM8:
 646                        disp &= 0x000000ff;
 647                        goto displace_or_inc;
 648                case IMM16:
 649                        disp &= 0x0000ffff;
 650                        goto displace_or_inc;
 651                case IMM24:
 652                        disp &= 0x00ffffff;
 653                        goto displace_or_inc;
 654                case IMM32:
 655                case IMM32_MEM:
 656                case IMM32_HIGH8:
 657                case IMM32_HIGH8_MEM:
 658                displace_or_inc:
 659                        kdebug("%s %lx", _inc ? "incr" : "disp", disp);
 660                        if (!_inc)
 661                                address += disp;
 662                        else
 663                                *_inc = disp;
 664                        break;
 665                default:
 666                        BUG();
 667                        return 0;
 668                }
 669        } while ((params >>= 8));
 670
 671        *_address = (void *) address;
 672        *_postinc = postinc;
 673        return 1;
 674}
 675
 676/*
 677 * determine the register that is acting as source/dest
 678 */
 679static int misalignment_reg(unsigned long *registers, unsigned params,
 680                            unsigned opcode, unsigned long disp,
 681                            unsigned long **_register)
 682{
 683        params &= 0x7fffffff;
 684
 685        if (params & 0xffffff00)
 686                return 0;
 687
 688        switch (params & 0xff) {
 689        case DM0:
 690                *_register = &registers[Dreg_index[opcode & 0x03]];
 691                break;
 692        case DM1:
 693                *_register = &registers[Dreg_index[opcode >> 2 & 0x03]];
 694                break;
 695        case DM2:
 696                *_register = &registers[Dreg_index[opcode >> 4 & 0x03]];
 697                break;
 698        case AM0:
 699                *_register = &registers[Areg_index[opcode & 0x03]];
 700                break;
 701        case AM1:
 702                *_register = &registers[Areg_index[opcode >> 2 & 0x03]];
 703                break;
 704        case AM2:
 705                *_register = &registers[Areg_index[opcode >> 4 & 0x03]];
 706                break;
 707        case RM0:
 708                *_register = &registers[Rreg_index[opcode & 0x0f]];
 709                break;
 710        case RM1:
 711                *_register = &registers[Rreg_index[opcode >> 2 & 0x0f]];
 712                break;
 713        case RM2:
 714                *_register = &registers[Rreg_index[opcode >> 4 & 0x0f]];
 715                break;
 716        case RM4:
 717                *_register = &registers[Rreg_index[opcode >> 8 & 0x0f]];
 718                break;
 719        case RM6:
 720                *_register = &registers[Rreg_index[opcode >> 12 & 0x0f]];
 721                break;
 722        case RD0:
 723                *_register = &registers[Rreg_index[disp & 0x0f]];
 724                break;
 725        case RD2:
 726                *_register = &registers[Rreg_index[disp >> 4 & 0x0f]];
 727                break;
 728        case SP:
 729                *_register = &registers[REG_SP >> 2];
 730                break;
 731
 732        default:
 733                BUG();
 734                return 0;
 735        }
 736
 737        return 1;
 738}
 739
 740/*
 741 * handle the conditional loop part of the move-and-loop instructions
 742 */
 743static void misalignment_MOV_Lcc(struct pt_regs *regs, uint32_t opcode)
 744{
 745        unsigned long epsw = regs->epsw;
 746        unsigned long NxorV;
 747
 748        kdebug("MOV_Lcc %x [flags=%lx]", opcode, epsw & 0xf);
 749
 750        /* calculate N^V and shift onto the same bit position as Z */
 751        NxorV = ((epsw >> 3) ^ epsw >> 1) & 1;
 752
 753        switch (opcode & 0xf) {
 754        case 0x0: /* MOV_LLT: N^V */
 755                if (NxorV)
 756                        goto take_the_loop;
 757                return;
 758        case 0x1: /* MOV_LGT: ~(Z or (N^V))*/
 759                if (!((epsw & EPSW_FLAG_Z) | NxorV))
 760                        goto take_the_loop;
 761                return;
 762        case 0x2: /* MOV_LGE: ~(N^V) */
 763                if (!NxorV)
 764                        goto take_the_loop;
 765                return;
 766        case 0x3: /* MOV_LLE: Z or (N^V) */
 767                if ((epsw & EPSW_FLAG_Z) | NxorV)
 768                        goto take_the_loop;
 769                return;
 770
 771        case 0x4: /* MOV_LCS: C */
 772                if (epsw & EPSW_FLAG_C)
 773                        goto take_the_loop;
 774                return;
 775        case 0x5: /* MOV_LHI: ~(C or Z) */
 776                if (!(epsw & (EPSW_FLAG_C | EPSW_FLAG_Z)))
 777                        goto take_the_loop;
 778                return;
 779        case 0x6: /* MOV_LCC: ~C */
 780                if (!(epsw & EPSW_FLAG_C))
 781                        goto take_the_loop;
 782                return;
 783        case 0x7: /* MOV_LLS: C or Z */
 784                if (epsw & (EPSW_FLAG_C | EPSW_FLAG_Z))
 785                        goto take_the_loop;
 786                return;
 787
 788        case 0x8: /* MOV_LEQ: Z */
 789                if (epsw & EPSW_FLAG_Z)
 790                        goto take_the_loop;
 791                return;
 792        case 0x9: /* MOV_LNE: ~Z */
 793                if (!(epsw & EPSW_FLAG_Z))
 794                        goto take_the_loop;
 795                return;
 796        case 0xa: /* MOV_LRA: always */
 797                goto take_the_loop;
 798
 799        default:
 800                BUG();
 801        }
 802
 803take_the_loop:
 804        /* wind the PC back to just after the SETLB insn */
 805        kdebug("loop LAR=%lx", regs->lar);
 806        regs->pc = regs->lar - 4;
 807}
 808
 809/*
 810 * misalignment handler tests
 811 */
 812#ifdef CONFIG_TEST_MISALIGNMENT_HANDLER
 813static u8 __initdata testbuf[512] __attribute__((aligned(16))) = {
 814        [257] = 0x11,
 815        [258] = 0x22,
 816        [259] = 0x33,
 817        [260] = 0x44,
 818};
 819
 820#define ASSERTCMP(X, OP, Y)                                             \
 821do {                                                                    \
 822        if (unlikely(!((X) OP (Y)))) {                                  \
 823                printk(KERN_ERR "\n");                                  \
 824                printk(KERN_ERR "MISALIGN: Assertion failed at line %u\n", \
 825                       __LINE__);                                       \
 826                printk(KERN_ERR "0x%lx " #OP " 0x%lx is false\n",       \
 827                       (unsigned long)(X), (unsigned long)(Y));         \
 828                BUG();                                                  \
 829        }                                                               \
 830} while(0)
 831
 832static int __init test_misalignment(void)
 833{
 834        register void *r asm("e0");
 835        register u32 y asm("e1");
 836        void *p = testbuf, *q;
 837        u32 tmp, tmp2, x;
 838
 839        printk(KERN_NOTICE "==>test_misalignment() [testbuf=%p]\n", p);
 840        p++;
 841
 842        printk(KERN_NOTICE "___ MOV (Am),Dn ___\n");
 843        q = p + 256;
 844        asm volatile("mov       (%0),%1" : "+a"(q), "=d"(x));
 845        ASSERTCMP(q, ==, p + 256);
 846        ASSERTCMP(x, ==, 0x44332211);
 847
 848        printk(KERN_NOTICE "___ MOV (256,Am),Dn ___\n");
 849        q = p;
 850        asm volatile("mov       (256,%0),%1" : "+a"(q), "=d"(x));
 851        ASSERTCMP(q, ==, p);
 852        ASSERTCMP(x, ==, 0x44332211);
 853
 854        printk(KERN_NOTICE "___ MOV (Di,Am),Dn ___\n");
 855        tmp = 256;
 856        q = p;
 857        asm volatile("mov       (%2,%0),%1" : "+a"(q), "=d"(x), "+d"(tmp));
 858        ASSERTCMP(q, ==, p);
 859        ASSERTCMP(x, ==, 0x44332211);
 860        ASSERTCMP(tmp, ==, 256);
 861
 862        printk(KERN_NOTICE "___ MOV (256,Rm),Rn ___\n");
 863        r = p;
 864        asm volatile("mov       (256,%0),%1" : "+r"(r), "=r"(y));
 865        ASSERTCMP(r, ==, p);
 866        ASSERTCMP(y, ==, 0x44332211);
 867
 868        printk(KERN_NOTICE "___ MOV (Rm+),Rn ___\n");
 869        r = p + 256;
 870        asm volatile("mov       (%0+),%1" : "+r"(r), "=r"(y));
 871        ASSERTCMP(r, ==, p + 256 + 4);
 872        ASSERTCMP(y, ==, 0x44332211);
 873
 874        printk(KERN_NOTICE "___ MOV (Rm+,8),Rn ___\n");
 875        r = p + 256;
 876        asm volatile("mov       (%0+,8),%1" : "+r"(r), "=r"(y));
 877        ASSERTCMP(r, ==, p + 256 + 8);
 878        ASSERTCMP(y, ==, 0x44332211);
 879
 880        printk(KERN_NOTICE "___ MOV (7,SP),Rn ___\n");
 881        asm volatile(
 882                "add    -16,sp          \n"
 883                "mov    +0x11,%0        \n"
 884                "movbu  %0,(7,sp)       \n"
 885                "mov    +0x22,%0        \n"
 886                "movbu  %0,(8,sp)       \n"
 887                "mov    +0x33,%0        \n"
 888                "movbu  %0,(9,sp)       \n"
 889                "mov    +0x44,%0        \n"
 890                "movbu  %0,(10,sp)      \n"
 891                "mov    (7,sp),%1       \n"
 892                "add    +16,sp          \n"
 893                : "+a"(q), "=d"(x));
 894        ASSERTCMP(x, ==, 0x44332211);
 895
 896        printk(KERN_NOTICE "___ MOV (259,SP),Rn ___\n");
 897        asm volatile(
 898                "add    -264,sp         \n"
 899                "mov    +0x11,%0        \n"
 900                "movbu  %0,(259,sp)     \n"
 901                "mov    +0x22,%0        \n"
 902                "movbu  %0,(260,sp)     \n"
 903                "mov    +0x33,%0        \n"
 904                "movbu  %0,(261,sp)     \n"
 905                "mov    +0x55,%0        \n"
 906                "movbu  %0,(262,sp)     \n"
 907                "mov    (259,sp),%1     \n"
 908                "add    +264,sp         \n"
 909                : "+d"(tmp), "=d"(x));
 910        ASSERTCMP(x, ==, 0x55332211);
 911
 912        printk(KERN_NOTICE "___ MOV (260,SP),Rn ___\n");
 913        asm volatile(
 914                "add    -264,sp         \n"
 915                "mov    +0x11,%0        \n"
 916                "movbu  %0,(260,sp)     \n"
 917                "mov    +0x22,%0        \n"
 918                "movbu  %0,(261,sp)     \n"
 919                "mov    +0x33,%0        \n"
 920                "movbu  %0,(262,sp)     \n"
 921                "mov    +0x55,%0        \n"
 922                "movbu  %0,(263,sp)     \n"
 923                "mov    (260,sp),%1     \n"
 924                "add    +264,sp         \n"
 925                : "+d"(tmp), "=d"(x));
 926        ASSERTCMP(x, ==, 0x55332211);
 927
 928
 929        printk(KERN_NOTICE "___ MOV_LNE ___\n");
 930        tmp = 1;
 931        tmp2 = 2;
 932        q = p + 256;
 933        asm volatile(
 934                "setlb                  \n"
 935                "mov    %2,%3           \n"
 936                "mov    %1,%2           \n"
 937                "cmp    +0,%1           \n"
 938                "mov_lne        (%0+,4),%1"
 939                : "+r"(q), "+d"(tmp), "+d"(tmp2), "=d"(x)
 940                :
 941                : "cc");
 942        ASSERTCMP(q, ==, p + 256 + 12);
 943        ASSERTCMP(x, ==, 0x44332211);
 944
 945        printk(KERN_NOTICE "___ MOV in SETLB ___\n");
 946        tmp = 1;
 947        tmp2 = 2;
 948        q = p + 256;
 949        asm volatile(
 950                "setlb                  \n"
 951                "mov    %1,%3           \n"
 952                "mov    (%0+),%1        \n"
 953                "cmp    +0,%1           \n"
 954                "lne                    "
 955                : "+a"(q), "+d"(tmp), "+d"(tmp2), "=d"(x)
 956                :
 957                : "cc");
 958
 959        ASSERTCMP(q, ==, p + 256 + 8);
 960        ASSERTCMP(x, ==, 0x44332211);
 961
 962        printk(KERN_NOTICE "<==test_misalignment()\n");
 963        return 0;
 964}
 965
 966arch_initcall(test_misalignment);
 967
 968#endif /* CONFIG_TEST_MISALIGNMENT_HANDLER */
 969