xref: /openbmc/linux/arch/parisc/kernel/unaligned.c (revision 46eeaa11bdd1bc9e077bdf741d32ca7235d263c6)
1de6cc651SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *    Unaligned memory access handler
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  *    Copyright (C) 2001 Randolph Chung <tausq@debian.org>
6e5e9e7f2SHelge Deller  *    Copyright (C) 2022 Helge Deller <deller@gmx.de>
71da177e4SLinus Torvalds  *    Significantly tweaked by LaMont Jones <lamont@debian.org>
81da177e4SLinus Torvalds  */
91da177e4SLinus Torvalds 
103f07c014SIngo Molnar #include <linux/sched/signal.h>
11e6fc0449SMatthew Wilcox #include <linux/signal.h>
126ee77658SAkinobu Mita #include <linux/ratelimit.h>
137c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
1466f80386SHelge Deller #include <linux/sysctl.h>
15646d0746SHelge Deller #include <asm/unaligned.h>
16d0c3be80SHelge Deller #include <asm/hardirq.h>
1758f1c654SHelge Deller #include <asm/traps.h>
181da177e4SLinus Torvalds 
191da177e4SLinus Torvalds /* #define DEBUG_UNALIGNED 1 */
201da177e4SLinus Torvalds 
211da177e4SLinus Torvalds #ifdef DEBUG_UNALIGNED
2291bae23cSHarvey Harrison #define DPRINTF(fmt, args...) do { printk(KERN_DEBUG "%s:%d:%s ", __FILE__, __LINE__, __func__ ); printk(KERN_DEBUG fmt, ##args ); } while (0)
231da177e4SLinus Torvalds #else
241da177e4SLinus Torvalds #define DPRINTF(fmt, args...)
251da177e4SLinus Torvalds #endif
261da177e4SLinus Torvalds 
27e5e9e7f2SHelge Deller #define RFMT "%#08lx"
281da177e4SLinus Torvalds 
291da177e4SLinus Torvalds /* 1111 1100 0000 0000 0001 0011 1100 0000 */
301da177e4SLinus Torvalds #define OPCODE1(a,b,c)	((a)<<26|(b)<<12|(c)<<6)
311da177e4SLinus Torvalds #define OPCODE2(a,b)	((a)<<26|(b)<<1)
321da177e4SLinus Torvalds #define OPCODE3(a,b)	((a)<<26|(b)<<2)
331da177e4SLinus Torvalds #define OPCODE4(a)	((a)<<26)
341da177e4SLinus Torvalds #define OPCODE1_MASK	OPCODE1(0x3f,1,0xf)
351da177e4SLinus Torvalds #define OPCODE2_MASK 	OPCODE2(0x3f,1)
361da177e4SLinus Torvalds #define OPCODE3_MASK	OPCODE3(0x3f,1)
371da177e4SLinus Torvalds #define OPCODE4_MASK    OPCODE4(0x3f)
381da177e4SLinus Torvalds 
391da177e4SLinus Torvalds /* skip LDB - never unaligned (index) */
401da177e4SLinus Torvalds #define OPCODE_LDH_I	OPCODE1(0x03,0,0x1)
411da177e4SLinus Torvalds #define OPCODE_LDW_I	OPCODE1(0x03,0,0x2)
421da177e4SLinus Torvalds #define OPCODE_LDD_I	OPCODE1(0x03,0,0x3)
431da177e4SLinus Torvalds #define OPCODE_LDDA_I	OPCODE1(0x03,0,0x4)
441da177e4SLinus Torvalds #define OPCODE_LDCD_I	OPCODE1(0x03,0,0x5)
451da177e4SLinus Torvalds #define OPCODE_LDWA_I	OPCODE1(0x03,0,0x6)
461da177e4SLinus Torvalds #define OPCODE_LDCW_I	OPCODE1(0x03,0,0x7)
471da177e4SLinus Torvalds /* skip LDB - never unaligned (short) */
481da177e4SLinus Torvalds #define OPCODE_LDH_S	OPCODE1(0x03,1,0x1)
491da177e4SLinus Torvalds #define OPCODE_LDW_S	OPCODE1(0x03,1,0x2)
501da177e4SLinus Torvalds #define OPCODE_LDD_S	OPCODE1(0x03,1,0x3)
511da177e4SLinus Torvalds #define OPCODE_LDDA_S	OPCODE1(0x03,1,0x4)
521da177e4SLinus Torvalds #define OPCODE_LDCD_S	OPCODE1(0x03,1,0x5)
531da177e4SLinus Torvalds #define OPCODE_LDWA_S	OPCODE1(0x03,1,0x6)
541da177e4SLinus Torvalds #define OPCODE_LDCW_S	OPCODE1(0x03,1,0x7)
551da177e4SLinus Torvalds /* skip STB - never unaligned */
561da177e4SLinus Torvalds #define OPCODE_STH	OPCODE1(0x03,1,0x9)
571da177e4SLinus Torvalds #define OPCODE_STW	OPCODE1(0x03,1,0xa)
581da177e4SLinus Torvalds #define OPCODE_STD	OPCODE1(0x03,1,0xb)
591da177e4SLinus Torvalds /* skip STBY - never unaligned */
601da177e4SLinus Torvalds /* skip STDBY - never unaligned */
611da177e4SLinus Torvalds #define OPCODE_STWA	OPCODE1(0x03,1,0xe)
621da177e4SLinus Torvalds #define OPCODE_STDA	OPCODE1(0x03,1,0xf)
631da177e4SLinus Torvalds 
641da177e4SLinus Torvalds #define OPCODE_FLDWX	OPCODE1(0x09,0,0x0)
651da177e4SLinus Torvalds #define OPCODE_FLDWXR	OPCODE1(0x09,0,0x1)
661da177e4SLinus Torvalds #define OPCODE_FSTWX	OPCODE1(0x09,0,0x8)
671da177e4SLinus Torvalds #define OPCODE_FSTWXR	OPCODE1(0x09,0,0x9)
681da177e4SLinus Torvalds #define OPCODE_FLDWS	OPCODE1(0x09,1,0x0)
691da177e4SLinus Torvalds #define OPCODE_FLDWSR	OPCODE1(0x09,1,0x1)
701da177e4SLinus Torvalds #define OPCODE_FSTWS	OPCODE1(0x09,1,0x8)
711da177e4SLinus Torvalds #define OPCODE_FSTWSR	OPCODE1(0x09,1,0x9)
721da177e4SLinus Torvalds #define OPCODE_FLDDX	OPCODE1(0x0b,0,0x0)
731da177e4SLinus Torvalds #define OPCODE_FSTDX	OPCODE1(0x0b,0,0x8)
741da177e4SLinus Torvalds #define OPCODE_FLDDS	OPCODE1(0x0b,1,0x0)
751da177e4SLinus Torvalds #define OPCODE_FSTDS	OPCODE1(0x0b,1,0x8)
761da177e4SLinus Torvalds 
771da177e4SLinus Torvalds #define OPCODE_LDD_L	OPCODE2(0x14,0)
781da177e4SLinus Torvalds #define OPCODE_FLDD_L	OPCODE2(0x14,1)
791da177e4SLinus Torvalds #define OPCODE_STD_L	OPCODE2(0x1c,0)
801da177e4SLinus Torvalds #define OPCODE_FSTD_L	OPCODE2(0x1c,1)
811da177e4SLinus Torvalds 
821da177e4SLinus Torvalds #define OPCODE_LDW_M	OPCODE3(0x17,1)
831da177e4SLinus Torvalds #define OPCODE_FLDW_L	OPCODE3(0x17,0)
841da177e4SLinus Torvalds #define OPCODE_FSTW_L	OPCODE3(0x1f,0)
851da177e4SLinus Torvalds #define OPCODE_STW_M	OPCODE3(0x1f,1)
861da177e4SLinus Torvalds 
871da177e4SLinus Torvalds #define OPCODE_LDH_L    OPCODE4(0x11)
881da177e4SLinus Torvalds #define OPCODE_LDW_L    OPCODE4(0x12)
891da177e4SLinus Torvalds #define OPCODE_LDWM     OPCODE4(0x13)
901da177e4SLinus Torvalds #define OPCODE_STH_L    OPCODE4(0x19)
911da177e4SLinus Torvalds #define OPCODE_STW_L    OPCODE4(0x1A)
921da177e4SLinus Torvalds #define OPCODE_STWM     OPCODE4(0x1B)
931da177e4SLinus Torvalds 
941da177e4SLinus Torvalds #define MAJOR_OP(i) (((i)>>26)&0x3f)
951da177e4SLinus Torvalds #define R1(i) (((i)>>21)&0x1f)
961da177e4SLinus Torvalds #define R2(i) (((i)>>16)&0x1f)
971da177e4SLinus Torvalds #define R3(i) ((i)&0x1f)
987ae1f550SHelge Deller #define FR3(i) ((((i)&0x1f)<<1)|(((i)>>6)&1))
991da177e4SLinus Torvalds #define IM(i,n) (((i)>>1&((1<<(n-1))-1))|((i)&1?((0-1L)<<(n-1)):0))
1001da177e4SLinus Torvalds #define IM5_2(i) IM((i)>>16,5)
1011da177e4SLinus Torvalds #define IM5_3(i) IM((i),5)
1021da177e4SLinus Torvalds #define IM14(i) IM((i),14)
1031da177e4SLinus Torvalds 
1041da177e4SLinus Torvalds #define ERR_NOTHANDLED	-1
1051da177e4SLinus Torvalds 
1068039de10SHelge Deller int unaligned_enabled __read_mostly = 1;
1071da177e4SLinus Torvalds 
emulate_ldh(struct pt_regs * regs,int toreg)1081da177e4SLinus Torvalds static int emulate_ldh(struct pt_regs *regs, int toreg)
1091da177e4SLinus Torvalds {
1101da177e4SLinus Torvalds 	unsigned long saddr = regs->ior;
111f85b2af1SHelge Deller 	unsigned long val = 0, temp1;
112d1434e03SHelge Deller 	ASM_EXCEPTIONTABLE_VAR(ret);
1131da177e4SLinus Torvalds 
1141da177e4SLinus Torvalds 	DPRINTF("load " RFMT ":" RFMT " to r%d for 2 bytes\n",
1151da177e4SLinus Torvalds 		regs->isr, regs->ior, toreg);
1161da177e4SLinus Torvalds 
1171da177e4SLinus Torvalds 	__asm__ __volatile__  (
1181da177e4SLinus Torvalds "	mtsp	%4, %%sr1\n"
119f85b2af1SHelge Deller "1:	ldbs	0(%%sr1,%3), %2\n"
1201da177e4SLinus Torvalds "2:	ldbs	1(%%sr1,%3), %0\n"
121f85b2af1SHelge Deller "	depw	%2, 23, 24, %0\n"
1221da177e4SLinus Torvalds "3:	\n"
123fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 3b, "%1")
124fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 3b, "%1")
125f85b2af1SHelge Deller 	: "+r" (val), "+r" (ret), "=&r" (temp1)
126f85b2af1SHelge Deller 	: "r" (saddr), "r" (regs->isr) );
1271da177e4SLinus Torvalds 
128e5e9e7f2SHelge Deller 	DPRINTF("val = " RFMT "\n", val);
1291da177e4SLinus Torvalds 
1301da177e4SLinus Torvalds 	if (toreg)
1311da177e4SLinus Torvalds 		regs->gr[toreg] = val;
1321da177e4SLinus Torvalds 
1331da177e4SLinus Torvalds 	return ret;
1341da177e4SLinus Torvalds }
1351da177e4SLinus Torvalds 
emulate_ldw(struct pt_regs * regs,int toreg,int flop)1361da177e4SLinus Torvalds static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
1371da177e4SLinus Torvalds {
1381da177e4SLinus Torvalds 	unsigned long saddr = regs->ior;
139e8aa7b17SHelge Deller 	unsigned long val = 0, temp1, temp2;
140d1434e03SHelge Deller 	ASM_EXCEPTIONTABLE_VAR(ret);
1411da177e4SLinus Torvalds 
1421da177e4SLinus Torvalds 	DPRINTF("load " RFMT ":" RFMT " to r%d for 4 bytes\n",
1431da177e4SLinus Torvalds 		regs->isr, regs->ior, toreg);
1441da177e4SLinus Torvalds 
1451da177e4SLinus Torvalds 	__asm__ __volatile__  (
146e8aa7b17SHelge Deller "	zdep	%4,28,2,%2\n"		/* r19=(ofs&3)*8 */
147e8aa7b17SHelge Deller "	mtsp	%5, %%sr1\n"
148e8aa7b17SHelge Deller "	depw	%%r0,31,2,%4\n"
149e8aa7b17SHelge Deller "1:	ldw	0(%%sr1,%4),%0\n"
150e8aa7b17SHelge Deller "2:	ldw	4(%%sr1,%4),%3\n"
15196b80fcdSHelge Deller "	subi	32,%2,%2\n"
152e8aa7b17SHelge Deller "	mtctl	%2,11\n"
153e8aa7b17SHelge Deller "	vshd	%0,%3,%0\n"
1541da177e4SLinus Torvalds "3:	\n"
155fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 3b, "%1")
156fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 3b, "%1")
157e8aa7b17SHelge Deller 	: "+r" (val), "+r" (ret), "=&r" (temp1), "=&r" (temp2)
158e8aa7b17SHelge Deller 	: "r" (saddr), "r" (regs->isr) );
1591da177e4SLinus Torvalds 
160e5e9e7f2SHelge Deller 	DPRINTF("val = " RFMT "\n", val);
1611da177e4SLinus Torvalds 
1621da177e4SLinus Torvalds 	if (flop)
1631da177e4SLinus Torvalds 		((__u32*)(regs->fr))[toreg] = val;
1641da177e4SLinus Torvalds 	else if (toreg)
1651da177e4SLinus Torvalds 		regs->gr[toreg] = val;
1661da177e4SLinus Torvalds 
1671da177e4SLinus Torvalds 	return ret;
1681da177e4SLinus Torvalds }
emulate_ldd(struct pt_regs * regs,int toreg,int flop)1691da177e4SLinus Torvalds static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
1701da177e4SLinus Torvalds {
1711da177e4SLinus Torvalds 	unsigned long saddr = regs->ior;
172*51408b47SGuenter Roeck 	unsigned long shift, temp1;
1731da177e4SLinus Torvalds 	__u64 val = 0;
174d1434e03SHelge Deller 	ASM_EXCEPTIONTABLE_VAR(ret);
1751da177e4SLinus Torvalds 
1761da177e4SLinus Torvalds 	DPRINTF("load " RFMT ":" RFMT " to r%d for 8 bytes\n",
1771da177e4SLinus Torvalds 		regs->isr, regs->ior, toreg);
1781da177e4SLinus Torvalds 
179d1434e03SHelge Deller 	if (!IS_ENABLED(CONFIG_64BIT) && !flop)
180d1434e03SHelge Deller 		return ERR_NOTHANDLED;
181d1434e03SHelge Deller 
182d1434e03SHelge Deller #ifdef CONFIG_64BIT
1831da177e4SLinus Torvalds 	__asm__ __volatile__  (
184*51408b47SGuenter Roeck "	depd,z	%2,60,3,%3\n"		/* shift=(ofs&7)*8 */
185*51408b47SGuenter Roeck "	mtsp	%5, %%sr1\n"
186*51408b47SGuenter Roeck "	depd	%%r0,63,3,%2\n"
187*51408b47SGuenter Roeck "1:	ldd	0(%%sr1,%2),%0\n"
188*51408b47SGuenter Roeck "2:	ldd	8(%%sr1,%2),%4\n"
189*51408b47SGuenter Roeck "	subi	64,%3,%3\n"
190*51408b47SGuenter Roeck "	mtsar	%3\n"
191*51408b47SGuenter Roeck "	shrpd	%0,%4,%%sar,%0\n"
1921da177e4SLinus Torvalds "3:	\n"
193fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 3b, "%1")
194fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 3b, "%1")
195*51408b47SGuenter Roeck 	: "+r" (val), "+r" (ret), "+r" (saddr), "=&r" (shift), "=&r" (temp1)
196*51408b47SGuenter Roeck 	: "r" (regs->isr) );
1971da177e4SLinus Torvalds #else
1981da177e4SLinus Torvalds 	__asm__ __volatile__  (
199*51408b47SGuenter Roeck "	zdep	%2,29,2,%3\n"		/* shift=(ofs&3)*8 */
200427c1073SHelge Deller "	mtsp	%5, %%sr1\n"
201427c1073SHelge Deller "	dep	%%r0,31,2,%2\n"
202427c1073SHelge Deller "1:	ldw	0(%%sr1,%2),%0\n"
203427c1073SHelge Deller "2:	ldw	4(%%sr1,%2),%R0\n"
204427c1073SHelge Deller "3:	ldw	8(%%sr1,%2),%4\n"
205427c1073SHelge Deller "	subi	32,%3,%3\n"
206427c1073SHelge Deller "	mtsar	%3\n"
207427c1073SHelge Deller "	vshd	%0,%R0,%0\n"
208427c1073SHelge Deller "	vshd	%R0,%4,%R0\n"
2091da177e4SLinus Torvalds "4:	\n"
210fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 4b, "%1")
211fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 4b, "%1")
212fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(3b, 4b, "%1")
213427c1073SHelge Deller 	: "+r" (val), "+r" (ret), "+r" (saddr), "=&r" (shift), "=&r" (temp1)
214427c1073SHelge Deller 	: "r" (regs->isr) );
2151da177e4SLinus Torvalds #endif
2161da177e4SLinus Torvalds 
2171da177e4SLinus Torvalds 	DPRINTF("val = 0x%llx\n", val);
2181da177e4SLinus Torvalds 
2191da177e4SLinus Torvalds 	if (flop)
2201da177e4SLinus Torvalds 		regs->fr[toreg] = val;
2211da177e4SLinus Torvalds 	else if (toreg)
2221da177e4SLinus Torvalds 		regs->gr[toreg] = val;
2231da177e4SLinus Torvalds 
2241da177e4SLinus Torvalds 	return ret;
2251da177e4SLinus Torvalds }
2261da177e4SLinus Torvalds 
emulate_sth(struct pt_regs * regs,int frreg)2271da177e4SLinus Torvalds static int emulate_sth(struct pt_regs *regs, int frreg)
2281da177e4SLinus Torvalds {
2293029ce31SHelge Deller 	unsigned long val = regs->gr[frreg], temp1;
230d1434e03SHelge Deller 	ASM_EXCEPTIONTABLE_VAR(ret);
2311da177e4SLinus Torvalds 
2321da177e4SLinus Torvalds 	if (!frreg)
2331da177e4SLinus Torvalds 		val = 0;
2341da177e4SLinus Torvalds 
235e5e9e7f2SHelge Deller 	DPRINTF("store r%d (" RFMT ") to " RFMT ":" RFMT " for 2 bytes\n", frreg,
2361da177e4SLinus Torvalds 		val, regs->isr, regs->ior);
2371da177e4SLinus Torvalds 
2381da177e4SLinus Torvalds 	__asm__ __volatile__ (
2393029ce31SHelge Deller "	mtsp %4, %%sr1\n"
2403029ce31SHelge Deller "	extrw,u %2, 23, 8, %1\n"
2413029ce31SHelge Deller "1:	stb %1, 0(%%sr1, %3)\n"
2423029ce31SHelge Deller "2:	stb %2, 1(%%sr1, %3)\n"
2431da177e4SLinus Torvalds "3:	\n"
244fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 3b, "%0")
245fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 3b, "%0")
2463029ce31SHelge Deller 	: "+r" (ret), "=&r" (temp1)
2473029ce31SHelge Deller 	: "r" (val), "r" (regs->ior), "r" (regs->isr) );
2481da177e4SLinus Torvalds 
2491da177e4SLinus Torvalds 	return ret;
2501da177e4SLinus Torvalds }
2511da177e4SLinus Torvalds 
emulate_stw(struct pt_regs * regs,int frreg,int flop)2521da177e4SLinus Torvalds static int emulate_stw(struct pt_regs *regs, int frreg, int flop)
2531da177e4SLinus Torvalds {
2541da177e4SLinus Torvalds 	unsigned long val;
255d1434e03SHelge Deller 	ASM_EXCEPTIONTABLE_VAR(ret);
2561da177e4SLinus Torvalds 
2571da177e4SLinus Torvalds 	if (flop)
2581da177e4SLinus Torvalds 		val = ((__u32*)(regs->fr))[frreg];
2591da177e4SLinus Torvalds 	else if (frreg)
2601da177e4SLinus Torvalds 		val = regs->gr[frreg];
2611da177e4SLinus Torvalds 	else
2621da177e4SLinus Torvalds 		val = 0;
2631da177e4SLinus Torvalds 
264e5e9e7f2SHelge Deller 	DPRINTF("store r%d (" RFMT ") to " RFMT ":" RFMT " for 4 bytes\n", frreg,
2651da177e4SLinus Torvalds 		val, regs->isr, regs->ior);
2661da177e4SLinus Torvalds 
2671da177e4SLinus Torvalds 
2681da177e4SLinus Torvalds 	__asm__ __volatile__ (
2691da177e4SLinus Torvalds "	mtsp %3, %%sr1\n"
2701da177e4SLinus Torvalds "	zdep	%2, 28, 2, %%r19\n"
2711da177e4SLinus Torvalds "	dep	%%r0, 31, 2, %2\n"
2721da177e4SLinus Torvalds "	mtsar	%%r19\n"
2731da177e4SLinus Torvalds "	depwi,z	-2, %%sar, 32, %%r19\n"
2741da177e4SLinus Torvalds "1:	ldw	0(%%sr1,%2),%%r20\n"
2751da177e4SLinus Torvalds "2:	ldw	4(%%sr1,%2),%%r21\n"
2761da177e4SLinus Torvalds "	vshd	%%r0, %1, %%r22\n"
2771da177e4SLinus Torvalds "	vshd	%1, %%r0, %%r1\n"
2781da177e4SLinus Torvalds "	and	%%r20, %%r19, %%r20\n"
2791da177e4SLinus Torvalds "	andcm	%%r21, %%r19, %%r21\n"
2801da177e4SLinus Torvalds "	or	%%r22, %%r20, %%r20\n"
2811da177e4SLinus Torvalds "	or	%%r1, %%r21, %%r21\n"
2821da177e4SLinus Torvalds "	stw	%%r20,0(%%sr1,%2)\n"
2831da177e4SLinus Torvalds "	stw	%%r21,4(%%sr1,%2)\n"
2841da177e4SLinus Torvalds "3:	\n"
285fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 3b, "%0")
286fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 3b, "%0")
287d1434e03SHelge Deller 	: "+r" (ret)
2881da177e4SLinus Torvalds 	: "r" (val), "r" (regs->ior), "r" (regs->isr)
289d1434e03SHelge Deller 	: "r19", "r20", "r21", "r22", "r1" );
2901da177e4SLinus Torvalds 
291a9727983SHelge Deller 	return ret;
2921da177e4SLinus Torvalds }
emulate_std(struct pt_regs * regs,int frreg,int flop)2931da177e4SLinus Torvalds static int emulate_std(struct pt_regs *regs, int frreg, int flop)
2941da177e4SLinus Torvalds {
2951da177e4SLinus Torvalds 	__u64 val;
296d1434e03SHelge Deller 	ASM_EXCEPTIONTABLE_VAR(ret);
2971da177e4SLinus Torvalds 
2981da177e4SLinus Torvalds 	if (flop)
2991da177e4SLinus Torvalds 		val = regs->fr[frreg];
3001da177e4SLinus Torvalds 	else if (frreg)
3011da177e4SLinus Torvalds 		val = regs->gr[frreg];
3021da177e4SLinus Torvalds 	else
3031da177e4SLinus Torvalds 		val = 0;
3041da177e4SLinus Torvalds 
3051da177e4SLinus Torvalds 	DPRINTF("store r%d (0x%016llx) to " RFMT ":" RFMT " for 8 bytes\n", frreg,
3061da177e4SLinus Torvalds 		val,  regs->isr, regs->ior);
3071da177e4SLinus Torvalds 
308d1434e03SHelge Deller 	if (!IS_ENABLED(CONFIG_64BIT) && !flop)
309d1434e03SHelge Deller 		return ERR_NOTHANDLED;
310d1434e03SHelge Deller 
311d1434e03SHelge Deller #ifdef CONFIG_64BIT
3121da177e4SLinus Torvalds 	__asm__ __volatile__ (
3131da177e4SLinus Torvalds "	mtsp %3, %%sr1\n"
3141da177e4SLinus Torvalds "	depd,z	%2, 60, 3, %%r19\n"
3151da177e4SLinus Torvalds "	depd	%%r0, 63, 3, %2\n"
3161da177e4SLinus Torvalds "	mtsar	%%r19\n"
3171da177e4SLinus Torvalds "	depdi,z	-2, %%sar, 64, %%r19\n"
3181da177e4SLinus Torvalds "1:	ldd	0(%%sr1,%2),%%r20\n"
3191da177e4SLinus Torvalds "2:	ldd	8(%%sr1,%2),%%r21\n"
3201da177e4SLinus Torvalds "	shrpd	%%r0, %1, %%sar, %%r22\n"
3211da177e4SLinus Torvalds "	shrpd	%1, %%r0, %%sar, %%r1\n"
3221da177e4SLinus Torvalds "	and	%%r20, %%r19, %%r20\n"
3231da177e4SLinus Torvalds "	andcm	%%r21, %%r19, %%r21\n"
3241da177e4SLinus Torvalds "	or	%%r22, %%r20, %%r20\n"
3251da177e4SLinus Torvalds "	or	%%r1, %%r21, %%r21\n"
3261da177e4SLinus Torvalds "3:	std	%%r20,0(%%sr1,%2)\n"
3271da177e4SLinus Torvalds "4:	std	%%r21,8(%%sr1,%2)\n"
3281da177e4SLinus Torvalds "5:	\n"
329fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 5b, "%0")
330fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 5b, "%0")
331fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(3b, 5b, "%0")
332fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(4b, 5b, "%0")
333d1434e03SHelge Deller 	: "+r" (ret)
3341da177e4SLinus Torvalds 	: "r" (val), "r" (regs->ior), "r" (regs->isr)
335d1434e03SHelge Deller 	: "r19", "r20", "r21", "r22", "r1" );
3361da177e4SLinus Torvalds #else
3371da177e4SLinus Torvalds     {
3381da177e4SLinus Torvalds 	__asm__ __volatile__ (
33998a9d5f0SHelge Deller "	mtsp	%3, %%sr1\n"
34098a9d5f0SHelge Deller "	zdep	%R1, 29, 2, %%r19\n"
34198a9d5f0SHelge Deller "	dep	%%r0, 31, 2, %2\n"
3421da177e4SLinus Torvalds "	mtsar	%%r19\n"
3431da177e4SLinus Torvalds "	zvdepi	-2, 32, %%r19\n"
34498a9d5f0SHelge Deller "1:	ldw	0(%%sr1,%2),%%r20\n"
34598a9d5f0SHelge Deller "2:	ldw	8(%%sr1,%2),%%r21\n"
34698a9d5f0SHelge Deller "	vshd	%1, %R1, %%r1\n"
3471da177e4SLinus Torvalds "	vshd	%%r0, %1, %1\n"
34898a9d5f0SHelge Deller "	vshd	%R1, %%r0, %R1\n"
3491da177e4SLinus Torvalds "	and	%%r20, %%r19, %%r20\n"
3501da177e4SLinus Torvalds "	andcm	%%r21, %%r19, %%r21\n"
3511da177e4SLinus Torvalds "	or	%1, %%r20, %1\n"
35298a9d5f0SHelge Deller "	or	%R1, %%r21, %R1\n"
35398a9d5f0SHelge Deller "3:	stw	%1,0(%%sr1,%2)\n"
35498a9d5f0SHelge Deller "4:	stw	%%r1,4(%%sr1,%2)\n"
35598a9d5f0SHelge Deller "5:	stw	%R1,8(%%sr1,%2)\n"
3561da177e4SLinus Torvalds "6:	\n"
357fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 6b, "%0")
358fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 6b, "%0")
359fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(3b, 6b, "%0")
360fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(4b, 6b, "%0")
361fa69a806SHelge Deller 	ASM_EXCEPTIONTABLE_ENTRY_EFAULT(5b, 6b, "%0")
362d1434e03SHelge Deller 	: "+r" (ret)
36398a9d5f0SHelge Deller 	: "r" (val), "r" (regs->ior), "r" (regs->isr)
364d1434e03SHelge Deller 	: "r19", "r20", "r21", "r1" );
3651da177e4SLinus Torvalds     }
3661da177e4SLinus Torvalds #endif
3671da177e4SLinus Torvalds 
3681da177e4SLinus Torvalds 	return ret;
3691da177e4SLinus Torvalds }
3701da177e4SLinus Torvalds 
handle_unaligned(struct pt_regs * regs)3711da177e4SLinus Torvalds void handle_unaligned(struct pt_regs *regs)
3721da177e4SLinus Torvalds {
3736ee77658SAkinobu Mita 	static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 5);
3741da177e4SLinus Torvalds 	unsigned long newbase = R1(regs->iir)?regs->gr[R1(regs->iir)]:0;
3751da177e4SLinus Torvalds 	int modify = 0;
3761da177e4SLinus Torvalds 	int ret = ERR_NOTHANDLED;
3771da177e4SLinus Torvalds 
378d0c3be80SHelge Deller 	__inc_irq_stat(irq_unaligned_count);
379d0c3be80SHelge Deller 
3801da177e4SLinus Torvalds 	/* log a message with pacing */
381f053725bSKyle McMartin 	if (user_mode(regs)) {
382f053725bSKyle McMartin 		if (current->thread.flags & PARISC_UAC_SIGBUS) {
383f053725bSKyle McMartin 			goto force_sigbus;
384f053725bSKyle McMartin 		}
385f053725bSKyle McMartin 
3866ee77658SAkinobu Mita 		if (!(current->thread.flags & PARISC_UAC_NOPRINT) &&
3876ee77658SAkinobu Mita 			__ratelimit(&ratelimit)) {
388e5e9e7f2SHelge Deller 			printk(KERN_WARNING "%s(%d): unaligned access to " RFMT
389e5e9e7f2SHelge Deller 				" at ip " RFMT " (iir " RFMT ")\n",
390e5e9e7f2SHelge Deller 				current->comm, task_pid_nr(current), regs->ior,
391e5e9e7f2SHelge Deller 				regs->iaoq[0], regs->iir);
3921da177e4SLinus Torvalds #ifdef DEBUG_UNALIGNED
3931da177e4SLinus Torvalds 			show_regs(regs);
3941da177e4SLinus Torvalds #endif
3951da177e4SLinus Torvalds 		}
396f053725bSKyle McMartin 
3971da177e4SLinus Torvalds 		if (!unaligned_enabled)
3981da177e4SLinus Torvalds 			goto force_sigbus;
3991da177e4SLinus Torvalds 	}
4001da177e4SLinus Torvalds 
4011da177e4SLinus Torvalds 	/* handle modification - OK, it's ugly, see the instruction manual */
4021da177e4SLinus Torvalds 	switch (MAJOR_OP(regs->iir))
4031da177e4SLinus Torvalds 	{
4041da177e4SLinus Torvalds 	case 0x03:
4051da177e4SLinus Torvalds 	case 0x09:
4061da177e4SLinus Torvalds 	case 0x0b:
4071da177e4SLinus Torvalds 		if (regs->iir&0x20)
4081da177e4SLinus Torvalds 		{
4091da177e4SLinus Torvalds 			modify = 1;
4101da177e4SLinus Torvalds 			if (regs->iir&0x1000)		/* short loads */
4111da177e4SLinus Torvalds 				if (regs->iir&0x200)
4121da177e4SLinus Torvalds 					newbase += IM5_3(regs->iir);
4131da177e4SLinus Torvalds 				else
4141da177e4SLinus Torvalds 					newbase += IM5_2(regs->iir);
4151da177e4SLinus Torvalds 			else if (regs->iir&0x2000)	/* scaled indexed */
4161da177e4SLinus Torvalds 			{
4171da177e4SLinus Torvalds 				int shift=0;
4181da177e4SLinus Torvalds 				switch (regs->iir & OPCODE1_MASK)
4191da177e4SLinus Torvalds 				{
4201da177e4SLinus Torvalds 				case OPCODE_LDH_I:
4211da177e4SLinus Torvalds 					shift= 1; break;
4221da177e4SLinus Torvalds 				case OPCODE_LDW_I:
4231da177e4SLinus Torvalds 					shift= 2; break;
4241da177e4SLinus Torvalds 				case OPCODE_LDD_I:
4251da177e4SLinus Torvalds 				case OPCODE_LDDA_I:
4261da177e4SLinus Torvalds 					shift= 3; break;
4271da177e4SLinus Torvalds 				}
4281da177e4SLinus Torvalds 				newbase += (R2(regs->iir)?regs->gr[R2(regs->iir)]:0)<<shift;
4291da177e4SLinus Torvalds 			} else				/* simple indexed */
4301da177e4SLinus Torvalds 				newbase += (R2(regs->iir)?regs->gr[R2(regs->iir)]:0);
4311da177e4SLinus Torvalds 		}
4321da177e4SLinus Torvalds 		break;
4331da177e4SLinus Torvalds 	case 0x13:
4341da177e4SLinus Torvalds 	case 0x1b:
4351da177e4SLinus Torvalds 		modify = 1;
4361da177e4SLinus Torvalds 		newbase += IM14(regs->iir);
4371da177e4SLinus Torvalds 		break;
4381da177e4SLinus Torvalds 	case 0x14:
4391da177e4SLinus Torvalds 	case 0x1c:
4401da177e4SLinus Torvalds 		if (regs->iir&8)
4411da177e4SLinus Torvalds 		{
4421da177e4SLinus Torvalds 			modify = 1;
4431da177e4SLinus Torvalds 			newbase += IM14(regs->iir&~0xe);
4441da177e4SLinus Torvalds 		}
4451da177e4SLinus Torvalds 		break;
4461da177e4SLinus Torvalds 	case 0x16:
4471da177e4SLinus Torvalds 	case 0x1e:
4481da177e4SLinus Torvalds 		modify = 1;
4491da177e4SLinus Torvalds 		newbase += IM14(regs->iir&6);
4501da177e4SLinus Torvalds 		break;
4511da177e4SLinus Torvalds 	case 0x17:
4521da177e4SLinus Torvalds 	case 0x1f:
4531da177e4SLinus Torvalds 		if (regs->iir&4)
4541da177e4SLinus Torvalds 		{
4551da177e4SLinus Torvalds 			modify = 1;
4561da177e4SLinus Torvalds 			newbase += IM14(regs->iir&~4);
4571da177e4SLinus Torvalds 		}
4581da177e4SLinus Torvalds 		break;
4591da177e4SLinus Torvalds 	}
4601da177e4SLinus Torvalds 
4611da177e4SLinus Torvalds 	/* TODO: make this cleaner... */
4621da177e4SLinus Torvalds 	switch (regs->iir & OPCODE1_MASK)
4631da177e4SLinus Torvalds 	{
4641da177e4SLinus Torvalds 	case OPCODE_LDH_I:
4651da177e4SLinus Torvalds 	case OPCODE_LDH_S:
4661da177e4SLinus Torvalds 		ret = emulate_ldh(regs, R3(regs->iir));
4671da177e4SLinus Torvalds 		break;
4681da177e4SLinus Torvalds 
4691da177e4SLinus Torvalds 	case OPCODE_LDW_I:
4701da177e4SLinus Torvalds 	case OPCODE_LDWA_I:
4711da177e4SLinus Torvalds 	case OPCODE_LDW_S:
4721da177e4SLinus Torvalds 	case OPCODE_LDWA_S:
4731da177e4SLinus Torvalds 		ret = emulate_ldw(regs, R3(regs->iir), 0);
4741da177e4SLinus Torvalds 		break;
4751da177e4SLinus Torvalds 
4761da177e4SLinus Torvalds 	case OPCODE_STH:
4771da177e4SLinus Torvalds 		ret = emulate_sth(regs, R2(regs->iir));
4781da177e4SLinus Torvalds 		break;
4791da177e4SLinus Torvalds 
4801da177e4SLinus Torvalds 	case OPCODE_STW:
4811da177e4SLinus Torvalds 	case OPCODE_STWA:
4821da177e4SLinus Torvalds 		ret = emulate_stw(regs, R2(regs->iir), 0);
4831da177e4SLinus Torvalds 		break;
4841da177e4SLinus Torvalds 
485d1434e03SHelge Deller #ifdef CONFIG_64BIT
4861da177e4SLinus Torvalds 	case OPCODE_LDD_I:
4871da177e4SLinus Torvalds 	case OPCODE_LDDA_I:
4881da177e4SLinus Torvalds 	case OPCODE_LDD_S:
4891da177e4SLinus Torvalds 	case OPCODE_LDDA_S:
4901da177e4SLinus Torvalds 		ret = emulate_ldd(regs, R3(regs->iir), 0);
4911da177e4SLinus Torvalds 		break;
4921da177e4SLinus Torvalds 
4931da177e4SLinus Torvalds 	case OPCODE_STD:
4941da177e4SLinus Torvalds 	case OPCODE_STDA:
4951da177e4SLinus Torvalds 		ret = emulate_std(regs, R2(regs->iir), 0);
4961da177e4SLinus Torvalds 		break;
4971da177e4SLinus Torvalds #endif
4981da177e4SLinus Torvalds 
4991da177e4SLinus Torvalds 	case OPCODE_FLDWX:
5001da177e4SLinus Torvalds 	case OPCODE_FLDWS:
5011da177e4SLinus Torvalds 	case OPCODE_FLDWXR:
5021da177e4SLinus Torvalds 	case OPCODE_FLDWSR:
5031da177e4SLinus Torvalds 		ret = emulate_ldw(regs, FR3(regs->iir), 1);
5041da177e4SLinus Torvalds 		break;
5051da177e4SLinus Torvalds 
5061da177e4SLinus Torvalds 	case OPCODE_FLDDX:
5071da177e4SLinus Torvalds 	case OPCODE_FLDDS:
5081da177e4SLinus Torvalds 		ret = emulate_ldd(regs, R3(regs->iir), 1);
5091da177e4SLinus Torvalds 		break;
5101da177e4SLinus Torvalds 
5111da177e4SLinus Torvalds 	case OPCODE_FSTWX:
5121da177e4SLinus Torvalds 	case OPCODE_FSTWS:
5131da177e4SLinus Torvalds 	case OPCODE_FSTWXR:
5141da177e4SLinus Torvalds 	case OPCODE_FSTWSR:
5151da177e4SLinus Torvalds 		ret = emulate_stw(regs, FR3(regs->iir), 1);
5161da177e4SLinus Torvalds 		break;
5171da177e4SLinus Torvalds 
5181da177e4SLinus Torvalds 	case OPCODE_FSTDX:
5191da177e4SLinus Torvalds 	case OPCODE_FSTDS:
5201da177e4SLinus Torvalds 		ret = emulate_std(regs, R3(regs->iir), 1);
5211da177e4SLinus Torvalds 		break;
5221da177e4SLinus Torvalds 
5231da177e4SLinus Torvalds 	case OPCODE_LDCD_I:
5241da177e4SLinus Torvalds 	case OPCODE_LDCW_I:
5251da177e4SLinus Torvalds 	case OPCODE_LDCD_S:
5261da177e4SLinus Torvalds 	case OPCODE_LDCW_S:
5271da177e4SLinus Torvalds 		ret = ERR_NOTHANDLED;	/* "undefined", but lets kill them. */
5281da177e4SLinus Torvalds 		break;
5291da177e4SLinus Torvalds 	}
5301da177e4SLinus Torvalds 	switch (regs->iir & OPCODE2_MASK)
5311da177e4SLinus Torvalds 	{
5321da177e4SLinus Torvalds 	case OPCODE_FLDD_L:
5331da177e4SLinus Torvalds 		ret = emulate_ldd(regs,R2(regs->iir),1);
5341da177e4SLinus Torvalds 		break;
5351da177e4SLinus Torvalds 	case OPCODE_FSTD_L:
5361da177e4SLinus Torvalds 		ret = emulate_std(regs, R2(regs->iir),1);
5371da177e4SLinus Torvalds 		break;
538d1434e03SHelge Deller #ifdef CONFIG_64BIT
5391da177e4SLinus Torvalds 	case OPCODE_LDD_L:
5401da177e4SLinus Torvalds 		ret = emulate_ldd(regs, R2(regs->iir),0);
5411da177e4SLinus Torvalds 		break;
5421da177e4SLinus Torvalds 	case OPCODE_STD_L:
5431da177e4SLinus Torvalds 		ret = emulate_std(regs, R2(regs->iir),0);
5441da177e4SLinus Torvalds 		break;
5451da177e4SLinus Torvalds #endif
546dd2288f4SHelge Deller 	}
5471da177e4SLinus Torvalds 	switch (regs->iir & OPCODE3_MASK)
5481da177e4SLinus Torvalds 	{
5491da177e4SLinus Torvalds 	case OPCODE_FLDW_L:
550a9727983SHelge Deller 		ret = emulate_ldw(regs, R2(regs->iir), 1);
5511da177e4SLinus Torvalds 		break;
5521da177e4SLinus Torvalds 	case OPCODE_LDW_M:
553a9727983SHelge Deller 		ret = emulate_ldw(regs, R2(regs->iir), 0);
5541da177e4SLinus Torvalds 		break;
5551da177e4SLinus Torvalds 
5561da177e4SLinus Torvalds 	case OPCODE_FSTW_L:
5571da177e4SLinus Torvalds 		ret = emulate_stw(regs, R2(regs->iir),1);
5581da177e4SLinus Torvalds 		break;
5591da177e4SLinus Torvalds 	case OPCODE_STW_M:
5601da177e4SLinus Torvalds 		ret = emulate_stw(regs, R2(regs->iir),0);
5611da177e4SLinus Torvalds 		break;
5621da177e4SLinus Torvalds 	}
5631da177e4SLinus Torvalds 	switch (regs->iir & OPCODE4_MASK)
5641da177e4SLinus Torvalds 	{
5651da177e4SLinus Torvalds 	case OPCODE_LDH_L:
5661da177e4SLinus Torvalds 		ret = emulate_ldh(regs, R2(regs->iir));
5671da177e4SLinus Torvalds 		break;
5681da177e4SLinus Torvalds 	case OPCODE_LDW_L:
5691da177e4SLinus Torvalds 	case OPCODE_LDWM:
5701da177e4SLinus Torvalds 		ret = emulate_ldw(regs, R2(regs->iir),0);
5711da177e4SLinus Torvalds 		break;
5721da177e4SLinus Torvalds 	case OPCODE_STH_L:
5731da177e4SLinus Torvalds 		ret = emulate_sth(regs, R2(regs->iir));
5741da177e4SLinus Torvalds 		break;
5751da177e4SLinus Torvalds 	case OPCODE_STW_L:
5761da177e4SLinus Torvalds 	case OPCODE_STWM:
5771da177e4SLinus Torvalds 		ret = emulate_stw(regs, R2(regs->iir),0);
5781da177e4SLinus Torvalds 		break;
5791da177e4SLinus Torvalds 	}
5801da177e4SLinus Torvalds 
5818b78f260SHelge Deller 	if (ret == 0 && modify && R1(regs->iir))
5821da177e4SLinus Torvalds 		regs->gr[R1(regs->iir)] = newbase;
5831da177e4SLinus Torvalds 
5841da177e4SLinus Torvalds 
5851da177e4SLinus Torvalds 	if (ret == ERR_NOTHANDLED)
5861da177e4SLinus Torvalds 		printk(KERN_CRIT "Not-handled unaligned insn 0x%08lx\n", regs->iir);
5871da177e4SLinus Torvalds 
5881da177e4SLinus Torvalds 	DPRINTF("ret = %d\n", ret);
5891da177e4SLinus Torvalds 
5901da177e4SLinus Torvalds 	if (ret)
5911da177e4SLinus Torvalds 	{
5928b78f260SHelge Deller 		/*
5938b78f260SHelge Deller 		 * The unaligned handler failed.
5948b78f260SHelge Deller 		 * If we were called by __get_user() or __put_user() jump
5958b78f260SHelge Deller 		 * to it's exception fixup handler instead of crashing.
5968b78f260SHelge Deller 		 */
5978b78f260SHelge Deller 		if (!user_mode(regs) && fixup_exception(regs))
5988b78f260SHelge Deller 			return;
5998b78f260SHelge Deller 
6001da177e4SLinus Torvalds 		printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret);
6011da177e4SLinus Torvalds 		die_if_kernel("Unaligned data reference", regs, 28);
6021da177e4SLinus Torvalds 
603d1434e03SHelge Deller 		if (ret == -EFAULT)
6041da177e4SLinus Torvalds 		{
605ccf75290SEric W. Biederman 			force_sig_fault(SIGSEGV, SEGV_MAPERR,
6062e1661d2SEric W. Biederman 					(void __user *)regs->ior);
6071da177e4SLinus Torvalds 		}
6081da177e4SLinus Torvalds 		else
6091da177e4SLinus Torvalds 		{
6101da177e4SLinus Torvalds force_sigbus:
6111da177e4SLinus Torvalds 			/* couldn't handle it ... */
612ccf75290SEric W. Biederman 			force_sig_fault(SIGBUS, BUS_ADRALN,
6132e1661d2SEric W. Biederman 					(void __user *)regs->ior);
6141da177e4SLinus Torvalds 		}
6151da177e4SLinus Torvalds 
6161da177e4SLinus Torvalds 		return;
6171da177e4SLinus Torvalds 	}
6181da177e4SLinus Torvalds 
6191da177e4SLinus Torvalds 	/* else we handled it, let life go on. */
6201da177e4SLinus Torvalds 	regs->gr[0]|=PSW_N;
6211da177e4SLinus Torvalds }
6221da177e4SLinus Torvalds 
6231da177e4SLinus Torvalds /*
6241da177e4SLinus Torvalds  * NB: check_unaligned() is only used for PCXS processors right
6251da177e4SLinus Torvalds  * now, so we only check for PA1.1 encodings at this point.
6261da177e4SLinus Torvalds  */
6271da177e4SLinus Torvalds 
6281da177e4SLinus Torvalds int
check_unaligned(struct pt_regs * regs)6291da177e4SLinus Torvalds check_unaligned(struct pt_regs *regs)
6301da177e4SLinus Torvalds {
6311da177e4SLinus Torvalds 	unsigned long align_mask;
6321da177e4SLinus Torvalds 
6331da177e4SLinus Torvalds 	/* Get alignment mask */
6341da177e4SLinus Torvalds 
6351da177e4SLinus Torvalds 	align_mask = 0UL;
6361da177e4SLinus Torvalds 	switch (regs->iir & OPCODE1_MASK) {
6371da177e4SLinus Torvalds 
6381da177e4SLinus Torvalds 	case OPCODE_LDH_I:
6391da177e4SLinus Torvalds 	case OPCODE_LDH_S:
6401da177e4SLinus Torvalds 	case OPCODE_STH:
6411da177e4SLinus Torvalds 		align_mask = 1UL;
6421da177e4SLinus Torvalds 		break;
6431da177e4SLinus Torvalds 
6441da177e4SLinus Torvalds 	case OPCODE_LDW_I:
6451da177e4SLinus Torvalds 	case OPCODE_LDWA_I:
6461da177e4SLinus Torvalds 	case OPCODE_LDW_S:
6471da177e4SLinus Torvalds 	case OPCODE_LDWA_S:
6481da177e4SLinus Torvalds 	case OPCODE_STW:
6491da177e4SLinus Torvalds 	case OPCODE_STWA:
6501da177e4SLinus Torvalds 		align_mask = 3UL;
6511da177e4SLinus Torvalds 		break;
6521da177e4SLinus Torvalds 
6531da177e4SLinus Torvalds 	default:
6541da177e4SLinus Torvalds 		switch (regs->iir & OPCODE4_MASK) {
6551da177e4SLinus Torvalds 		case OPCODE_LDH_L:
6561da177e4SLinus Torvalds 		case OPCODE_STH_L:
6571da177e4SLinus Torvalds 			align_mask = 1UL;
6581da177e4SLinus Torvalds 			break;
6591da177e4SLinus Torvalds 		case OPCODE_LDW_L:
6601da177e4SLinus Torvalds 		case OPCODE_LDWM:
6611da177e4SLinus Torvalds 		case OPCODE_STW_L:
6621da177e4SLinus Torvalds 		case OPCODE_STWM:
6631da177e4SLinus Torvalds 			align_mask = 3UL;
6641da177e4SLinus Torvalds 			break;
6651da177e4SLinus Torvalds 		}
6661da177e4SLinus Torvalds 		break;
6671da177e4SLinus Torvalds 	}
6681da177e4SLinus Torvalds 
6691da177e4SLinus Torvalds 	return (int)(regs->ior & align_mask);
6701da177e4SLinus Torvalds }
6711da177e4SLinus Torvalds 
672