xref: /openbmc/linux/arch/powerpc/lib/sstep.c (revision ecc23d0a422a3118fcf6e4f0a46e17a6c2047b02)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
214cf11afSPaul Mackerras /*
314cf11afSPaul Mackerras  * Single-step support.
414cf11afSPaul Mackerras  *
514cf11afSPaul Mackerras  * Copyright (C) 2004 Paul Mackerras <paulus@au.ibm.com>, IBM
614cf11afSPaul Mackerras  */
714cf11afSPaul Mackerras #include <linux/kernel.h>
80d69a052SGui,Jian #include <linux/kprobes.h>
914cf11afSPaul Mackerras #include <linux/ptrace.h>
10268bb0ceSLinus Torvalds #include <linux/prefetch.h>
1114cf11afSPaul Mackerras #include <asm/sstep.h>
1214cf11afSPaul Mackerras #include <asm/processor.h>
137c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
145e9d0e3dSMichael Ellerman #include <asm/cpu_has_feature.h>
150016a4cfSPaul Mackerras #include <asm/cputable.h>
1650b80a12SJordan Niethe #include <asm/disassemble.h>
1714cf11afSPaul Mackerras 
18c032524fSPaul Mackerras #ifdef CONFIG_PPC64
1914cf11afSPaul Mackerras /* Bits in SRR1 that are copied from MSR */
20af308377SStephen Rothwell #define MSR_MASK	0xffffffff87c0ffffUL
21c032524fSPaul Mackerras #else
22c032524fSPaul Mackerras #define MSR_MASK	0x87c0ffff
23c032524fSPaul Mackerras #endif
2414cf11afSPaul Mackerras 
250016a4cfSPaul Mackerras /* Bits in XER */
260016a4cfSPaul Mackerras #define XER_SO		0x80000000U
270016a4cfSPaul Mackerras #define XER_OV		0x40000000U
280016a4cfSPaul Mackerras #define XER_CA		0x20000000U
29924c8febSSandipan Das #define XER_OV32	0x00080000U
30924c8febSSandipan Das #define XER_CA32	0x00040000U
310016a4cfSPaul Mackerras 
32af99da74SBalamuruhan S #ifdef CONFIG_VSX
33af99da74SBalamuruhan S #define VSX_REGISTER_XTP(rd)   ((((rd) & 1) << 5) | ((rd) & 0xfe))
34af99da74SBalamuruhan S #endif
35af99da74SBalamuruhan S 
36cd64d169SSean MacLennan #ifdef CONFIG_PPC_FPU
370016a4cfSPaul Mackerras /*
380016a4cfSPaul Mackerras  * Functions in ldstfp.S
390016a4cfSPaul Mackerras  */
40c22435a5SPaul Mackerras extern void get_fpr(int rn, double *p);
41c22435a5SPaul Mackerras extern void put_fpr(int rn, const double *p);
42c22435a5SPaul Mackerras extern void get_vr(int rn, __vector128 *p);
43c22435a5SPaul Mackerras extern void put_vr(int rn, __vector128 *p);
44350779a2SPaul Mackerras extern void load_vsrn(int vsr, const void *p);
45350779a2SPaul Mackerras extern void store_vsrn(int vsr, void *p);
46350779a2SPaul Mackerras extern void conv_sp_to_dp(const float *sp, double *dp);
47350779a2SPaul Mackerras extern void conv_dp_to_sp(const double *dp, float *sp);
48350779a2SPaul Mackerras #endif
49350779a2SPaul Mackerras 
50350779a2SPaul Mackerras #ifdef __powerpc64__
51350779a2SPaul Mackerras /*
52350779a2SPaul Mackerras  * Functions in quad.S
53350779a2SPaul Mackerras  */
54350779a2SPaul Mackerras extern int do_lq(unsigned long ea, unsigned long *regs);
55350779a2SPaul Mackerras extern int do_stq(unsigned long ea, unsigned long val0, unsigned long val1);
56350779a2SPaul Mackerras extern int do_lqarx(unsigned long ea, unsigned long *regs);
57350779a2SPaul Mackerras extern int do_stqcx(unsigned long ea, unsigned long val0, unsigned long val1,
58350779a2SPaul Mackerras 		    unsigned int *crp);
59350779a2SPaul Mackerras #endif
60350779a2SPaul Mackerras 
61350779a2SPaul Mackerras #ifdef __LITTLE_ENDIAN__
62350779a2SPaul Mackerras #define IS_LE	1
63350779a2SPaul Mackerras #define IS_BE	0
64350779a2SPaul Mackerras #else
65350779a2SPaul Mackerras #define IS_LE	0
66350779a2SPaul Mackerras #define IS_BE	1
67cd64d169SSean MacLennan #endif
680016a4cfSPaul Mackerras 
6914cf11afSPaul Mackerras /*
70b91e136cSMichael Ellerman  * Emulate the truncation of 64 bit values in 32-bit mode.
71b91e136cSMichael Ellerman  */
truncate_if_32bit(unsigned long msr,unsigned long val)7271f6e58eSNaveen N. Rao static nokprobe_inline unsigned long truncate_if_32bit(unsigned long msr,
7371f6e58eSNaveen N. Rao 							unsigned long val)
74b91e136cSMichael Ellerman {
75b91e136cSMichael Ellerman 	if ((msr & MSR_64BIT) == 0)
76b91e136cSMichael Ellerman 		val &= 0xffffffffUL;
77b91e136cSMichael Ellerman 	return val;
78b91e136cSMichael Ellerman }
79b91e136cSMichael Ellerman 
80b91e136cSMichael Ellerman /*
8114cf11afSPaul Mackerras  * Determine whether a conditional branch instruction would branch.
8214cf11afSPaul Mackerras  */
branch_taken(unsigned int instr,const struct pt_regs * regs,struct instruction_op * op)833cdfcbfdSPaul Mackerras static nokprobe_inline int branch_taken(unsigned int instr,
843cdfcbfdSPaul Mackerras 					const struct pt_regs *regs,
853cdfcbfdSPaul Mackerras 					struct instruction_op *op)
8614cf11afSPaul Mackerras {
8714cf11afSPaul Mackerras 	unsigned int bo = (instr >> 21) & 0x1f;
8814cf11afSPaul Mackerras 	unsigned int bi;
8914cf11afSPaul Mackerras 
9014cf11afSPaul Mackerras 	if ((bo & 4) == 0) {
9114cf11afSPaul Mackerras 		/* decrement counter */
923cdfcbfdSPaul Mackerras 		op->type |= DECCTR;
933cdfcbfdSPaul Mackerras 		if (((bo >> 1) & 1) ^ (regs->ctr == 1))
9414cf11afSPaul Mackerras 			return 0;
9514cf11afSPaul Mackerras 	}
9614cf11afSPaul Mackerras 	if ((bo & 0x10) == 0) {
9714cf11afSPaul Mackerras 		/* check bit from CR */
9814cf11afSPaul Mackerras 		bi = (instr >> 16) & 0x1f;
9914cf11afSPaul Mackerras 		if (((regs->ccr >> (31 - bi)) & 1) != ((bo >> 3) & 1))
10014cf11afSPaul Mackerras 			return 0;
10114cf11afSPaul Mackerras 	}
10214cf11afSPaul Mackerras 	return 1;
10314cf11afSPaul Mackerras }
10414cf11afSPaul Mackerras 
address_ok(struct pt_regs * regs,unsigned long ea,int nb)105b9da9c8aSPaul Mackerras static nokprobe_inline long address_ok(struct pt_regs *regs,
106b9da9c8aSPaul Mackerras 				       unsigned long ea, int nb)
1070016a4cfSPaul Mackerras {
1080016a4cfSPaul Mackerras 	if (!user_mode(regs))
1090016a4cfSPaul Mackerras 		return 1;
11023fc539eSArnd Bergmann 	if (access_ok((void __user *)ea, nb))
111b9da9c8aSPaul Mackerras 		return 1;
11223fc539eSArnd Bergmann 	if (access_ok((void __user *)ea, 1))
113b9da9c8aSPaul Mackerras 		/* Access overlaps the end of the user region */
1145ae4998bSChristoph Hellwig 		regs->dar = TASK_SIZE_MAX - 1;
115b9da9c8aSPaul Mackerras 	else
116b9da9c8aSPaul Mackerras 		regs->dar = ea;
117b9da9c8aSPaul Mackerras 	return 0;
1180016a4cfSPaul Mackerras }
1190016a4cfSPaul Mackerras 
12014cf11afSPaul Mackerras /*
1210016a4cfSPaul Mackerras  * Calculate effective address for a D-form instruction
1220016a4cfSPaul Mackerras  */
dform_ea(unsigned int instr,const struct pt_regs * regs)1233cdfcbfdSPaul Mackerras static nokprobe_inline unsigned long dform_ea(unsigned int instr,
1243cdfcbfdSPaul Mackerras 					      const struct pt_regs *regs)
1250016a4cfSPaul Mackerras {
1260016a4cfSPaul Mackerras 	int ra;
1270016a4cfSPaul Mackerras 	unsigned long ea;
1280016a4cfSPaul Mackerras 
1290016a4cfSPaul Mackerras 	ra = (instr >> 16) & 0x1f;
1300016a4cfSPaul Mackerras 	ea = (signed short) instr;		/* sign-extend */
131be96f633SPaul Mackerras 	if (ra)
1320016a4cfSPaul Mackerras 		ea += regs->gpr[ra];
133b91e136cSMichael Ellerman 
134d120cdbcSPaul Mackerras 	return ea;
1350016a4cfSPaul Mackerras }
1360016a4cfSPaul Mackerras 
1370016a4cfSPaul Mackerras #ifdef __powerpc64__
1380016a4cfSPaul Mackerras /*
1390016a4cfSPaul Mackerras  * Calculate effective address for a DS-form instruction
1400016a4cfSPaul Mackerras  */
dsform_ea(unsigned int instr,const struct pt_regs * regs)1413cdfcbfdSPaul Mackerras static nokprobe_inline unsigned long dsform_ea(unsigned int instr,
1423cdfcbfdSPaul Mackerras 					       const struct pt_regs *regs)
1430016a4cfSPaul Mackerras {
1440016a4cfSPaul Mackerras 	int ra;
1450016a4cfSPaul Mackerras 	unsigned long ea;
1460016a4cfSPaul Mackerras 
1470016a4cfSPaul Mackerras 	ra = (instr >> 16) & 0x1f;
1480016a4cfSPaul Mackerras 	ea = (signed short) (instr & ~3);	/* sign-extend */
149be96f633SPaul Mackerras 	if (ra)
1500016a4cfSPaul Mackerras 		ea += regs->gpr[ra];
151b91e136cSMichael Ellerman 
152d120cdbcSPaul Mackerras 	return ea;
1530016a4cfSPaul Mackerras }
154350779a2SPaul Mackerras 
155350779a2SPaul Mackerras /*
156350779a2SPaul Mackerras  * Calculate effective address for a DQ-form instruction
157350779a2SPaul Mackerras  */
dqform_ea(unsigned int instr,const struct pt_regs * regs)158350779a2SPaul Mackerras static nokprobe_inline unsigned long dqform_ea(unsigned int instr,
159350779a2SPaul Mackerras 					       const struct pt_regs *regs)
160350779a2SPaul Mackerras {
161350779a2SPaul Mackerras 	int ra;
162350779a2SPaul Mackerras 	unsigned long ea;
163350779a2SPaul Mackerras 
164350779a2SPaul Mackerras 	ra = (instr >> 16) & 0x1f;
165350779a2SPaul Mackerras 	ea = (signed short) (instr & ~0xf);	/* sign-extend */
166350779a2SPaul Mackerras 	if (ra)
167350779a2SPaul Mackerras 		ea += regs->gpr[ra];
168350779a2SPaul Mackerras 
169d120cdbcSPaul Mackerras 	return ea;
170350779a2SPaul Mackerras }
1710016a4cfSPaul Mackerras #endif /* __powerpc64 */
1720016a4cfSPaul Mackerras 
1730016a4cfSPaul Mackerras /*
1740016a4cfSPaul Mackerras  * Calculate effective address for an X-form instruction
1750016a4cfSPaul Mackerras  */
xform_ea(unsigned int instr,const struct pt_regs * regs)17671f6e58eSNaveen N. Rao static nokprobe_inline unsigned long xform_ea(unsigned int instr,
1773cdfcbfdSPaul Mackerras 					      const struct pt_regs *regs)
1780016a4cfSPaul Mackerras {
1790016a4cfSPaul Mackerras 	int ra, rb;
1800016a4cfSPaul Mackerras 	unsigned long ea;
1810016a4cfSPaul Mackerras 
1820016a4cfSPaul Mackerras 	ra = (instr >> 16) & 0x1f;
1830016a4cfSPaul Mackerras 	rb = (instr >> 11) & 0x1f;
1840016a4cfSPaul Mackerras 	ea = regs->gpr[rb];
185be96f633SPaul Mackerras 	if (ra)
1860016a4cfSPaul Mackerras 		ea += regs->gpr[ra];
187b91e136cSMichael Ellerman 
188d120cdbcSPaul Mackerras 	return ea;
1890016a4cfSPaul Mackerras }
1900016a4cfSPaul Mackerras 
1910016a4cfSPaul Mackerras /*
19250b80a12SJordan Niethe  * Calculate effective address for a MLS:D-form / 8LS:D-form
19350b80a12SJordan Niethe  * prefixed instruction
19450b80a12SJordan Niethe  */
mlsd_8lsd_ea(unsigned int instr,unsigned int suffix,const struct pt_regs * regs)19550b80a12SJordan Niethe static nokprobe_inline unsigned long mlsd_8lsd_ea(unsigned int instr,
19650b80a12SJordan Niethe 						  unsigned int suffix,
19750b80a12SJordan Niethe 						  const struct pt_regs *regs)
19850b80a12SJordan Niethe {
19950b80a12SJordan Niethe 	int ra, prefix_r;
20050b80a12SJordan Niethe 	unsigned int  dd;
20150b80a12SJordan Niethe 	unsigned long ea, d0, d1, d;
20250b80a12SJordan Niethe 
20368a180a4SBalamuruhan S 	prefix_r = GET_PREFIX_R(instr);
20468a180a4SBalamuruhan S 	ra = GET_PREFIX_RA(suffix);
20550b80a12SJordan Niethe 
20650b80a12SJordan Niethe 	d0 = instr & 0x3ffff;
20750b80a12SJordan Niethe 	d1 = suffix & 0xffff;
20850b80a12SJordan Niethe 	d = (d0 << 16) | d1;
20950b80a12SJordan Niethe 
21050b80a12SJordan Niethe 	/*
21150b80a12SJordan Niethe 	 * sign extend a 34 bit number
21250b80a12SJordan Niethe 	 */
21350b80a12SJordan Niethe 	dd = (unsigned int)(d >> 2);
21450b80a12SJordan Niethe 	ea = (signed int)dd;
21550b80a12SJordan Niethe 	ea = (ea << 2) | (d & 0x3);
21650b80a12SJordan Niethe 
21750b80a12SJordan Niethe 	if (!prefix_r && ra)
21850b80a12SJordan Niethe 		ea += regs->gpr[ra];
21950b80a12SJordan Niethe 	else if (!prefix_r && !ra)
22050b80a12SJordan Niethe 		; /* Leave ea as is */
2215ab187e0SCédric Le Goater 	else if (prefix_r)
22250b80a12SJordan Niethe 		ea += regs->nip;
2235ab187e0SCédric Le Goater 
2245ab187e0SCédric Le Goater 	/*
2255ab187e0SCédric Le Goater 	 * (prefix_r && ra) is an invalid form. Should already be
2265ab187e0SCédric Le Goater 	 * checked for by caller!
2275ab187e0SCédric Le Goater 	 */
22850b80a12SJordan Niethe 
22950b80a12SJordan Niethe 	return ea;
23050b80a12SJordan Niethe }
23150b80a12SJordan Niethe 
23250b80a12SJordan Niethe /*
2330016a4cfSPaul Mackerras  * Return the largest power of 2, not greater than sizeof(unsigned long),
2340016a4cfSPaul Mackerras  * such that x is a multiple of it.
2350016a4cfSPaul Mackerras  */
max_align(unsigned long x)23671f6e58eSNaveen N. Rao static nokprobe_inline unsigned long max_align(unsigned long x)
2370016a4cfSPaul Mackerras {
2380016a4cfSPaul Mackerras 	x |= sizeof(unsigned long);
2390016a4cfSPaul Mackerras 	return x & -x;		/* isolates rightmost bit */
2400016a4cfSPaul Mackerras }
2410016a4cfSPaul Mackerras 
byterev_2(unsigned long x)24271f6e58eSNaveen N. Rao static nokprobe_inline unsigned long byterev_2(unsigned long x)
2430016a4cfSPaul Mackerras {
2440016a4cfSPaul Mackerras 	return ((x >> 8) & 0xff) | ((x & 0xff) << 8);
2450016a4cfSPaul Mackerras }
2460016a4cfSPaul Mackerras 
byterev_4(unsigned long x)24771f6e58eSNaveen N. Rao static nokprobe_inline unsigned long byterev_4(unsigned long x)
2480016a4cfSPaul Mackerras {
2490016a4cfSPaul Mackerras 	return ((x >> 24) & 0xff) | ((x >> 8) & 0xff00) |
2500016a4cfSPaul Mackerras 		((x & 0xff00) << 8) | ((x & 0xff) << 24);
2510016a4cfSPaul Mackerras }
2520016a4cfSPaul Mackerras 
2530016a4cfSPaul Mackerras #ifdef __powerpc64__
byterev_8(unsigned long x)25471f6e58eSNaveen N. Rao static nokprobe_inline unsigned long byterev_8(unsigned long x)
2550016a4cfSPaul Mackerras {
2560016a4cfSPaul Mackerras 	return (byterev_4(x) << 32) | byterev_4(x >> 32);
2570016a4cfSPaul Mackerras }
2580016a4cfSPaul Mackerras #endif
2590016a4cfSPaul Mackerras 
do_byte_reverse(void * ptr,int nb)260d955189aSPaul Mackerras static nokprobe_inline void do_byte_reverse(void *ptr, int nb)
261d955189aSPaul Mackerras {
262d955189aSPaul Mackerras 	switch (nb) {
263d955189aSPaul Mackerras 	case 2:
264d955189aSPaul Mackerras 		*(u16 *)ptr = byterev_2(*(u16 *)ptr);
265d955189aSPaul Mackerras 		break;
266d955189aSPaul Mackerras 	case 4:
267d955189aSPaul Mackerras 		*(u32 *)ptr = byterev_4(*(u32 *)ptr);
268d955189aSPaul Mackerras 		break;
269d955189aSPaul Mackerras #ifdef __powerpc64__
270d955189aSPaul Mackerras 	case 8:
271d955189aSPaul Mackerras 		*(unsigned long *)ptr = byterev_8(*(unsigned long *)ptr);
272d955189aSPaul Mackerras 		break;
273d955189aSPaul Mackerras 	case 16: {
274d955189aSPaul Mackerras 		unsigned long *up = (unsigned long *)ptr;
275d955189aSPaul Mackerras 		unsigned long tmp;
276d955189aSPaul Mackerras 		tmp = byterev_8(up[0]);
277d955189aSPaul Mackerras 		up[0] = byterev_8(up[1]);
278d955189aSPaul Mackerras 		up[1] = tmp;
279d955189aSPaul Mackerras 		break;
280d955189aSPaul Mackerras 	}
281af99da74SBalamuruhan S 	case 32: {
282af99da74SBalamuruhan S 		unsigned long *up = (unsigned long *)ptr;
283af99da74SBalamuruhan S 		unsigned long tmp;
284af99da74SBalamuruhan S 
285af99da74SBalamuruhan S 		tmp = byterev_8(up[0]);
286af99da74SBalamuruhan S 		up[0] = byterev_8(up[3]);
287af99da74SBalamuruhan S 		up[3] = tmp;
288af99da74SBalamuruhan S 		tmp = byterev_8(up[2]);
289af99da74SBalamuruhan S 		up[2] = byterev_8(up[1]);
290af99da74SBalamuruhan S 		up[1] = tmp;
291af99da74SBalamuruhan S 		break;
292af99da74SBalamuruhan S 	}
293af99da74SBalamuruhan S 
294d955189aSPaul Mackerras #endif
295d955189aSPaul Mackerras 	default:
296d955189aSPaul Mackerras 		WARN_ON_ONCE(1);
297d955189aSPaul Mackerras 	}
298d955189aSPaul Mackerras }
299d955189aSPaul Mackerras 
300e28d0b67SChristophe Leroy static __always_inline int
__read_mem_aligned(unsigned long * dest,unsigned long ea,int nb,struct pt_regs * regs)301e28d0b67SChristophe Leroy __read_mem_aligned(unsigned long *dest, unsigned long ea, int nb, struct pt_regs *regs)
3020016a4cfSPaul Mackerras {
3030016a4cfSPaul Mackerras 	unsigned long x = 0;
3040016a4cfSPaul Mackerras 
3050016a4cfSPaul Mackerras 	switch (nb) {
3060016a4cfSPaul Mackerras 	case 1:
307e28d0b67SChristophe Leroy 		unsafe_get_user(x, (unsigned char __user *)ea, Efault);
3080016a4cfSPaul Mackerras 		break;
3090016a4cfSPaul Mackerras 	case 2:
310e28d0b67SChristophe Leroy 		unsafe_get_user(x, (unsigned short __user *)ea, Efault);
3110016a4cfSPaul Mackerras 		break;
3120016a4cfSPaul Mackerras 	case 4:
313e28d0b67SChristophe Leroy 		unsafe_get_user(x, (unsigned int __user *)ea, Efault);
3140016a4cfSPaul Mackerras 		break;
3150016a4cfSPaul Mackerras #ifdef __powerpc64__
3160016a4cfSPaul Mackerras 	case 8:
317e28d0b67SChristophe Leroy 		unsafe_get_user(x, (unsigned long __user *)ea, Efault);
3180016a4cfSPaul Mackerras 		break;
3190016a4cfSPaul Mackerras #endif
3200016a4cfSPaul Mackerras 	}
3210016a4cfSPaul Mackerras 	*dest = x;
322e28d0b67SChristophe Leroy 	return 0;
323e28d0b67SChristophe Leroy 
324e28d0b67SChristophe Leroy Efault:
325b9da9c8aSPaul Mackerras 	regs->dar = ea;
326e28d0b67SChristophe Leroy 	return -EFAULT;
327e28d0b67SChristophe Leroy }
328e28d0b67SChristophe Leroy 
329e28d0b67SChristophe Leroy static nokprobe_inline int
read_mem_aligned(unsigned long * dest,unsigned long ea,int nb,struct pt_regs * regs)330e28d0b67SChristophe Leroy read_mem_aligned(unsigned long *dest, unsigned long ea, int nb, struct pt_regs *regs)
331e28d0b67SChristophe Leroy {
332e28d0b67SChristophe Leroy 	int err;
333e28d0b67SChristophe Leroy 
334e28d0b67SChristophe Leroy 	if (is_kernel_addr(ea))
335e28d0b67SChristophe Leroy 		return __read_mem_aligned(dest, ea, nb, regs);
336e28d0b67SChristophe Leroy 
337e28d0b67SChristophe Leroy 	if (user_read_access_begin((void __user *)ea, nb)) {
338e28d0b67SChristophe Leroy 		err = __read_mem_aligned(dest, ea, nb, regs);
339e28d0b67SChristophe Leroy 		user_read_access_end();
340e28d0b67SChristophe Leroy 	} else {
341e28d0b67SChristophe Leroy 		err = -EFAULT;
342e28d0b67SChristophe Leroy 		regs->dar = ea;
343e28d0b67SChristophe Leroy 	}
344e28d0b67SChristophe Leroy 
3450016a4cfSPaul Mackerras 	return err;
3460016a4cfSPaul Mackerras }
3470016a4cfSPaul Mackerras 
348e0a0986bSPaul Mackerras /*
349e0a0986bSPaul Mackerras  * Copy from userspace to a buffer, using the largest possible
350e0a0986bSPaul Mackerras  * aligned accesses, up to sizeof(long).
351e0a0986bSPaul Mackerras  */
__copy_mem_in(u8 * dest,unsigned long ea,int nb,struct pt_regs * regs)352e28d0b67SChristophe Leroy static __always_inline int __copy_mem_in(u8 *dest, unsigned long ea, int nb, struct pt_regs *regs)
3530016a4cfSPaul Mackerras {
354e0a0986bSPaul Mackerras 	int c;
3550016a4cfSPaul Mackerras 
3560016a4cfSPaul Mackerras 	for (; nb > 0; nb -= c) {
3570016a4cfSPaul Mackerras 		c = max_align(ea);
3580016a4cfSPaul Mackerras 		if (c > nb)
3590016a4cfSPaul Mackerras 			c = max_align(nb);
360e0a0986bSPaul Mackerras 		switch (c) {
361e0a0986bSPaul Mackerras 		case 1:
362e28d0b67SChristophe Leroy 			unsafe_get_user(*dest, (u8 __user *)ea, Efault);
363e0a0986bSPaul Mackerras 			break;
3646506b471STom Musta 		case 2:
365e28d0b67SChristophe Leroy 			unsafe_get_user(*(u16 *)dest, (u16 __user *)ea, Efault);
3666506b471STom Musta 			break;
3676506b471STom Musta 		case 4:
368e28d0b67SChristophe Leroy 			unsafe_get_user(*(u32 *)dest, (u32 __user *)ea, Efault);
3696506b471STom Musta 			break;
3706506b471STom Musta #ifdef __powerpc64__
3716506b471STom Musta 		case 8:
372e28d0b67SChristophe Leroy 			unsafe_get_user(*(u64 *)dest, (u64 __user *)ea, Efault);
3736506b471STom Musta 			break;
3746506b471STom Musta #endif
3756506b471STom Musta 		}
376e0a0986bSPaul Mackerras 		dest += c;
377e0a0986bSPaul Mackerras 		ea += c;
378e0a0986bSPaul Mackerras 	}
3790016a4cfSPaul Mackerras 	return 0;
380e28d0b67SChristophe Leroy 
381e28d0b67SChristophe Leroy Efault:
382e28d0b67SChristophe Leroy 	regs->dar = ea;
383e28d0b67SChristophe Leroy 	return -EFAULT;
384e28d0b67SChristophe Leroy }
385e28d0b67SChristophe Leroy 
copy_mem_in(u8 * dest,unsigned long ea,int nb,struct pt_regs * regs)386e28d0b67SChristophe Leroy static nokprobe_inline int copy_mem_in(u8 *dest, unsigned long ea, int nb, struct pt_regs *regs)
387e28d0b67SChristophe Leroy {
388e28d0b67SChristophe Leroy 	int err;
389e28d0b67SChristophe Leroy 
390e28d0b67SChristophe Leroy 	if (is_kernel_addr(ea))
391e28d0b67SChristophe Leroy 		return __copy_mem_in(dest, ea, nb, regs);
392e28d0b67SChristophe Leroy 
393e28d0b67SChristophe Leroy 	if (user_read_access_begin((void __user *)ea, nb)) {
394e28d0b67SChristophe Leroy 		err = __copy_mem_in(dest, ea, nb, regs);
395e28d0b67SChristophe Leroy 		user_read_access_end();
396e28d0b67SChristophe Leroy 	} else {
397e28d0b67SChristophe Leroy 		err = -EFAULT;
398e28d0b67SChristophe Leroy 		regs->dar = ea;
399e28d0b67SChristophe Leroy 	}
400e28d0b67SChristophe Leroy 
401e28d0b67SChristophe Leroy 	return err;
4020016a4cfSPaul Mackerras }
4030016a4cfSPaul Mackerras 
read_mem_unaligned(unsigned long * dest,unsigned long ea,int nb,struct pt_regs * regs)404e0a0986bSPaul Mackerras static nokprobe_inline int read_mem_unaligned(unsigned long *dest,
405e0a0986bSPaul Mackerras 					      unsigned long ea, int nb,
406e0a0986bSPaul Mackerras 					      struct pt_regs *regs)
407e0a0986bSPaul Mackerras {
408e0a0986bSPaul Mackerras 	union {
409e0a0986bSPaul Mackerras 		unsigned long ul;
410e0a0986bSPaul Mackerras 		u8 b[sizeof(unsigned long)];
411e0a0986bSPaul Mackerras 	} u;
412e0a0986bSPaul Mackerras 	int i;
413e0a0986bSPaul Mackerras 	int err;
414e0a0986bSPaul Mackerras 
415e0a0986bSPaul Mackerras 	u.ul = 0;
416e0a0986bSPaul Mackerras 	i = IS_BE ? sizeof(unsigned long) - nb : 0;
417b9da9c8aSPaul Mackerras 	err = copy_mem_in(&u.b[i], ea, nb, regs);
418e0a0986bSPaul Mackerras 	if (!err)
419e0a0986bSPaul Mackerras 		*dest = u.ul;
420e0a0986bSPaul Mackerras 	return err;
421e0a0986bSPaul Mackerras }
422e0a0986bSPaul Mackerras 
4230016a4cfSPaul Mackerras /*
4240016a4cfSPaul Mackerras  * Read memory at address ea for nb bytes, return 0 for success
425e0a0986bSPaul Mackerras  * or -EFAULT if an error occurred.  N.B. nb must be 1, 2, 4 or 8.
426e0a0986bSPaul Mackerras  * If nb < sizeof(long), the result is right-justified on BE systems.
4270016a4cfSPaul Mackerras  */
read_mem(unsigned long * dest,unsigned long ea,int nb,struct pt_regs * regs)42871f6e58eSNaveen N. Rao static int read_mem(unsigned long *dest, unsigned long ea, int nb,
4290016a4cfSPaul Mackerras 			      struct pt_regs *regs)
4300016a4cfSPaul Mackerras {
4310016a4cfSPaul Mackerras 	if (!address_ok(regs, ea, nb))
4320016a4cfSPaul Mackerras 		return -EFAULT;
4330016a4cfSPaul Mackerras 	if ((ea & (nb - 1)) == 0)
434b9da9c8aSPaul Mackerras 		return read_mem_aligned(dest, ea, nb, regs);
4350016a4cfSPaul Mackerras 	return read_mem_unaligned(dest, ea, nb, regs);
4360016a4cfSPaul Mackerras }
43771f6e58eSNaveen N. Rao NOKPROBE_SYMBOL(read_mem);
4380016a4cfSPaul Mackerras 
439e28d0b67SChristophe Leroy static __always_inline int
__write_mem_aligned(unsigned long val,unsigned long ea,int nb,struct pt_regs * regs)440e28d0b67SChristophe Leroy __write_mem_aligned(unsigned long val, unsigned long ea, int nb, struct pt_regs *regs)
4410016a4cfSPaul Mackerras {
4420016a4cfSPaul Mackerras 	switch (nb) {
4430016a4cfSPaul Mackerras 	case 1:
444e28d0b67SChristophe Leroy 		unsafe_put_user(val, (unsigned char __user *)ea, Efault);
4450016a4cfSPaul Mackerras 		break;
4460016a4cfSPaul Mackerras 	case 2:
447e28d0b67SChristophe Leroy 		unsafe_put_user(val, (unsigned short __user *)ea, Efault);
4480016a4cfSPaul Mackerras 		break;
4490016a4cfSPaul Mackerras 	case 4:
450e28d0b67SChristophe Leroy 		unsafe_put_user(val, (unsigned int __user *)ea, Efault);
4510016a4cfSPaul Mackerras 		break;
4520016a4cfSPaul Mackerras #ifdef __powerpc64__
4530016a4cfSPaul Mackerras 	case 8:
454e28d0b67SChristophe Leroy 		unsafe_put_user(val, (unsigned long __user *)ea, Efault);
4550016a4cfSPaul Mackerras 		break;
4560016a4cfSPaul Mackerras #endif
4570016a4cfSPaul Mackerras 	}
458e28d0b67SChristophe Leroy 	return 0;
459e28d0b67SChristophe Leroy 
460e28d0b67SChristophe Leroy Efault:
461b9da9c8aSPaul Mackerras 	regs->dar = ea;
462e28d0b67SChristophe Leroy 	return -EFAULT;
463e28d0b67SChristophe Leroy }
464e28d0b67SChristophe Leroy 
465e28d0b67SChristophe Leroy static nokprobe_inline int
write_mem_aligned(unsigned long val,unsigned long ea,int nb,struct pt_regs * regs)466e28d0b67SChristophe Leroy write_mem_aligned(unsigned long val, unsigned long ea, int nb, struct pt_regs *regs)
467e28d0b67SChristophe Leroy {
468e28d0b67SChristophe Leroy 	int err;
469e28d0b67SChristophe Leroy 
470e28d0b67SChristophe Leroy 	if (is_kernel_addr(ea))
471e28d0b67SChristophe Leroy 		return __write_mem_aligned(val, ea, nb, regs);
472e28d0b67SChristophe Leroy 
473e28d0b67SChristophe Leroy 	if (user_write_access_begin((void __user *)ea, nb)) {
474e28d0b67SChristophe Leroy 		err = __write_mem_aligned(val, ea, nb, regs);
475e28d0b67SChristophe Leroy 		user_write_access_end();
476e28d0b67SChristophe Leroy 	} else {
477e28d0b67SChristophe Leroy 		err = -EFAULT;
478e28d0b67SChristophe Leroy 		regs->dar = ea;
479e28d0b67SChristophe Leroy 	}
480e28d0b67SChristophe Leroy 
4810016a4cfSPaul Mackerras 	return err;
4820016a4cfSPaul Mackerras }
4830016a4cfSPaul Mackerras 
484e0a0986bSPaul Mackerras /*
485e0a0986bSPaul Mackerras  * Copy from a buffer to userspace, using the largest possible
486e0a0986bSPaul Mackerras  * aligned accesses, up to sizeof(long).
487e0a0986bSPaul Mackerras  */
__copy_mem_out(u8 * dest,unsigned long ea,int nb,struct pt_regs * regs)4880d5769f9SChristophe Leroy static __always_inline int __copy_mem_out(u8 *dest, unsigned long ea, int nb, struct pt_regs *regs)
4890016a4cfSPaul Mackerras {
490e0a0986bSPaul Mackerras 	int c;
4910016a4cfSPaul Mackerras 
492e0a0986bSPaul Mackerras 	for (; nb > 0; nb -= c) {
493e0a0986bSPaul Mackerras 		c = max_align(ea);
494e0a0986bSPaul Mackerras 		if (c > nb)
495e0a0986bSPaul Mackerras 			c = max_align(nb);
496e0a0986bSPaul Mackerras 		switch (c) {
497e0a0986bSPaul Mackerras 		case 1:
498e28d0b67SChristophe Leroy 			unsafe_put_user(*dest, (u8 __user *)ea, Efault);
499e0a0986bSPaul Mackerras 			break;
5006506b471STom Musta 		case 2:
501e28d0b67SChristophe Leroy 			unsafe_put_user(*(u16 *)dest, (u16 __user *)ea, Efault);
5026506b471STom Musta 			break;
5036506b471STom Musta 		case 4:
504e28d0b67SChristophe Leroy 			unsafe_put_user(*(u32 *)dest, (u32 __user *)ea, Efault);
5056506b471STom Musta 			break;
5066506b471STom Musta #ifdef __powerpc64__
5076506b471STom Musta 		case 8:
508e28d0b67SChristophe Leroy 			unsafe_put_user(*(u64 *)dest, (u64 __user *)ea, Efault);
5096506b471STom Musta 			break;
5106506b471STom Musta #endif
5116506b471STom Musta 		}
512e0a0986bSPaul Mackerras 		dest += c;
51317e8de7eSTom Musta 		ea += c;
5140016a4cfSPaul Mackerras 	}
5150016a4cfSPaul Mackerras 	return 0;
516e28d0b67SChristophe Leroy 
517e28d0b67SChristophe Leroy Efault:
518e28d0b67SChristophe Leroy 	regs->dar = ea;
519e28d0b67SChristophe Leroy 	return -EFAULT;
520e28d0b67SChristophe Leroy }
521e28d0b67SChristophe Leroy 
copy_mem_out(u8 * dest,unsigned long ea,int nb,struct pt_regs * regs)522e28d0b67SChristophe Leroy static nokprobe_inline int copy_mem_out(u8 *dest, unsigned long ea, int nb, struct pt_regs *regs)
523e28d0b67SChristophe Leroy {
524e28d0b67SChristophe Leroy 	int err;
525e28d0b67SChristophe Leroy 
526e28d0b67SChristophe Leroy 	if (is_kernel_addr(ea))
527e28d0b67SChristophe Leroy 		return __copy_mem_out(dest, ea, nb, regs);
528e28d0b67SChristophe Leroy 
529e28d0b67SChristophe Leroy 	if (user_write_access_begin((void __user *)ea, nb)) {
530e28d0b67SChristophe Leroy 		err = __copy_mem_out(dest, ea, nb, regs);
531e28d0b67SChristophe Leroy 		user_write_access_end();
532e28d0b67SChristophe Leroy 	} else {
533e28d0b67SChristophe Leroy 		err = -EFAULT;
534e28d0b67SChristophe Leroy 		regs->dar = ea;
535e28d0b67SChristophe Leroy 	}
536e28d0b67SChristophe Leroy 
537e28d0b67SChristophe Leroy 	return err;
5380016a4cfSPaul Mackerras }
5390016a4cfSPaul Mackerras 
write_mem_unaligned(unsigned long val,unsigned long ea,int nb,struct pt_regs * regs)540e0a0986bSPaul Mackerras static nokprobe_inline int write_mem_unaligned(unsigned long val,
541e0a0986bSPaul Mackerras 					       unsigned long ea, int nb,
542e0a0986bSPaul Mackerras 					       struct pt_regs *regs)
543e0a0986bSPaul Mackerras {
544e0a0986bSPaul Mackerras 	union {
545e0a0986bSPaul Mackerras 		unsigned long ul;
546e0a0986bSPaul Mackerras 		u8 b[sizeof(unsigned long)];
547e0a0986bSPaul Mackerras 	} u;
548e0a0986bSPaul Mackerras 	int i;
549e0a0986bSPaul Mackerras 
550e0a0986bSPaul Mackerras 	u.ul = val;
551e0a0986bSPaul Mackerras 	i = IS_BE ? sizeof(unsigned long) - nb : 0;
552b9da9c8aSPaul Mackerras 	return copy_mem_out(&u.b[i], ea, nb, regs);
553e0a0986bSPaul Mackerras }
554e0a0986bSPaul Mackerras 
5550016a4cfSPaul Mackerras /*
5560016a4cfSPaul Mackerras  * Write memory at address ea for nb bytes, return 0 for success
557e0a0986bSPaul Mackerras  * or -EFAULT if an error occurred.  N.B. nb must be 1, 2, 4 or 8.
5580016a4cfSPaul Mackerras  */
write_mem(unsigned long val,unsigned long ea,int nb,struct pt_regs * regs)55971f6e58eSNaveen N. Rao static int write_mem(unsigned long val, unsigned long ea, int nb,
5600016a4cfSPaul Mackerras 			       struct pt_regs *regs)
5610016a4cfSPaul Mackerras {
5620016a4cfSPaul Mackerras 	if (!address_ok(regs, ea, nb))
5630016a4cfSPaul Mackerras 		return -EFAULT;
5640016a4cfSPaul Mackerras 	if ((ea & (nb - 1)) == 0)
565b9da9c8aSPaul Mackerras 		return write_mem_aligned(val, ea, nb, regs);
5660016a4cfSPaul Mackerras 	return write_mem_unaligned(val, ea, nb, regs);
5670016a4cfSPaul Mackerras }
56871f6e58eSNaveen N. Rao NOKPROBE_SYMBOL(write_mem);
5690016a4cfSPaul Mackerras 
570cd64d169SSean MacLennan #ifdef CONFIG_PPC_FPU
5710016a4cfSPaul Mackerras /*
572c22435a5SPaul Mackerras  * These access either the real FP register or the image in the
573c22435a5SPaul Mackerras  * thread_struct, depending on regs->msr & MSR_FP.
5740016a4cfSPaul Mackerras  */
do_fp_load(struct instruction_op * op,unsigned long ea,struct pt_regs * regs,bool cross_endian)575d2b65ac6SPaul Mackerras static int do_fp_load(struct instruction_op *op, unsigned long ea,
576d2b65ac6SPaul Mackerras 		      struct pt_regs *regs, bool cross_endian)
5770016a4cfSPaul Mackerras {
578d2b65ac6SPaul Mackerras 	int err, rn, nb;
579c22435a5SPaul Mackerras 	union {
580d2b65ac6SPaul Mackerras 		int i;
581d2b65ac6SPaul Mackerras 		unsigned int u;
582c22435a5SPaul Mackerras 		float f;
5831f41fb79SPaul Mackerras 		double d[2];
5841f41fb79SPaul Mackerras 		unsigned long l[2];
5851f41fb79SPaul Mackerras 		u8 b[2 * sizeof(double)];
586c22435a5SPaul Mackerras 	} u;
5870016a4cfSPaul Mackerras 
588d2b65ac6SPaul Mackerras 	nb = GETSIZE(op->type);
58928b8ba8eSNaveen N Rao 	if (nb > sizeof(u))
59028b8ba8eSNaveen N Rao 		return -EINVAL;
5910016a4cfSPaul Mackerras 	if (!address_ok(regs, ea, nb))
5920016a4cfSPaul Mackerras 		return -EFAULT;
593d2b65ac6SPaul Mackerras 	rn = op->reg;
594b9da9c8aSPaul Mackerras 	err = copy_mem_in(u.b, ea, nb, regs);
5950016a4cfSPaul Mackerras 	if (err)
5960016a4cfSPaul Mackerras 		return err;
597d955189aSPaul Mackerras 	if (unlikely(cross_endian)) {
598d955189aSPaul Mackerras 		do_byte_reverse(u.b, min(nb, 8));
599d955189aSPaul Mackerras 		if (nb == 16)
600d955189aSPaul Mackerras 			do_byte_reverse(&u.b[8], 8);
601d955189aSPaul Mackerras 	}
602c22435a5SPaul Mackerras 	preempt_disable();
603d2b65ac6SPaul Mackerras 	if (nb == 4) {
604d2b65ac6SPaul Mackerras 		if (op->type & FPCONV)
6051f41fb79SPaul Mackerras 			conv_sp_to_dp(&u.f, &u.d[0]);
606d2b65ac6SPaul Mackerras 		else if (op->type & SIGNEXT)
607d2b65ac6SPaul Mackerras 			u.l[0] = u.i;
608d2b65ac6SPaul Mackerras 		else
609d2b65ac6SPaul Mackerras 			u.l[0] = u.u;
610d2b65ac6SPaul Mackerras 	}
611c22435a5SPaul Mackerras 	if (regs->msr & MSR_FP)
6121f41fb79SPaul Mackerras 		put_fpr(rn, &u.d[0]);
613c22435a5SPaul Mackerras 	else
6141f41fb79SPaul Mackerras 		current->thread.TS_FPR(rn) = u.l[0];
6151f41fb79SPaul Mackerras 	if (nb == 16) {
6161f41fb79SPaul Mackerras 		/* lfdp */
6171f41fb79SPaul Mackerras 		rn |= 1;
6181f41fb79SPaul Mackerras 		if (regs->msr & MSR_FP)
6191f41fb79SPaul Mackerras 			put_fpr(rn, &u.d[1]);
6201f41fb79SPaul Mackerras 		else
6211f41fb79SPaul Mackerras 			current->thread.TS_FPR(rn) = u.l[1];
6221f41fb79SPaul Mackerras 	}
623c22435a5SPaul Mackerras 	preempt_enable();
624c22435a5SPaul Mackerras 	return 0;
6250016a4cfSPaul Mackerras }
62671f6e58eSNaveen N. Rao NOKPROBE_SYMBOL(do_fp_load);
6270016a4cfSPaul Mackerras 
do_fp_store(struct instruction_op * op,unsigned long ea,struct pt_regs * regs,bool cross_endian)628d2b65ac6SPaul Mackerras static int do_fp_store(struct instruction_op *op, unsigned long ea,
629d2b65ac6SPaul Mackerras 		       struct pt_regs *regs, bool cross_endian)
6300016a4cfSPaul Mackerras {
631d2b65ac6SPaul Mackerras 	int rn, nb;
632c22435a5SPaul Mackerras 	union {
633d2b65ac6SPaul Mackerras 		unsigned int u;
634c22435a5SPaul Mackerras 		float f;
6351f41fb79SPaul Mackerras 		double d[2];
6361f41fb79SPaul Mackerras 		unsigned long l[2];
6371f41fb79SPaul Mackerras 		u8 b[2 * sizeof(double)];
638c22435a5SPaul Mackerras 	} u;
6390016a4cfSPaul Mackerras 
640d2b65ac6SPaul Mackerras 	nb = GETSIZE(op->type);
64128b8ba8eSNaveen N Rao 	if (nb > sizeof(u))
64228b8ba8eSNaveen N Rao 		return -EINVAL;
6430016a4cfSPaul Mackerras 	if (!address_ok(regs, ea, nb))
6440016a4cfSPaul Mackerras 		return -EFAULT;
645d2b65ac6SPaul Mackerras 	rn = op->reg;
646c22435a5SPaul Mackerras 	preempt_disable();
647c22435a5SPaul Mackerras 	if (regs->msr & MSR_FP)
6481f41fb79SPaul Mackerras 		get_fpr(rn, &u.d[0]);
649c22435a5SPaul Mackerras 	else
6501f41fb79SPaul Mackerras 		u.l[0] = current->thread.TS_FPR(rn);
651d2b65ac6SPaul Mackerras 	if (nb == 4) {
652d2b65ac6SPaul Mackerras 		if (op->type & FPCONV)
6531f41fb79SPaul Mackerras 			conv_dp_to_sp(&u.d[0], &u.f);
654d2b65ac6SPaul Mackerras 		else
655d2b65ac6SPaul Mackerras 			u.u = u.l[0];
656d2b65ac6SPaul Mackerras 	}
6571f41fb79SPaul Mackerras 	if (nb == 16) {
6581f41fb79SPaul Mackerras 		rn |= 1;
6591f41fb79SPaul Mackerras 		if (regs->msr & MSR_FP)
6601f41fb79SPaul Mackerras 			get_fpr(rn, &u.d[1]);
6611f41fb79SPaul Mackerras 		else
6621f41fb79SPaul Mackerras 			u.l[1] = current->thread.TS_FPR(rn);
6631f41fb79SPaul Mackerras 	}
664c22435a5SPaul Mackerras 	preempt_enable();
665d955189aSPaul Mackerras 	if (unlikely(cross_endian)) {
666d955189aSPaul Mackerras 		do_byte_reverse(u.b, min(nb, 8));
667d955189aSPaul Mackerras 		if (nb == 16)
668d955189aSPaul Mackerras 			do_byte_reverse(&u.b[8], 8);
669d955189aSPaul Mackerras 	}
670b9da9c8aSPaul Mackerras 	return copy_mem_out(u.b, ea, nb, regs);
6710016a4cfSPaul Mackerras }
67271f6e58eSNaveen N. Rao NOKPROBE_SYMBOL(do_fp_store);
673cd64d169SSean MacLennan #endif
6740016a4cfSPaul Mackerras 
6750016a4cfSPaul Mackerras #ifdef CONFIG_ALTIVEC
6760016a4cfSPaul Mackerras /* For Altivec/VMX, no need to worry about alignment */
do_vec_load(int rn,unsigned long ea,int size,struct pt_regs * regs,bool cross_endian)677c22435a5SPaul Mackerras static nokprobe_inline int do_vec_load(int rn, unsigned long ea,
678d955189aSPaul Mackerras 				       int size, struct pt_regs *regs,
679d955189aSPaul Mackerras 				       bool cross_endian)
6800016a4cfSPaul Mackerras {
681c22435a5SPaul Mackerras 	int err;
682c22435a5SPaul Mackerras 	union {
683c22435a5SPaul Mackerras 		__vector128 v;
684c22435a5SPaul Mackerras 		u8 b[sizeof(__vector128)];
685c22435a5SPaul Mackerras 	} u = {};
686c22435a5SPaul Mackerras 
68728b8ba8eSNaveen N Rao 	if (size > sizeof(u))
68828b8ba8eSNaveen N Rao 		return -EINVAL;
68928b8ba8eSNaveen N Rao 
6900016a4cfSPaul Mackerras 	if (!address_ok(regs, ea & ~0xfUL, 16))
6910016a4cfSPaul Mackerras 		return -EFAULT;
692c22435a5SPaul Mackerras 	/* align to multiple of size */
693c22435a5SPaul Mackerras 	ea &= ~(size - 1);
694b9da9c8aSPaul Mackerras 	err = copy_mem_in(&u.b[ea & 0xf], ea, size, regs);
695c22435a5SPaul Mackerras 	if (err)
696c22435a5SPaul Mackerras 		return err;
697d955189aSPaul Mackerras 	if (unlikely(cross_endian))
698d955189aSPaul Mackerras 		do_byte_reverse(&u.b[ea & 0xf], size);
699c22435a5SPaul Mackerras 	preempt_disable();
700c22435a5SPaul Mackerras 	if (regs->msr & MSR_VEC)
701c22435a5SPaul Mackerras 		put_vr(rn, &u.v);
702c22435a5SPaul Mackerras 	else
703c22435a5SPaul Mackerras 		current->thread.vr_state.vr[rn] = u.v;
704c22435a5SPaul Mackerras 	preempt_enable();
705c22435a5SPaul Mackerras 	return 0;
7060016a4cfSPaul Mackerras }
7070016a4cfSPaul Mackerras 
do_vec_store(int rn,unsigned long ea,int size,struct pt_regs * regs,bool cross_endian)708c22435a5SPaul Mackerras static nokprobe_inline int do_vec_store(int rn, unsigned long ea,
709d955189aSPaul Mackerras 					int size, struct pt_regs *regs,
710d955189aSPaul Mackerras 					bool cross_endian)
7110016a4cfSPaul Mackerras {
712c22435a5SPaul Mackerras 	union {
713c22435a5SPaul Mackerras 		__vector128 v;
714c22435a5SPaul Mackerras 		u8 b[sizeof(__vector128)];
715c22435a5SPaul Mackerras 	} u;
716c22435a5SPaul Mackerras 
71728b8ba8eSNaveen N Rao 	if (size > sizeof(u))
71828b8ba8eSNaveen N Rao 		return -EINVAL;
71928b8ba8eSNaveen N Rao 
7200016a4cfSPaul Mackerras 	if (!address_ok(regs, ea & ~0xfUL, 16))
7210016a4cfSPaul Mackerras 		return -EFAULT;
722c22435a5SPaul Mackerras 	/* align to multiple of size */
723c22435a5SPaul Mackerras 	ea &= ~(size - 1);
724c22435a5SPaul Mackerras 
725c22435a5SPaul Mackerras 	preempt_disable();
726c22435a5SPaul Mackerras 	if (regs->msr & MSR_VEC)
727c22435a5SPaul Mackerras 		get_vr(rn, &u.v);
728c22435a5SPaul Mackerras 	else
729c22435a5SPaul Mackerras 		u.v = current->thread.vr_state.vr[rn];
730c22435a5SPaul Mackerras 	preempt_enable();
731d955189aSPaul Mackerras 	if (unlikely(cross_endian))
732d955189aSPaul Mackerras 		do_byte_reverse(&u.b[ea & 0xf], size);
733b9da9c8aSPaul Mackerras 	return copy_mem_out(&u.b[ea & 0xf], ea, size, regs);
7340016a4cfSPaul Mackerras }
7350016a4cfSPaul Mackerras #endif /* CONFIG_ALTIVEC */
7360016a4cfSPaul Mackerras 
737350779a2SPaul Mackerras #ifdef __powerpc64__
emulate_lq(struct pt_regs * regs,unsigned long ea,int reg,bool cross_endian)738350779a2SPaul Mackerras static nokprobe_inline int emulate_lq(struct pt_regs *regs, unsigned long ea,
739d955189aSPaul Mackerras 				      int reg, bool cross_endian)
740350779a2SPaul Mackerras {
741350779a2SPaul Mackerras 	int err;
742350779a2SPaul Mackerras 
743350779a2SPaul Mackerras 	if (!address_ok(regs, ea, 16))
744350779a2SPaul Mackerras 		return -EFAULT;
745350779a2SPaul Mackerras 	/* if aligned, should be atomic */
746d955189aSPaul Mackerras 	if ((ea & 0xf) == 0) {
747d955189aSPaul Mackerras 		err = do_lq(ea, &regs->gpr[reg]);
748d955189aSPaul Mackerras 	} else {
749350779a2SPaul Mackerras 		err = read_mem(&regs->gpr[reg + IS_LE], ea, 8, regs);
750350779a2SPaul Mackerras 		if (!err)
751350779a2SPaul Mackerras 			err = read_mem(&regs->gpr[reg + IS_BE], ea + 8, 8, regs);
752d955189aSPaul Mackerras 	}
753d955189aSPaul Mackerras 	if (!err && unlikely(cross_endian))
754d955189aSPaul Mackerras 		do_byte_reverse(&regs->gpr[reg], 16);
755350779a2SPaul Mackerras 	return err;
756350779a2SPaul Mackerras }
757350779a2SPaul Mackerras 
emulate_stq(struct pt_regs * regs,unsigned long ea,int reg,bool cross_endian)758350779a2SPaul Mackerras static nokprobe_inline int emulate_stq(struct pt_regs *regs, unsigned long ea,
759d955189aSPaul Mackerras 				       int reg, bool cross_endian)
760350779a2SPaul Mackerras {
761350779a2SPaul Mackerras 	int err;
762d955189aSPaul Mackerras 	unsigned long vals[2];
763350779a2SPaul Mackerras 
764350779a2SPaul Mackerras 	if (!address_ok(regs, ea, 16))
765350779a2SPaul Mackerras 		return -EFAULT;
766d955189aSPaul Mackerras 	vals[0] = regs->gpr[reg];
767d955189aSPaul Mackerras 	vals[1] = regs->gpr[reg + 1];
768d955189aSPaul Mackerras 	if (unlikely(cross_endian))
769d955189aSPaul Mackerras 		do_byte_reverse(vals, 16);
770d955189aSPaul Mackerras 
771350779a2SPaul Mackerras 	/* if aligned, should be atomic */
772350779a2SPaul Mackerras 	if ((ea & 0xf) == 0)
773d955189aSPaul Mackerras 		return do_stq(ea, vals[0], vals[1]);
774350779a2SPaul Mackerras 
775d955189aSPaul Mackerras 	err = write_mem(vals[IS_LE], ea, 8, regs);
776350779a2SPaul Mackerras 	if (!err)
777d955189aSPaul Mackerras 		err = write_mem(vals[IS_BE], ea + 8, 8, regs);
778350779a2SPaul Mackerras 	return err;
779350779a2SPaul Mackerras }
780350779a2SPaul Mackerras #endif /* __powerpc64 */
781350779a2SPaul Mackerras 
7820016a4cfSPaul Mackerras #ifdef CONFIG_VSX
emulate_vsx_load(struct instruction_op * op,union vsx_reg * reg,const void * mem,bool rev)783*277ecc3dSMichal Suchanek static nokprobe_inline void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg,
784d955189aSPaul Mackerras 					     const void *mem, bool rev)
7850016a4cfSPaul Mackerras {
786350779a2SPaul Mackerras 	int size, read_size;
787350779a2SPaul Mackerras 	int i, j;
788350779a2SPaul Mackerras 	const unsigned int *wp;
789350779a2SPaul Mackerras 	const unsigned short *hp;
790350779a2SPaul Mackerras 	const unsigned char *bp;
7910016a4cfSPaul Mackerras 
792350779a2SPaul Mackerras 	size = GETSIZE(op->type);
793350779a2SPaul Mackerras 	reg->d[0] = reg->d[1] = 0;
794350779a2SPaul Mackerras 
795350779a2SPaul Mackerras 	switch (op->element_size) {
796af99da74SBalamuruhan S 	case 32:
797af99da74SBalamuruhan S 		/* [p]lxvp[x] */
798350779a2SPaul Mackerras 	case 16:
799350779a2SPaul Mackerras 		/* whole vector; lxv[x] or lxvl[l] */
800350779a2SPaul Mackerras 		if (size == 0)
801350779a2SPaul Mackerras 			break;
802350779a2SPaul Mackerras 		memcpy(reg, mem, size);
803d955189aSPaul Mackerras 		if (IS_LE && (op->vsx_flags & VSX_LDLEFT))
804d955189aSPaul Mackerras 			rev = !rev;
805d955189aSPaul Mackerras 		if (rev)
806af99da74SBalamuruhan S 			do_byte_reverse(reg, size);
807350779a2SPaul Mackerras 		break;
808350779a2SPaul Mackerras 	case 8:
809350779a2SPaul Mackerras 		/* scalar loads, lxvd2x, lxvdsx */
810350779a2SPaul Mackerras 		read_size = (size >= 8) ? 8 : size;
811350779a2SPaul Mackerras 		i = IS_LE ? 8 : 8 - read_size;
812350779a2SPaul Mackerras 		memcpy(&reg->b[i], mem, read_size);
813d955189aSPaul Mackerras 		if (rev)
814d955189aSPaul Mackerras 			do_byte_reverse(&reg->b[i], 8);
815350779a2SPaul Mackerras 		if (size < 8) {
816350779a2SPaul Mackerras 			if (op->type & SIGNEXT) {
817350779a2SPaul Mackerras 				/* size == 4 is the only case here */
818350779a2SPaul Mackerras 				reg->d[IS_LE] = (signed int) reg->d[IS_LE];
819350779a2SPaul Mackerras 			} else if (op->vsx_flags & VSX_FPCONV) {
820350779a2SPaul Mackerras 				preempt_disable();
821350779a2SPaul Mackerras 				conv_sp_to_dp(&reg->fp[1 + IS_LE],
822350779a2SPaul Mackerras 					      &reg->dp[IS_LE]);
823350779a2SPaul Mackerras 				preempt_enable();
824350779a2SPaul Mackerras 			}
825350779a2SPaul Mackerras 		} else {
826d955189aSPaul Mackerras 			if (size == 16) {
827d955189aSPaul Mackerras 				unsigned long v = *(unsigned long *)(mem + 8);
828d955189aSPaul Mackerras 				reg->d[IS_BE] = !rev ? v : byterev_8(v);
829d955189aSPaul Mackerras 			} else if (op->vsx_flags & VSX_SPLAT)
830350779a2SPaul Mackerras 				reg->d[IS_BE] = reg->d[IS_LE];
831350779a2SPaul Mackerras 		}
832350779a2SPaul Mackerras 		break;
833350779a2SPaul Mackerras 	case 4:
834350779a2SPaul Mackerras 		/* lxvw4x, lxvwsx */
835350779a2SPaul Mackerras 		wp = mem;
836350779a2SPaul Mackerras 		for (j = 0; j < size / 4; ++j) {
837350779a2SPaul Mackerras 			i = IS_LE ? 3 - j : j;
838d955189aSPaul Mackerras 			reg->w[i] = !rev ? *wp++ : byterev_4(*wp++);
839350779a2SPaul Mackerras 		}
840350779a2SPaul Mackerras 		if (op->vsx_flags & VSX_SPLAT) {
841350779a2SPaul Mackerras 			u32 val = reg->w[IS_LE ? 3 : 0];
842350779a2SPaul Mackerras 			for (; j < 4; ++j) {
843350779a2SPaul Mackerras 				i = IS_LE ? 3 - j : j;
844350779a2SPaul Mackerras 				reg->w[i] = val;
845350779a2SPaul Mackerras 			}
846350779a2SPaul Mackerras 		}
847350779a2SPaul Mackerras 		break;
848350779a2SPaul Mackerras 	case 2:
849350779a2SPaul Mackerras 		/* lxvh8x */
850350779a2SPaul Mackerras 		hp = mem;
851350779a2SPaul Mackerras 		for (j = 0; j < size / 2; ++j) {
852350779a2SPaul Mackerras 			i = IS_LE ? 7 - j : j;
853d955189aSPaul Mackerras 			reg->h[i] = !rev ? *hp++ : byterev_2(*hp++);
854350779a2SPaul Mackerras 		}
855350779a2SPaul Mackerras 		break;
856350779a2SPaul Mackerras 	case 1:
857350779a2SPaul Mackerras 		/* lxvb16x */
858350779a2SPaul Mackerras 		bp = mem;
859350779a2SPaul Mackerras 		for (j = 0; j < size; ++j) {
860350779a2SPaul Mackerras 			i = IS_LE ? 15 - j : j;
861350779a2SPaul Mackerras 			reg->b[i] = *bp++;
862350779a2SPaul Mackerras 		}
863350779a2SPaul Mackerras 		break;
864350779a2SPaul Mackerras 	}
865350779a2SPaul Mackerras }
8660016a4cfSPaul Mackerras 
emulate_vsx_store(struct instruction_op * op,const union vsx_reg * reg,void * mem,bool rev)867*277ecc3dSMichal Suchanek static nokprobe_inline void emulate_vsx_store(struct instruction_op *op, const union vsx_reg *reg,
868d955189aSPaul Mackerras 					      void *mem, bool rev)
8690016a4cfSPaul Mackerras {
870350779a2SPaul Mackerras 	int size, write_size;
871350779a2SPaul Mackerras 	int i, j;
872350779a2SPaul Mackerras 	union vsx_reg buf;
873350779a2SPaul Mackerras 	unsigned int *wp;
874350779a2SPaul Mackerras 	unsigned short *hp;
875350779a2SPaul Mackerras 	unsigned char *bp;
8760016a4cfSPaul Mackerras 
877350779a2SPaul Mackerras 	size = GETSIZE(op->type);
878350779a2SPaul Mackerras 
879350779a2SPaul Mackerras 	switch (op->element_size) {
880af99da74SBalamuruhan S 	case 32:
881af99da74SBalamuruhan S 		/* [p]stxvp[x] */
882af99da74SBalamuruhan S 		if (size == 0)
883af99da74SBalamuruhan S 			break;
884af99da74SBalamuruhan S 		if (rev) {
885af99da74SBalamuruhan S 			/* reverse 32 bytes */
886344717a1SRavi Bangoria 			union vsx_reg buf32[2];
887344717a1SRavi Bangoria 			buf32[0].d[0] = byterev_8(reg[1].d[1]);
888344717a1SRavi Bangoria 			buf32[0].d[1] = byterev_8(reg[1].d[0]);
889344717a1SRavi Bangoria 			buf32[1].d[0] = byterev_8(reg[0].d[1]);
890344717a1SRavi Bangoria 			buf32[1].d[1] = byterev_8(reg[0].d[0]);
891344717a1SRavi Bangoria 			memcpy(mem, buf32, size);
892344717a1SRavi Bangoria 		} else {
893af99da74SBalamuruhan S 			memcpy(mem, reg, size);
894344717a1SRavi Bangoria 		}
895af99da74SBalamuruhan S 		break;
896350779a2SPaul Mackerras 	case 16:
897350779a2SPaul Mackerras 		/* stxv, stxvx, stxvl, stxvll */
898350779a2SPaul Mackerras 		if (size == 0)
899350779a2SPaul Mackerras 			break;
900d955189aSPaul Mackerras 		if (IS_LE && (op->vsx_flags & VSX_LDLEFT))
901d955189aSPaul Mackerras 			rev = !rev;
902d955189aSPaul Mackerras 		if (rev) {
903350779a2SPaul Mackerras 			/* reverse 16 bytes */
904350779a2SPaul Mackerras 			buf.d[0] = byterev_8(reg->d[1]);
905350779a2SPaul Mackerras 			buf.d[1] = byterev_8(reg->d[0]);
906350779a2SPaul Mackerras 			reg = &buf;
9070016a4cfSPaul Mackerras 		}
908350779a2SPaul Mackerras 		memcpy(mem, reg, size);
909350779a2SPaul Mackerras 		break;
910350779a2SPaul Mackerras 	case 8:
911350779a2SPaul Mackerras 		/* scalar stores, stxvd2x */
912350779a2SPaul Mackerras 		write_size = (size >= 8) ? 8 : size;
913350779a2SPaul Mackerras 		i = IS_LE ? 8 : 8 - write_size;
914350779a2SPaul Mackerras 		if (size < 8 && op->vsx_flags & VSX_FPCONV) {
915350779a2SPaul Mackerras 			buf.d[0] = buf.d[1] = 0;
916350779a2SPaul Mackerras 			preempt_disable();
917350779a2SPaul Mackerras 			conv_dp_to_sp(&reg->dp[IS_LE], &buf.fp[1 + IS_LE]);
918350779a2SPaul Mackerras 			preempt_enable();
919350779a2SPaul Mackerras 			reg = &buf;
920350779a2SPaul Mackerras 		}
921350779a2SPaul Mackerras 		memcpy(mem, &reg->b[i], write_size);
922350779a2SPaul Mackerras 		if (size == 16)
923350779a2SPaul Mackerras 			memcpy(mem + 8, &reg->d[IS_BE], 8);
924d955189aSPaul Mackerras 		if (unlikely(rev)) {
925d955189aSPaul Mackerras 			do_byte_reverse(mem, write_size);
926d955189aSPaul Mackerras 			if (size == 16)
927d955189aSPaul Mackerras 				do_byte_reverse(mem + 8, 8);
928d955189aSPaul Mackerras 		}
929350779a2SPaul Mackerras 		break;
930350779a2SPaul Mackerras 	case 4:
931350779a2SPaul Mackerras 		/* stxvw4x */
932350779a2SPaul Mackerras 		wp = mem;
933350779a2SPaul Mackerras 		for (j = 0; j < size / 4; ++j) {
934350779a2SPaul Mackerras 			i = IS_LE ? 3 - j : j;
935d955189aSPaul Mackerras 			*wp++ = !rev ? reg->w[i] : byterev_4(reg->w[i]);
936350779a2SPaul Mackerras 		}
937350779a2SPaul Mackerras 		break;
938350779a2SPaul Mackerras 	case 2:
939350779a2SPaul Mackerras 		/* stxvh8x */
940350779a2SPaul Mackerras 		hp = mem;
941350779a2SPaul Mackerras 		for (j = 0; j < size / 2; ++j) {
942350779a2SPaul Mackerras 			i = IS_LE ? 7 - j : j;
943d955189aSPaul Mackerras 			*hp++ = !rev ? reg->h[i] : byterev_2(reg->h[i]);
944350779a2SPaul Mackerras 		}
945350779a2SPaul Mackerras 		break;
946350779a2SPaul Mackerras 	case 1:
947350779a2SPaul Mackerras 		/* stvxb16x */
948350779a2SPaul Mackerras 		bp = mem;
949350779a2SPaul Mackerras 		for (j = 0; j < size; ++j) {
950350779a2SPaul Mackerras 			i = IS_LE ? 15 - j : j;
951350779a2SPaul Mackerras 			*bp++ = reg->b[i];
952350779a2SPaul Mackerras 		}
953350779a2SPaul Mackerras 		break;
954350779a2SPaul Mackerras 	}
955350779a2SPaul Mackerras }
956c22435a5SPaul Mackerras 
do_vsx_load(struct instruction_op * op,unsigned long ea,struct pt_regs * regs,bool cross_endian)957c22435a5SPaul Mackerras static nokprobe_inline int do_vsx_load(struct instruction_op *op,
958d955189aSPaul Mackerras 				       unsigned long ea, struct pt_regs *regs,
959d955189aSPaul Mackerras 				       bool cross_endian)
960c22435a5SPaul Mackerras {
961c22435a5SPaul Mackerras 	int reg = op->reg;
962af99da74SBalamuruhan S 	int i, j, nr_vsx_regs;
963af99da74SBalamuruhan S 	u8 mem[32];
964af99da74SBalamuruhan S 	union vsx_reg buf[2];
965c22435a5SPaul Mackerras 	int size = GETSIZE(op->type);
966c22435a5SPaul Mackerras 
967b9da9c8aSPaul Mackerras 	if (!address_ok(regs, ea, size) || copy_mem_in(mem, ea, size, regs))
968c22435a5SPaul Mackerras 		return -EFAULT;
969c22435a5SPaul Mackerras 
9705c88a17eSJordan Niethe 	nr_vsx_regs = max(1ul, size / sizeof(__vector128));
971af99da74SBalamuruhan S 	emulate_vsx_load(op, buf, mem, cross_endian);
972c22435a5SPaul Mackerras 	preempt_disable();
973c22435a5SPaul Mackerras 	if (reg < 32) {
974c22435a5SPaul Mackerras 		/* FP regs + extensions */
975c22435a5SPaul Mackerras 		if (regs->msr & MSR_FP) {
976af99da74SBalamuruhan S 			for (i = 0; i < nr_vsx_regs; i++) {
977af99da74SBalamuruhan S 				j = IS_LE ? nr_vsx_regs - i - 1 : i;
978af99da74SBalamuruhan S 				load_vsrn(reg + i, &buf[j].v);
979c22435a5SPaul Mackerras 			}
980c22435a5SPaul Mackerras 		} else {
981af99da74SBalamuruhan S 			for (i = 0; i < nr_vsx_regs; i++) {
982af99da74SBalamuruhan S 				j = IS_LE ? nr_vsx_regs - i - 1 : i;
983af99da74SBalamuruhan S 				current->thread.fp_state.fpr[reg + i][0] = buf[j].d[0];
984af99da74SBalamuruhan S 				current->thread.fp_state.fpr[reg + i][1] = buf[j].d[1];
985af99da74SBalamuruhan S 			}
986af99da74SBalamuruhan S 		}
987af99da74SBalamuruhan S 	} else {
988af99da74SBalamuruhan S 		if (regs->msr & MSR_VEC) {
989af99da74SBalamuruhan S 			for (i = 0; i < nr_vsx_regs; i++) {
990af99da74SBalamuruhan S 				j = IS_LE ? nr_vsx_regs - i - 1 : i;
991af99da74SBalamuruhan S 				load_vsrn(reg + i, &buf[j].v);
992af99da74SBalamuruhan S 			}
993af99da74SBalamuruhan S 		} else {
994af99da74SBalamuruhan S 			for (i = 0; i < nr_vsx_regs; i++) {
995af99da74SBalamuruhan S 				j = IS_LE ? nr_vsx_regs - i - 1 : i;
996af99da74SBalamuruhan S 				current->thread.vr_state.vr[reg - 32 + i] = buf[j].v;
997af99da74SBalamuruhan S 			}
998af99da74SBalamuruhan S 		}
999c22435a5SPaul Mackerras 	}
1000c22435a5SPaul Mackerras 	preempt_enable();
1001c22435a5SPaul Mackerras 	return 0;
1002c22435a5SPaul Mackerras }
1003c22435a5SPaul Mackerras 
do_vsx_store(struct instruction_op * op,unsigned long ea,struct pt_regs * regs,bool cross_endian)1004c22435a5SPaul Mackerras static nokprobe_inline int do_vsx_store(struct instruction_op *op,
1005d955189aSPaul Mackerras 					unsigned long ea, struct pt_regs *regs,
1006d955189aSPaul Mackerras 					bool cross_endian)
1007c22435a5SPaul Mackerras {
1008c22435a5SPaul Mackerras 	int reg = op->reg;
1009af99da74SBalamuruhan S 	int i, j, nr_vsx_regs;
1010af99da74SBalamuruhan S 	u8 mem[32];
1011af99da74SBalamuruhan S 	union vsx_reg buf[2];
1012c22435a5SPaul Mackerras 	int size = GETSIZE(op->type);
1013c22435a5SPaul Mackerras 
1014c22435a5SPaul Mackerras 	if (!address_ok(regs, ea, size))
1015c22435a5SPaul Mackerras 		return -EFAULT;
1016c22435a5SPaul Mackerras 
10175c88a17eSJordan Niethe 	nr_vsx_regs = max(1ul, size / sizeof(__vector128));
1018c22435a5SPaul Mackerras 	preempt_disable();
1019c22435a5SPaul Mackerras 	if (reg < 32) {
1020c22435a5SPaul Mackerras 		/* FP regs + extensions */
1021c22435a5SPaul Mackerras 		if (regs->msr & MSR_FP) {
1022af99da74SBalamuruhan S 			for (i = 0; i < nr_vsx_regs; i++) {
1023af99da74SBalamuruhan S 				j = IS_LE ? nr_vsx_regs - i - 1 : i;
1024af99da74SBalamuruhan S 				store_vsrn(reg + i, &buf[j].v);
1025c22435a5SPaul Mackerras 			}
1026c22435a5SPaul Mackerras 		} else {
1027af99da74SBalamuruhan S 			for (i = 0; i < nr_vsx_regs; i++) {
1028af99da74SBalamuruhan S 				j = IS_LE ? nr_vsx_regs - i - 1 : i;
1029af99da74SBalamuruhan S 				buf[j].d[0] = current->thread.fp_state.fpr[reg + i][0];
1030af99da74SBalamuruhan S 				buf[j].d[1] = current->thread.fp_state.fpr[reg + i][1];
1031af99da74SBalamuruhan S 			}
1032af99da74SBalamuruhan S 		}
1033af99da74SBalamuruhan S 	} else {
1034af99da74SBalamuruhan S 		if (regs->msr & MSR_VEC) {
1035af99da74SBalamuruhan S 			for (i = 0; i < nr_vsx_regs; i++) {
1036af99da74SBalamuruhan S 				j = IS_LE ? nr_vsx_regs - i - 1 : i;
1037af99da74SBalamuruhan S 				store_vsrn(reg + i, &buf[j].v);
1038af99da74SBalamuruhan S 			}
1039af99da74SBalamuruhan S 		} else {
1040af99da74SBalamuruhan S 			for (i = 0; i < nr_vsx_regs; i++) {
1041af99da74SBalamuruhan S 				j = IS_LE ? nr_vsx_regs - i - 1 : i;
1042af99da74SBalamuruhan S 				buf[j].v = current->thread.vr_state.vr[reg - 32 + i];
1043af99da74SBalamuruhan S 			}
1044af99da74SBalamuruhan S 		}
1045c22435a5SPaul Mackerras 	}
1046c22435a5SPaul Mackerras 	preempt_enable();
1047af99da74SBalamuruhan S 	emulate_vsx_store(op, buf, mem, cross_endian);
1048b9da9c8aSPaul Mackerras 	return  copy_mem_out(mem, ea, size, regs);
1049c22435a5SPaul Mackerras }
10500016a4cfSPaul Mackerras #endif /* CONFIG_VSX */
10510016a4cfSPaul Mackerras 
__emulate_dcbz(unsigned long ea)10520d5769f9SChristophe Leroy static __always_inline int __emulate_dcbz(unsigned long ea)
1053e28d0b67SChristophe Leroy {
1054e28d0b67SChristophe Leroy 	unsigned long i;
1055e28d0b67SChristophe Leroy 	unsigned long size = l1_dcache_bytes();
1056e28d0b67SChristophe Leroy 
1057e28d0b67SChristophe Leroy 	for (i = 0; i < size; i += sizeof(long))
1058e28d0b67SChristophe Leroy 		unsafe_put_user(0, (unsigned long __user *)(ea + i), Efault);
1059e28d0b67SChristophe Leroy 
1060e28d0b67SChristophe Leroy 	return 0;
1061e28d0b67SChristophe Leroy 
1062e28d0b67SChristophe Leroy Efault:
1063e28d0b67SChristophe Leroy 	return -EFAULT;
1064e28d0b67SChristophe Leroy }
1065e28d0b67SChristophe Leroy 
emulate_dcbz(unsigned long ea,struct pt_regs * regs)1066b2543f7bSPaul Mackerras int emulate_dcbz(unsigned long ea, struct pt_regs *regs)
1067b2543f7bSPaul Mackerras {
1068b2543f7bSPaul Mackerras 	int err;
106967484e0dSChristophe Leroy 	unsigned long size = l1_dcache_bytes();
1070b2543f7bSPaul Mackerras 
10716836f099SChristophe Leroy 	ea = truncate_if_32bit(regs->msr, ea);
1072b2543f7bSPaul Mackerras 	ea &= ~(size - 1);
1073b2543f7bSPaul Mackerras 	if (!address_ok(regs, ea, size))
1074b2543f7bSPaul Mackerras 		return -EFAULT;
1075e28d0b67SChristophe Leroy 
1076e28d0b67SChristophe Leroy 	if (is_kernel_addr(ea)) {
1077e28d0b67SChristophe Leroy 		err = __emulate_dcbz(ea);
1078e28d0b67SChristophe Leroy 	} else if (user_write_access_begin((void __user *)ea, size)) {
1079e28d0b67SChristophe Leroy 		err = __emulate_dcbz(ea);
1080e28d0b67SChristophe Leroy 		user_write_access_end();
1081e28d0b67SChristophe Leroy 	} else {
1082e28d0b67SChristophe Leroy 		err = -EFAULT;
1083e28d0b67SChristophe Leroy 	}
1084e28d0b67SChristophe Leroy 
1085e28d0b67SChristophe Leroy 	if (err)
1086b9da9c8aSPaul Mackerras 		regs->dar = ea;
1087e28d0b67SChristophe Leroy 
1088e28d0b67SChristophe Leroy 
1089b2543f7bSPaul Mackerras 	return err;
1090b2543f7bSPaul Mackerras }
1091b2543f7bSPaul Mackerras NOKPROBE_SYMBOL(emulate_dcbz);
1092b2543f7bSPaul Mackerras 
10930016a4cfSPaul Mackerras #define __put_user_asmx(x, addr, err, op, cr)		\
10940016a4cfSPaul Mackerras 	__asm__ __volatile__(				\
10958219d31eSAnders Roxell 		".machine push\n"			\
10968219d31eSAnders Roxell 		".machine power8\n"			\
10970016a4cfSPaul Mackerras 		"1:	" op " %2,0,%3\n"		\
10988219d31eSAnders Roxell 		".machine pop\n"			\
10990016a4cfSPaul Mackerras 		"	mfcr	%1\n"			\
11000016a4cfSPaul Mackerras 		"2:\n"					\
11010016a4cfSPaul Mackerras 		".section .fixup,\"ax\"\n"		\
11020016a4cfSPaul Mackerras 		"3:	li	%0,%4\n"		\
11030016a4cfSPaul Mackerras 		"	b	2b\n"			\
11040016a4cfSPaul Mackerras 		".previous\n"				\
110524bfa6a9SNicholas Piggin 		EX_TABLE(1b, 3b)			\
11060016a4cfSPaul Mackerras 		: "=r" (err), "=r" (cr)			\
11070016a4cfSPaul Mackerras 		: "r" (x), "r" (addr), "i" (-EFAULT), "0" (err))
11080016a4cfSPaul Mackerras 
11090016a4cfSPaul Mackerras #define __get_user_asmx(x, addr, err, op)		\
11100016a4cfSPaul Mackerras 	__asm__ __volatile__(				\
11118219d31eSAnders Roxell 		".machine push\n"			\
11128219d31eSAnders Roxell 		".machine power8\n"			\
11130016a4cfSPaul Mackerras 		"1:	"op" %1,0,%2\n"			\
11148219d31eSAnders Roxell 		".machine pop\n"			\
11150016a4cfSPaul Mackerras 		"2:\n"					\
11160016a4cfSPaul Mackerras 		".section .fixup,\"ax\"\n"		\
11170016a4cfSPaul Mackerras 		"3:	li	%0,%3\n"		\
11180016a4cfSPaul Mackerras 		"	b	2b\n"			\
11190016a4cfSPaul Mackerras 		".previous\n"				\
112024bfa6a9SNicholas Piggin 		EX_TABLE(1b, 3b)			\
11210016a4cfSPaul Mackerras 		: "=r" (err), "=r" (x)			\
11220016a4cfSPaul Mackerras 		: "r" (addr), "i" (-EFAULT), "0" (err))
11230016a4cfSPaul Mackerras 
11240016a4cfSPaul Mackerras #define __cacheop_user_asmx(addr, err, op)		\
11250016a4cfSPaul Mackerras 	__asm__ __volatile__(				\
11260016a4cfSPaul Mackerras 		"1:	"op" 0,%1\n"			\
11270016a4cfSPaul Mackerras 		"2:\n"					\
11280016a4cfSPaul Mackerras 		".section .fixup,\"ax\"\n"		\
11290016a4cfSPaul Mackerras 		"3:	li	%0,%3\n"		\
11300016a4cfSPaul Mackerras 		"	b	2b\n"			\
11310016a4cfSPaul Mackerras 		".previous\n"				\
113224bfa6a9SNicholas Piggin 		EX_TABLE(1b, 3b)			\
11330016a4cfSPaul Mackerras 		: "=r" (err)				\
11340016a4cfSPaul Mackerras 		: "r" (addr), "i" (-EFAULT), "0" (err))
11350016a4cfSPaul Mackerras 
set_cr0(const struct pt_regs * regs,struct instruction_op * op)11363cdfcbfdSPaul Mackerras static nokprobe_inline void set_cr0(const struct pt_regs *regs,
1137ad47ff3eSAnton Blanchard 				    struct instruction_op *op)
11380016a4cfSPaul Mackerras {
1139ad47ff3eSAnton Blanchard 	long val = op->val;
11400016a4cfSPaul Mackerras 
11413cdfcbfdSPaul Mackerras 	op->type |= SETCC;
11423cdfcbfdSPaul Mackerras 	op->ccval = (regs->ccr & 0x0fffffff) | ((regs->xer >> 3) & 0x10000000);
1143b91e136cSMichael Ellerman 	if (!(regs->msr & MSR_64BIT))
11440016a4cfSPaul Mackerras 		val = (int) val;
11450016a4cfSPaul Mackerras 	if (val < 0)
11463cdfcbfdSPaul Mackerras 		op->ccval |= 0x80000000;
11470016a4cfSPaul Mackerras 	else if (val > 0)
11483cdfcbfdSPaul Mackerras 		op->ccval |= 0x40000000;
11490016a4cfSPaul Mackerras 	else
11503cdfcbfdSPaul Mackerras 		op->ccval |= 0x20000000;
11510016a4cfSPaul Mackerras }
11520016a4cfSPaul Mackerras 
set_ca32(struct instruction_op * op,bool val)1153dc39c1d6SSandipan Das static nokprobe_inline void set_ca32(struct instruction_op *op, bool val)
1154dc39c1d6SSandipan Das {
1155dc39c1d6SSandipan Das 	if (cpu_has_feature(CPU_FTR_ARCH_300)) {
1156dc39c1d6SSandipan Das 		if (val)
1157dc39c1d6SSandipan Das 			op->xerval |= XER_CA32;
1158dc39c1d6SSandipan Das 		else
1159dc39c1d6SSandipan Das 			op->xerval &= ~XER_CA32;
1160dc39c1d6SSandipan Das 	}
1161dc39c1d6SSandipan Das }
1162dc39c1d6SSandipan Das 
add_with_carry(const struct pt_regs * regs,struct instruction_op * op,int rd,unsigned long val1,unsigned long val2,unsigned long carry_in)11633cdfcbfdSPaul Mackerras static nokprobe_inline void add_with_carry(const struct pt_regs *regs,
11643cdfcbfdSPaul Mackerras 				     struct instruction_op *op, int rd,
11650016a4cfSPaul Mackerras 				     unsigned long val1, unsigned long val2,
11660016a4cfSPaul Mackerras 				     unsigned long carry_in)
11670016a4cfSPaul Mackerras {
11680016a4cfSPaul Mackerras 	unsigned long val = val1 + val2;
11690016a4cfSPaul Mackerras 
11700016a4cfSPaul Mackerras 	if (carry_in)
11710016a4cfSPaul Mackerras 		++val;
11729923a6daSYang Li 	op->type = COMPUTE | SETREG | SETXER;
11733cdfcbfdSPaul Mackerras 	op->reg = rd;
11743cdfcbfdSPaul Mackerras 	op->val = val;
11756836f099SChristophe Leroy 	val = truncate_if_32bit(regs->msr, val);
11766836f099SChristophe Leroy 	val1 = truncate_if_32bit(regs->msr, val1);
11773cdfcbfdSPaul Mackerras 	op->xerval = regs->xer;
11780016a4cfSPaul Mackerras 	if (val < val1 || (carry_in && val == val1))
11793cdfcbfdSPaul Mackerras 		op->xerval |= XER_CA;
11800016a4cfSPaul Mackerras 	else
11813cdfcbfdSPaul Mackerras 		op->xerval &= ~XER_CA;
1182dc39c1d6SSandipan Das 
1183dc39c1d6SSandipan Das 	set_ca32(op, (unsigned int)val < (unsigned int)val1 ||
1184dc39c1d6SSandipan Das 			(carry_in && (unsigned int)val == (unsigned int)val1));
11850016a4cfSPaul Mackerras }
11860016a4cfSPaul Mackerras 
do_cmp_signed(const struct pt_regs * regs,struct instruction_op * op,long v1,long v2,int crfld)11873cdfcbfdSPaul Mackerras static nokprobe_inline void do_cmp_signed(const struct pt_regs *regs,
11883cdfcbfdSPaul Mackerras 					  struct instruction_op *op,
11893cdfcbfdSPaul Mackerras 					  long v1, long v2, int crfld)
11900016a4cfSPaul Mackerras {
11910016a4cfSPaul Mackerras 	unsigned int crval, shift;
11920016a4cfSPaul Mackerras 
11939923a6daSYang Li 	op->type = COMPUTE | SETCC;
11940016a4cfSPaul Mackerras 	crval = (regs->xer >> 31) & 1;		/* get SO bit */
11950016a4cfSPaul Mackerras 	if (v1 < v2)
11960016a4cfSPaul Mackerras 		crval |= 8;
11970016a4cfSPaul Mackerras 	else if (v1 > v2)
11980016a4cfSPaul Mackerras 		crval |= 4;
11990016a4cfSPaul Mackerras 	else
12000016a4cfSPaul Mackerras 		crval |= 2;
12010016a4cfSPaul Mackerras 	shift = (7 - crfld) * 4;
12023cdfcbfdSPaul Mackerras 	op->ccval = (regs->ccr & ~(0xf << shift)) | (crval << shift);
12030016a4cfSPaul Mackerras }
12040016a4cfSPaul Mackerras 
do_cmp_unsigned(const struct pt_regs * regs,struct instruction_op * op,unsigned long v1,unsigned long v2,int crfld)12053cdfcbfdSPaul Mackerras static nokprobe_inline void do_cmp_unsigned(const struct pt_regs *regs,
12063cdfcbfdSPaul Mackerras 					    struct instruction_op *op,
12073cdfcbfdSPaul Mackerras 					    unsigned long v1,
12080016a4cfSPaul Mackerras 					    unsigned long v2, int crfld)
12090016a4cfSPaul Mackerras {
12100016a4cfSPaul Mackerras 	unsigned int crval, shift;
12110016a4cfSPaul Mackerras 
12129923a6daSYang Li 	op->type = COMPUTE | SETCC;
12130016a4cfSPaul Mackerras 	crval = (regs->xer >> 31) & 1;		/* get SO bit */
12140016a4cfSPaul Mackerras 	if (v1 < v2)
12150016a4cfSPaul Mackerras 		crval |= 8;
12160016a4cfSPaul Mackerras 	else if (v1 > v2)
12170016a4cfSPaul Mackerras 		crval |= 4;
12180016a4cfSPaul Mackerras 	else
12190016a4cfSPaul Mackerras 		crval |= 2;
12200016a4cfSPaul Mackerras 	shift = (7 - crfld) * 4;
12213cdfcbfdSPaul Mackerras 	op->ccval = (regs->ccr & ~(0xf << shift)) | (crval << shift);
12220016a4cfSPaul Mackerras }
12230016a4cfSPaul Mackerras 
do_cmpb(const struct pt_regs * regs,struct instruction_op * op,unsigned long v1,unsigned long v2)12243cdfcbfdSPaul Mackerras static nokprobe_inline void do_cmpb(const struct pt_regs *regs,
12253cdfcbfdSPaul Mackerras 				    struct instruction_op *op,
12263cdfcbfdSPaul Mackerras 				    unsigned long v1, unsigned long v2)
122702c0f62aSMatt Brown {
122802c0f62aSMatt Brown 	unsigned long long out_val, mask;
122902c0f62aSMatt Brown 	int i;
123002c0f62aSMatt Brown 
123102c0f62aSMatt Brown 	out_val = 0;
123202c0f62aSMatt Brown 	for (i = 0; i < 8; i++) {
123302c0f62aSMatt Brown 		mask = 0xffUL << (i * 8);
123402c0f62aSMatt Brown 		if ((v1 & mask) == (v2 & mask))
123502c0f62aSMatt Brown 			out_val |= mask;
123602c0f62aSMatt Brown 	}
12373cdfcbfdSPaul Mackerras 	op->val = out_val;
123802c0f62aSMatt Brown }
123902c0f62aSMatt Brown 
1240dcbd19b4SMatt Brown /*
1241dcbd19b4SMatt Brown  * The size parameter is used to adjust the equivalent popcnt instruction.
1242dcbd19b4SMatt Brown  * popcntb = 8, popcntw = 32, popcntd = 64
1243dcbd19b4SMatt Brown  */
do_popcnt(const struct pt_regs * regs,struct instruction_op * op,unsigned long v1,int size)12443cdfcbfdSPaul Mackerras static nokprobe_inline void do_popcnt(const struct pt_regs *regs,
12453cdfcbfdSPaul Mackerras 				      struct instruction_op *op,
12463cdfcbfdSPaul Mackerras 				      unsigned long v1, int size)
1247dcbd19b4SMatt Brown {
1248dcbd19b4SMatt Brown 	unsigned long long out = v1;
1249dcbd19b4SMatt Brown 
125020acf7fcSFinn Thain 	out -= (out >> 1) & 0x5555555555555555ULL;
125120acf7fcSFinn Thain 	out = (0x3333333333333333ULL & out) +
125220acf7fcSFinn Thain 	      (0x3333333333333333ULL & (out >> 2));
125320acf7fcSFinn Thain 	out = (out + (out >> 4)) & 0x0f0f0f0f0f0f0f0fULL;
1254dcbd19b4SMatt Brown 
1255dcbd19b4SMatt Brown 	if (size == 8) {	/* popcntb */
12563cdfcbfdSPaul Mackerras 		op->val = out;
1257dcbd19b4SMatt Brown 		return;
1258dcbd19b4SMatt Brown 	}
1259dcbd19b4SMatt Brown 	out += out >> 8;
1260dcbd19b4SMatt Brown 	out += out >> 16;
1261dcbd19b4SMatt Brown 	if (size == 32) {	/* popcntw */
126220acf7fcSFinn Thain 		op->val = out & 0x0000003f0000003fULL;
1263dcbd19b4SMatt Brown 		return;
1264dcbd19b4SMatt Brown 	}
1265dcbd19b4SMatt Brown 
1266dcbd19b4SMatt Brown 	out = (out + (out >> 32)) & 0x7f;
12673cdfcbfdSPaul Mackerras 	op->val = out;	/* popcntd */
1268dcbd19b4SMatt Brown }
1269dcbd19b4SMatt Brown 
1270f312793dSMatt Brown #ifdef CONFIG_PPC64
do_bpermd(const struct pt_regs * regs,struct instruction_op * op,unsigned long v1,unsigned long v2)12713cdfcbfdSPaul Mackerras static nokprobe_inline void do_bpermd(const struct pt_regs *regs,
12723cdfcbfdSPaul Mackerras 				      struct instruction_op *op,
12733cdfcbfdSPaul Mackerras 				      unsigned long v1, unsigned long v2)
1274f312793dSMatt Brown {
1275f312793dSMatt Brown 	unsigned char perm, idx;
1276f312793dSMatt Brown 	unsigned int i;
1277f312793dSMatt Brown 
1278f312793dSMatt Brown 	perm = 0;
1279f312793dSMatt Brown 	for (i = 0; i < 8; i++) {
1280f312793dSMatt Brown 		idx = (v1 >> (i * 8)) & 0xff;
1281f312793dSMatt Brown 		if (idx < 64)
1282f312793dSMatt Brown 			if (v2 & PPC_BIT(idx))
1283f312793dSMatt Brown 				perm |= 1 << i;
1284f312793dSMatt Brown 	}
12853cdfcbfdSPaul Mackerras 	op->val = perm;
1286f312793dSMatt Brown }
1287f312793dSMatt Brown #endif /* CONFIG_PPC64 */
12882c979c48SMatt Brown /*
12892c979c48SMatt Brown  * The size parameter adjusts the equivalent prty instruction.
12902c979c48SMatt Brown  * prtyw = 32, prtyd = 64
12912c979c48SMatt Brown  */
do_prty(const struct pt_regs * regs,struct instruction_op * op,unsigned long v,int size)12923cdfcbfdSPaul Mackerras static nokprobe_inline void do_prty(const struct pt_regs *regs,
12933cdfcbfdSPaul Mackerras 				    struct instruction_op *op,
12943cdfcbfdSPaul Mackerras 				    unsigned long v, int size)
12952c979c48SMatt Brown {
12962c979c48SMatt Brown 	unsigned long long res = v ^ (v >> 8);
12972c979c48SMatt Brown 
12982c979c48SMatt Brown 	res ^= res >> 16;
12992c979c48SMatt Brown 	if (size == 32) {		/* prtyw */
130020acf7fcSFinn Thain 		op->val = res & 0x0000000100000001ULL;
13012c979c48SMatt Brown 		return;
13022c979c48SMatt Brown 	}
13032c979c48SMatt Brown 
13042c979c48SMatt Brown 	res ^= res >> 32;
13053cdfcbfdSPaul Mackerras 	op->val = res & 1;	/*prtyd */
13062c979c48SMatt Brown }
1307f312793dSMatt Brown 
trap_compare(long v1,long v2)130871f6e58eSNaveen N. Rao static nokprobe_inline int trap_compare(long v1, long v2)
1309cf87c3f6SPaul Mackerras {
1310cf87c3f6SPaul Mackerras 	int ret = 0;
1311cf87c3f6SPaul Mackerras 
1312cf87c3f6SPaul Mackerras 	if (v1 < v2)
1313cf87c3f6SPaul Mackerras 		ret |= 0x10;
1314cf87c3f6SPaul Mackerras 	else if (v1 > v2)
1315cf87c3f6SPaul Mackerras 		ret |= 0x08;
1316cf87c3f6SPaul Mackerras 	else
1317cf87c3f6SPaul Mackerras 		ret |= 0x04;
1318cf87c3f6SPaul Mackerras 	if ((unsigned long)v1 < (unsigned long)v2)
1319cf87c3f6SPaul Mackerras 		ret |= 0x02;
1320cf87c3f6SPaul Mackerras 	else if ((unsigned long)v1 > (unsigned long)v2)
1321cf87c3f6SPaul Mackerras 		ret |= 0x01;
1322cf87c3f6SPaul Mackerras 	return ret;
1323cf87c3f6SPaul Mackerras }
1324cf87c3f6SPaul Mackerras 
13250016a4cfSPaul Mackerras /*
13260016a4cfSPaul Mackerras  * Elements of 32-bit rotate and mask instructions.
13270016a4cfSPaul Mackerras  */
13280016a4cfSPaul Mackerras #define MASK32(mb, me)	((0xffffffffUL >> (mb)) + \
13290016a4cfSPaul Mackerras 			 ((signed long)-0x80000000L >> (me)) + ((me) >= (mb)))
13300016a4cfSPaul Mackerras #ifdef __powerpc64__
13310016a4cfSPaul Mackerras #define MASK64_L(mb)	(~0UL >> (mb))
13320016a4cfSPaul Mackerras #define MASK64_R(me)	((signed long)-0x8000000000000000L >> (me))
13330016a4cfSPaul Mackerras #define MASK64(mb, me)	(MASK64_L(mb) + MASK64_R(me) + ((me) >= (mb)))
13340016a4cfSPaul Mackerras #define DATA32(x)	(((x) & 0xffffffffUL) | (((x) & 0xffffffffUL) << 32))
13350016a4cfSPaul Mackerras #else
13360016a4cfSPaul Mackerras #define DATA32(x)	(x)
13370016a4cfSPaul Mackerras #endif
13380016a4cfSPaul Mackerras #define ROTATE(x, n)	((n) ? (((x) << (n)) | ((x) >> (8 * sizeof(long) - (n)))) : (x))
13390016a4cfSPaul Mackerras 
13400016a4cfSPaul Mackerras /*
13413cdfcbfdSPaul Mackerras  * Decode an instruction, and return information about it in *op
13423cdfcbfdSPaul Mackerras  * without changing *regs.
13433cdfcbfdSPaul Mackerras  * Integer arithmetic and logical instructions, branches, and barrier
13443cdfcbfdSPaul Mackerras  * instructions can be emulated just using the information in *op.
13453cdfcbfdSPaul Mackerras  *
13463cdfcbfdSPaul Mackerras  * Return value is 1 if the instruction can be emulated just by
13473cdfcbfdSPaul Mackerras  * updating *regs with the information in *op, -1 if we need the
13483cdfcbfdSPaul Mackerras  * GPRs but *regs doesn't contain the full register set, or 0
13493cdfcbfdSPaul Mackerras  * otherwise.
135014cf11afSPaul Mackerras  */
analyse_instr(struct instruction_op * op,const struct pt_regs * regs,ppc_inst_t instr)13513cdfcbfdSPaul Mackerras int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
1352c545b9f0SChristophe Leroy 		  ppc_inst_t instr)
135314cf11afSPaul Mackerras {
135450b80a12SJordan Niethe #ifdef CONFIG_PPC64
135550b80a12SJordan Niethe 	unsigned int suffixopcode, prefixtype, prefix_r;
135650b80a12SJordan Niethe #endif
1357930d6288SSandipan Das 	unsigned int opcode, ra, rb, rc, rd, spr, u;
135814cf11afSPaul Mackerras 	unsigned long int imm;
13590016a4cfSPaul Mackerras 	unsigned long int val, val2;
1360be96f633SPaul Mackerras 	unsigned int mb, me, sh;
1361650b55b7SJordan Niethe 	unsigned int word, suffix;
13620016a4cfSPaul Mackerras 	long ival;
136314cf11afSPaul Mackerras 
1364777e26f0SJordan Niethe 	word = ppc_inst_val(instr);
1365650b55b7SJordan Niethe 	suffix = ppc_inst_suffix(instr);
1366650b55b7SJordan Niethe 
1367be96f633SPaul Mackerras 	op->type = COMPUTE;
1368be96f633SPaul Mackerras 
13698094892dSJordan Niethe 	opcode = ppc_inst_primary_opcode(instr);
137014cf11afSPaul Mackerras 	switch (opcode) {
137114cf11afSPaul Mackerras 	case 16:	/* bc */
1372be96f633SPaul Mackerras 		op->type = BRANCH;
1373777e26f0SJordan Niethe 		imm = (signed short)(word & 0xfffc);
1374777e26f0SJordan Niethe 		if ((word & 2) == 0)
137514cf11afSPaul Mackerras 			imm += regs->nip;
13763cdfcbfdSPaul Mackerras 		op->val = truncate_if_32bit(regs->msr, imm);
1377777e26f0SJordan Niethe 		if (word & 1)
13783cdfcbfdSPaul Mackerras 			op->type |= SETLK;
1379777e26f0SJordan Niethe 		if (branch_taken(word, regs, op))
13803cdfcbfdSPaul Mackerras 			op->type |= BRTAKEN;
138114cf11afSPaul Mackerras 		return 1;
138214cf11afSPaul Mackerras 	case 17:	/* sc */
1383777e26f0SJordan Niethe 		if ((word & 0xfe2) == 2)
1384be96f633SPaul Mackerras 			op->type = SYSCALL;
13857fa95f9aSNicholas Piggin 		else if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) &&
13868813ff49SAnanth N Mavinakayanahalli 				(word & 0xfe3) == 1) {	/* scv */
13877fa95f9aSNicholas Piggin 			op->type = SYSCALL_VECTORED_0;
13888813ff49SAnanth N Mavinakayanahalli 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
13898813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
13908813ff49SAnanth N Mavinakayanahalli 		} else
1391be96f633SPaul Mackerras 			op->type = UNKNOWN;
1392be96f633SPaul Mackerras 		return 0;
139314cf11afSPaul Mackerras 	case 18:	/* b */
13943cdfcbfdSPaul Mackerras 		op->type = BRANCH | BRTAKEN;
1395777e26f0SJordan Niethe 		imm = word & 0x03fffffc;
139614cf11afSPaul Mackerras 		if (imm & 0x02000000)
139714cf11afSPaul Mackerras 			imm -= 0x04000000;
1398777e26f0SJordan Niethe 		if ((word & 2) == 0)
139914cf11afSPaul Mackerras 			imm += regs->nip;
14003cdfcbfdSPaul Mackerras 		op->val = truncate_if_32bit(regs->msr, imm);
1401777e26f0SJordan Niethe 		if (word & 1)
14023cdfcbfdSPaul Mackerras 			op->type |= SETLK;
140314cf11afSPaul Mackerras 		return 1;
140414cf11afSPaul Mackerras 	case 19:
1405777e26f0SJordan Niethe 		switch ((word >> 1) & 0x3ff) {
1406cf87c3f6SPaul Mackerras 		case 0:		/* mcrf */
14073cdfcbfdSPaul Mackerras 			op->type = COMPUTE + SETCC;
1408777e26f0SJordan Niethe 			rd = 7 - ((word >> 23) & 0x7);
1409777e26f0SJordan Niethe 			ra = 7 - ((word >> 18) & 0x7);
141087c4b83eSAnton Blanchard 			rd *= 4;
141187c4b83eSAnton Blanchard 			ra *= 4;
1412cf87c3f6SPaul Mackerras 			val = (regs->ccr >> ra) & 0xf;
14133cdfcbfdSPaul Mackerras 			op->ccval = (regs->ccr & ~(0xfUL << rd)) | (val << rd);
14143cdfcbfdSPaul Mackerras 			return 1;
1415cf87c3f6SPaul Mackerras 
14160016a4cfSPaul Mackerras 		case 16:	/* bclr */
14170016a4cfSPaul Mackerras 		case 528:	/* bcctr */
1418be96f633SPaul Mackerras 			op->type = BRANCH;
1419777e26f0SJordan Niethe 			imm = (word & 0x400)? regs->ctr: regs->link;
14203cdfcbfdSPaul Mackerras 			op->val = truncate_if_32bit(regs->msr, imm);
1421777e26f0SJordan Niethe 			if (word & 1)
14223cdfcbfdSPaul Mackerras 				op->type |= SETLK;
1423777e26f0SJordan Niethe 			if (branch_taken(word, regs, op))
14243cdfcbfdSPaul Mackerras 				op->type |= BRTAKEN;
142514cf11afSPaul Mackerras 			return 1;
14260016a4cfSPaul Mackerras 
14270016a4cfSPaul Mackerras 		case 18:	/* rfid, scary */
1428be96f633SPaul Mackerras 			if (regs->msr & MSR_PR)
1429be96f633SPaul Mackerras 				goto priv;
1430be96f633SPaul Mackerras 			op->type = RFI;
1431be96f633SPaul Mackerras 			return 0;
14320016a4cfSPaul Mackerras 
14330016a4cfSPaul Mackerras 		case 150:	/* isync */
14343cdfcbfdSPaul Mackerras 			op->type = BARRIER | BARRIER_ISYNC;
14353cdfcbfdSPaul Mackerras 			return 1;
14360016a4cfSPaul Mackerras 
14370016a4cfSPaul Mackerras 		case 33:	/* crnor */
14380016a4cfSPaul Mackerras 		case 129:	/* crandc */
14390016a4cfSPaul Mackerras 		case 193:	/* crxor */
14400016a4cfSPaul Mackerras 		case 225:	/* crnand */
14410016a4cfSPaul Mackerras 		case 257:	/* crand */
14420016a4cfSPaul Mackerras 		case 289:	/* creqv */
14430016a4cfSPaul Mackerras 		case 417:	/* crorc */
14440016a4cfSPaul Mackerras 		case 449:	/* cror */
14453cdfcbfdSPaul Mackerras 			op->type = COMPUTE + SETCC;
1446777e26f0SJordan Niethe 			ra = (word >> 16) & 0x1f;
1447777e26f0SJordan Niethe 			rb = (word >> 11) & 0x1f;
1448777e26f0SJordan Niethe 			rd = (word >> 21) & 0x1f;
14490016a4cfSPaul Mackerras 			ra = (regs->ccr >> (31 - ra)) & 1;
14500016a4cfSPaul Mackerras 			rb = (regs->ccr >> (31 - rb)) & 1;
1451777e26f0SJordan Niethe 			val = (word >> (6 + ra * 2 + rb)) & 1;
14523cdfcbfdSPaul Mackerras 			op->ccval = (regs->ccr & ~(1UL << (31 - rd))) |
14530016a4cfSPaul Mackerras 				(val << (31 - rd));
14543cdfcbfdSPaul Mackerras 			return 1;
14550016a4cfSPaul Mackerras 		}
14560016a4cfSPaul Mackerras 		break;
14570016a4cfSPaul Mackerras 	case 31:
1458777e26f0SJordan Niethe 		switch ((word >> 1) & 0x3ff) {
14590016a4cfSPaul Mackerras 		case 598:	/* sync */
14603cdfcbfdSPaul Mackerras 			op->type = BARRIER + BARRIER_SYNC;
14610016a4cfSPaul Mackerras #ifdef __powerpc64__
1462777e26f0SJordan Niethe 			switch ((word >> 21) & 3) {
14630016a4cfSPaul Mackerras 			case 1:		/* lwsync */
14643cdfcbfdSPaul Mackerras 				op->type = BARRIER + BARRIER_LWSYNC;
14653cdfcbfdSPaul Mackerras 				break;
14660016a4cfSPaul Mackerras 			case 2:		/* ptesync */
14673cdfcbfdSPaul Mackerras 				op->type = BARRIER + BARRIER_PTESYNC;
14683cdfcbfdSPaul Mackerras 				break;
14690016a4cfSPaul Mackerras 			}
14700016a4cfSPaul Mackerras #endif
14713cdfcbfdSPaul Mackerras 			return 1;
14720016a4cfSPaul Mackerras 
14730016a4cfSPaul Mackerras 		case 854:	/* eieio */
14743cdfcbfdSPaul Mackerras 			op->type = BARRIER + BARRIER_EIEIO;
14753cdfcbfdSPaul Mackerras 			return 1;
14760016a4cfSPaul Mackerras 		}
14770016a4cfSPaul Mackerras 		break;
14780016a4cfSPaul Mackerras 	}
14790016a4cfSPaul Mackerras 
1480777e26f0SJordan Niethe 	rd = (word >> 21) & 0x1f;
1481777e26f0SJordan Niethe 	ra = (word >> 16) & 0x1f;
1482777e26f0SJordan Niethe 	rb = (word >> 11) & 0x1f;
1483777e26f0SJordan Niethe 	rc = (word >> 6) & 0x1f;
14840016a4cfSPaul Mackerras 
14850016a4cfSPaul Mackerras 	switch (opcode) {
1486cf87c3f6SPaul Mackerras #ifdef __powerpc64__
14873920742bSJordan Niethe 	case 1:
1488ef6879f8SBalamuruhan S 		if (!cpu_has_feature(CPU_FTR_ARCH_31))
14898813ff49SAnanth N Mavinakayanahalli 			goto unknown_opcode;
1490ef6879f8SBalamuruhan S 
149168a180a4SBalamuruhan S 		prefix_r = GET_PREFIX_R(word);
149268a180a4SBalamuruhan S 		ra = GET_PREFIX_RA(suffix);
14933920742bSJordan Niethe 		rd = (suffix >> 21) & 0x1f;
14943920742bSJordan Niethe 		op->reg = rd;
14953920742bSJordan Niethe 		op->val = regs->gpr[rd];
14963920742bSJordan Niethe 		suffixopcode = get_op(suffix);
14973920742bSJordan Niethe 		prefixtype = (word >> 24) & 0x3;
14983920742bSJordan Niethe 		switch (prefixtype) {
14993920742bSJordan Niethe 		case 2:
15003920742bSJordan Niethe 			if (prefix_r && ra)
15013920742bSJordan Niethe 				return 0;
15023920742bSJordan Niethe 			switch (suffixopcode) {
15033920742bSJordan Niethe 			case 14:	/* paddi */
15043920742bSJordan Niethe 				op->type = COMPUTE | PREFIXED;
15053920742bSJordan Niethe 				op->val = mlsd_8lsd_ea(word, suffix, regs);
15063920742bSJordan Niethe 				goto compute_done;
15073920742bSJordan Niethe 			}
15083920742bSJordan Niethe 		}
15093920742bSJordan Niethe 		break;
1510cf87c3f6SPaul Mackerras 	case 2:		/* tdi */
1511777e26f0SJordan Niethe 		if (rd & trap_compare(regs->gpr[ra], (short) word))
1512cf87c3f6SPaul Mackerras 			goto trap;
15133cdfcbfdSPaul Mackerras 		return 1;
1514cf87c3f6SPaul Mackerras #endif
1515cf87c3f6SPaul Mackerras 	case 3:		/* twi */
1516777e26f0SJordan Niethe 		if (rd & trap_compare((int)regs->gpr[ra], (short) word))
1517cf87c3f6SPaul Mackerras 			goto trap;
15183cdfcbfdSPaul Mackerras 		return 1;
1519cf87c3f6SPaul Mackerras 
1520930d6288SSandipan Das #ifdef __powerpc64__
1521930d6288SSandipan Das 	case 4:
1522718aae91SAnanth N Mavinakayanahalli 		/*
1523718aae91SAnanth N Mavinakayanahalli 		 * There are very many instructions with this primary opcode
1524718aae91SAnanth N Mavinakayanahalli 		 * introduced in the ISA as early as v2.03. However, the ones
1525718aae91SAnanth N Mavinakayanahalli 		 * we currently emulate were all introduced with ISA 3.0
1526718aae91SAnanth N Mavinakayanahalli 		 */
1527930d6288SSandipan Das 		if (!cpu_has_feature(CPU_FTR_ARCH_300))
15288813ff49SAnanth N Mavinakayanahalli 			goto unknown_opcode;
1529930d6288SSandipan Das 
1530777e26f0SJordan Niethe 		switch (word & 0x3f) {
1531930d6288SSandipan Das 		case 48:	/* maddhd */
1532930d6288SSandipan Das 			asm volatile(PPC_MADDHD(%0, %1, %2, %3) :
1533930d6288SSandipan Das 				     "=r" (op->val) : "r" (regs->gpr[ra]),
1534930d6288SSandipan Das 				     "r" (regs->gpr[rb]), "r" (regs->gpr[rc]));
1535930d6288SSandipan Das 			goto compute_done;
1536930d6288SSandipan Das 
1537930d6288SSandipan Das 		case 49:	/* maddhdu */
1538930d6288SSandipan Das 			asm volatile(PPC_MADDHDU(%0, %1, %2, %3) :
1539930d6288SSandipan Das 				     "=r" (op->val) : "r" (regs->gpr[ra]),
1540930d6288SSandipan Das 				     "r" (regs->gpr[rb]), "r" (regs->gpr[rc]));
1541930d6288SSandipan Das 			goto compute_done;
1542930d6288SSandipan Das 
1543930d6288SSandipan Das 		case 51:	/* maddld */
1544930d6288SSandipan Das 			asm volatile(PPC_MADDLD(%0, %1, %2, %3) :
1545930d6288SSandipan Das 				     "=r" (op->val) : "r" (regs->gpr[ra]),
1546930d6288SSandipan Das 				     "r" (regs->gpr[rb]), "r" (regs->gpr[rc]));
1547930d6288SSandipan Das 			goto compute_done;
1548930d6288SSandipan Das 		}
1549930d6288SSandipan Das 
1550930d6288SSandipan Das 		/*
1551930d6288SSandipan Das 		 * There are other instructions from ISA 3.0 with the same
1552930d6288SSandipan Das 		 * primary opcode which do not have emulation support yet.
1553930d6288SSandipan Das 		 */
1554718aae91SAnanth N Mavinakayanahalli 		goto unknown_opcode;
1555930d6288SSandipan Das #endif
1556930d6288SSandipan Das 
15570016a4cfSPaul Mackerras 	case 7:		/* mulli */
1558777e26f0SJordan Niethe 		op->val = regs->gpr[ra] * (short) word;
15593cdfcbfdSPaul Mackerras 		goto compute_done;
15600016a4cfSPaul Mackerras 
15610016a4cfSPaul Mackerras 	case 8:		/* subfic */
1562777e26f0SJordan Niethe 		imm = (short) word;
15633cdfcbfdSPaul Mackerras 		add_with_carry(regs, op, rd, ~regs->gpr[ra], imm, 1);
15643cdfcbfdSPaul Mackerras 		return 1;
15650016a4cfSPaul Mackerras 
15660016a4cfSPaul Mackerras 	case 10:	/* cmpli */
1567777e26f0SJordan Niethe 		imm = (unsigned short) word;
15680016a4cfSPaul Mackerras 		val = regs->gpr[ra];
15690016a4cfSPaul Mackerras #ifdef __powerpc64__
15700016a4cfSPaul Mackerras 		if ((rd & 1) == 0)
15710016a4cfSPaul Mackerras 			val = (unsigned int) val;
15720016a4cfSPaul Mackerras #endif
15733cdfcbfdSPaul Mackerras 		do_cmp_unsigned(regs, op, val, imm, rd >> 2);
15743cdfcbfdSPaul Mackerras 		return 1;
15750016a4cfSPaul Mackerras 
15760016a4cfSPaul Mackerras 	case 11:	/* cmpi */
1577777e26f0SJordan Niethe 		imm = (short) word;
15780016a4cfSPaul Mackerras 		val = regs->gpr[ra];
15790016a4cfSPaul Mackerras #ifdef __powerpc64__
15800016a4cfSPaul Mackerras 		if ((rd & 1) == 0)
15810016a4cfSPaul Mackerras 			val = (int) val;
15820016a4cfSPaul Mackerras #endif
15833cdfcbfdSPaul Mackerras 		do_cmp_signed(regs, op, val, imm, rd >> 2);
15843cdfcbfdSPaul Mackerras 		return 1;
15850016a4cfSPaul Mackerras 
15860016a4cfSPaul Mackerras 	case 12:	/* addic */
1587777e26f0SJordan Niethe 		imm = (short) word;
15883cdfcbfdSPaul Mackerras 		add_with_carry(regs, op, rd, regs->gpr[ra], imm, 0);
15893cdfcbfdSPaul Mackerras 		return 1;
15900016a4cfSPaul Mackerras 
15910016a4cfSPaul Mackerras 	case 13:	/* addic. */
1592777e26f0SJordan Niethe 		imm = (short) word;
15933cdfcbfdSPaul Mackerras 		add_with_carry(regs, op, rd, regs->gpr[ra], imm, 0);
1594ad47ff3eSAnton Blanchard 		set_cr0(regs, op);
15953cdfcbfdSPaul Mackerras 		return 1;
15960016a4cfSPaul Mackerras 
15970016a4cfSPaul Mackerras 	case 14:	/* addi */
1598777e26f0SJordan Niethe 		imm = (short) word;
15990016a4cfSPaul Mackerras 		if (ra)
16000016a4cfSPaul Mackerras 			imm += regs->gpr[ra];
16013cdfcbfdSPaul Mackerras 		op->val = imm;
16023cdfcbfdSPaul Mackerras 		goto compute_done;
16030016a4cfSPaul Mackerras 
16040016a4cfSPaul Mackerras 	case 15:	/* addis */
1605777e26f0SJordan Niethe 		imm = ((short) word) << 16;
16060016a4cfSPaul Mackerras 		if (ra)
16070016a4cfSPaul Mackerras 			imm += regs->gpr[ra];
16083cdfcbfdSPaul Mackerras 		op->val = imm;
16093cdfcbfdSPaul Mackerras 		goto compute_done;
16100016a4cfSPaul Mackerras 
1611958465eeSPaul Mackerras 	case 19:
1612777e26f0SJordan Niethe 		if (((word >> 1) & 0x1f) == 2) {
1613958465eeSPaul Mackerras 			/* addpcis */
16148813ff49SAnanth N Mavinakayanahalli 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
16158813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
1616777e26f0SJordan Niethe 			imm = (short) (word & 0xffc1);	/* d0 + d2 fields */
1617777e26f0SJordan Niethe 			imm |= (word >> 15) & 0x3e;	/* d1 field */
1618958465eeSPaul Mackerras 			op->val = regs->nip + (imm << 16) + 4;
1619958465eeSPaul Mackerras 			goto compute_done;
1620958465eeSPaul Mackerras 		}
1621958465eeSPaul Mackerras 		op->type = UNKNOWN;
1622958465eeSPaul Mackerras 		return 0;
1623958465eeSPaul Mackerras 
16240016a4cfSPaul Mackerras 	case 20:	/* rlwimi */
1625777e26f0SJordan Niethe 		mb = (word >> 6) & 0x1f;
1626777e26f0SJordan Niethe 		me = (word >> 1) & 0x1f;
16270016a4cfSPaul Mackerras 		val = DATA32(regs->gpr[rd]);
16280016a4cfSPaul Mackerras 		imm = MASK32(mb, me);
16293cdfcbfdSPaul Mackerras 		op->val = (regs->gpr[ra] & ~imm) | (ROTATE(val, rb) & imm);
16300016a4cfSPaul Mackerras 		goto logical_done;
16310016a4cfSPaul Mackerras 
16320016a4cfSPaul Mackerras 	case 21:	/* rlwinm */
1633777e26f0SJordan Niethe 		mb = (word >> 6) & 0x1f;
1634777e26f0SJordan Niethe 		me = (word >> 1) & 0x1f;
16350016a4cfSPaul Mackerras 		val = DATA32(regs->gpr[rd]);
16363cdfcbfdSPaul Mackerras 		op->val = ROTATE(val, rb) & MASK32(mb, me);
16370016a4cfSPaul Mackerras 		goto logical_done;
16380016a4cfSPaul Mackerras 
16390016a4cfSPaul Mackerras 	case 23:	/* rlwnm */
1640777e26f0SJordan Niethe 		mb = (word >> 6) & 0x1f;
1641777e26f0SJordan Niethe 		me = (word >> 1) & 0x1f;
16420016a4cfSPaul Mackerras 		rb = regs->gpr[rb] & 0x1f;
16430016a4cfSPaul Mackerras 		val = DATA32(regs->gpr[rd]);
16443cdfcbfdSPaul Mackerras 		op->val = ROTATE(val, rb) & MASK32(mb, me);
16450016a4cfSPaul Mackerras 		goto logical_done;
16460016a4cfSPaul Mackerras 
16470016a4cfSPaul Mackerras 	case 24:	/* ori */
1648777e26f0SJordan Niethe 		op->val = regs->gpr[rd] | (unsigned short) word;
16493cdfcbfdSPaul Mackerras 		goto logical_done_nocc;
16500016a4cfSPaul Mackerras 
16510016a4cfSPaul Mackerras 	case 25:	/* oris */
1652777e26f0SJordan Niethe 		imm = (unsigned short) word;
16533cdfcbfdSPaul Mackerras 		op->val = regs->gpr[rd] | (imm << 16);
16543cdfcbfdSPaul Mackerras 		goto logical_done_nocc;
16550016a4cfSPaul Mackerras 
16560016a4cfSPaul Mackerras 	case 26:	/* xori */
1657777e26f0SJordan Niethe 		op->val = regs->gpr[rd] ^ (unsigned short) word;
16583cdfcbfdSPaul Mackerras 		goto logical_done_nocc;
16590016a4cfSPaul Mackerras 
16600016a4cfSPaul Mackerras 	case 27:	/* xoris */
1661777e26f0SJordan Niethe 		imm = (unsigned short) word;
16623cdfcbfdSPaul Mackerras 		op->val = regs->gpr[rd] ^ (imm << 16);
16633cdfcbfdSPaul Mackerras 		goto logical_done_nocc;
16640016a4cfSPaul Mackerras 
16650016a4cfSPaul Mackerras 	case 28:	/* andi. */
1666777e26f0SJordan Niethe 		op->val = regs->gpr[rd] & (unsigned short) word;
1667ad47ff3eSAnton Blanchard 		set_cr0(regs, op);
16683cdfcbfdSPaul Mackerras 		goto logical_done_nocc;
16690016a4cfSPaul Mackerras 
16700016a4cfSPaul Mackerras 	case 29:	/* andis. */
1671777e26f0SJordan Niethe 		imm = (unsigned short) word;
16723cdfcbfdSPaul Mackerras 		op->val = regs->gpr[rd] & (imm << 16);
1673ad47ff3eSAnton Blanchard 		set_cr0(regs, op);
16743cdfcbfdSPaul Mackerras 		goto logical_done_nocc;
16750016a4cfSPaul Mackerras 
16760016a4cfSPaul Mackerras #ifdef __powerpc64__
16770016a4cfSPaul Mackerras 	case 30:	/* rld* */
1678777e26f0SJordan Niethe 		mb = ((word >> 6) & 0x1f) | (word & 0x20);
16790016a4cfSPaul Mackerras 		val = regs->gpr[rd];
1680777e26f0SJordan Niethe 		if ((word & 0x10) == 0) {
1681777e26f0SJordan Niethe 			sh = rb | ((word & 2) << 4);
16820016a4cfSPaul Mackerras 			val = ROTATE(val, sh);
1683777e26f0SJordan Niethe 			switch ((word >> 2) & 3) {
16840016a4cfSPaul Mackerras 			case 0:		/* rldicl */
16853cdfcbfdSPaul Mackerras 				val &= MASK64_L(mb);
16863cdfcbfdSPaul Mackerras 				break;
16870016a4cfSPaul Mackerras 			case 1:		/* rldicr */
16883cdfcbfdSPaul Mackerras 				val &= MASK64_R(mb);
16893cdfcbfdSPaul Mackerras 				break;
16900016a4cfSPaul Mackerras 			case 2:		/* rldic */
16913cdfcbfdSPaul Mackerras 				val &= MASK64(mb, 63 - sh);
16923cdfcbfdSPaul Mackerras 				break;
16930016a4cfSPaul Mackerras 			case 3:		/* rldimi */
16940016a4cfSPaul Mackerras 				imm = MASK64(mb, 63 - sh);
16953cdfcbfdSPaul Mackerras 				val = (regs->gpr[ra] & ~imm) |
16960016a4cfSPaul Mackerras 					(val & imm);
16970016a4cfSPaul Mackerras 			}
16983cdfcbfdSPaul Mackerras 			op->val = val;
16993cdfcbfdSPaul Mackerras 			goto logical_done;
17000016a4cfSPaul Mackerras 		} else {
17010016a4cfSPaul Mackerras 			sh = regs->gpr[rb] & 0x3f;
17020016a4cfSPaul Mackerras 			val = ROTATE(val, sh);
1703777e26f0SJordan Niethe 			switch ((word >> 1) & 7) {
17040016a4cfSPaul Mackerras 			case 0:		/* rldcl */
17053cdfcbfdSPaul Mackerras 				op->val = val & MASK64_L(mb);
17060016a4cfSPaul Mackerras 				goto logical_done;
17070016a4cfSPaul Mackerras 			case 1:		/* rldcr */
17083cdfcbfdSPaul Mackerras 				op->val = val & MASK64_R(mb);
17090016a4cfSPaul Mackerras 				goto logical_done;
17100016a4cfSPaul Mackerras 			}
17110016a4cfSPaul Mackerras 		}
17120016a4cfSPaul Mackerras #endif
17133cdfcbfdSPaul Mackerras 		op->type = UNKNOWN;	/* illegal instruction */
17143cdfcbfdSPaul Mackerras 		return 0;
17150016a4cfSPaul Mackerras 
17160016a4cfSPaul Mackerras 	case 31:
1717f1bbb99fSPaul Mackerras 		/* isel occupies 32 minor opcodes */
1718777e26f0SJordan Niethe 		if (((word >> 1) & 0x1f) == 15) {
1719777e26f0SJordan Niethe 			mb = (word >> 6) & 0x1f; /* bc field */
1720f1bbb99fSPaul Mackerras 			val = (regs->ccr >> (31 - mb)) & 1;
1721f1bbb99fSPaul Mackerras 			val2 = (ra) ? regs->gpr[ra] : 0;
1722f1bbb99fSPaul Mackerras 
1723f1bbb99fSPaul Mackerras 			op->val = (val) ? val2 : regs->gpr[rb];
1724f1bbb99fSPaul Mackerras 			goto compute_done;
1725f1bbb99fSPaul Mackerras 		}
1726f1bbb99fSPaul Mackerras 
1727777e26f0SJordan Niethe 		switch ((word >> 1) & 0x3ff) {
1728cf87c3f6SPaul Mackerras 		case 4:		/* tw */
1729cf87c3f6SPaul Mackerras 			if (rd == 0x1f ||
1730cf87c3f6SPaul Mackerras 			    (rd & trap_compare((int)regs->gpr[ra],
1731cf87c3f6SPaul Mackerras 					       (int)regs->gpr[rb])))
1732cf87c3f6SPaul Mackerras 				goto trap;
17333cdfcbfdSPaul Mackerras 			return 1;
1734cf87c3f6SPaul Mackerras #ifdef __powerpc64__
1735cf87c3f6SPaul Mackerras 		case 68:	/* td */
1736cf87c3f6SPaul Mackerras 			if (rd & trap_compare(regs->gpr[ra], regs->gpr[rb]))
1737cf87c3f6SPaul Mackerras 				goto trap;
17383cdfcbfdSPaul Mackerras 			return 1;
1739cf87c3f6SPaul Mackerras #endif
17400016a4cfSPaul Mackerras 		case 83:	/* mfmsr */
17410016a4cfSPaul Mackerras 			if (regs->msr & MSR_PR)
1742be96f633SPaul Mackerras 				goto priv;
1743be96f633SPaul Mackerras 			op->type = MFMSR;
1744be96f633SPaul Mackerras 			op->reg = rd;
1745be96f633SPaul Mackerras 			return 0;
17460016a4cfSPaul Mackerras 		case 146:	/* mtmsr */
17470016a4cfSPaul Mackerras 			if (regs->msr & MSR_PR)
1748be96f633SPaul Mackerras 				goto priv;
1749be96f633SPaul Mackerras 			op->type = MTMSR;
1750be96f633SPaul Mackerras 			op->reg = rd;
1751be96f633SPaul Mackerras 			op->val = 0xffffffff & ~(MSR_ME | MSR_LE);
1752be96f633SPaul Mackerras 			return 0;
1753c032524fSPaul Mackerras #ifdef CONFIG_PPC64
17540016a4cfSPaul Mackerras 		case 178:	/* mtmsrd */
17550016a4cfSPaul Mackerras 			if (regs->msr & MSR_PR)
1756be96f633SPaul Mackerras 				goto priv;
1757be96f633SPaul Mackerras 			op->type = MTMSR;
1758be96f633SPaul Mackerras 			op->reg = rd;
1759be96f633SPaul Mackerras 			/* only MSR_EE and MSR_RI get changed if bit 15 set */
1760be96f633SPaul Mackerras 			/* mtmsrd doesn't change MSR_HV, MSR_ME or MSR_LE */
1761777e26f0SJordan Niethe 			imm = (word & 0x10000)? 0x8002: 0xefffffffffffeffeUL;
1762be96f633SPaul Mackerras 			op->val = imm;
1763be96f633SPaul Mackerras 			return 0;
1764c032524fSPaul Mackerras #endif
1765be96f633SPaul Mackerras 
17660016a4cfSPaul Mackerras 		case 19:	/* mfcr */
17673cdfcbfdSPaul Mackerras 			imm = 0xffffffffUL;
1768777e26f0SJordan Niethe 			if ((word >> 20) & 1) {
176964e756c5SAnton Blanchard 				imm = 0xf0000000UL;
177064e756c5SAnton Blanchard 				for (sh = 0; sh < 8; ++sh) {
1771777e26f0SJordan Niethe 					if (word & (0x80000 >> sh))
177264e756c5SAnton Blanchard 						break;
177364e756c5SAnton Blanchard 					imm >>= 4;
177464e756c5SAnton Blanchard 				}
177564e756c5SAnton Blanchard 			}
17763cdfcbfdSPaul Mackerras 			op->val = regs->ccr & imm;
17773cdfcbfdSPaul Mackerras 			goto compute_done;
17780016a4cfSPaul Mackerras 
17795b75bd76SSathvika Vasireddy 		case 128:	/* setb */
17805b75bd76SSathvika Vasireddy 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
17815b75bd76SSathvika Vasireddy 				goto unknown_opcode;
17825b75bd76SSathvika Vasireddy 			/*
17835b75bd76SSathvika Vasireddy 			 * 'ra' encodes the CR field number (bfa) in the top 3 bits.
17845b75bd76SSathvika Vasireddy 			 * Since each CR field is 4 bits,
17855b75bd76SSathvika Vasireddy 			 * we can simply mask off the bottom two bits (bfa * 4)
17865b75bd76SSathvika Vasireddy 			 * to yield the first bit in the CR field.
17875b75bd76SSathvika Vasireddy 			 */
17885b75bd76SSathvika Vasireddy 			ra = ra & ~0x3;
17895b75bd76SSathvika Vasireddy 			/* 'val' stores bits of the CR field (bfa) */
17905b75bd76SSathvika Vasireddy 			val = regs->ccr >> (CR0_SHIFT - ra);
17915b75bd76SSathvika Vasireddy 			/* checks if the LT bit of CR field (bfa) is set */
17925b75bd76SSathvika Vasireddy 			if (val & 8)
17935b75bd76SSathvika Vasireddy 				op->val = -1;
17945b75bd76SSathvika Vasireddy 			/* checks if the GT bit of CR field (bfa) is set */
17955b75bd76SSathvika Vasireddy 			else if (val & 4)
17965b75bd76SSathvika Vasireddy 				op->val = 1;
17975b75bd76SSathvika Vasireddy 			else
17985b75bd76SSathvika Vasireddy 				op->val = 0;
17995b75bd76SSathvika Vasireddy 			goto compute_done;
18005b75bd76SSathvika Vasireddy 
18010016a4cfSPaul Mackerras 		case 144:	/* mtcrf */
18023cdfcbfdSPaul Mackerras 			op->type = COMPUTE + SETCC;
18030016a4cfSPaul Mackerras 			imm = 0xf0000000UL;
18040016a4cfSPaul Mackerras 			val = regs->gpr[rd];
18055bcaa4ccSAnton Blanchard 			op->ccval = regs->ccr;
18060016a4cfSPaul Mackerras 			for (sh = 0; sh < 8; ++sh) {
1807777e26f0SJordan Niethe 				if (word & (0x80000 >> sh))
18085bcaa4ccSAnton Blanchard 					op->ccval = (op->ccval & ~imm) |
18090016a4cfSPaul Mackerras 						(val & imm);
18100016a4cfSPaul Mackerras 				imm >>= 4;
18110016a4cfSPaul Mackerras 			}
18123cdfcbfdSPaul Mackerras 			return 1;
18130016a4cfSPaul Mackerras 
18140016a4cfSPaul Mackerras 		case 339:	/* mfspr */
1815777e26f0SJordan Niethe 			spr = ((word >> 16) & 0x1f) | ((word >> 6) & 0x3e0);
1816be96f633SPaul Mackerras 			op->type = MFSPR;
1817be96f633SPaul Mackerras 			op->reg = rd;
1818be96f633SPaul Mackerras 			op->spr = spr;
18193cdfcbfdSPaul Mackerras 			if (spr == SPRN_XER || spr == SPRN_LR ||
18203cdfcbfdSPaul Mackerras 			    spr == SPRN_CTR)
18213cdfcbfdSPaul Mackerras 				return 1;
1822be96f633SPaul Mackerras 			return 0;
18230016a4cfSPaul Mackerras 
18240016a4cfSPaul Mackerras 		case 467:	/* mtspr */
1825777e26f0SJordan Niethe 			spr = ((word >> 16) & 0x1f) | ((word >> 6) & 0x3e0);
1826be96f633SPaul Mackerras 			op->type = MTSPR;
1827be96f633SPaul Mackerras 			op->val = regs->gpr[rd];
1828be96f633SPaul Mackerras 			op->spr = spr;
18293cdfcbfdSPaul Mackerras 			if (spr == SPRN_XER || spr == SPRN_LR ||
18303cdfcbfdSPaul Mackerras 			    spr == SPRN_CTR)
18313cdfcbfdSPaul Mackerras 				return 1;
1832be96f633SPaul Mackerras 			return 0;
18330016a4cfSPaul Mackerras 
18340016a4cfSPaul Mackerras /*
18350016a4cfSPaul Mackerras  * Compare instructions
18360016a4cfSPaul Mackerras  */
18370016a4cfSPaul Mackerras 		case 0:	/* cmp */
18380016a4cfSPaul Mackerras 			val = regs->gpr[ra];
18390016a4cfSPaul Mackerras 			val2 = regs->gpr[rb];
18400016a4cfSPaul Mackerras #ifdef __powerpc64__
18410016a4cfSPaul Mackerras 			if ((rd & 1) == 0) {
18420016a4cfSPaul Mackerras 				/* word (32-bit) compare */
18430016a4cfSPaul Mackerras 				val = (int) val;
18440016a4cfSPaul Mackerras 				val2 = (int) val2;
184514cf11afSPaul Mackerras 			}
18460016a4cfSPaul Mackerras #endif
18473cdfcbfdSPaul Mackerras 			do_cmp_signed(regs, op, val, val2, rd >> 2);
18483cdfcbfdSPaul Mackerras 			return 1;
18490016a4cfSPaul Mackerras 
18500016a4cfSPaul Mackerras 		case 32:	/* cmpl */
18510016a4cfSPaul Mackerras 			val = regs->gpr[ra];
18520016a4cfSPaul Mackerras 			val2 = regs->gpr[rb];
18530016a4cfSPaul Mackerras #ifdef __powerpc64__
18540016a4cfSPaul Mackerras 			if ((rd & 1) == 0) {
18550016a4cfSPaul Mackerras 				/* word (32-bit) compare */
18560016a4cfSPaul Mackerras 				val = (unsigned int) val;
18570016a4cfSPaul Mackerras 				val2 = (unsigned int) val2;
185814cf11afSPaul Mackerras 			}
18590016a4cfSPaul Mackerras #endif
18603cdfcbfdSPaul Mackerras 			do_cmp_unsigned(regs, op, val, val2, rd >> 2);
18613cdfcbfdSPaul Mackerras 			return 1;
18620016a4cfSPaul Mackerras 
186302c0f62aSMatt Brown 		case 508: /* cmpb */
18643cdfcbfdSPaul Mackerras 			do_cmpb(regs, op, regs->gpr[rd], regs->gpr[rb]);
18653cdfcbfdSPaul Mackerras 			goto logical_done_nocc;
186602c0f62aSMatt Brown 
18670016a4cfSPaul Mackerras /*
18680016a4cfSPaul Mackerras  * Arithmetic instructions
18690016a4cfSPaul Mackerras  */
18700016a4cfSPaul Mackerras 		case 8:	/* subfc */
18713cdfcbfdSPaul Mackerras 			add_with_carry(regs, op, rd, ~regs->gpr[ra],
18720016a4cfSPaul Mackerras 				       regs->gpr[rb], 1);
18730016a4cfSPaul Mackerras 			goto arith_done;
18740016a4cfSPaul Mackerras #ifdef __powerpc64__
18750016a4cfSPaul Mackerras 		case 9:	/* mulhdu */
18763cdfcbfdSPaul Mackerras 			asm("mulhdu %0,%1,%2" : "=r" (op->val) :
18770016a4cfSPaul Mackerras 			    "r" (regs->gpr[ra]), "r" (regs->gpr[rb]));
18780016a4cfSPaul Mackerras 			goto arith_done;
18790016a4cfSPaul Mackerras #endif
18800016a4cfSPaul Mackerras 		case 10:	/* addc */
18813cdfcbfdSPaul Mackerras 			add_with_carry(regs, op, rd, regs->gpr[ra],
18820016a4cfSPaul Mackerras 				       regs->gpr[rb], 0);
18830016a4cfSPaul Mackerras 			goto arith_done;
18840016a4cfSPaul Mackerras 
18850016a4cfSPaul Mackerras 		case 11:	/* mulhwu */
18863cdfcbfdSPaul Mackerras 			asm("mulhwu %0,%1,%2" : "=r" (op->val) :
18870016a4cfSPaul Mackerras 			    "r" (regs->gpr[ra]), "r" (regs->gpr[rb]));
18880016a4cfSPaul Mackerras 			goto arith_done;
18890016a4cfSPaul Mackerras 
18900016a4cfSPaul Mackerras 		case 40:	/* subf */
18913cdfcbfdSPaul Mackerras 			op->val = regs->gpr[rb] - regs->gpr[ra];
18920016a4cfSPaul Mackerras 			goto arith_done;
18930016a4cfSPaul Mackerras #ifdef __powerpc64__
18940016a4cfSPaul Mackerras 		case 73:	/* mulhd */
18953cdfcbfdSPaul Mackerras 			asm("mulhd %0,%1,%2" : "=r" (op->val) :
18960016a4cfSPaul Mackerras 			    "r" (regs->gpr[ra]), "r" (regs->gpr[rb]));
18970016a4cfSPaul Mackerras 			goto arith_done;
18980016a4cfSPaul Mackerras #endif
18990016a4cfSPaul Mackerras 		case 75:	/* mulhw */
19003cdfcbfdSPaul Mackerras 			asm("mulhw %0,%1,%2" : "=r" (op->val) :
19010016a4cfSPaul Mackerras 			    "r" (regs->gpr[ra]), "r" (regs->gpr[rb]));
19020016a4cfSPaul Mackerras 			goto arith_done;
19030016a4cfSPaul Mackerras 
19040016a4cfSPaul Mackerras 		case 104:	/* neg */
19053cdfcbfdSPaul Mackerras 			op->val = -regs->gpr[ra];
19060016a4cfSPaul Mackerras 			goto arith_done;
19070016a4cfSPaul Mackerras 
19080016a4cfSPaul Mackerras 		case 136:	/* subfe */
19093cdfcbfdSPaul Mackerras 			add_with_carry(regs, op, rd, ~regs->gpr[ra],
19103cdfcbfdSPaul Mackerras 				       regs->gpr[rb], regs->xer & XER_CA);
19110016a4cfSPaul Mackerras 			goto arith_done;
19120016a4cfSPaul Mackerras 
19130016a4cfSPaul Mackerras 		case 138:	/* adde */
19143cdfcbfdSPaul Mackerras 			add_with_carry(regs, op, rd, regs->gpr[ra],
19153cdfcbfdSPaul Mackerras 				       regs->gpr[rb], regs->xer & XER_CA);
19160016a4cfSPaul Mackerras 			goto arith_done;
19170016a4cfSPaul Mackerras 
19180016a4cfSPaul Mackerras 		case 200:	/* subfze */
19193cdfcbfdSPaul Mackerras 			add_with_carry(regs, op, rd, ~regs->gpr[ra], 0L,
19200016a4cfSPaul Mackerras 				       regs->xer & XER_CA);
19210016a4cfSPaul Mackerras 			goto arith_done;
19220016a4cfSPaul Mackerras 
19230016a4cfSPaul Mackerras 		case 202:	/* addze */
19243cdfcbfdSPaul Mackerras 			add_with_carry(regs, op, rd, regs->gpr[ra], 0L,
19250016a4cfSPaul Mackerras 				       regs->xer & XER_CA);
19260016a4cfSPaul Mackerras 			goto arith_done;
19270016a4cfSPaul Mackerras 
19280016a4cfSPaul Mackerras 		case 232:	/* subfme */
19293cdfcbfdSPaul Mackerras 			add_with_carry(regs, op, rd, ~regs->gpr[ra], -1L,
19300016a4cfSPaul Mackerras 				       regs->xer & XER_CA);
19310016a4cfSPaul Mackerras 			goto arith_done;
19320016a4cfSPaul Mackerras #ifdef __powerpc64__
19330016a4cfSPaul Mackerras 		case 233:	/* mulld */
19343cdfcbfdSPaul Mackerras 			op->val = regs->gpr[ra] * regs->gpr[rb];
19350016a4cfSPaul Mackerras 			goto arith_done;
19360016a4cfSPaul Mackerras #endif
19370016a4cfSPaul Mackerras 		case 234:	/* addme */
19383cdfcbfdSPaul Mackerras 			add_with_carry(regs, op, rd, regs->gpr[ra], -1L,
19390016a4cfSPaul Mackerras 				       regs->xer & XER_CA);
19400016a4cfSPaul Mackerras 			goto arith_done;
19410016a4cfSPaul Mackerras 
19420016a4cfSPaul Mackerras 		case 235:	/* mullw */
19431575fe06SAnton Blanchard 			op->val = (long)(int) regs->gpr[ra] *
19441575fe06SAnton Blanchard 				(int) regs->gpr[rb];
19451575fe06SAnton Blanchard 
19460016a4cfSPaul Mackerras 			goto arith_done;
19476324320dSSandipan Das #ifdef __powerpc64__
19486324320dSSandipan Das 		case 265:	/* modud */
19496324320dSSandipan Das 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
19508813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
19516324320dSSandipan Das 			op->val = regs->gpr[ra] % regs->gpr[rb];
19526324320dSSandipan Das 			goto compute_done;
19536324320dSSandipan Das #endif
19540016a4cfSPaul Mackerras 		case 266:	/* add */
19553cdfcbfdSPaul Mackerras 			op->val = regs->gpr[ra] + regs->gpr[rb];
19560016a4cfSPaul Mackerras 			goto arith_done;
19576c180071SPrasannaKumar Muralidharan 
19586c180071SPrasannaKumar Muralidharan 		case 267:	/* moduw */
19596c180071SPrasannaKumar Muralidharan 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
19608813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
19616c180071SPrasannaKumar Muralidharan 			op->val = (unsigned int) regs->gpr[ra] %
19626c180071SPrasannaKumar Muralidharan 				(unsigned int) regs->gpr[rb];
19636c180071SPrasannaKumar Muralidharan 			goto compute_done;
19640016a4cfSPaul Mackerras #ifdef __powerpc64__
19650016a4cfSPaul Mackerras 		case 457:	/* divdu */
19663cdfcbfdSPaul Mackerras 			op->val = regs->gpr[ra] / regs->gpr[rb];
19670016a4cfSPaul Mackerras 			goto arith_done;
19680016a4cfSPaul Mackerras #endif
19690016a4cfSPaul Mackerras 		case 459:	/* divwu */
19703cdfcbfdSPaul Mackerras 			op->val = (unsigned int) regs->gpr[ra] /
19710016a4cfSPaul Mackerras 				(unsigned int) regs->gpr[rb];
19720016a4cfSPaul Mackerras 			goto arith_done;
19730016a4cfSPaul Mackerras #ifdef __powerpc64__
19740016a4cfSPaul Mackerras 		case 489:	/* divd */
19753cdfcbfdSPaul Mackerras 			op->val = (long int) regs->gpr[ra] /
19760016a4cfSPaul Mackerras 				(long int) regs->gpr[rb];
19770016a4cfSPaul Mackerras 			goto arith_done;
19780016a4cfSPaul Mackerras #endif
19790016a4cfSPaul Mackerras 		case 491:	/* divw */
19803cdfcbfdSPaul Mackerras 			op->val = (int) regs->gpr[ra] /
19810016a4cfSPaul Mackerras 				(int) regs->gpr[rb];
19820016a4cfSPaul Mackerras 			goto arith_done;
1983151c32bfSBalamuruhan S #ifdef __powerpc64__
1984151c32bfSBalamuruhan S 		case 425:	/* divde[.] */
1985151c32bfSBalamuruhan S 			asm volatile(PPC_DIVDE(%0, %1, %2) :
1986151c32bfSBalamuruhan S 				"=r" (op->val) : "r" (regs->gpr[ra]),
1987151c32bfSBalamuruhan S 				"r" (regs->gpr[rb]));
1988151c32bfSBalamuruhan S 			goto arith_done;
1989151c32bfSBalamuruhan S 		case 393:	/* divdeu[.] */
1990151c32bfSBalamuruhan S 			asm volatile(PPC_DIVDEU(%0, %1, %2) :
1991151c32bfSBalamuruhan S 				"=r" (op->val) : "r" (regs->gpr[ra]),
1992151c32bfSBalamuruhan S 				"r" (regs->gpr[rb]));
1993151c32bfSBalamuruhan S 			goto arith_done;
1994151c32bfSBalamuruhan S #endif
1995a23987efSSandipan Das 		case 755:	/* darn */
1996a23987efSSandipan Das 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
19978813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
1998a23987efSSandipan Das 			switch (ra & 0x3) {
1999a23987efSSandipan Das 			case 0:
2000a23987efSSandipan Das 				/* 32-bit conditioned */
2001a23987efSSandipan Das 				asm volatile(PPC_DARN(%0, 0) : "=r" (op->val));
2002a23987efSSandipan Das 				goto compute_done;
2003a23987efSSandipan Das 
2004a23987efSSandipan Das 			case 1:
2005a23987efSSandipan Das 				/* 64-bit conditioned */
2006a23987efSSandipan Das 				asm volatile(PPC_DARN(%0, 1) : "=r" (op->val));
2007a23987efSSandipan Das 				goto compute_done;
2008a23987efSSandipan Das 
2009a23987efSSandipan Das 			case 2:
2010a23987efSSandipan Das 				/* 64-bit raw */
2011a23987efSSandipan Das 				asm volatile(PPC_DARN(%0, 2) : "=r" (op->val));
2012a23987efSSandipan Das 				goto compute_done;
2013a23987efSSandipan Das 			}
2014a23987efSSandipan Das 
201522b89ba1SSandipan Das 			goto unknown_opcode;
20166324320dSSandipan Das #ifdef __powerpc64__
20176324320dSSandipan Das 		case 777:	/* modsd */
20186324320dSSandipan Das 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
20198813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
20206324320dSSandipan Das 			op->val = (long int) regs->gpr[ra] %
20216324320dSSandipan Das 				(long int) regs->gpr[rb];
20226324320dSSandipan Das 			goto compute_done;
20236324320dSSandipan Das #endif
20246c180071SPrasannaKumar Muralidharan 		case 779:	/* modsw */
20256c180071SPrasannaKumar Muralidharan 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
20268813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
20276c180071SPrasannaKumar Muralidharan 			op->val = (int) regs->gpr[ra] %
20286c180071SPrasannaKumar Muralidharan 				(int) regs->gpr[rb];
20296c180071SPrasannaKumar Muralidharan 			goto compute_done;
20306c180071SPrasannaKumar Muralidharan 
20310016a4cfSPaul Mackerras 
20320016a4cfSPaul Mackerras /*
20330016a4cfSPaul Mackerras  * Logical instructions
20340016a4cfSPaul Mackerras  */
20350016a4cfSPaul Mackerras 		case 26:	/* cntlzw */
2036b0490a04SSandipan Das 			val = (unsigned int) regs->gpr[rd];
2037b0490a04SSandipan Das 			op->val = ( val ? __builtin_clz(val) : 32 );
20380016a4cfSPaul Mackerras 			goto logical_done;
20390016a4cfSPaul Mackerras #ifdef __powerpc64__
20400016a4cfSPaul Mackerras 		case 58:	/* cntlzd */
2041b0490a04SSandipan Das 			val = regs->gpr[rd];
2042b0490a04SSandipan Das 			op->val = ( val ? __builtin_clzl(val) : 64 );
20430016a4cfSPaul Mackerras 			goto logical_done;
20440016a4cfSPaul Mackerras #endif
20450016a4cfSPaul Mackerras 		case 28:	/* and */
20463cdfcbfdSPaul Mackerras 			op->val = regs->gpr[rd] & regs->gpr[rb];
20470016a4cfSPaul Mackerras 			goto logical_done;
20480016a4cfSPaul Mackerras 
20490016a4cfSPaul Mackerras 		case 60:	/* andc */
20503cdfcbfdSPaul Mackerras 			op->val = regs->gpr[rd] & ~regs->gpr[rb];
20510016a4cfSPaul Mackerras 			goto logical_done;
20520016a4cfSPaul Mackerras 
2053dcbd19b4SMatt Brown 		case 122:	/* popcntb */
20543cdfcbfdSPaul Mackerras 			do_popcnt(regs, op, regs->gpr[rd], 8);
20555762e083SPaul Mackerras 			goto logical_done_nocc;
2056dcbd19b4SMatt Brown 
20570016a4cfSPaul Mackerras 		case 124:	/* nor */
20583cdfcbfdSPaul Mackerras 			op->val = ~(regs->gpr[rd] | regs->gpr[rb]);
20590016a4cfSPaul Mackerras 			goto logical_done;
20602c979c48SMatt Brown 
20612c979c48SMatt Brown 		case 154:	/* prtyw */
20623cdfcbfdSPaul Mackerras 			do_prty(regs, op, regs->gpr[rd], 32);
20635762e083SPaul Mackerras 			goto logical_done_nocc;
20642c979c48SMatt Brown 
20652c979c48SMatt Brown 		case 186:	/* prtyd */
20663cdfcbfdSPaul Mackerras 			do_prty(regs, op, regs->gpr[rd], 64);
20675762e083SPaul Mackerras 			goto logical_done_nocc;
2068f312793dSMatt Brown #ifdef CONFIG_PPC64
2069f312793dSMatt Brown 		case 252:	/* bpermd */
20703cdfcbfdSPaul Mackerras 			do_bpermd(regs, op, regs->gpr[rd], regs->gpr[rb]);
20715762e083SPaul Mackerras 			goto logical_done_nocc;
2072f312793dSMatt Brown #endif
20730016a4cfSPaul Mackerras 		case 284:	/* xor */
20743cdfcbfdSPaul Mackerras 			op->val = ~(regs->gpr[rd] ^ regs->gpr[rb]);
20750016a4cfSPaul Mackerras 			goto logical_done;
20760016a4cfSPaul Mackerras 
20770016a4cfSPaul Mackerras 		case 316:	/* xor */
20783cdfcbfdSPaul Mackerras 			op->val = regs->gpr[rd] ^ regs->gpr[rb];
20790016a4cfSPaul Mackerras 			goto logical_done;
20800016a4cfSPaul Mackerras 
2081dcbd19b4SMatt Brown 		case 378:	/* popcntw */
20823cdfcbfdSPaul Mackerras 			do_popcnt(regs, op, regs->gpr[rd], 32);
20835762e083SPaul Mackerras 			goto logical_done_nocc;
2084dcbd19b4SMatt Brown 
20850016a4cfSPaul Mackerras 		case 412:	/* orc */
20863cdfcbfdSPaul Mackerras 			op->val = regs->gpr[rd] | ~regs->gpr[rb];
20870016a4cfSPaul Mackerras 			goto logical_done;
20880016a4cfSPaul Mackerras 
20890016a4cfSPaul Mackerras 		case 444:	/* or */
20903cdfcbfdSPaul Mackerras 			op->val = regs->gpr[rd] | regs->gpr[rb];
20910016a4cfSPaul Mackerras 			goto logical_done;
20920016a4cfSPaul Mackerras 
20930016a4cfSPaul Mackerras 		case 476:	/* nand */
20943cdfcbfdSPaul Mackerras 			op->val = ~(regs->gpr[rd] & regs->gpr[rb]);
20950016a4cfSPaul Mackerras 			goto logical_done;
2096dcbd19b4SMatt Brown #ifdef CONFIG_PPC64
2097dcbd19b4SMatt Brown 		case 506:	/* popcntd */
20983cdfcbfdSPaul Mackerras 			do_popcnt(regs, op, regs->gpr[rd], 64);
20995762e083SPaul Mackerras 			goto logical_done_nocc;
2100dcbd19b4SMatt Brown #endif
210132628b5cSSandipan Das 		case 538:	/* cnttzw */
210232628b5cSSandipan Das 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
21038813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
210432628b5cSSandipan Das 			val = (unsigned int) regs->gpr[rd];
210532628b5cSSandipan Das 			op->val = (val ? __builtin_ctz(val) : 32);
210632628b5cSSandipan Das 			goto logical_done;
210732628b5cSSandipan Das #ifdef __powerpc64__
210832628b5cSSandipan Das 		case 570:	/* cnttzd */
210932628b5cSSandipan Das 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
21108813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
211132628b5cSSandipan Das 			val = regs->gpr[rd];
211232628b5cSSandipan Das 			op->val = (val ? __builtin_ctzl(val) : 64);
211332628b5cSSandipan Das 			goto logical_done;
211432628b5cSSandipan Das #endif
21150016a4cfSPaul Mackerras 		case 922:	/* extsh */
21163cdfcbfdSPaul Mackerras 			op->val = (signed short) regs->gpr[rd];
21170016a4cfSPaul Mackerras 			goto logical_done;
21180016a4cfSPaul Mackerras 
21190016a4cfSPaul Mackerras 		case 954:	/* extsb */
21203cdfcbfdSPaul Mackerras 			op->val = (signed char) regs->gpr[rd];
21210016a4cfSPaul Mackerras 			goto logical_done;
21220016a4cfSPaul Mackerras #ifdef __powerpc64__
21230016a4cfSPaul Mackerras 		case 986:	/* extsw */
21243cdfcbfdSPaul Mackerras 			op->val = (signed int) regs->gpr[rd];
21250016a4cfSPaul Mackerras 			goto logical_done;
21260016a4cfSPaul Mackerras #endif
21270016a4cfSPaul Mackerras 
21280016a4cfSPaul Mackerras /*
21290016a4cfSPaul Mackerras  * Shift instructions
21300016a4cfSPaul Mackerras  */
21310016a4cfSPaul Mackerras 		case 24:	/* slw */
21320016a4cfSPaul Mackerras 			sh = regs->gpr[rb] & 0x3f;
21330016a4cfSPaul Mackerras 			if (sh < 32)
21343cdfcbfdSPaul Mackerras 				op->val = (regs->gpr[rd] << sh) & 0xffffffffUL;
21350016a4cfSPaul Mackerras 			else
21363cdfcbfdSPaul Mackerras 				op->val = 0;
21370016a4cfSPaul Mackerras 			goto logical_done;
21380016a4cfSPaul Mackerras 
21390016a4cfSPaul Mackerras 		case 536:	/* srw */
21400016a4cfSPaul Mackerras 			sh = regs->gpr[rb] & 0x3f;
21410016a4cfSPaul Mackerras 			if (sh < 32)
21423cdfcbfdSPaul Mackerras 				op->val = (regs->gpr[rd] & 0xffffffffUL) >> sh;
21430016a4cfSPaul Mackerras 			else
21443cdfcbfdSPaul Mackerras 				op->val = 0;
21450016a4cfSPaul Mackerras 			goto logical_done;
21460016a4cfSPaul Mackerras 
21470016a4cfSPaul Mackerras 		case 792:	/* sraw */
21483cdfcbfdSPaul Mackerras 			op->type = COMPUTE + SETREG + SETXER;
21490016a4cfSPaul Mackerras 			sh = regs->gpr[rb] & 0x3f;
21500016a4cfSPaul Mackerras 			ival = (signed int) regs->gpr[rd];
21513cdfcbfdSPaul Mackerras 			op->val = ival >> (sh < 32 ? sh : 31);
21523cdfcbfdSPaul Mackerras 			op->xerval = regs->xer;
2153e698b966SPaul Mackerras 			if (ival < 0 && (sh >= 32 || (ival & ((1ul << sh) - 1)) != 0))
21543cdfcbfdSPaul Mackerras 				op->xerval |= XER_CA;
21550016a4cfSPaul Mackerras 			else
21563cdfcbfdSPaul Mackerras 				op->xerval &= ~XER_CA;
21570a75aff1SSandipan Das 			set_ca32(op, op->xerval & XER_CA);
21580016a4cfSPaul Mackerras 			goto logical_done;
21590016a4cfSPaul Mackerras 
21600016a4cfSPaul Mackerras 		case 824:	/* srawi */
21613cdfcbfdSPaul Mackerras 			op->type = COMPUTE + SETREG + SETXER;
21620016a4cfSPaul Mackerras 			sh = rb;
21630016a4cfSPaul Mackerras 			ival = (signed int) regs->gpr[rd];
21643cdfcbfdSPaul Mackerras 			op->val = ival >> sh;
21653cdfcbfdSPaul Mackerras 			op->xerval = regs->xer;
2166e698b966SPaul Mackerras 			if (ival < 0 && (ival & ((1ul << sh) - 1)) != 0)
21673cdfcbfdSPaul Mackerras 				op->xerval |= XER_CA;
21680016a4cfSPaul Mackerras 			else
21693cdfcbfdSPaul Mackerras 				op->xerval &= ~XER_CA;
21700a75aff1SSandipan Das 			set_ca32(op, op->xerval & XER_CA);
21710016a4cfSPaul Mackerras 			goto logical_done;
21720016a4cfSPaul Mackerras 
21730016a4cfSPaul Mackerras #ifdef __powerpc64__
21740016a4cfSPaul Mackerras 		case 27:	/* sld */
2175e698b966SPaul Mackerras 			sh = regs->gpr[rb] & 0x7f;
21760016a4cfSPaul Mackerras 			if (sh < 64)
21773cdfcbfdSPaul Mackerras 				op->val = regs->gpr[rd] << sh;
21780016a4cfSPaul Mackerras 			else
21793cdfcbfdSPaul Mackerras 				op->val = 0;
21800016a4cfSPaul Mackerras 			goto logical_done;
21810016a4cfSPaul Mackerras 
21820016a4cfSPaul Mackerras 		case 539:	/* srd */
21830016a4cfSPaul Mackerras 			sh = regs->gpr[rb] & 0x7f;
21840016a4cfSPaul Mackerras 			if (sh < 64)
21853cdfcbfdSPaul Mackerras 				op->val = regs->gpr[rd] >> sh;
21860016a4cfSPaul Mackerras 			else
21873cdfcbfdSPaul Mackerras 				op->val = 0;
21880016a4cfSPaul Mackerras 			goto logical_done;
21890016a4cfSPaul Mackerras 
21900016a4cfSPaul Mackerras 		case 794:	/* srad */
21913cdfcbfdSPaul Mackerras 			op->type = COMPUTE + SETREG + SETXER;
21920016a4cfSPaul Mackerras 			sh = regs->gpr[rb] & 0x7f;
21930016a4cfSPaul Mackerras 			ival = (signed long int) regs->gpr[rd];
21943cdfcbfdSPaul Mackerras 			op->val = ival >> (sh < 64 ? sh : 63);
21953cdfcbfdSPaul Mackerras 			op->xerval = regs->xer;
2196e698b966SPaul Mackerras 			if (ival < 0 && (sh >= 64 || (ival & ((1ul << sh) - 1)) != 0))
21973cdfcbfdSPaul Mackerras 				op->xerval |= XER_CA;
21980016a4cfSPaul Mackerras 			else
21993cdfcbfdSPaul Mackerras 				op->xerval &= ~XER_CA;
22000a75aff1SSandipan Das 			set_ca32(op, op->xerval & XER_CA);
22010016a4cfSPaul Mackerras 			goto logical_done;
22020016a4cfSPaul Mackerras 
22030016a4cfSPaul Mackerras 		case 826:	/* sradi with sh_5 = 0 */
22040016a4cfSPaul Mackerras 		case 827:	/* sradi with sh_5 = 1 */
22053cdfcbfdSPaul Mackerras 			op->type = COMPUTE + SETREG + SETXER;
2206777e26f0SJordan Niethe 			sh = rb | ((word & 2) << 4);
22070016a4cfSPaul Mackerras 			ival = (signed long int) regs->gpr[rd];
22083cdfcbfdSPaul Mackerras 			op->val = ival >> sh;
22093cdfcbfdSPaul Mackerras 			op->xerval = regs->xer;
2210e698b966SPaul Mackerras 			if (ival < 0 && (ival & ((1ul << sh) - 1)) != 0)
22113cdfcbfdSPaul Mackerras 				op->xerval |= XER_CA;
22120016a4cfSPaul Mackerras 			else
22133cdfcbfdSPaul Mackerras 				op->xerval &= ~XER_CA;
22140a75aff1SSandipan Das 			set_ca32(op, op->xerval & XER_CA);
22150016a4cfSPaul Mackerras 			goto logical_done;
22163e751acbSSandipan Das 
22173e751acbSSandipan Das 		case 890:	/* extswsli with sh_5 = 0 */
22183e751acbSSandipan Das 		case 891:	/* extswsli with sh_5 = 1 */
22193e751acbSSandipan Das 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
22208813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
22213e751acbSSandipan Das 			op->type = COMPUTE + SETREG;
2222777e26f0SJordan Niethe 			sh = rb | ((word & 2) << 4);
22233e751acbSSandipan Das 			val = (signed int) regs->gpr[rd];
22243e751acbSSandipan Das 			if (sh)
22253e751acbSSandipan Das 				op->val = ROTATE(val, sh) & MASK64(0, 63 - sh);
22263e751acbSSandipan Das 			else
22273e751acbSSandipan Das 				op->val = val;
22283e751acbSSandipan Das 			goto logical_done;
22293e751acbSSandipan Das 
22300016a4cfSPaul Mackerras #endif /* __powerpc64__ */
22310016a4cfSPaul Mackerras 
22320016a4cfSPaul Mackerras /*
22330016a4cfSPaul Mackerras  * Cache instructions
22340016a4cfSPaul Mackerras  */
22350016a4cfSPaul Mackerras 		case 54:	/* dcbst */
2236be96f633SPaul Mackerras 			op->type = MKOP(CACHEOP, DCBST, 0);
2237777e26f0SJordan Niethe 			op->ea = xform_ea(word, regs);
223814cf11afSPaul Mackerras 			return 0;
22390016a4cfSPaul Mackerras 
22400016a4cfSPaul Mackerras 		case 86:	/* dcbf */
2241be96f633SPaul Mackerras 			op->type = MKOP(CACHEOP, DCBF, 0);
2242777e26f0SJordan Niethe 			op->ea = xform_ea(word, regs);
22430016a4cfSPaul Mackerras 			return 0;
22440016a4cfSPaul Mackerras 
22450016a4cfSPaul Mackerras 		case 246:	/* dcbtst */
2246be96f633SPaul Mackerras 			op->type = MKOP(CACHEOP, DCBTST, 0);
2247777e26f0SJordan Niethe 			op->ea = xform_ea(word, regs);
2248be96f633SPaul Mackerras 			op->reg = rd;
2249be96f633SPaul Mackerras 			return 0;
22500016a4cfSPaul Mackerras 
22510016a4cfSPaul Mackerras 		case 278:	/* dcbt */
2252be96f633SPaul Mackerras 			op->type = MKOP(CACHEOP, DCBTST, 0);
2253777e26f0SJordan Niethe 			op->ea = xform_ea(word, regs);
2254be96f633SPaul Mackerras 			op->reg = rd;
2255be96f633SPaul Mackerras 			return 0;
2256cf87c3f6SPaul Mackerras 
2257cf87c3f6SPaul Mackerras 		case 982:	/* icbi */
2258cf87c3f6SPaul Mackerras 			op->type = MKOP(CACHEOP, ICBI, 0);
2259777e26f0SJordan Niethe 			op->ea = xform_ea(word, regs);
2260cf87c3f6SPaul Mackerras 			return 0;
2261b2543f7bSPaul Mackerras 
2262b2543f7bSPaul Mackerras 		case 1014:	/* dcbz */
2263b2543f7bSPaul Mackerras 			op->type = MKOP(CACHEOP, DCBZ, 0);
2264777e26f0SJordan Niethe 			op->ea = xform_ea(word, regs);
2265b2543f7bSPaul Mackerras 			return 0;
22660016a4cfSPaul Mackerras 		}
22670016a4cfSPaul Mackerras 		break;
22680016a4cfSPaul Mackerras 	}
22690016a4cfSPaul Mackerras 
22700016a4cfSPaul Mackerras /*
2271be96f633SPaul Mackerras  * Loads and stores.
22720016a4cfSPaul Mackerras  */
2273be96f633SPaul Mackerras 	op->type = UNKNOWN;
2274be96f633SPaul Mackerras 	op->update_reg = ra;
2275be96f633SPaul Mackerras 	op->reg = rd;
2276be96f633SPaul Mackerras 	op->val = regs->gpr[rd];
2277777e26f0SJordan Niethe 	u = (word >> 20) & UPDATE;
2278350779a2SPaul Mackerras 	op->vsx_flags = 0;
22790016a4cfSPaul Mackerras 
22800016a4cfSPaul Mackerras 	switch (opcode) {
22810016a4cfSPaul Mackerras 	case 31:
2282777e26f0SJordan Niethe 		u = word & UPDATE;
2283777e26f0SJordan Niethe 		op->ea = xform_ea(word, regs);
2284777e26f0SJordan Niethe 		switch ((word >> 1) & 0x3ff) {
22850016a4cfSPaul Mackerras 		case 20:	/* lwarx */
2286be96f633SPaul Mackerras 			op->type = MKOP(LARX, 0, 4);
2287be96f633SPaul Mackerras 			break;
22880016a4cfSPaul Mackerras 
22890016a4cfSPaul Mackerras 		case 150:	/* stwcx. */
2290be96f633SPaul Mackerras 			op->type = MKOP(STCX, 0, 4);
2291be96f633SPaul Mackerras 			break;
22920016a4cfSPaul Mackerras 
2293b86cf14fSNicholas Piggin #ifdef CONFIG_PPC_HAS_LBARX_LHARX
2294350779a2SPaul Mackerras 		case 52:	/* lbarx */
2295350779a2SPaul Mackerras 			op->type = MKOP(LARX, 0, 1);
2296350779a2SPaul Mackerras 			break;
2297350779a2SPaul Mackerras 
2298350779a2SPaul Mackerras 		case 694:	/* stbcx. */
2299350779a2SPaul Mackerras 			op->type = MKOP(STCX, 0, 1);
2300350779a2SPaul Mackerras 			break;
2301350779a2SPaul Mackerras 
2302350779a2SPaul Mackerras 		case 116:	/* lharx */
2303350779a2SPaul Mackerras 			op->type = MKOP(LARX, 0, 2);
2304350779a2SPaul Mackerras 			break;
2305350779a2SPaul Mackerras 
2306350779a2SPaul Mackerras 		case 726:	/* sthcx. */
2307350779a2SPaul Mackerras 			op->type = MKOP(STCX, 0, 2);
2308350779a2SPaul Mackerras 			break;
2309b86cf14fSNicholas Piggin #endif
2310b86cf14fSNicholas Piggin #ifdef __powerpc64__
2311b86cf14fSNicholas Piggin 		case 84:	/* ldarx */
2312b86cf14fSNicholas Piggin 			op->type = MKOP(LARX, 0, 8);
2313b86cf14fSNicholas Piggin 			break;
2314b86cf14fSNicholas Piggin 
2315b86cf14fSNicholas Piggin 		case 214:	/* stdcx. */
2316b86cf14fSNicholas Piggin 			op->type = MKOP(STCX, 0, 8);
2317b86cf14fSNicholas Piggin 			break;
2318350779a2SPaul Mackerras 
2319350779a2SPaul Mackerras 		case 276:	/* lqarx */
2320350779a2SPaul Mackerras 			if (!((rd & 1) || rd == ra || rd == rb))
2321350779a2SPaul Mackerras 				op->type = MKOP(LARX, 0, 16);
2322350779a2SPaul Mackerras 			break;
2323350779a2SPaul Mackerras 
2324350779a2SPaul Mackerras 		case 182:	/* stqcx. */
2325350779a2SPaul Mackerras 			if (!(rd & 1))
2326350779a2SPaul Mackerras 				op->type = MKOP(STCX, 0, 16);
2327be96f633SPaul Mackerras 			break;
23280016a4cfSPaul Mackerras #endif
23290016a4cfSPaul Mackerras 
23300016a4cfSPaul Mackerras 		case 23:	/* lwzx */
23310016a4cfSPaul Mackerras 		case 55:	/* lwzux */
2332be96f633SPaul Mackerras 			op->type = MKOP(LOAD, u, 4);
2333be96f633SPaul Mackerras 			break;
23340016a4cfSPaul Mackerras 
23350016a4cfSPaul Mackerras 		case 87:	/* lbzx */
23360016a4cfSPaul Mackerras 		case 119:	/* lbzux */
2337be96f633SPaul Mackerras 			op->type = MKOP(LOAD, u, 1);
2338be96f633SPaul Mackerras 			break;
23390016a4cfSPaul Mackerras 
23400016a4cfSPaul Mackerras #ifdef CONFIG_ALTIVEC
2341e61ccc7bSPaul Mackerras 		/*
2342e61ccc7bSPaul Mackerras 		 * Note: for the load/store vector element instructions,
2343e61ccc7bSPaul Mackerras 		 * bits of the EA say which field of the VMX register to use.
2344e61ccc7bSPaul Mackerras 		 */
2345e61ccc7bSPaul Mackerras 		case 7:		/* lvebx */
2346e61ccc7bSPaul Mackerras 			op->type = MKOP(LOAD_VMX, 0, 1);
2347e61ccc7bSPaul Mackerras 			op->element_size = 1;
2348e61ccc7bSPaul Mackerras 			break;
2349e61ccc7bSPaul Mackerras 
2350e61ccc7bSPaul Mackerras 		case 39:	/* lvehx */
2351e61ccc7bSPaul Mackerras 			op->type = MKOP(LOAD_VMX, 0, 2);
2352e61ccc7bSPaul Mackerras 			op->element_size = 2;
2353e61ccc7bSPaul Mackerras 			break;
2354e61ccc7bSPaul Mackerras 
2355e61ccc7bSPaul Mackerras 		case 71:	/* lvewx */
2356e61ccc7bSPaul Mackerras 			op->type = MKOP(LOAD_VMX, 0, 4);
2357e61ccc7bSPaul Mackerras 			op->element_size = 4;
2358e61ccc7bSPaul Mackerras 			break;
2359e61ccc7bSPaul Mackerras 
23600016a4cfSPaul Mackerras 		case 103:	/* lvx */
23610016a4cfSPaul Mackerras 		case 359:	/* lvxl */
2362be96f633SPaul Mackerras 			op->type = MKOP(LOAD_VMX, 0, 16);
2363350779a2SPaul Mackerras 			op->element_size = 16;
23640016a4cfSPaul Mackerras 			break;
23650016a4cfSPaul Mackerras 
2366e61ccc7bSPaul Mackerras 		case 135:	/* stvebx */
2367e61ccc7bSPaul Mackerras 			op->type = MKOP(STORE_VMX, 0, 1);
2368e61ccc7bSPaul Mackerras 			op->element_size = 1;
2369e61ccc7bSPaul Mackerras 			break;
2370e61ccc7bSPaul Mackerras 
2371e61ccc7bSPaul Mackerras 		case 167:	/* stvehx */
2372e61ccc7bSPaul Mackerras 			op->type = MKOP(STORE_VMX, 0, 2);
2373e61ccc7bSPaul Mackerras 			op->element_size = 2;
2374e61ccc7bSPaul Mackerras 			break;
2375e61ccc7bSPaul Mackerras 
2376e61ccc7bSPaul Mackerras 		case 199:	/* stvewx */
2377e61ccc7bSPaul Mackerras 			op->type = MKOP(STORE_VMX, 0, 4);
2378e61ccc7bSPaul Mackerras 			op->element_size = 4;
2379e61ccc7bSPaul Mackerras 			break;
2380e61ccc7bSPaul Mackerras 
23810016a4cfSPaul Mackerras 		case 231:	/* stvx */
23820016a4cfSPaul Mackerras 		case 487:	/* stvxl */
2383be96f633SPaul Mackerras 			op->type = MKOP(STORE_VMX, 0, 16);
23840016a4cfSPaul Mackerras 			break;
23850016a4cfSPaul Mackerras #endif /* CONFIG_ALTIVEC */
23860016a4cfSPaul Mackerras 
23870016a4cfSPaul Mackerras #ifdef __powerpc64__
2388350779a2SPaul Mackerras 		case 21:	/* ldx */
2389350779a2SPaul Mackerras 		case 53:	/* ldux */
2390350779a2SPaul Mackerras 			op->type = MKOP(LOAD, u, 8);
2391350779a2SPaul Mackerras 			break;
2392350779a2SPaul Mackerras 
23930016a4cfSPaul Mackerras 		case 149:	/* stdx */
23940016a4cfSPaul Mackerras 		case 181:	/* stdux */
2395be96f633SPaul Mackerras 			op->type = MKOP(STORE, u, 8);
2396be96f633SPaul Mackerras 			break;
23970016a4cfSPaul Mackerras #endif
23980016a4cfSPaul Mackerras 
23990016a4cfSPaul Mackerras 		case 151:	/* stwx */
24000016a4cfSPaul Mackerras 		case 183:	/* stwux */
2401be96f633SPaul Mackerras 			op->type = MKOP(STORE, u, 4);
2402be96f633SPaul Mackerras 			break;
24030016a4cfSPaul Mackerras 
24040016a4cfSPaul Mackerras 		case 215:	/* stbx */
24050016a4cfSPaul Mackerras 		case 247:	/* stbux */
2406be96f633SPaul Mackerras 			op->type = MKOP(STORE, u, 1);
2407be96f633SPaul Mackerras 			break;
24080016a4cfSPaul Mackerras 
24090016a4cfSPaul Mackerras 		case 279:	/* lhzx */
24100016a4cfSPaul Mackerras 		case 311:	/* lhzux */
2411be96f633SPaul Mackerras 			op->type = MKOP(LOAD, u, 2);
2412be96f633SPaul Mackerras 			break;
24130016a4cfSPaul Mackerras 
24140016a4cfSPaul Mackerras #ifdef __powerpc64__
24150016a4cfSPaul Mackerras 		case 341:	/* lwax */
24160016a4cfSPaul Mackerras 		case 373:	/* lwaux */
2417be96f633SPaul Mackerras 			op->type = MKOP(LOAD, SIGNEXT | u, 4);
2418be96f633SPaul Mackerras 			break;
24190016a4cfSPaul Mackerras #endif
24200016a4cfSPaul Mackerras 
24210016a4cfSPaul Mackerras 		case 343:	/* lhax */
24220016a4cfSPaul Mackerras 		case 375:	/* lhaux */
2423be96f633SPaul Mackerras 			op->type = MKOP(LOAD, SIGNEXT | u, 2);
2424be96f633SPaul Mackerras 			break;
24250016a4cfSPaul Mackerras 
24260016a4cfSPaul Mackerras 		case 407:	/* sthx */
24270016a4cfSPaul Mackerras 		case 439:	/* sthux */
2428be96f633SPaul Mackerras 			op->type = MKOP(STORE, u, 2);
2429be96f633SPaul Mackerras 			break;
24300016a4cfSPaul Mackerras 
24310016a4cfSPaul Mackerras #ifdef __powerpc64__
24320016a4cfSPaul Mackerras 		case 532:	/* ldbrx */
2433be96f633SPaul Mackerras 			op->type = MKOP(LOAD, BYTEREV, 8);
2434be96f633SPaul Mackerras 			break;
24350016a4cfSPaul Mackerras 
24360016a4cfSPaul Mackerras #endif
2437c9f6f4edSPaul Mackerras 		case 533:	/* lswx */
2438c9f6f4edSPaul Mackerras 			op->type = MKOP(LOAD_MULTI, 0, regs->xer & 0x7f);
2439c9f6f4edSPaul Mackerras 			break;
24400016a4cfSPaul Mackerras 
24410016a4cfSPaul Mackerras 		case 534:	/* lwbrx */
2442be96f633SPaul Mackerras 			op->type = MKOP(LOAD, BYTEREV, 4);
2443be96f633SPaul Mackerras 			break;
24440016a4cfSPaul Mackerras 
2445c9f6f4edSPaul Mackerras 		case 597:	/* lswi */
2446c9f6f4edSPaul Mackerras 			if (rb == 0)
2447c9f6f4edSPaul Mackerras 				rb = 32;	/* # bytes to load */
2448c9f6f4edSPaul Mackerras 			op->type = MKOP(LOAD_MULTI, 0, rb);
2449d120cdbcSPaul Mackerras 			op->ea = ra ? regs->gpr[ra] : 0;
2450c9f6f4edSPaul Mackerras 			break;
2451c9f6f4edSPaul Mackerras 
2452b69a1da9SPaul Bolle #ifdef CONFIG_PPC_FPU
24530016a4cfSPaul Mackerras 		case 535:	/* lfsx */
24540016a4cfSPaul Mackerras 		case 567:	/* lfsux */
2455d2b65ac6SPaul Mackerras 			op->type = MKOP(LOAD_FP, u | FPCONV, 4);
24560016a4cfSPaul Mackerras 			break;
24570016a4cfSPaul Mackerras 
24580016a4cfSPaul Mackerras 		case 599:	/* lfdx */
24590016a4cfSPaul Mackerras 		case 631:	/* lfdux */
2460be96f633SPaul Mackerras 			op->type = MKOP(LOAD_FP, u, 8);
24610016a4cfSPaul Mackerras 			break;
24620016a4cfSPaul Mackerras 
24630016a4cfSPaul Mackerras 		case 663:	/* stfsx */
24640016a4cfSPaul Mackerras 		case 695:	/* stfsux */
2465d2b65ac6SPaul Mackerras 			op->type = MKOP(STORE_FP, u | FPCONV, 4);
24660016a4cfSPaul Mackerras 			break;
24670016a4cfSPaul Mackerras 
24680016a4cfSPaul Mackerras 		case 727:	/* stfdx */
24690016a4cfSPaul Mackerras 		case 759:	/* stfdux */
2470be96f633SPaul Mackerras 			op->type = MKOP(STORE_FP, u, 8);
24710016a4cfSPaul Mackerras 			break;
24721f41fb79SPaul Mackerras 
24731f41fb79SPaul Mackerras #ifdef __powerpc64__
24741f41fb79SPaul Mackerras 		case 791:	/* lfdpx */
24751f41fb79SPaul Mackerras 			op->type = MKOP(LOAD_FP, 0, 16);
24761f41fb79SPaul Mackerras 			break;
24771f41fb79SPaul Mackerras 
2478d2b65ac6SPaul Mackerras 		case 855:	/* lfiwax */
2479d2b65ac6SPaul Mackerras 			op->type = MKOP(LOAD_FP, SIGNEXT, 4);
2480d2b65ac6SPaul Mackerras 			break;
2481d2b65ac6SPaul Mackerras 
2482d2b65ac6SPaul Mackerras 		case 887:	/* lfiwzx */
2483d2b65ac6SPaul Mackerras 			op->type = MKOP(LOAD_FP, 0, 4);
2484d2b65ac6SPaul Mackerras 			break;
2485d2b65ac6SPaul Mackerras 
24861f41fb79SPaul Mackerras 		case 919:	/* stfdpx */
24871f41fb79SPaul Mackerras 			op->type = MKOP(STORE_FP, 0, 16);
24881f41fb79SPaul Mackerras 			break;
2489d2b65ac6SPaul Mackerras 
2490d2b65ac6SPaul Mackerras 		case 983:	/* stfiwx */
2491d2b65ac6SPaul Mackerras 			op->type = MKOP(STORE_FP, 0, 4);
2492d2b65ac6SPaul Mackerras 			break;
24931f41fb79SPaul Mackerras #endif /* __powerpc64 */
24941f41fb79SPaul Mackerras #endif /* CONFIG_PPC_FPU */
24950016a4cfSPaul Mackerras 
24960016a4cfSPaul Mackerras #ifdef __powerpc64__
24970016a4cfSPaul Mackerras 		case 660:	/* stdbrx */
2498be96f633SPaul Mackerras 			op->type = MKOP(STORE, BYTEREV, 8);
2499be96f633SPaul Mackerras 			op->val = byterev_8(regs->gpr[rd]);
2500be96f633SPaul Mackerras 			break;
25010016a4cfSPaul Mackerras 
25020016a4cfSPaul Mackerras #endif
2503c9f6f4edSPaul Mackerras 		case 661:	/* stswx */
2504c9f6f4edSPaul Mackerras 			op->type = MKOP(STORE_MULTI, 0, regs->xer & 0x7f);
2505c9f6f4edSPaul Mackerras 			break;
2506c9f6f4edSPaul Mackerras 
25070016a4cfSPaul Mackerras 		case 662:	/* stwbrx */
2508be96f633SPaul Mackerras 			op->type = MKOP(STORE, BYTEREV, 4);
2509be96f633SPaul Mackerras 			op->val = byterev_4(regs->gpr[rd]);
2510be96f633SPaul Mackerras 			break;
25110016a4cfSPaul Mackerras 
25121f41fb79SPaul Mackerras 		case 725:	/* stswi */
2513c9f6f4edSPaul Mackerras 			if (rb == 0)
2514c9f6f4edSPaul Mackerras 				rb = 32;	/* # bytes to store */
2515c9f6f4edSPaul Mackerras 			op->type = MKOP(STORE_MULTI, 0, rb);
2516d120cdbcSPaul Mackerras 			op->ea = ra ? regs->gpr[ra] : 0;
2517c9f6f4edSPaul Mackerras 			break;
2518c9f6f4edSPaul Mackerras 
25190016a4cfSPaul Mackerras 		case 790:	/* lhbrx */
2520be96f633SPaul Mackerras 			op->type = MKOP(LOAD, BYTEREV, 2);
2521be96f633SPaul Mackerras 			break;
25220016a4cfSPaul Mackerras 
25230016a4cfSPaul Mackerras 		case 918:	/* sthbrx */
2524be96f633SPaul Mackerras 			op->type = MKOP(STORE, BYTEREV, 2);
2525be96f633SPaul Mackerras 			op->val = byterev_2(regs->gpr[rd]);
2526be96f633SPaul Mackerras 			break;
25270016a4cfSPaul Mackerras 
25280016a4cfSPaul Mackerras #ifdef CONFIG_VSX
2529350779a2SPaul Mackerras 		case 12:	/* lxsiwzx */
2530777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2531350779a2SPaul Mackerras 			op->type = MKOP(LOAD_VSX, 0, 4);
2532350779a2SPaul Mackerras 			op->element_size = 8;
2533350779a2SPaul Mackerras 			break;
2534350779a2SPaul Mackerras 
2535350779a2SPaul Mackerras 		case 76:	/* lxsiwax */
2536777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2537350779a2SPaul Mackerras 			op->type = MKOP(LOAD_VSX, SIGNEXT, 4);
2538350779a2SPaul Mackerras 			op->element_size = 8;
2539350779a2SPaul Mackerras 			break;
2540350779a2SPaul Mackerras 
2541350779a2SPaul Mackerras 		case 140:	/* stxsiwx */
2542777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2543350779a2SPaul Mackerras 			op->type = MKOP(STORE_VSX, 0, 4);
2544350779a2SPaul Mackerras 			op->element_size = 8;
2545350779a2SPaul Mackerras 			break;
2546350779a2SPaul Mackerras 
2547350779a2SPaul Mackerras 		case 268:	/* lxvx */
25488813ff49SAnanth N Mavinakayanahalli 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
25498813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
2550777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2551350779a2SPaul Mackerras 			op->type = MKOP(LOAD_VSX, 0, 16);
2552350779a2SPaul Mackerras 			op->element_size = 16;
2553350779a2SPaul Mackerras 			op->vsx_flags = VSX_CHECK_VEC;
2554350779a2SPaul Mackerras 			break;
2555350779a2SPaul Mackerras 
2556350779a2SPaul Mackerras 		case 269:	/* lxvl */
2557350779a2SPaul Mackerras 		case 301: {	/* lxvll */
2558350779a2SPaul Mackerras 			int nb;
25598813ff49SAnanth N Mavinakayanahalli 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
25608813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
2561777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2562350779a2SPaul Mackerras 			op->ea = ra ? regs->gpr[ra] : 0;
2563350779a2SPaul Mackerras 			nb = regs->gpr[rb] & 0xff;
2564350779a2SPaul Mackerras 			if (nb > 16)
2565350779a2SPaul Mackerras 				nb = 16;
2566350779a2SPaul Mackerras 			op->type = MKOP(LOAD_VSX, 0, nb);
2567350779a2SPaul Mackerras 			op->element_size = 16;
2568777e26f0SJordan Niethe 			op->vsx_flags = ((word & 0x20) ? VSX_LDLEFT : 0) |
2569350779a2SPaul Mackerras 				VSX_CHECK_VEC;
2570350779a2SPaul Mackerras 			break;
2571350779a2SPaul Mackerras 		}
2572350779a2SPaul Mackerras 		case 332:	/* lxvdsx */
2573777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2574350779a2SPaul Mackerras 			op->type = MKOP(LOAD_VSX, 0, 8);
2575350779a2SPaul Mackerras 			op->element_size = 8;
2576350779a2SPaul Mackerras 			op->vsx_flags = VSX_SPLAT;
2577350779a2SPaul Mackerras 			break;
2578350779a2SPaul Mackerras 
2579af99da74SBalamuruhan S 		case 333:       /* lxvpx */
2580af99da74SBalamuruhan S 			if (!cpu_has_feature(CPU_FTR_ARCH_31))
25818813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
2582af99da74SBalamuruhan S 			op->reg = VSX_REGISTER_XTP(rd);
2583af99da74SBalamuruhan S 			op->type = MKOP(LOAD_VSX, 0, 32);
2584af99da74SBalamuruhan S 			op->element_size = 32;
2585af99da74SBalamuruhan S 			break;
2586af99da74SBalamuruhan S 
2587350779a2SPaul Mackerras 		case 364:	/* lxvwsx */
25888813ff49SAnanth N Mavinakayanahalli 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
25898813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
2590777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2591350779a2SPaul Mackerras 			op->type = MKOP(LOAD_VSX, 0, 4);
2592350779a2SPaul Mackerras 			op->element_size = 4;
2593350779a2SPaul Mackerras 			op->vsx_flags = VSX_SPLAT | VSX_CHECK_VEC;
2594350779a2SPaul Mackerras 			break;
2595350779a2SPaul Mackerras 
2596350779a2SPaul Mackerras 		case 396:	/* stxvx */
25978813ff49SAnanth N Mavinakayanahalli 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
25988813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
2599777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2600350779a2SPaul Mackerras 			op->type = MKOP(STORE_VSX, 0, 16);
2601350779a2SPaul Mackerras 			op->element_size = 16;
2602350779a2SPaul Mackerras 			op->vsx_flags = VSX_CHECK_VEC;
2603350779a2SPaul Mackerras 			break;
2604350779a2SPaul Mackerras 
2605350779a2SPaul Mackerras 		case 397:	/* stxvl */
2606350779a2SPaul Mackerras 		case 429: {	/* stxvll */
2607350779a2SPaul Mackerras 			int nb;
26088813ff49SAnanth N Mavinakayanahalli 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
26098813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
2610777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2611350779a2SPaul Mackerras 			op->ea = ra ? regs->gpr[ra] : 0;
2612350779a2SPaul Mackerras 			nb = regs->gpr[rb] & 0xff;
2613350779a2SPaul Mackerras 			if (nb > 16)
2614350779a2SPaul Mackerras 				nb = 16;
2615350779a2SPaul Mackerras 			op->type = MKOP(STORE_VSX, 0, nb);
2616350779a2SPaul Mackerras 			op->element_size = 16;
2617777e26f0SJordan Niethe 			op->vsx_flags = ((word & 0x20) ? VSX_LDLEFT : 0) |
2618350779a2SPaul Mackerras 				VSX_CHECK_VEC;
2619350779a2SPaul Mackerras 			break;
2620350779a2SPaul Mackerras 		}
2621af99da74SBalamuruhan S 		case 461:       /* stxvpx */
2622af99da74SBalamuruhan S 			if (!cpu_has_feature(CPU_FTR_ARCH_31))
26238813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
2624af99da74SBalamuruhan S 			op->reg = VSX_REGISTER_XTP(rd);
2625af99da74SBalamuruhan S 			op->type = MKOP(STORE_VSX, 0, 32);
2626af99da74SBalamuruhan S 			op->element_size = 32;
2627af99da74SBalamuruhan S 			break;
2628350779a2SPaul Mackerras 		case 524:	/* lxsspx */
2629777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2630350779a2SPaul Mackerras 			op->type = MKOP(LOAD_VSX, 0, 4);
2631350779a2SPaul Mackerras 			op->element_size = 8;
2632350779a2SPaul Mackerras 			op->vsx_flags = VSX_FPCONV;
2633350779a2SPaul Mackerras 			break;
2634350779a2SPaul Mackerras 
2635350779a2SPaul Mackerras 		case 588:	/* lxsdx */
2636777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2637350779a2SPaul Mackerras 			op->type = MKOP(LOAD_VSX, 0, 8);
2638350779a2SPaul Mackerras 			op->element_size = 8;
2639350779a2SPaul Mackerras 			break;
2640350779a2SPaul Mackerras 
2641350779a2SPaul Mackerras 		case 652:	/* stxsspx */
2642777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2643350779a2SPaul Mackerras 			op->type = MKOP(STORE_VSX, 0, 4);
2644350779a2SPaul Mackerras 			op->element_size = 8;
2645350779a2SPaul Mackerras 			op->vsx_flags = VSX_FPCONV;
2646350779a2SPaul Mackerras 			break;
2647350779a2SPaul Mackerras 
2648350779a2SPaul Mackerras 		case 716:	/* stxsdx */
2649777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2650350779a2SPaul Mackerras 			op->type = MKOP(STORE_VSX, 0, 8);
2651350779a2SPaul Mackerras 			op->element_size = 8;
2652350779a2SPaul Mackerras 			break;
2653350779a2SPaul Mackerras 
2654350779a2SPaul Mackerras 		case 780:	/* lxvw4x */
2655777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2656350779a2SPaul Mackerras 			op->type = MKOP(LOAD_VSX, 0, 16);
2657350779a2SPaul Mackerras 			op->element_size = 4;
2658350779a2SPaul Mackerras 			break;
2659350779a2SPaul Mackerras 
2660350779a2SPaul Mackerras 		case 781:	/* lxsibzx */
26618813ff49SAnanth N Mavinakayanahalli 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
26628813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
2663777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2664350779a2SPaul Mackerras 			op->type = MKOP(LOAD_VSX, 0, 1);
2665350779a2SPaul Mackerras 			op->element_size = 8;
2666350779a2SPaul Mackerras 			op->vsx_flags = VSX_CHECK_VEC;
2667350779a2SPaul Mackerras 			break;
2668350779a2SPaul Mackerras 
2669350779a2SPaul Mackerras 		case 812:	/* lxvh8x */
26708813ff49SAnanth N Mavinakayanahalli 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
26718813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
2672777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2673350779a2SPaul Mackerras 			op->type = MKOP(LOAD_VSX, 0, 16);
2674350779a2SPaul Mackerras 			op->element_size = 2;
2675350779a2SPaul Mackerras 			op->vsx_flags = VSX_CHECK_VEC;
2676350779a2SPaul Mackerras 			break;
2677350779a2SPaul Mackerras 
2678350779a2SPaul Mackerras 		case 813:	/* lxsihzx */
26798813ff49SAnanth N Mavinakayanahalli 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
26808813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
2681777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2682350779a2SPaul Mackerras 			op->type = MKOP(LOAD_VSX, 0, 2);
2683350779a2SPaul Mackerras 			op->element_size = 8;
2684350779a2SPaul Mackerras 			op->vsx_flags = VSX_CHECK_VEC;
2685350779a2SPaul Mackerras 			break;
2686350779a2SPaul Mackerras 
2687350779a2SPaul Mackerras 		case 844:	/* lxvd2x */
2688777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2689350779a2SPaul Mackerras 			op->type = MKOP(LOAD_VSX, 0, 16);
2690350779a2SPaul Mackerras 			op->element_size = 8;
2691350779a2SPaul Mackerras 			break;
2692350779a2SPaul Mackerras 
2693350779a2SPaul Mackerras 		case 876:	/* lxvb16x */
26948813ff49SAnanth N Mavinakayanahalli 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
26958813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
2696777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2697350779a2SPaul Mackerras 			op->type = MKOP(LOAD_VSX, 0, 16);
2698350779a2SPaul Mackerras 			op->element_size = 1;
2699350779a2SPaul Mackerras 			op->vsx_flags = VSX_CHECK_VEC;
2700350779a2SPaul Mackerras 			break;
2701350779a2SPaul Mackerras 
2702350779a2SPaul Mackerras 		case 908:	/* stxvw4x */
2703777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2704350779a2SPaul Mackerras 			op->type = MKOP(STORE_VSX, 0, 16);
2705350779a2SPaul Mackerras 			op->element_size = 4;
2706350779a2SPaul Mackerras 			break;
2707350779a2SPaul Mackerras 
2708350779a2SPaul Mackerras 		case 909:	/* stxsibx */
27098813ff49SAnanth N Mavinakayanahalli 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
27108813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
2711777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2712350779a2SPaul Mackerras 			op->type = MKOP(STORE_VSX, 0, 1);
2713350779a2SPaul Mackerras 			op->element_size = 8;
2714350779a2SPaul Mackerras 			op->vsx_flags = VSX_CHECK_VEC;
2715350779a2SPaul Mackerras 			break;
2716350779a2SPaul Mackerras 
2717350779a2SPaul Mackerras 		case 940:	/* stxvh8x */
27188813ff49SAnanth N Mavinakayanahalli 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
27198813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
2720777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2721350779a2SPaul Mackerras 			op->type = MKOP(STORE_VSX, 0, 16);
2722350779a2SPaul Mackerras 			op->element_size = 2;
2723350779a2SPaul Mackerras 			op->vsx_flags = VSX_CHECK_VEC;
2724350779a2SPaul Mackerras 			break;
2725350779a2SPaul Mackerras 
2726350779a2SPaul Mackerras 		case 941:	/* stxsihx */
27278813ff49SAnanth N Mavinakayanahalli 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
27288813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
2729777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2730350779a2SPaul Mackerras 			op->type = MKOP(STORE_VSX, 0, 2);
2731350779a2SPaul Mackerras 			op->element_size = 8;
2732350779a2SPaul Mackerras 			op->vsx_flags = VSX_CHECK_VEC;
27330016a4cfSPaul Mackerras 			break;
27340016a4cfSPaul Mackerras 
27350016a4cfSPaul Mackerras 		case 972:	/* stxvd2x */
2736777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2737350779a2SPaul Mackerras 			op->type = MKOP(STORE_VSX, 0, 16);
2738350779a2SPaul Mackerras 			op->element_size = 8;
2739350779a2SPaul Mackerras 			break;
2740350779a2SPaul Mackerras 
2741350779a2SPaul Mackerras 		case 1004:	/* stxvb16x */
27428813ff49SAnanth N Mavinakayanahalli 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
27438813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
2744777e26f0SJordan Niethe 			op->reg = rd | ((word & 1) << 5);
2745350779a2SPaul Mackerras 			op->type = MKOP(STORE_VSX, 0, 16);
2746350779a2SPaul Mackerras 			op->element_size = 1;
2747350779a2SPaul Mackerras 			op->vsx_flags = VSX_CHECK_VEC;
27480016a4cfSPaul Mackerras 			break;
27490016a4cfSPaul Mackerras 
27500016a4cfSPaul Mackerras #endif /* CONFIG_VSX */
27510016a4cfSPaul Mackerras 		}
27520016a4cfSPaul Mackerras 		break;
27530016a4cfSPaul Mackerras 
27540016a4cfSPaul Mackerras 	case 32:	/* lwz */
27550016a4cfSPaul Mackerras 	case 33:	/* lwzu */
2756be96f633SPaul Mackerras 		op->type = MKOP(LOAD, u, 4);
2757777e26f0SJordan Niethe 		op->ea = dform_ea(word, regs);
2758be96f633SPaul Mackerras 		break;
27590016a4cfSPaul Mackerras 
27600016a4cfSPaul Mackerras 	case 34:	/* lbz */
27610016a4cfSPaul Mackerras 	case 35:	/* lbzu */
2762be96f633SPaul Mackerras 		op->type = MKOP(LOAD, u, 1);
2763777e26f0SJordan Niethe 		op->ea = dform_ea(word, regs);
2764be96f633SPaul Mackerras 		break;
27650016a4cfSPaul Mackerras 
27660016a4cfSPaul Mackerras 	case 36:	/* stw */
27678e9f6937STiejun Chen 	case 37:	/* stwu */
2768be96f633SPaul Mackerras 		op->type = MKOP(STORE, u, 4);
2769777e26f0SJordan Niethe 		op->ea = dform_ea(word, regs);
27708e9f6937STiejun Chen 		break;
27718e9f6937STiejun Chen 
27720016a4cfSPaul Mackerras 	case 38:	/* stb */
27730016a4cfSPaul Mackerras 	case 39:	/* stbu */
2774be96f633SPaul Mackerras 		op->type = MKOP(STORE, u, 1);
2775777e26f0SJordan Niethe 		op->ea = dform_ea(word, regs);
2776be96f633SPaul Mackerras 		break;
27770016a4cfSPaul Mackerras 
27780016a4cfSPaul Mackerras 	case 40:	/* lhz */
27790016a4cfSPaul Mackerras 	case 41:	/* lhzu */
2780be96f633SPaul Mackerras 		op->type = MKOP(LOAD, u, 2);
2781777e26f0SJordan Niethe 		op->ea = dform_ea(word, regs);
2782be96f633SPaul Mackerras 		break;
27830016a4cfSPaul Mackerras 
27840016a4cfSPaul Mackerras 	case 42:	/* lha */
27850016a4cfSPaul Mackerras 	case 43:	/* lhau */
2786be96f633SPaul Mackerras 		op->type = MKOP(LOAD, SIGNEXT | u, 2);
2787777e26f0SJordan Niethe 		op->ea = dform_ea(word, regs);
2788be96f633SPaul Mackerras 		break;
27890016a4cfSPaul Mackerras 
27900016a4cfSPaul Mackerras 	case 44:	/* sth */
27910016a4cfSPaul Mackerras 	case 45:	/* sthu */
2792be96f633SPaul Mackerras 		op->type = MKOP(STORE, u, 2);
2793777e26f0SJordan Niethe 		op->ea = dform_ea(word, regs);
2794be96f633SPaul Mackerras 		break;
27950016a4cfSPaul Mackerras 
27960016a4cfSPaul Mackerras 	case 46:	/* lmw */
27970016a4cfSPaul Mackerras 		if (ra >= rd)
27980016a4cfSPaul Mackerras 			break;		/* invalid form, ra in range to load */
2799c9f6f4edSPaul Mackerras 		op->type = MKOP(LOAD_MULTI, 0, 4 * (32 - rd));
2800777e26f0SJordan Niethe 		op->ea = dform_ea(word, regs);
2801be96f633SPaul Mackerras 		break;
28020016a4cfSPaul Mackerras 
28030016a4cfSPaul Mackerras 	case 47:	/* stmw */
2804c9f6f4edSPaul Mackerras 		op->type = MKOP(STORE_MULTI, 0, 4 * (32 - rd));
2805777e26f0SJordan Niethe 		op->ea = dform_ea(word, regs);
2806be96f633SPaul Mackerras 		break;
28070016a4cfSPaul Mackerras 
2808cd64d169SSean MacLennan #ifdef CONFIG_PPC_FPU
28090016a4cfSPaul Mackerras 	case 48:	/* lfs */
28100016a4cfSPaul Mackerras 	case 49:	/* lfsu */
2811d2b65ac6SPaul Mackerras 		op->type = MKOP(LOAD_FP, u | FPCONV, 4);
2812777e26f0SJordan Niethe 		op->ea = dform_ea(word, regs);
28130016a4cfSPaul Mackerras 		break;
28140016a4cfSPaul Mackerras 
28150016a4cfSPaul Mackerras 	case 50:	/* lfd */
28160016a4cfSPaul Mackerras 	case 51:	/* lfdu */
2817be96f633SPaul Mackerras 		op->type = MKOP(LOAD_FP, u, 8);
2818777e26f0SJordan Niethe 		op->ea = dform_ea(word, regs);
28190016a4cfSPaul Mackerras 		break;
28200016a4cfSPaul Mackerras 
28210016a4cfSPaul Mackerras 	case 52:	/* stfs */
28220016a4cfSPaul Mackerras 	case 53:	/* stfsu */
2823d2b65ac6SPaul Mackerras 		op->type = MKOP(STORE_FP, u | FPCONV, 4);
2824777e26f0SJordan Niethe 		op->ea = dform_ea(word, regs);
28250016a4cfSPaul Mackerras 		break;
28260016a4cfSPaul Mackerras 
28270016a4cfSPaul Mackerras 	case 54:	/* stfd */
28280016a4cfSPaul Mackerras 	case 55:	/* stfdu */
2829be96f633SPaul Mackerras 		op->type = MKOP(STORE_FP, u, 8);
2830777e26f0SJordan Niethe 		op->ea = dform_ea(word, regs);
28310016a4cfSPaul Mackerras 		break;
2832cd64d169SSean MacLennan #endif
28330016a4cfSPaul Mackerras 
28340016a4cfSPaul Mackerras #ifdef __powerpc64__
2835350779a2SPaul Mackerras 	case 56:	/* lq */
2836350779a2SPaul Mackerras 		if (!((rd & 1) || (rd == ra)))
2837350779a2SPaul Mackerras 			op->type = MKOP(LOAD, 0, 16);
2838777e26f0SJordan Niethe 		op->ea = dqform_ea(word, regs);
2839350779a2SPaul Mackerras 		break;
2840350779a2SPaul Mackerras #endif
2841350779a2SPaul Mackerras 
2842350779a2SPaul Mackerras #ifdef CONFIG_VSX
28431f41fb79SPaul Mackerras 	case 57:	/* lfdp, lxsd, lxssp */
2844777e26f0SJordan Niethe 		op->ea = dsform_ea(word, regs);
2845777e26f0SJordan Niethe 		switch (word & 3) {
28461f41fb79SPaul Mackerras 		case 0:		/* lfdp */
28471f41fb79SPaul Mackerras 			if (rd & 1)
28481f41fb79SPaul Mackerras 				break;		/* reg must be even */
28491f41fb79SPaul Mackerras 			op->type = MKOP(LOAD_FP, 0, 16);
28501f41fb79SPaul Mackerras 			break;
2851350779a2SPaul Mackerras 		case 2:		/* lxsd */
28528813ff49SAnanth N Mavinakayanahalli 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
28538813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
2854350779a2SPaul Mackerras 			op->reg = rd + 32;
2855350779a2SPaul Mackerras 			op->type = MKOP(LOAD_VSX, 0, 8);
2856350779a2SPaul Mackerras 			op->element_size = 8;
2857350779a2SPaul Mackerras 			op->vsx_flags = VSX_CHECK_VEC;
2858350779a2SPaul Mackerras 			break;
2859350779a2SPaul Mackerras 		case 3:		/* lxssp */
28608813ff49SAnanth N Mavinakayanahalli 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
28618813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
2862350779a2SPaul Mackerras 			op->reg = rd + 32;
2863350779a2SPaul Mackerras 			op->type = MKOP(LOAD_VSX, 0, 4);
2864350779a2SPaul Mackerras 			op->element_size = 8;
2865350779a2SPaul Mackerras 			op->vsx_flags = VSX_FPCONV | VSX_CHECK_VEC;
2866350779a2SPaul Mackerras 			break;
2867350779a2SPaul Mackerras 		}
2868350779a2SPaul Mackerras 		break;
2869350779a2SPaul Mackerras #endif /* CONFIG_VSX */
2870350779a2SPaul Mackerras 
2871350779a2SPaul Mackerras #ifdef __powerpc64__
28720016a4cfSPaul Mackerras 	case 58:	/* ld[u], lwa */
2873777e26f0SJordan Niethe 		op->ea = dsform_ea(word, regs);
2874777e26f0SJordan Niethe 		switch (word & 3) {
28750016a4cfSPaul Mackerras 		case 0:		/* ld */
2876be96f633SPaul Mackerras 			op->type = MKOP(LOAD, 0, 8);
2877be96f633SPaul Mackerras 			break;
28780016a4cfSPaul Mackerras 		case 1:		/* ldu */
2879be96f633SPaul Mackerras 			op->type = MKOP(LOAD, UPDATE, 8);
2880be96f633SPaul Mackerras 			break;
28810016a4cfSPaul Mackerras 		case 2:		/* lwa */
2882be96f633SPaul Mackerras 			op->type = MKOP(LOAD, SIGNEXT, 4);
2883be96f633SPaul Mackerras 			break;
28840016a4cfSPaul Mackerras 		}
28850016a4cfSPaul Mackerras 		break;
2886350779a2SPaul Mackerras #endif
28870016a4cfSPaul Mackerras 
2888350779a2SPaul Mackerras #ifdef CONFIG_VSX
2889af99da74SBalamuruhan S 	case 6:
2890af99da74SBalamuruhan S 		if (!cpu_has_feature(CPU_FTR_ARCH_31))
28918813ff49SAnanth N Mavinakayanahalli 			goto unknown_opcode;
2892af99da74SBalamuruhan S 		op->ea = dqform_ea(word, regs);
2893af99da74SBalamuruhan S 		op->reg = VSX_REGISTER_XTP(rd);
2894af99da74SBalamuruhan S 		op->element_size = 32;
2895af99da74SBalamuruhan S 		switch (word & 0xf) {
2896af99da74SBalamuruhan S 		case 0:         /* lxvp */
2897af99da74SBalamuruhan S 			op->type = MKOP(LOAD_VSX, 0, 32);
2898af99da74SBalamuruhan S 			break;
2899af99da74SBalamuruhan S 		case 1:         /* stxvp */
2900af99da74SBalamuruhan S 			op->type = MKOP(STORE_VSX, 0, 32);
2901af99da74SBalamuruhan S 			break;
2902af99da74SBalamuruhan S 		}
2903af99da74SBalamuruhan S 		break;
2904af99da74SBalamuruhan S 
29051f41fb79SPaul Mackerras 	case 61:	/* stfdp, lxv, stxsd, stxssp, stxv */
2906777e26f0SJordan Niethe 		switch (word & 7) {
29071f41fb79SPaul Mackerras 		case 0:		/* stfdp with LSB of DS field = 0 */
29081f41fb79SPaul Mackerras 		case 4:		/* stfdp with LSB of DS field = 1 */
2909777e26f0SJordan Niethe 			op->ea = dsform_ea(word, regs);
29101f41fb79SPaul Mackerras 			op->type = MKOP(STORE_FP, 0, 16);
29111f41fb79SPaul Mackerras 			break;
29121f41fb79SPaul Mackerras 
2913350779a2SPaul Mackerras 		case 1:		/* lxv */
29148813ff49SAnanth N Mavinakayanahalli 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
29158813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
2916777e26f0SJordan Niethe 			op->ea = dqform_ea(word, regs);
2917777e26f0SJordan Niethe 			if (word & 8)
2918350779a2SPaul Mackerras 				op->reg = rd + 32;
2919350779a2SPaul Mackerras 			op->type = MKOP(LOAD_VSX, 0, 16);
2920350779a2SPaul Mackerras 			op->element_size = 16;
2921350779a2SPaul Mackerras 			op->vsx_flags = VSX_CHECK_VEC;
2922350779a2SPaul Mackerras 			break;
2923350779a2SPaul Mackerras 
2924350779a2SPaul Mackerras 		case 2:		/* stxsd with LSB of DS field = 0 */
2925350779a2SPaul Mackerras 		case 6:		/* stxsd with LSB of DS field = 1 */
29268813ff49SAnanth N Mavinakayanahalli 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
29278813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
2928777e26f0SJordan Niethe 			op->ea = dsform_ea(word, regs);
2929350779a2SPaul Mackerras 			op->reg = rd + 32;
2930350779a2SPaul Mackerras 			op->type = MKOP(STORE_VSX, 0, 8);
2931350779a2SPaul Mackerras 			op->element_size = 8;
2932350779a2SPaul Mackerras 			op->vsx_flags = VSX_CHECK_VEC;
2933350779a2SPaul Mackerras 			break;
2934350779a2SPaul Mackerras 
2935350779a2SPaul Mackerras 		case 3:		/* stxssp with LSB of DS field = 0 */
2936350779a2SPaul Mackerras 		case 7:		/* stxssp with LSB of DS field = 1 */
29378813ff49SAnanth N Mavinakayanahalli 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
29388813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
2939777e26f0SJordan Niethe 			op->ea = dsform_ea(word, regs);
2940350779a2SPaul Mackerras 			op->reg = rd + 32;
2941350779a2SPaul Mackerras 			op->type = MKOP(STORE_VSX, 0, 4);
2942350779a2SPaul Mackerras 			op->element_size = 8;
2943350779a2SPaul Mackerras 			op->vsx_flags = VSX_FPCONV | VSX_CHECK_VEC;
2944350779a2SPaul Mackerras 			break;
2945350779a2SPaul Mackerras 
2946350779a2SPaul Mackerras 		case 5:		/* stxv */
29478813ff49SAnanth N Mavinakayanahalli 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
29488813ff49SAnanth N Mavinakayanahalli 				goto unknown_opcode;
2949777e26f0SJordan Niethe 			op->ea = dqform_ea(word, regs);
2950777e26f0SJordan Niethe 			if (word & 8)
2951350779a2SPaul Mackerras 				op->reg = rd + 32;
2952350779a2SPaul Mackerras 			op->type = MKOP(STORE_VSX, 0, 16);
2953350779a2SPaul Mackerras 			op->element_size = 16;
2954350779a2SPaul Mackerras 			op->vsx_flags = VSX_CHECK_VEC;
2955350779a2SPaul Mackerras 			break;
2956350779a2SPaul Mackerras 		}
2957350779a2SPaul Mackerras 		break;
2958350779a2SPaul Mackerras #endif /* CONFIG_VSX */
2959350779a2SPaul Mackerras 
2960350779a2SPaul Mackerras #ifdef __powerpc64__
29610016a4cfSPaul Mackerras 	case 62:	/* std[u] */
2962777e26f0SJordan Niethe 		op->ea = dsform_ea(word, regs);
2963777e26f0SJordan Niethe 		switch (word & 3) {
29640016a4cfSPaul Mackerras 		case 0:		/* std */
2965be96f633SPaul Mackerras 			op->type = MKOP(STORE, 0, 8);
2966be96f633SPaul Mackerras 			break;
29670016a4cfSPaul Mackerras 		case 1:		/* stdu */
2968be96f633SPaul Mackerras 			op->type = MKOP(STORE, UPDATE, 8);
2969be96f633SPaul Mackerras 			break;
2970350779a2SPaul Mackerras 		case 2:		/* stq */
2971350779a2SPaul Mackerras 			if (!(rd & 1))
2972350779a2SPaul Mackerras 				op->type = MKOP(STORE, 0, 16);
2973350779a2SPaul Mackerras 			break;
29740016a4cfSPaul Mackerras 		}
29750016a4cfSPaul Mackerras 		break;
297650b80a12SJordan Niethe 	case 1: /* Prefixed instructions */
2977ef6879f8SBalamuruhan S 		if (!cpu_has_feature(CPU_FTR_ARCH_31))
29788813ff49SAnanth N Mavinakayanahalli 			goto unknown_opcode;
2979ef6879f8SBalamuruhan S 
298068a180a4SBalamuruhan S 		prefix_r = GET_PREFIX_R(word);
298168a180a4SBalamuruhan S 		ra = GET_PREFIX_RA(suffix);
298250b80a12SJordan Niethe 		op->update_reg = ra;
298350b80a12SJordan Niethe 		rd = (suffix >> 21) & 0x1f;
298450b80a12SJordan Niethe 		op->reg = rd;
298550b80a12SJordan Niethe 		op->val = regs->gpr[rd];
298650b80a12SJordan Niethe 
298750b80a12SJordan Niethe 		suffixopcode = get_op(suffix);
298850b80a12SJordan Niethe 		prefixtype = (word >> 24) & 0x3;
298950b80a12SJordan Niethe 		switch (prefixtype) {
299050b80a12SJordan Niethe 		case 0: /* Type 00  Eight-Byte Load/Store */
299150b80a12SJordan Niethe 			if (prefix_r && ra)
299250b80a12SJordan Niethe 				break;
299350b80a12SJordan Niethe 			op->ea = mlsd_8lsd_ea(word, suffix, regs);
299450b80a12SJordan Niethe 			switch (suffixopcode) {
299550b80a12SJordan Niethe 			case 41:	/* plwa */
299650b80a12SJordan Niethe 				op->type = MKOP(LOAD, PREFIXED | SIGNEXT, 4);
299750b80a12SJordan Niethe 				break;
29981817de2fSRavi Bangoria #ifdef CONFIG_VSX
299950b80a12SJordan Niethe 			case 42:        /* plxsd */
300050b80a12SJordan Niethe 				op->reg = rd + 32;
300150b80a12SJordan Niethe 				op->type = MKOP(LOAD_VSX, PREFIXED, 8);
300250b80a12SJordan Niethe 				op->element_size = 8;
300350b80a12SJordan Niethe 				op->vsx_flags = VSX_CHECK_VEC;
300450b80a12SJordan Niethe 				break;
300550b80a12SJordan Niethe 			case 43:	/* plxssp */
300650b80a12SJordan Niethe 				op->reg = rd + 32;
300750b80a12SJordan Niethe 				op->type = MKOP(LOAD_VSX, PREFIXED, 4);
300850b80a12SJordan Niethe 				op->element_size = 8;
300950b80a12SJordan Niethe 				op->vsx_flags = VSX_FPCONV | VSX_CHECK_VEC;
301050b80a12SJordan Niethe 				break;
301150b80a12SJordan Niethe 			case 46:	/* pstxsd */
301250b80a12SJordan Niethe 				op->reg = rd + 32;
301350b80a12SJordan Niethe 				op->type = MKOP(STORE_VSX, PREFIXED, 8);
301450b80a12SJordan Niethe 				op->element_size = 8;
301550b80a12SJordan Niethe 				op->vsx_flags = VSX_CHECK_VEC;
301650b80a12SJordan Niethe 				break;
301750b80a12SJordan Niethe 			case 47:	/* pstxssp */
301850b80a12SJordan Niethe 				op->reg = rd + 32;
301950b80a12SJordan Niethe 				op->type = MKOP(STORE_VSX, PREFIXED, 4);
302050b80a12SJordan Niethe 				op->element_size = 8;
302150b80a12SJordan Niethe 				op->vsx_flags = VSX_FPCONV | VSX_CHECK_VEC;
302250b80a12SJordan Niethe 				break;
302350b80a12SJordan Niethe 			case 51:	/* plxv1 */
302450b80a12SJordan Niethe 				op->reg += 32;
302550b80a12SJordan Niethe 				fallthrough;
302650b80a12SJordan Niethe 			case 50:	/* plxv0 */
302750b80a12SJordan Niethe 				op->type = MKOP(LOAD_VSX, PREFIXED, 16);
302850b80a12SJordan Niethe 				op->element_size = 16;
302950b80a12SJordan Niethe 				op->vsx_flags = VSX_CHECK_VEC;
303050b80a12SJordan Niethe 				break;
303150b80a12SJordan Niethe 			case 55:	/* pstxv1 */
303250b80a12SJordan Niethe 				op->reg = rd + 32;
303350b80a12SJordan Niethe 				fallthrough;
303450b80a12SJordan Niethe 			case 54:	/* pstxv0 */
303550b80a12SJordan Niethe 				op->type = MKOP(STORE_VSX, PREFIXED, 16);
303650b80a12SJordan Niethe 				op->element_size = 16;
303750b80a12SJordan Niethe 				op->vsx_flags = VSX_CHECK_VEC;
303850b80a12SJordan Niethe 				break;
30391817de2fSRavi Bangoria #endif /* CONFIG_VSX */
304050b80a12SJordan Niethe 			case 56:        /* plq */
304150b80a12SJordan Niethe 				op->type = MKOP(LOAD, PREFIXED, 16);
304250b80a12SJordan Niethe 				break;
304350b80a12SJordan Niethe 			case 57:	/* pld */
304450b80a12SJordan Niethe 				op->type = MKOP(LOAD, PREFIXED, 8);
304550b80a12SJordan Niethe 				break;
3046af99da74SBalamuruhan S #ifdef CONFIG_VSX
3047af99da74SBalamuruhan S 			case 58:        /* plxvp */
3048af99da74SBalamuruhan S 				op->reg = VSX_REGISTER_XTP(rd);
3049af99da74SBalamuruhan S 				op->type = MKOP(LOAD_VSX, PREFIXED, 32);
3050af99da74SBalamuruhan S 				op->element_size = 32;
3051af99da74SBalamuruhan S 				break;
3052af99da74SBalamuruhan S #endif /* CONFIG_VSX */
30531817de2fSRavi Bangoria 			case 60:        /* pstq */
305450b80a12SJordan Niethe 				op->type = MKOP(STORE, PREFIXED, 16);
305550b80a12SJordan Niethe 				break;
305650b80a12SJordan Niethe 			case 61:	/* pstd */
305750b80a12SJordan Niethe 				op->type = MKOP(STORE, PREFIXED, 8);
305850b80a12SJordan Niethe 				break;
3059af99da74SBalamuruhan S #ifdef CONFIG_VSX
3060af99da74SBalamuruhan S 			case 62:        /* pstxvp */
3061af99da74SBalamuruhan S 				op->reg = VSX_REGISTER_XTP(rd);
3062af99da74SBalamuruhan S 				op->type = MKOP(STORE_VSX, PREFIXED, 32);
3063af99da74SBalamuruhan S 				op->element_size = 32;
3064af99da74SBalamuruhan S 				break;
3065af99da74SBalamuruhan S #endif /* CONFIG_VSX */
306650b80a12SJordan Niethe 			}
306750b80a12SJordan Niethe 			break;
306850b80a12SJordan Niethe 		case 1: /* Type 01 Eight-Byte Register-to-Register */
306950b80a12SJordan Niethe 			break;
307050b80a12SJordan Niethe 		case 2: /* Type 10 Modified Load/Store */
307150b80a12SJordan Niethe 			if (prefix_r && ra)
307250b80a12SJordan Niethe 				break;
307350b80a12SJordan Niethe 			op->ea = mlsd_8lsd_ea(word, suffix, regs);
307450b80a12SJordan Niethe 			switch (suffixopcode) {
307550b80a12SJordan Niethe 			case 32:	/* plwz */
307650b80a12SJordan Niethe 				op->type = MKOP(LOAD, PREFIXED, 4);
307750b80a12SJordan Niethe 				break;
307850b80a12SJordan Niethe 			case 34:	/* plbz */
307950b80a12SJordan Niethe 				op->type = MKOP(LOAD, PREFIXED, 1);
308050b80a12SJordan Niethe 				break;
308150b80a12SJordan Niethe 			case 36:	/* pstw */
308250b80a12SJordan Niethe 				op->type = MKOP(STORE, PREFIXED, 4);
308350b80a12SJordan Niethe 				break;
308450b80a12SJordan Niethe 			case 38:	/* pstb */
308550b80a12SJordan Niethe 				op->type = MKOP(STORE, PREFIXED, 1);
308650b80a12SJordan Niethe 				break;
308750b80a12SJordan Niethe 			case 40:	/* plhz */
308850b80a12SJordan Niethe 				op->type = MKOP(LOAD, PREFIXED, 2);
308950b80a12SJordan Niethe 				break;
309050b80a12SJordan Niethe 			case 42:	/* plha */
309150b80a12SJordan Niethe 				op->type = MKOP(LOAD, PREFIXED | SIGNEXT, 2);
309250b80a12SJordan Niethe 				break;
309350b80a12SJordan Niethe 			case 44:	/* psth */
309450b80a12SJordan Niethe 				op->type = MKOP(STORE, PREFIXED, 2);
309550b80a12SJordan Niethe 				break;
309650b80a12SJordan Niethe 			case 48:        /* plfs */
309750b80a12SJordan Niethe 				op->type = MKOP(LOAD_FP, PREFIXED | FPCONV, 4);
309850b80a12SJordan Niethe 				break;
309950b80a12SJordan Niethe 			case 50:        /* plfd */
310050b80a12SJordan Niethe 				op->type = MKOP(LOAD_FP, PREFIXED, 8);
310150b80a12SJordan Niethe 				break;
310250b80a12SJordan Niethe 			case 52:        /* pstfs */
310350b80a12SJordan Niethe 				op->type = MKOP(STORE_FP, PREFIXED | FPCONV, 4);
310450b80a12SJordan Niethe 				break;
310550b80a12SJordan Niethe 			case 54:        /* pstfd */
310650b80a12SJordan Niethe 				op->type = MKOP(STORE_FP, PREFIXED, 8);
310750b80a12SJordan Niethe 				break;
310850b80a12SJordan Niethe 			}
310950b80a12SJordan Niethe 			break;
311050b80a12SJordan Niethe 		case 3: /* Type 11 Modified Register-to-Register */
311150b80a12SJordan Niethe 			break;
311250b80a12SJordan Niethe 		}
31130016a4cfSPaul Mackerras #endif /* __powerpc64__ */
31140016a4cfSPaul Mackerras 
31150016a4cfSPaul Mackerras 	}
311683afab4cSRavi Bangoria 
3117bbda4b6cSSandipan Das 	if (OP_IS_LOAD_STORE(op->type) && (op->type & UPDATE)) {
3118bbda4b6cSSandipan Das 		switch (GETTYPE(op->type)) {
3119bbda4b6cSSandipan Das 		case LOAD:
3120bbda4b6cSSandipan Das 			if (ra == rd)
3121bbda4b6cSSandipan Das 				goto unknown_opcode;
3122bbda4b6cSSandipan Das 			fallthrough;
3123bbda4b6cSSandipan Das 		case STORE:
3124bbda4b6cSSandipan Das 		case LOAD_FP:
3125bbda4b6cSSandipan Das 		case STORE_FP:
3126bbda4b6cSSandipan Das 			if (ra == 0)
3127bbda4b6cSSandipan Das 				goto unknown_opcode;
3128bbda4b6cSSandipan Das 		}
3129bbda4b6cSSandipan Das 	}
3130bbda4b6cSSandipan Das 
313183afab4cSRavi Bangoria #ifdef CONFIG_VSX
313283afab4cSRavi Bangoria 	if ((GETTYPE(op->type) == LOAD_VSX ||
313383afab4cSRavi Bangoria 	     GETTYPE(op->type) == STORE_VSX) &&
313483afab4cSRavi Bangoria 	    !cpu_has_feature(CPU_FTR_VSX)) {
313583afab4cSRavi Bangoria 		return -1;
313683afab4cSRavi Bangoria 	}
313783afab4cSRavi Bangoria #endif /* CONFIG_VSX */
313883afab4cSRavi Bangoria 
3139be96f633SPaul Mackerras 	return 0;
31400016a4cfSPaul Mackerras 
31418813ff49SAnanth N Mavinakayanahalli  unknown_opcode:
31428813ff49SAnanth N Mavinakayanahalli 	op->type = UNKNOWN;
31438813ff49SAnanth N Mavinakayanahalli 	return 0;
31448813ff49SAnanth N Mavinakayanahalli 
31450016a4cfSPaul Mackerras  logical_done:
3146777e26f0SJordan Niethe 	if (word & 1)
3147ad47ff3eSAnton Blanchard 		set_cr0(regs, op);
31483cdfcbfdSPaul Mackerras  logical_done_nocc:
31493cdfcbfdSPaul Mackerras 	op->reg = ra;
31503cdfcbfdSPaul Mackerras 	op->type |= SETREG;
31513cdfcbfdSPaul Mackerras 	return 1;
31520016a4cfSPaul Mackerras 
31530016a4cfSPaul Mackerras  arith_done:
3154777e26f0SJordan Niethe 	if (word & 1)
3155ad47ff3eSAnton Blanchard 		set_cr0(regs, op);
31563cdfcbfdSPaul Mackerras  compute_done:
31573cdfcbfdSPaul Mackerras 	op->reg = rd;
31583cdfcbfdSPaul Mackerras 	op->type |= SETREG;
3159be96f633SPaul Mackerras 	return 1;
3160be96f633SPaul Mackerras 
3161be96f633SPaul Mackerras  priv:
3162be96f633SPaul Mackerras 	op->type = INTERRUPT | 0x700;
3163be96f633SPaul Mackerras 	op->val = SRR1_PROGPRIV;
3164be96f633SPaul Mackerras 	return 0;
3165be96f633SPaul Mackerras 
3166cf87c3f6SPaul Mackerras  trap:
3167cf87c3f6SPaul Mackerras 	op->type = INTERRUPT | 0x700;
3168cf87c3f6SPaul Mackerras 	op->val = SRR1_PROGTRAP;
3169cf87c3f6SPaul Mackerras 	return 0;
3170be96f633SPaul Mackerras }
3171be96f633SPaul Mackerras EXPORT_SYMBOL_GPL(analyse_instr);
317271f6e58eSNaveen N. Rao NOKPROBE_SYMBOL(analyse_instr);
3173be96f633SPaul Mackerras 
3174be96f633SPaul Mackerras /*
3175be96f633SPaul Mackerras  * For PPC32 we always use stwu with r1 to change the stack pointer.
3176be96f633SPaul Mackerras  * So this emulated store may corrupt the exception frame, now we
3177be96f633SPaul Mackerras  * have to provide the exception frame trampoline, which is pushed
3178be96f633SPaul Mackerras  * below the kprobed function stack. So we only update gpr[1] but
3179be96f633SPaul Mackerras  * don't emulate the real store operation. We will do real store
3180be96f633SPaul Mackerras  * operation safely in exception return code by checking this flag.
3181be96f633SPaul Mackerras  */
handle_stack_update(unsigned long ea,struct pt_regs * regs)318271f6e58eSNaveen N. Rao static nokprobe_inline int handle_stack_update(unsigned long ea, struct pt_regs *regs)
3183be96f633SPaul Mackerras {
3184be96f633SPaul Mackerras 	/*
3185be96f633SPaul Mackerras 	 * Check if we already set since that means we'll
3186be96f633SPaul Mackerras 	 * lose the previous value.
3187be96f633SPaul Mackerras 	 */
3188be96f633SPaul Mackerras 	WARN_ON(test_thread_flag(TIF_EMULATE_STACK_STORE));
3189be96f633SPaul Mackerras 	set_thread_flag(TIF_EMULATE_STACK_STORE);
3190be96f633SPaul Mackerras 	return 0;
3191be96f633SPaul Mackerras }
3192be96f633SPaul Mackerras 
do_signext(unsigned long * valp,int size)319371f6e58eSNaveen N. Rao static nokprobe_inline void do_signext(unsigned long *valp, int size)
3194be96f633SPaul Mackerras {
3195be96f633SPaul Mackerras 	switch (size) {
3196be96f633SPaul Mackerras 	case 2:
3197be96f633SPaul Mackerras 		*valp = (signed short) *valp;
3198be96f633SPaul Mackerras 		break;
3199be96f633SPaul Mackerras 	case 4:
3200be96f633SPaul Mackerras 		*valp = (signed int) *valp;
3201be96f633SPaul Mackerras 		break;
3202be96f633SPaul Mackerras 	}
3203be96f633SPaul Mackerras }
3204be96f633SPaul Mackerras 
do_byterev(unsigned long * valp,int size)320571f6e58eSNaveen N. Rao static nokprobe_inline void do_byterev(unsigned long *valp, int size)
3206be96f633SPaul Mackerras {
3207be96f633SPaul Mackerras 	switch (size) {
3208be96f633SPaul Mackerras 	case 2:
3209be96f633SPaul Mackerras 		*valp = byterev_2(*valp);
3210be96f633SPaul Mackerras 		break;
3211be96f633SPaul Mackerras 	case 4:
3212be96f633SPaul Mackerras 		*valp = byterev_4(*valp);
3213be96f633SPaul Mackerras 		break;
3214be96f633SPaul Mackerras #ifdef __powerpc64__
3215be96f633SPaul Mackerras 	case 8:
3216be96f633SPaul Mackerras 		*valp = byterev_8(*valp);
3217be96f633SPaul Mackerras 		break;
3218be96f633SPaul Mackerras #endif
3219be96f633SPaul Mackerras 	}
3220be96f633SPaul Mackerras }
3221be96f633SPaul Mackerras 
3222be96f633SPaul Mackerras /*
32233cdfcbfdSPaul Mackerras  * Emulate an instruction that can be executed just by updating
32243cdfcbfdSPaul Mackerras  * fields in *regs.
32253cdfcbfdSPaul Mackerras  */
emulate_update_regs(struct pt_regs * regs,struct instruction_op * op)32263cdfcbfdSPaul Mackerras void emulate_update_regs(struct pt_regs *regs, struct instruction_op *op)
32273cdfcbfdSPaul Mackerras {
32283cdfcbfdSPaul Mackerras 	unsigned long next_pc;
32293cdfcbfdSPaul Mackerras 
323050b80a12SJordan Niethe 	next_pc = truncate_if_32bit(regs->msr, regs->nip + GETLENGTH(op->type));
3231e6684d07SRavi Bangoria 	switch (GETTYPE(op->type)) {
32323cdfcbfdSPaul Mackerras 	case COMPUTE:
32333cdfcbfdSPaul Mackerras 		if (op->type & SETREG)
32343cdfcbfdSPaul Mackerras 			regs->gpr[op->reg] = op->val;
32353cdfcbfdSPaul Mackerras 		if (op->type & SETCC)
32363cdfcbfdSPaul Mackerras 			regs->ccr = op->ccval;
32373cdfcbfdSPaul Mackerras 		if (op->type & SETXER)
32383cdfcbfdSPaul Mackerras 			regs->xer = op->xerval;
32393cdfcbfdSPaul Mackerras 		break;
32403cdfcbfdSPaul Mackerras 
32413cdfcbfdSPaul Mackerras 	case BRANCH:
32423cdfcbfdSPaul Mackerras 		if (op->type & SETLK)
32433cdfcbfdSPaul Mackerras 			regs->link = next_pc;
32443cdfcbfdSPaul Mackerras 		if (op->type & BRTAKEN)
32453cdfcbfdSPaul Mackerras 			next_pc = op->val;
32463cdfcbfdSPaul Mackerras 		if (op->type & DECCTR)
32473cdfcbfdSPaul Mackerras 			--regs->ctr;
32483cdfcbfdSPaul Mackerras 		break;
32493cdfcbfdSPaul Mackerras 
32503cdfcbfdSPaul Mackerras 	case BARRIER:
32513cdfcbfdSPaul Mackerras 		switch (op->type & BARRIER_MASK) {
32523cdfcbfdSPaul Mackerras 		case BARRIER_SYNC:
32533cdfcbfdSPaul Mackerras 			mb();
32543cdfcbfdSPaul Mackerras 			break;
32553cdfcbfdSPaul Mackerras 		case BARRIER_ISYNC:
32563cdfcbfdSPaul Mackerras 			isync();
32573cdfcbfdSPaul Mackerras 			break;
32583cdfcbfdSPaul Mackerras 		case BARRIER_EIEIO:
32593cdfcbfdSPaul Mackerras 			eieio();
32603cdfcbfdSPaul Mackerras 			break;
3261fe663df7SAnders Roxell #ifdef CONFIG_PPC64
32623cdfcbfdSPaul Mackerras 		case BARRIER_LWSYNC:
32633cdfcbfdSPaul Mackerras 			asm volatile("lwsync" : : : "memory");
32643cdfcbfdSPaul Mackerras 			break;
32653cdfcbfdSPaul Mackerras 		case BARRIER_PTESYNC:
32663cdfcbfdSPaul Mackerras 			asm volatile("ptesync" : : : "memory");
32673cdfcbfdSPaul Mackerras 			break;
3268fe663df7SAnders Roxell #endif
32693cdfcbfdSPaul Mackerras 		}
32703cdfcbfdSPaul Mackerras 		break;
32713cdfcbfdSPaul Mackerras 
32723cdfcbfdSPaul Mackerras 	case MFSPR:
32733cdfcbfdSPaul Mackerras 		switch (op->spr) {
32743cdfcbfdSPaul Mackerras 		case SPRN_XER:
32753cdfcbfdSPaul Mackerras 			regs->gpr[op->reg] = regs->xer & 0xffffffffUL;
32763cdfcbfdSPaul Mackerras 			break;
32773cdfcbfdSPaul Mackerras 		case SPRN_LR:
32783cdfcbfdSPaul Mackerras 			regs->gpr[op->reg] = regs->link;
32793cdfcbfdSPaul Mackerras 			break;
32803cdfcbfdSPaul Mackerras 		case SPRN_CTR:
32813cdfcbfdSPaul Mackerras 			regs->gpr[op->reg] = regs->ctr;
32823cdfcbfdSPaul Mackerras 			break;
32833cdfcbfdSPaul Mackerras 		default:
32843cdfcbfdSPaul Mackerras 			WARN_ON_ONCE(1);
32853cdfcbfdSPaul Mackerras 		}
32863cdfcbfdSPaul Mackerras 		break;
32873cdfcbfdSPaul Mackerras 
32883cdfcbfdSPaul Mackerras 	case MTSPR:
32893cdfcbfdSPaul Mackerras 		switch (op->spr) {
32903cdfcbfdSPaul Mackerras 		case SPRN_XER:
32913cdfcbfdSPaul Mackerras 			regs->xer = op->val & 0xffffffffUL;
32923cdfcbfdSPaul Mackerras 			break;
32933cdfcbfdSPaul Mackerras 		case SPRN_LR:
32943cdfcbfdSPaul Mackerras 			regs->link = op->val;
32953cdfcbfdSPaul Mackerras 			break;
32963cdfcbfdSPaul Mackerras 		case SPRN_CTR:
32973cdfcbfdSPaul Mackerras 			regs->ctr = op->val;
32983cdfcbfdSPaul Mackerras 			break;
32993cdfcbfdSPaul Mackerras 		default:
33003cdfcbfdSPaul Mackerras 			WARN_ON_ONCE(1);
33013cdfcbfdSPaul Mackerras 		}
33023cdfcbfdSPaul Mackerras 		break;
33033cdfcbfdSPaul Mackerras 
33043cdfcbfdSPaul Mackerras 	default:
33053cdfcbfdSPaul Mackerras 		WARN_ON_ONCE(1);
33063cdfcbfdSPaul Mackerras 	}
330759dc5bfcSNicholas Piggin 	regs_set_return_ip(regs, next_pc);
33083cdfcbfdSPaul Mackerras }
330967ac0bfeSNaveen N. Rao NOKPROBE_SYMBOL(emulate_update_regs);
33103cdfcbfdSPaul Mackerras 
33113cdfcbfdSPaul Mackerras /*
3312a53d5182SPaul Mackerras  * Emulate a previously-analysed load or store instruction.
3313a53d5182SPaul Mackerras  * Return values are:
3314a53d5182SPaul Mackerras  * 0 = instruction emulated successfully
3315a53d5182SPaul Mackerras  * -EFAULT = address out of range or access faulted (regs->dar
3316a53d5182SPaul Mackerras  *	     contains the faulting address)
3317a53d5182SPaul Mackerras  * -EACCES = misaligned access, instruction requires alignment
3318a53d5182SPaul Mackerras  * -EINVAL = unknown operation in *op
3319a53d5182SPaul Mackerras  */
emulate_loadstore(struct pt_regs * regs,struct instruction_op * op)3320a53d5182SPaul Mackerras int emulate_loadstore(struct pt_regs *regs, struct instruction_op *op)
3321a53d5182SPaul Mackerras {
3322a53d5182SPaul Mackerras 	int err, size, type;
3323a53d5182SPaul Mackerras 	int i, rd, nb;
3324a53d5182SPaul Mackerras 	unsigned int cr;
3325a53d5182SPaul Mackerras 	unsigned long val;
3326a53d5182SPaul Mackerras 	unsigned long ea;
3327a53d5182SPaul Mackerras 	bool cross_endian;
3328a53d5182SPaul Mackerras 
3329a53d5182SPaul Mackerras 	err = 0;
3330a53d5182SPaul Mackerras 	size = GETSIZE(op->type);
3331e6684d07SRavi Bangoria 	type = GETTYPE(op->type);
3332a53d5182SPaul Mackerras 	cross_endian = (regs->msr & MSR_LE) != (MSR_KERNEL & MSR_LE);
3333a53d5182SPaul Mackerras 	ea = truncate_if_32bit(regs->msr, op->ea);
3334a53d5182SPaul Mackerras 
3335a53d5182SPaul Mackerras 	switch (type) {
3336a53d5182SPaul Mackerras 	case LARX:
3337a53d5182SPaul Mackerras 		if (ea & (size - 1))
3338a53d5182SPaul Mackerras 			return -EACCES;		/* can't handle misaligned */
3339a53d5182SPaul Mackerras 		if (!address_ok(regs, ea, size))
3340a53d5182SPaul Mackerras 			return -EFAULT;
3341a53d5182SPaul Mackerras 		err = 0;
33423b79b261SMichael Ellerman 		val = 0;
3343a53d5182SPaul Mackerras 		switch (size) {
3344b86cf14fSNicholas Piggin #ifdef CONFIG_PPC_HAS_LBARX_LHARX
3345a53d5182SPaul Mackerras 		case 1:
3346a53d5182SPaul Mackerras 			__get_user_asmx(val, ea, err, "lbarx");
3347a53d5182SPaul Mackerras 			break;
3348a53d5182SPaul Mackerras 		case 2:
3349a53d5182SPaul Mackerras 			__get_user_asmx(val, ea, err, "lharx");
3350a53d5182SPaul Mackerras 			break;
3351a53d5182SPaul Mackerras #endif
3352a53d5182SPaul Mackerras 		case 4:
3353a53d5182SPaul Mackerras 			__get_user_asmx(val, ea, err, "lwarx");
3354a53d5182SPaul Mackerras 			break;
3355a53d5182SPaul Mackerras #ifdef __powerpc64__
3356a53d5182SPaul Mackerras 		case 8:
3357a53d5182SPaul Mackerras 			__get_user_asmx(val, ea, err, "ldarx");
3358a53d5182SPaul Mackerras 			break;
3359a53d5182SPaul Mackerras 		case 16:
3360a53d5182SPaul Mackerras 			err = do_lqarx(ea, &regs->gpr[op->reg]);
3361a53d5182SPaul Mackerras 			break;
3362a53d5182SPaul Mackerras #endif
3363a53d5182SPaul Mackerras 		default:
3364a53d5182SPaul Mackerras 			return -EINVAL;
3365a53d5182SPaul Mackerras 		}
3366a53d5182SPaul Mackerras 		if (err) {
3367a53d5182SPaul Mackerras 			regs->dar = ea;
3368a53d5182SPaul Mackerras 			break;
3369a53d5182SPaul Mackerras 		}
3370a53d5182SPaul Mackerras 		if (size < 16)
3371a53d5182SPaul Mackerras 			regs->gpr[op->reg] = val;
3372a53d5182SPaul Mackerras 		break;
3373a53d5182SPaul Mackerras 
3374a53d5182SPaul Mackerras 	case STCX:
3375a53d5182SPaul Mackerras 		if (ea & (size - 1))
3376a53d5182SPaul Mackerras 			return -EACCES;		/* can't handle misaligned */
3377a53d5182SPaul Mackerras 		if (!address_ok(regs, ea, size))
3378a53d5182SPaul Mackerras 			return -EFAULT;
3379a53d5182SPaul Mackerras 		err = 0;
3380a53d5182SPaul Mackerras 		switch (size) {
3381a53d5182SPaul Mackerras #ifdef __powerpc64__
3382a53d5182SPaul Mackerras 		case 1:
3383a53d5182SPaul Mackerras 			__put_user_asmx(op->val, ea, err, "stbcx.", cr);
3384a53d5182SPaul Mackerras 			break;
3385a53d5182SPaul Mackerras 		case 2:
3386a633cb1eSAnders Roxell 			__put_user_asmx(op->val, ea, err, "sthcx.", cr);
3387a53d5182SPaul Mackerras 			break;
3388a53d5182SPaul Mackerras #endif
3389a53d5182SPaul Mackerras 		case 4:
3390a53d5182SPaul Mackerras 			__put_user_asmx(op->val, ea, err, "stwcx.", cr);
3391a53d5182SPaul Mackerras 			break;
3392a53d5182SPaul Mackerras #ifdef __powerpc64__
3393a53d5182SPaul Mackerras 		case 8:
3394a53d5182SPaul Mackerras 			__put_user_asmx(op->val, ea, err, "stdcx.", cr);
3395a53d5182SPaul Mackerras 			break;
3396a53d5182SPaul Mackerras 		case 16:
3397a53d5182SPaul Mackerras 			err = do_stqcx(ea, regs->gpr[op->reg],
3398a53d5182SPaul Mackerras 				       regs->gpr[op->reg + 1], &cr);
3399a53d5182SPaul Mackerras 			break;
3400a53d5182SPaul Mackerras #endif
3401a53d5182SPaul Mackerras 		default:
3402a53d5182SPaul Mackerras 			return -EINVAL;
3403a53d5182SPaul Mackerras 		}
3404a53d5182SPaul Mackerras 		if (!err)
3405a53d5182SPaul Mackerras 			regs->ccr = (regs->ccr & 0x0fffffff) |
3406a53d5182SPaul Mackerras 				(cr & 0xe0000000) |
3407a53d5182SPaul Mackerras 				((regs->xer >> 3) & 0x10000000);
3408a53d5182SPaul Mackerras 		else
3409a53d5182SPaul Mackerras 			regs->dar = ea;
3410a53d5182SPaul Mackerras 		break;
3411a53d5182SPaul Mackerras 
3412a53d5182SPaul Mackerras 	case LOAD:
3413a53d5182SPaul Mackerras #ifdef __powerpc64__
3414a53d5182SPaul Mackerras 		if (size == 16) {
3415a53d5182SPaul Mackerras 			err = emulate_lq(regs, ea, op->reg, cross_endian);
3416a53d5182SPaul Mackerras 			break;
3417a53d5182SPaul Mackerras 		}
3418a53d5182SPaul Mackerras #endif
3419a53d5182SPaul Mackerras 		err = read_mem(&regs->gpr[op->reg], ea, size, regs);
3420a53d5182SPaul Mackerras 		if (!err) {
3421a53d5182SPaul Mackerras 			if (op->type & SIGNEXT)
3422a53d5182SPaul Mackerras 				do_signext(&regs->gpr[op->reg], size);
3423a53d5182SPaul Mackerras 			if ((op->type & BYTEREV) == (cross_endian ? 0 : BYTEREV))
3424a53d5182SPaul Mackerras 				do_byterev(&regs->gpr[op->reg], size);
3425a53d5182SPaul Mackerras 		}
3426a53d5182SPaul Mackerras 		break;
3427a53d5182SPaul Mackerras 
3428a53d5182SPaul Mackerras #ifdef CONFIG_PPC_FPU
3429a53d5182SPaul Mackerras 	case LOAD_FP:
3430a53d5182SPaul Mackerras 		/*
3431a53d5182SPaul Mackerras 		 * If the instruction is in userspace, we can emulate it even
3432a53d5182SPaul Mackerras 		 * if the VMX state is not live, because we have the state
3433a53d5182SPaul Mackerras 		 * stored in the thread_struct.  If the instruction is in
3434a53d5182SPaul Mackerras 		 * the kernel, we must not touch the state in the thread_struct.
3435a53d5182SPaul Mackerras 		 */
3436a53d5182SPaul Mackerras 		if (!(regs->msr & MSR_PR) && !(regs->msr & MSR_FP))
3437a53d5182SPaul Mackerras 			return 0;
3438d2b65ac6SPaul Mackerras 		err = do_fp_load(op, ea, regs, cross_endian);
3439a53d5182SPaul Mackerras 		break;
3440a53d5182SPaul Mackerras #endif
3441a53d5182SPaul Mackerras #ifdef CONFIG_ALTIVEC
3442a53d5182SPaul Mackerras 	case LOAD_VMX:
3443a53d5182SPaul Mackerras 		if (!(regs->msr & MSR_PR) && !(regs->msr & MSR_VEC))
3444a53d5182SPaul Mackerras 			return 0;
3445a53d5182SPaul Mackerras 		err = do_vec_load(op->reg, ea, size, regs, cross_endian);
3446a53d5182SPaul Mackerras 		break;
3447a53d5182SPaul Mackerras #endif
3448a53d5182SPaul Mackerras #ifdef CONFIG_VSX
3449a53d5182SPaul Mackerras 	case LOAD_VSX: {
3450a53d5182SPaul Mackerras 		unsigned long msrbit = MSR_VSX;
3451a53d5182SPaul Mackerras 
3452a53d5182SPaul Mackerras 		/*
3453a53d5182SPaul Mackerras 		 * Some VSX instructions check the MSR_VEC bit rather than MSR_VSX
3454a53d5182SPaul Mackerras 		 * when the target of the instruction is a vector register.
3455a53d5182SPaul Mackerras 		 */
3456a53d5182SPaul Mackerras 		if (op->reg >= 32 && (op->vsx_flags & VSX_CHECK_VEC))
3457a53d5182SPaul Mackerras 			msrbit = MSR_VEC;
3458a53d5182SPaul Mackerras 		if (!(regs->msr & MSR_PR) && !(regs->msr & msrbit))
3459a53d5182SPaul Mackerras 			return 0;
3460a53d5182SPaul Mackerras 		err = do_vsx_load(op, ea, regs, cross_endian);
3461a53d5182SPaul Mackerras 		break;
3462a53d5182SPaul Mackerras 	}
3463a53d5182SPaul Mackerras #endif
3464a53d5182SPaul Mackerras 	case LOAD_MULTI:
3465a53d5182SPaul Mackerras 		if (!address_ok(regs, ea, size))
3466a53d5182SPaul Mackerras 			return -EFAULT;
3467a53d5182SPaul Mackerras 		rd = op->reg;
3468a53d5182SPaul Mackerras 		for (i = 0; i < size; i += 4) {
3469a53d5182SPaul Mackerras 			unsigned int v32 = 0;
3470a53d5182SPaul Mackerras 
3471a53d5182SPaul Mackerras 			nb = size - i;
3472a53d5182SPaul Mackerras 			if (nb > 4)
3473a53d5182SPaul Mackerras 				nb = 4;
3474a53d5182SPaul Mackerras 			err = copy_mem_in((u8 *) &v32, ea, nb, regs);
3475a53d5182SPaul Mackerras 			if (err)
3476a53d5182SPaul Mackerras 				break;
3477a53d5182SPaul Mackerras 			if (unlikely(cross_endian))
3478a53d5182SPaul Mackerras 				v32 = byterev_4(v32);
3479a53d5182SPaul Mackerras 			regs->gpr[rd] = v32;
3480a53d5182SPaul Mackerras 			ea += 4;
348145f62159SPaul Mackerras 			/* reg number wraps from 31 to 0 for lsw[ix] */
348245f62159SPaul Mackerras 			rd = (rd + 1) & 0x1f;
3483a53d5182SPaul Mackerras 		}
3484a53d5182SPaul Mackerras 		break;
3485a53d5182SPaul Mackerras 
3486a53d5182SPaul Mackerras 	case STORE:
3487a53d5182SPaul Mackerras #ifdef __powerpc64__
3488a53d5182SPaul Mackerras 		if (size == 16) {
3489a53d5182SPaul Mackerras 			err = emulate_stq(regs, ea, op->reg, cross_endian);
3490a53d5182SPaul Mackerras 			break;
3491a53d5182SPaul Mackerras 		}
3492a53d5182SPaul Mackerras #endif
3493a53d5182SPaul Mackerras 		if ((op->type & UPDATE) && size == sizeof(long) &&
3494a53d5182SPaul Mackerras 		    op->reg == 1 && op->update_reg == 1 &&
3495a53d5182SPaul Mackerras 		    !(regs->msr & MSR_PR) &&
3496a53d5182SPaul Mackerras 		    ea >= regs->gpr[1] - STACK_INT_FRAME_SIZE) {
3497a53d5182SPaul Mackerras 			err = handle_stack_update(ea, regs);
3498a53d5182SPaul Mackerras 			break;
3499a53d5182SPaul Mackerras 		}
3500a53d5182SPaul Mackerras 		if (unlikely(cross_endian))
3501a53d5182SPaul Mackerras 			do_byterev(&op->val, size);
3502a53d5182SPaul Mackerras 		err = write_mem(op->val, ea, size, regs);
3503a53d5182SPaul Mackerras 		break;
3504a53d5182SPaul Mackerras 
3505a53d5182SPaul Mackerras #ifdef CONFIG_PPC_FPU
3506a53d5182SPaul Mackerras 	case STORE_FP:
3507a53d5182SPaul Mackerras 		if (!(regs->msr & MSR_PR) && !(regs->msr & MSR_FP))
3508a53d5182SPaul Mackerras 			return 0;
3509d2b65ac6SPaul Mackerras 		err = do_fp_store(op, ea, regs, cross_endian);
3510a53d5182SPaul Mackerras 		break;
3511a53d5182SPaul Mackerras #endif
3512a53d5182SPaul Mackerras #ifdef CONFIG_ALTIVEC
3513a53d5182SPaul Mackerras 	case STORE_VMX:
3514a53d5182SPaul Mackerras 		if (!(regs->msr & MSR_PR) && !(regs->msr & MSR_VEC))
3515a53d5182SPaul Mackerras 			return 0;
3516a53d5182SPaul Mackerras 		err = do_vec_store(op->reg, ea, size, regs, cross_endian);
3517a53d5182SPaul Mackerras 		break;
3518a53d5182SPaul Mackerras #endif
3519a53d5182SPaul Mackerras #ifdef CONFIG_VSX
3520a53d5182SPaul Mackerras 	case STORE_VSX: {
3521a53d5182SPaul Mackerras 		unsigned long msrbit = MSR_VSX;
3522a53d5182SPaul Mackerras 
3523a53d5182SPaul Mackerras 		/*
3524a53d5182SPaul Mackerras 		 * Some VSX instructions check the MSR_VEC bit rather than MSR_VSX
3525a53d5182SPaul Mackerras 		 * when the target of the instruction is a vector register.
3526a53d5182SPaul Mackerras 		 */
3527a53d5182SPaul Mackerras 		if (op->reg >= 32 && (op->vsx_flags & VSX_CHECK_VEC))
3528a53d5182SPaul Mackerras 			msrbit = MSR_VEC;
3529a53d5182SPaul Mackerras 		if (!(regs->msr & MSR_PR) && !(regs->msr & msrbit))
3530a53d5182SPaul Mackerras 			return 0;
3531a53d5182SPaul Mackerras 		err = do_vsx_store(op, ea, regs, cross_endian);
3532a53d5182SPaul Mackerras 		break;
3533a53d5182SPaul Mackerras 	}
3534a53d5182SPaul Mackerras #endif
3535a53d5182SPaul Mackerras 	case STORE_MULTI:
3536a53d5182SPaul Mackerras 		if (!address_ok(regs, ea, size))
3537a53d5182SPaul Mackerras 			return -EFAULT;
3538a53d5182SPaul Mackerras 		rd = op->reg;
3539a53d5182SPaul Mackerras 		for (i = 0; i < size; i += 4) {
3540a53d5182SPaul Mackerras 			unsigned int v32 = regs->gpr[rd];
3541a53d5182SPaul Mackerras 
3542a53d5182SPaul Mackerras 			nb = size - i;
3543a53d5182SPaul Mackerras 			if (nb > 4)
3544a53d5182SPaul Mackerras 				nb = 4;
3545a53d5182SPaul Mackerras 			if (unlikely(cross_endian))
3546a53d5182SPaul Mackerras 				v32 = byterev_4(v32);
3547a53d5182SPaul Mackerras 			err = copy_mem_out((u8 *) &v32, ea, nb, regs);
3548a53d5182SPaul Mackerras 			if (err)
3549a53d5182SPaul Mackerras 				break;
3550a53d5182SPaul Mackerras 			ea += 4;
355145f62159SPaul Mackerras 			/* reg number wraps from 31 to 0 for stsw[ix] */
355245f62159SPaul Mackerras 			rd = (rd + 1) & 0x1f;
3553a53d5182SPaul Mackerras 		}
3554a53d5182SPaul Mackerras 		break;
3555a53d5182SPaul Mackerras 
3556a53d5182SPaul Mackerras 	default:
3557a53d5182SPaul Mackerras 		return -EINVAL;
3558a53d5182SPaul Mackerras 	}
3559a53d5182SPaul Mackerras 
3560a53d5182SPaul Mackerras 	if (err)
3561a53d5182SPaul Mackerras 		return err;
3562a53d5182SPaul Mackerras 
3563a53d5182SPaul Mackerras 	if (op->type & UPDATE)
3564a53d5182SPaul Mackerras 		regs->gpr[op->update_reg] = op->ea;
3565a53d5182SPaul Mackerras 
3566a53d5182SPaul Mackerras 	return 0;
3567a53d5182SPaul Mackerras }
3568a53d5182SPaul Mackerras NOKPROBE_SYMBOL(emulate_loadstore);
3569a53d5182SPaul Mackerras 
3570a53d5182SPaul Mackerras /*
3571be96f633SPaul Mackerras  * Emulate instructions that cause a transfer of control,
3572be96f633SPaul Mackerras  * loads and stores, and a few other instructions.
3573be96f633SPaul Mackerras  * Returns 1 if the step was emulated, 0 if not,
3574be96f633SPaul Mackerras  * or -1 if the instruction is one that should not be stepped,
3575be96f633SPaul Mackerras  * such as an rfid, or a mtmsrd that would clear MSR_RI.
3576be96f633SPaul Mackerras  */
emulate_step(struct pt_regs * regs,ppc_inst_t instr)3577c545b9f0SChristophe Leroy int emulate_step(struct pt_regs *regs, ppc_inst_t instr)
3578be96f633SPaul Mackerras {
3579be96f633SPaul Mackerras 	struct instruction_op op;
3580a53d5182SPaul Mackerras 	int r, err, type;
3581be96f633SPaul Mackerras 	unsigned long val;
3582d120cdbcSPaul Mackerras 	unsigned long ea;
3583be96f633SPaul Mackerras 
3584be96f633SPaul Mackerras 	r = analyse_instr(&op, regs, instr);
35853cdfcbfdSPaul Mackerras 	if (r < 0)
3586be96f633SPaul Mackerras 		return r;
35873cdfcbfdSPaul Mackerras 	if (r > 0) {
35883cdfcbfdSPaul Mackerras 		emulate_update_regs(regs, &op);
35893cdfcbfdSPaul Mackerras 		return 1;
35903cdfcbfdSPaul Mackerras 	}
3591be96f633SPaul Mackerras 
3592be96f633SPaul Mackerras 	err = 0;
3593e6684d07SRavi Bangoria 	type = GETTYPE(op.type);
3594d120cdbcSPaul Mackerras 
3595a53d5182SPaul Mackerras 	if (OP_IS_LOAD_STORE(type)) {
3596a53d5182SPaul Mackerras 		err = emulate_loadstore(regs, &op);
3597a53d5182SPaul Mackerras 		if (err)
3598a53d5182SPaul Mackerras 			return 0;
3599a53d5182SPaul Mackerras 		goto instr_done;
3600a53d5182SPaul Mackerras 	}
3601d120cdbcSPaul Mackerras 
3602d120cdbcSPaul Mackerras 	switch (type) {
3603be96f633SPaul Mackerras 	case CACHEOP:
3604a53d5182SPaul Mackerras 		ea = truncate_if_32bit(regs->msr, op.ea);
3605d120cdbcSPaul Mackerras 		if (!address_ok(regs, ea, 8))
3606be96f633SPaul Mackerras 			return 0;
3607be96f633SPaul Mackerras 		switch (op.type & CACHEOP_MASK) {
3608be96f633SPaul Mackerras 		case DCBST:
3609d120cdbcSPaul Mackerras 			__cacheop_user_asmx(ea, err, "dcbst");
3610be96f633SPaul Mackerras 			break;
3611be96f633SPaul Mackerras 		case DCBF:
3612d120cdbcSPaul Mackerras 			__cacheop_user_asmx(ea, err, "dcbf");
3613be96f633SPaul Mackerras 			break;
3614be96f633SPaul Mackerras 		case DCBTST:
3615be96f633SPaul Mackerras 			if (op.reg == 0)
3616d120cdbcSPaul Mackerras 				prefetchw((void *) ea);
3617be96f633SPaul Mackerras 			break;
3618be96f633SPaul Mackerras 		case DCBT:
3619be96f633SPaul Mackerras 			if (op.reg == 0)
3620d120cdbcSPaul Mackerras 				prefetch((void *) ea);
3621be96f633SPaul Mackerras 			break;
3622cf87c3f6SPaul Mackerras 		case ICBI:
3623d120cdbcSPaul Mackerras 			__cacheop_user_asmx(ea, err, "icbi");
3624cf87c3f6SPaul Mackerras 			break;
3625b2543f7bSPaul Mackerras 		case DCBZ:
3626b2543f7bSPaul Mackerras 			err = emulate_dcbz(ea, regs);
3627b2543f7bSPaul Mackerras 			break;
3628be96f633SPaul Mackerras 		}
3629b9da9c8aSPaul Mackerras 		if (err) {
3630b9da9c8aSPaul Mackerras 			regs->dar = ea;
3631be96f633SPaul Mackerras 			return 0;
3632b9da9c8aSPaul Mackerras 		}
36330016a4cfSPaul Mackerras 		goto instr_done;
3634be96f633SPaul Mackerras 
3635be96f633SPaul Mackerras 	case MFMSR:
3636be96f633SPaul Mackerras 		regs->gpr[op.reg] = regs->msr & MSR_MASK;
3637be96f633SPaul Mackerras 		goto instr_done;
3638be96f633SPaul Mackerras 
3639be96f633SPaul Mackerras 	case MTMSR:
3640be96f633SPaul Mackerras 		val = regs->gpr[op.reg];
3641be96f633SPaul Mackerras 		if ((val & MSR_RI) == 0)
3642be96f633SPaul Mackerras 			/* can't step mtmsr[d] that would clear MSR_RI */
3643be96f633SPaul Mackerras 			return -1;
3644be96f633SPaul Mackerras 		/* here op.val is the mask of bits to change */
364559dc5bfcSNicholas Piggin 		regs_set_return_msr(regs, (regs->msr & ~op.val) | (val & op.val));
3646be96f633SPaul Mackerras 		goto instr_done;
3647be96f633SPaul Mackerras 
3648be96f633SPaul Mackerras 	case SYSCALL:	/* sc */
3649be96f633SPaul Mackerras 		/*
3650a553476cSNicholas Piggin 		 * Per ISA v3.1, section 7.5.15 'Trace Interrupt', we can't
3651a553476cSNicholas Piggin 		 * single step a system call instruction:
3652a553476cSNicholas Piggin 		 *
3653a553476cSNicholas Piggin 		 *   Successful completion for an instruction means that the
3654a553476cSNicholas Piggin 		 *   instruction caused no other interrupt. Thus a Trace
3655a553476cSNicholas Piggin 		 *   interrupt never occurs for a System Call or System Call
3656a553476cSNicholas Piggin 		 *   Vectored instruction, or for a Trap instruction that
3657a553476cSNicholas Piggin 		 *   traps.
3658be96f633SPaul Mackerras 		 */
3659a553476cSNicholas Piggin 		return -1;
36607fa95f9aSNicholas Piggin 	case SYSCALL_VECTORED_0:	/* scv 0 */
3661a553476cSNicholas Piggin 		return -1;
3662be96f633SPaul Mackerras 	case RFI:
3663be96f633SPaul Mackerras 		return -1;
3664be96f633SPaul Mackerras 	}
3665be96f633SPaul Mackerras 	return 0;
3666be96f633SPaul Mackerras 
3667be96f633SPaul Mackerras  instr_done:
366859dc5bfcSNicholas Piggin 	regs_set_return_ip(regs,
366959dc5bfcSNicholas Piggin 		truncate_if_32bit(regs->msr, regs->nip + GETLENGTH(op.type)));
3670be96f633SPaul Mackerras 	return 1;
367114cf11afSPaul Mackerras }
367271f6e58eSNaveen N. Rao NOKPROBE_SYMBOL(emulate_step);
3673