11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Unaligned memory access handler 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001 Randolph Chung <tausq@debian.org> 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Significantly tweaked by LaMont Jones <lamont@debian.org> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2, or (at your option) 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * any later version. 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details. 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23e6fc0449be45a0e7520da6a17a64520743b9aa20Matthew Wilcox#include <linux/jiffies.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 26e6fc0449be45a0e7520da6a17a64520743b9aa20Matthew Wilcox#include <linux/sched.h> 27e6fc0449be45a0e7520da6a17a64520743b9aa20Matthew Wilcox#include <linux/signal.h> 286ee77658ce387ad6c85dcbda4a68bc33efd8de39Akinobu Mita#include <linux/ratelimit.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 30d0c3be806a3fe7f4abdb0f7e7287addb55e73f35Helge Deller#include <asm/hardirq.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* #define DEBUG_UNALIGNED 1 */ 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_UNALIGNED 3591bae23ce185b74c9b6dda86b92bb204a1c951c3Harvey Harrison#define DPRINTF(fmt, args...) do { printk(KERN_DEBUG "%s:%d:%s ", __FILE__, __LINE__, __func__ ); printk(KERN_DEBUG fmt, ##args ); } while (0) 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DPRINTF(fmt, args...) 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 400b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller#ifdef CONFIG_64BIT 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RFMT "%016lx" 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RFMT "%08lx" 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FIXUP_BRANCH(lbl) \ 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "\tldil L%%" #lbl ", %%r1\n" \ 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "\tldo R%%" #lbl "(%%r1), %%r1\n" \ 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "\tbv,n %%r0(%%r1)\n" 503fd3a74f45c935f7d6d5c2fb48f06324b18826b7Carlos O'Donell/* If you use FIXUP_BRANCH, then you must list this clobber */ 513fd3a74f45c935f7d6d5c2fb48f06324b18826b7Carlos O'Donell#define FIXUP_BRANCH_CLOBBER "r1" 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1111 1100 0000 0000 0001 0011 1100 0000 */ 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE1(a,b,c) ((a)<<26|(b)<<12|(c)<<6) 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE2(a,b) ((a)<<26|(b)<<1) 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE3(a,b) ((a)<<26|(b)<<2) 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE4(a) ((a)<<26) 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE1_MASK OPCODE1(0x3f,1,0xf) 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE2_MASK OPCODE2(0x3f,1) 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE3_MASK OPCODE3(0x3f,1) 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE4_MASK OPCODE4(0x3f) 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* skip LDB - never unaligned (index) */ 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_LDH_I OPCODE1(0x03,0,0x1) 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_LDW_I OPCODE1(0x03,0,0x2) 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_LDD_I OPCODE1(0x03,0,0x3) 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_LDDA_I OPCODE1(0x03,0,0x4) 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_LDCD_I OPCODE1(0x03,0,0x5) 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_LDWA_I OPCODE1(0x03,0,0x6) 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_LDCW_I OPCODE1(0x03,0,0x7) 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* skip LDB - never unaligned (short) */ 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_LDH_S OPCODE1(0x03,1,0x1) 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_LDW_S OPCODE1(0x03,1,0x2) 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_LDD_S OPCODE1(0x03,1,0x3) 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_LDDA_S OPCODE1(0x03,1,0x4) 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_LDCD_S OPCODE1(0x03,1,0x5) 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_LDWA_S OPCODE1(0x03,1,0x6) 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_LDCW_S OPCODE1(0x03,1,0x7) 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* skip STB - never unaligned */ 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_STH OPCODE1(0x03,1,0x9) 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_STW OPCODE1(0x03,1,0xa) 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_STD OPCODE1(0x03,1,0xb) 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* skip STBY - never unaligned */ 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* skip STDBY - never unaligned */ 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_STWA OPCODE1(0x03,1,0xe) 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_STDA OPCODE1(0x03,1,0xf) 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_FLDWX OPCODE1(0x09,0,0x0) 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_FLDWXR OPCODE1(0x09,0,0x1) 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_FSTWX OPCODE1(0x09,0,0x8) 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_FSTWXR OPCODE1(0x09,0,0x9) 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_FLDWS OPCODE1(0x09,1,0x0) 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_FLDWSR OPCODE1(0x09,1,0x1) 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_FSTWS OPCODE1(0x09,1,0x8) 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_FSTWSR OPCODE1(0x09,1,0x9) 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_FLDDX OPCODE1(0x0b,0,0x0) 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_FSTDX OPCODE1(0x0b,0,0x8) 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_FLDDS OPCODE1(0x0b,1,0x0) 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_FSTDS OPCODE1(0x0b,1,0x8) 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_LDD_L OPCODE2(0x14,0) 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_FLDD_L OPCODE2(0x14,1) 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_STD_L OPCODE2(0x1c,0) 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_FSTD_L OPCODE2(0x1c,1) 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_LDW_M OPCODE3(0x17,1) 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_FLDW_L OPCODE3(0x17,0) 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_FSTW_L OPCODE3(0x1f,0) 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_STW_M OPCODE3(0x1f,1) 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_LDH_L OPCODE4(0x11) 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_LDW_L OPCODE4(0x12) 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_LDWM OPCODE4(0x13) 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_STH_L OPCODE4(0x19) 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_STW_L OPCODE4(0x1A) 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define OPCODE_STWM OPCODE4(0x1B) 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAJOR_OP(i) (((i)>>26)&0x3f) 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define R1(i) (((i)>>21)&0x1f) 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define R2(i) (((i)>>16)&0x1f) 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define R3(i) ((i)&0x1f) 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FR3(i) ((((i)<<1)&0x1f)|(((i)>>6)&1)) 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IM(i,n) (((i)>>1&((1<<(n-1))-1))|((i)&1?((0-1L)<<(n-1)):0)) 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IM5_2(i) IM((i)>>16,5) 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IM5_3(i) IM((i),5) 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IM14(i) IM((i),14) 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ERR_NOTHANDLED -1 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ERR_PAGEFAULT -2 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1318039de10aae3cd4cf0ef0ccebd58aff0e8810df2Helge Dellerint unaligned_enabled __read_mostly = 1; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid die_if_kernel (char *str, struct pt_regs *regs, long err); 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int emulate_ldh(struct pt_regs *regs, int toreg) 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long saddr = regs->ior; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long val = 0; 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTF("load " RFMT ":" RFMT " to r%d for 2 bytes\n", 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->isr, regs->ior, toreg); 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __asm__ __volatile__ ( 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" mtsp %4, %%sr1\n" 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"1: ldbs 0(%%sr1,%3), %%r20\n" 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"2: ldbs 1(%%sr1,%3), %0\n" 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" depw %%r20, 23, 24, %0\n" 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" copy %%r0, %1\n" 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"3: \n" 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" .section .fixup,\"ax\"\n" 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"4: ldi -2, %1\n" 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FIXUP_BRANCH(3b) 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" .previous\n" 1550b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(1b, 4b) 1560b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(2b, 4b) 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "=r" (val), "=r" (ret) 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "0" (val), "r" (saddr), "r" (regs->isr) 1593fd3a74f45c935f7d6d5c2fb48f06324b18826b7Carlos O'Donell : "r20", FIXUP_BRANCH_CLOBBER ); 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTF("val = 0x" RFMT "\n", val); 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (toreg) 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->gr[toreg] = val; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int emulate_ldw(struct pt_regs *regs, int toreg, int flop) 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long saddr = regs->ior; 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long val = 0; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTF("load " RFMT ":" RFMT " to r%d for 4 bytes\n", 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->isr, regs->ior, toreg); 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __asm__ __volatile__ ( 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" zdep %3,28,2,%%r19\n" /* r19=(ofs&3)*8 */ 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" mtsp %4, %%sr1\n" 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" depw %%r0,31,2,%3\n" 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"1: ldw 0(%%sr1,%3),%0\n" 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"2: ldw 4(%%sr1,%3),%%r20\n" 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" subi 32,%%r19,%%r19\n" 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" mtctl %%r19,11\n" 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" vshd %0,%%r20,%0\n" 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" copy %%r0, %1\n" 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"3: \n" 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" .section .fixup,\"ax\"\n" 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"4: ldi -2, %1\n" 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FIXUP_BRANCH(3b) 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" .previous\n" 1930b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(1b, 4b) 1940b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(2b, 4b) 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "=r" (val), "=r" (ret) 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "0" (val), "r" (saddr), "r" (regs->isr) 1973fd3a74f45c935f7d6d5c2fb48f06324b18826b7Carlos O'Donell : "r19", "r20", FIXUP_BRANCH_CLOBBER ); 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTF("val = 0x" RFMT "\n", val); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (flop) 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((__u32*)(regs->fr))[toreg] = val; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (toreg) 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->gr[toreg] = val; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int emulate_ldd(struct pt_regs *regs, int toreg, int flop) 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long saddr = regs->ior; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __u64 val = 0; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTF("load " RFMT ":" RFMT " to r%d for 8 bytes\n", 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->isr, regs->ior, toreg); 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PA20 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2180b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller#ifndef CONFIG_64BIT 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!flop) 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __asm__ __volatile__ ( 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" depd,z %3,60,3,%%r19\n" /* r19=(ofs&7)*8 */ 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" mtsp %4, %%sr1\n" 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" depd %%r0,63,3,%3\n" 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"1: ldd 0(%%sr1,%3),%0\n" 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"2: ldd 8(%%sr1,%3),%%r20\n" 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" subi 64,%%r19,%%r19\n" 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" mtsar %%r19\n" 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" shrpd %0,%%r20,%%sar,%0\n" 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" copy %%r0, %1\n" 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"3: \n" 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" .section .fixup,\"ax\"\n" 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"4: ldi -2, %1\n" 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FIXUP_BRANCH(3b) 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" .previous\n" 2370b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(1b,4b) 2380b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(2b,4b) 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "=r" (val), "=r" (ret) 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "0" (val), "r" (saddr), "r" (regs->isr) 2413fd3a74f45c935f7d6d5c2fb48f06324b18826b7Carlos O'Donell : "r19", "r20", FIXUP_BRANCH_CLOBBER ); 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long valh=0,vall=0; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __asm__ __volatile__ ( 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" zdep %5,29,2,%%r19\n" /* r19=(ofs&3)*8 */ 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" mtsp %6, %%sr1\n" 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" dep %%r0,31,2,%5\n" 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"1: ldw 0(%%sr1,%5),%0\n" 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"2: ldw 4(%%sr1,%5),%1\n" 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"3: ldw 8(%%sr1,%5),%%r20\n" 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" subi 32,%%r19,%%r19\n" 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" mtsar %%r19\n" 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" vshd %0,%1,%0\n" 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" vshd %1,%%r20,%1\n" 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" copy %%r0, %2\n" 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"4: \n" 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" .section .fixup,\"ax\"\n" 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"5: ldi -2, %2\n" 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FIXUP_BRANCH(4b) 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" .previous\n" 2620b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(1b,5b) 2630b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(2b,5b) 2640b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(3b,5b) 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "=r" (valh), "=r" (vall), "=r" (ret) 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "0" (valh), "1" (vall), "r" (saddr), "r" (regs->isr) 2673fd3a74f45c935f7d6d5c2fb48f06324b18826b7Carlos O'Donell : "r19", "r20", FIXUP_BRANCH_CLOBBER ); 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val=((__u64)valh<<32)|(__u64)vall; 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTF("val = 0x%llx\n", val); 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (flop) 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->fr[toreg] = val; 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (toreg) 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->gr[toreg] = val; 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int emulate_sth(struct pt_regs *regs, int frreg) 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long val = regs->gr[frreg]; 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!frreg) 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 2 bytes\n", frreg, 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val, regs->isr, regs->ior); 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __asm__ __volatile__ ( 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" mtsp %3, %%sr1\n" 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" extrw,u %1, 23, 8, %%r19\n" 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"1: stb %1, 1(%%sr1, %2)\n" 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"2: stb %%r19, 0(%%sr1, %2)\n" 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" copy %%r0, %0\n" 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"3: \n" 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" .section .fixup,\"ax\"\n" 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"4: ldi -2, %0\n" 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FIXUP_BRANCH(3b) 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" .previous\n" 3040b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(1b,4b) 3050b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(2b,4b) 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "=r" (ret) 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "r" (val), "r" (regs->ior), "r" (regs->isr) 3083fd3a74f45c935f7d6d5c2fb48f06324b18826b7Carlos O'Donell : "r19", FIXUP_BRANCH_CLOBBER ); 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int emulate_stw(struct pt_regs *regs, int frreg, int flop) 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long val; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (flop) 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = ((__u32*)(regs->fr))[frreg]; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (frreg) 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = regs->gr[frreg]; 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 4 bytes\n", frreg, 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val, regs->isr, regs->ior); 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __asm__ __volatile__ ( 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" mtsp %3, %%sr1\n" 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" zdep %2, 28, 2, %%r19\n" 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" dep %%r0, 31, 2, %2\n" 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" mtsar %%r19\n" 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" depwi,z -2, %%sar, 32, %%r19\n" 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"1: ldw 0(%%sr1,%2),%%r20\n" 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"2: ldw 4(%%sr1,%2),%%r21\n" 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" vshd %%r0, %1, %%r22\n" 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" vshd %1, %%r0, %%r1\n" 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" and %%r20, %%r19, %%r20\n" 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" andcm %%r21, %%r19, %%r21\n" 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" or %%r22, %%r20, %%r20\n" 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" or %%r1, %%r21, %%r21\n" 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" stw %%r20,0(%%sr1,%2)\n" 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" stw %%r21,4(%%sr1,%2)\n" 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" copy %%r0, %0\n" 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"3: \n" 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" .section .fixup,\"ax\"\n" 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"4: ldi -2, %0\n" 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FIXUP_BRANCH(3b) 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" .previous\n" 3510b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(1b,4b) 3520b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(2b,4b) 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "=r" (ret) 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "r" (val), "r" (regs->ior), "r" (regs->isr) 3553fd3a74f45c935f7d6d5c2fb48f06324b18826b7Carlos O'Donell : "r19", "r20", "r21", "r22", "r1", FIXUP_BRANCH_CLOBBER ); 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int emulate_std(struct pt_regs *regs, int frreg, int flop) 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __u64 val; 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (flop) 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = regs->fr[frreg]; 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (frreg) 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = regs->gr[frreg]; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = 0; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTF("store r%d (0x%016llx) to " RFMT ":" RFMT " for 8 bytes\n", frreg, 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val, regs->isr, regs->ior); 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PA20 3750b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller#ifndef CONFIG_64BIT 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!flop) 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __asm__ __volatile__ ( 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" mtsp %3, %%sr1\n" 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" depd,z %2, 60, 3, %%r19\n" 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" depd %%r0, 63, 3, %2\n" 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" mtsar %%r19\n" 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" depdi,z -2, %%sar, 64, %%r19\n" 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"1: ldd 0(%%sr1,%2),%%r20\n" 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"2: ldd 8(%%sr1,%2),%%r21\n" 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" shrpd %%r0, %1, %%sar, %%r22\n" 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" shrpd %1, %%r0, %%sar, %%r1\n" 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" and %%r20, %%r19, %%r20\n" 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" andcm %%r21, %%r19, %%r21\n" 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" or %%r22, %%r20, %%r20\n" 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" or %%r1, %%r21, %%r21\n" 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"3: std %%r20,0(%%sr1,%2)\n" 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"4: std %%r21,8(%%sr1,%2)\n" 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" copy %%r0, %0\n" 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"5: \n" 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" .section .fixup,\"ax\"\n" 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"6: ldi -2, %0\n" 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FIXUP_BRANCH(5b) 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" .previous\n" 4010b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(1b,6b) 4020b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(2b,6b) 4030b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(3b,6b) 4040b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(4b,6b) 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "=r" (ret) 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "r" (val), "r" (regs->ior), "r" (regs->isr) 4073fd3a74f45c935f7d6d5c2fb48f06324b18826b7Carlos O'Donell : "r19", "r20", "r21", "r22", "r1", FIXUP_BRANCH_CLOBBER ); 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long valh=(val>>32),vall=(val&0xffffffffl); 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __asm__ __volatile__ ( 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" mtsp %4, %%sr1\n" 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" zdep %2, 29, 2, %%r19\n" 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" dep %%r0, 31, 2, %2\n" 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" mtsar %%r19\n" 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" zvdepi -2, 32, %%r19\n" 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"1: ldw 0(%%sr1,%3),%%r20\n" 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"2: ldw 8(%%sr1,%3),%%r21\n" 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" vshd %1, %2, %%r1\n" 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" vshd %%r0, %1, %1\n" 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" vshd %2, %%r0, %2\n" 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" and %%r20, %%r19, %%r20\n" 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" andcm %%r21, %%r19, %%r21\n" 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" or %1, %%r20, %1\n" 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" or %2, %%r21, %2\n" 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"3: stw %1,0(%%sr1,%1)\n" 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"4: stw %%r1,4(%%sr1,%3)\n" 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"5: stw %2,8(%%sr1,%3)\n" 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" copy %%r0, %0\n" 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"6: \n" 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" .section .fixup,\"ax\"\n" 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"7: ldi -2, %0\n" 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FIXUP_BRANCH(6b) 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds" .previous\n" 4350b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(1b,7b) 4360b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(2b,7b) 4370b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(3b,7b) 4380b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(4b,7b) 4390b3d643f9ead9b5141dedbb2d1b06ce15469fc4aHelge Deller ASM_EXCEPTIONTABLE_ENTRY(5b,7b) 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "=r" (ret) 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr) 4423fd3a74f45c935f7d6d5c2fb48f06324b18826b7Carlos O'Donell : "r19", "r20", "r21", "r1", FIXUP_BRANCH_CLOBBER ); 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid handle_unaligned(struct pt_regs *regs) 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4516ee77658ce387ad6c85dcbda4a68bc33efd8de39Akinobu Mita static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 5); 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long newbase = R1(regs->iir)?regs->gr[R1(regs->iir)]:0; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int modify = 0; 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = ERR_NOTHANDLED; 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct siginfo si; 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds register int flop=0; /* true if this is a flop */ 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 458d0c3be806a3fe7f4abdb0f7e7287addb55e73f35Helge Deller __inc_irq_stat(irq_unaligned_count); 459d0c3be806a3fe7f4abdb0f7e7287addb55e73f35Helge Deller 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* log a message with pacing */ 461f053725b8985d10c2cc4b837a80a381104c936a4Kyle McMartin if (user_mode(regs)) { 462f053725b8985d10c2cc4b837a80a381104c936a4Kyle McMartin if (current->thread.flags & PARISC_UAC_SIGBUS) { 463f053725b8985d10c2cc4b837a80a381104c936a4Kyle McMartin goto force_sigbus; 464f053725b8985d10c2cc4b837a80a381104c936a4Kyle McMartin } 465f053725b8985d10c2cc4b837a80a381104c936a4Kyle McMartin 4666ee77658ce387ad6c85dcbda4a68bc33efd8de39Akinobu Mita if (!(current->thread.flags & PARISC_UAC_NOPRINT) && 4676ee77658ce387ad6c85dcbda4a68bc33efd8de39Akinobu Mita __ratelimit(&ratelimit)) { 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char buf[256]; 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(buf, "%s(%d): unaligned access to 0x" RFMT " at ip=0x" RFMT "\n", 47019c5870c0eefd27c6d09d867465e0571262e05d0Alexey Dobriyan current->comm, task_pid_nr(current), regs->ior, regs->iaoq[0]); 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "%s", buf); 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_UNALIGNED 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds show_regs(regs); 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 476f053725b8985d10c2cc4b837a80a381104c936a4Kyle McMartin 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!unaligned_enabled) 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto force_sigbus; 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* handle modification - OK, it's ugly, see the instruction manual */ 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (MAJOR_OP(regs->iir)) 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x03: 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x09: 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x0b: 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (regs->iir&0x20) 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds modify = 1; 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (regs->iir&0x1000) /* short loads */ 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (regs->iir&0x200) 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds newbase += IM5_3(regs->iir); 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds newbase += IM5_2(regs->iir); 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (regs->iir&0x2000) /* scaled indexed */ 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int shift=0; 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (regs->iir & OPCODE1_MASK) 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDH_I: 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds shift= 1; break; 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDW_I: 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds shift= 2; break; 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDD_I: 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDDA_I: 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds shift= 3; break; 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds newbase += (R2(regs->iir)?regs->gr[R2(regs->iir)]:0)<<shift; 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else /* simple indexed */ 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds newbase += (R2(regs->iir)?regs->gr[R2(regs->iir)]:0); 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x13: 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x1b: 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds modify = 1; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds newbase += IM14(regs->iir); 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x14: 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x1c: 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (regs->iir&8) 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds modify = 1; 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds newbase += IM14(regs->iir&~0xe); 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x16: 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x1e: 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds modify = 1; 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds newbase += IM14(regs->iir&6); 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x17: 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x1f: 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (regs->iir&4) 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds modify = 1; 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds newbase += IM14(regs->iir&~4); 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* TODO: make this cleaner... */ 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (regs->iir & OPCODE1_MASK) 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDH_I: 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDH_S: 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_ldh(regs, R3(regs->iir)); 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDW_I: 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDWA_I: 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDW_S: 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDWA_S: 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_ldw(regs, R3(regs->iir),0); 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_STH: 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_sth(regs, R2(regs->iir)); 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_STW: 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_STWA: 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_stw(regs, R2(regs->iir),0); 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PA20 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDD_I: 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDDA_I: 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDD_S: 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDDA_S: 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_ldd(regs, R3(regs->iir),0); 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_STD: 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_STDA: 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_std(regs, R2(regs->iir),0); 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_FLDWX: 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_FLDWS: 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_FLDWXR: 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_FLDWSR: 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flop=1; 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_ldw(regs,FR3(regs->iir),1); 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_FLDDX: 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_FLDDS: 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flop=1; 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_ldd(regs,R3(regs->iir),1); 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_FSTWX: 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_FSTWS: 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_FSTWXR: 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_FSTWSR: 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flop=1; 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_stw(regs,FR3(regs->iir),1); 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_FSTDX: 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_FSTDS: 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flop=1; 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_std(regs,R3(regs->iir),1); 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDCD_I: 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDCW_I: 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDCD_S: 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDCW_S: 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = ERR_NOTHANDLED; /* "undefined", but lets kill them. */ 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PA20 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (regs->iir & OPCODE2_MASK) 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_FLDD_L: 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flop=1; 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_ldd(regs,R2(regs->iir),1); 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_FSTD_L: 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flop=1; 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_std(regs, R2(regs->iir),1); 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDD_L: 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_ldd(regs, R2(regs->iir),0); 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_STD_L: 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_std(regs, R2(regs->iir),0); 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (regs->iir & OPCODE3_MASK) 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_FLDW_L: 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flop=1; 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_ldw(regs, R2(regs->iir),0); 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDW_M: 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_ldw(regs, R2(regs->iir),1); 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_FSTW_L: 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flop=1; 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_stw(regs, R2(regs->iir),1); 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_STW_M: 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_stw(regs, R2(regs->iir),0); 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (regs->iir & OPCODE4_MASK) 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDH_L: 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_ldh(regs, R2(regs->iir)); 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDW_L: 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDWM: 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_ldw(regs, R2(regs->iir),0); 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_STH_L: 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_sth(regs, R2(regs->iir)); 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_STW_L: 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_STWM: 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = emulate_stw(regs, R2(regs->iir),0); 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (modify && R1(regs->iir)) 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->gr[R1(regs->iir)] = newbase; 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret == ERR_NOTHANDLED) 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_CRIT "Not-handled unaligned insn 0x%08lx\n", regs->iir); 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTF("ret = %d\n", ret); 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret); 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds die_if_kernel("Unaligned data reference", regs, 28); 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret == ERR_PAGEFAULT) 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds si.si_signo = SIGSEGV; 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds si.si_errno = 0; 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds si.si_code = SEGV_MAPERR; 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds si.si_addr = (void __user *)regs->ior; 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig_info(SIGSEGV, &si, current); 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsforce_sigbus: 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* couldn't handle it ... */ 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds si.si_signo = SIGBUS; 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds si.si_errno = 0; 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds si.si_code = BUS_ADRALN; 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds si.si_addr = (void __user *)regs->ior; 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig_info(SIGBUS, &si, current); 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* else we handled it, let life go on. */ 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->gr[0]|=PSW_N; 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NB: check_unaligned() is only used for PCXS processors right 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * now, so we only check for PA1.1 encodings at this point. 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscheck_unaligned(struct pt_regs *regs) 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long align_mask; 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Get alignment mask */ 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds align_mask = 0UL; 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (regs->iir & OPCODE1_MASK) { 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDH_I: 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDH_S: 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_STH: 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds align_mask = 1UL; 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDW_I: 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDWA_I: 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDW_S: 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDWA_S: 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_STW: 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_STWA: 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds align_mask = 3UL; 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (regs->iir & OPCODE4_MASK) { 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDH_L: 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_STH_L: 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds align_mask = 1UL; 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDW_L: 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_LDWM: 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_STW_L: 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case OPCODE_STWM: 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds align_mask = 3UL; 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (int)(regs->ior & align_mask); 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 758