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, ®s->gpr[reg]);
748d955189aSPaul Mackerras } else {
749350779a2SPaul Mackerras err = read_mem(®s->gpr[reg + IS_LE], ea, 8, regs);
750350779a2SPaul Mackerras if (!err)
751350779a2SPaul Mackerras err = read_mem(®s->gpr[reg + IS_BE], ea + 8, 8, regs);
752d955189aSPaul Mackerras }
753d955189aSPaul Mackerras if (!err && unlikely(cross_endian))
754d955189aSPaul Mackerras do_byte_reverse(®s->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(®->b[i], mem, read_size);
813d955189aSPaul Mackerras if (rev)
814d955189aSPaul Mackerras do_byte_reverse(®->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(®->fp[1 + IS_LE],
822350779a2SPaul Mackerras ®->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(®->dp[IS_LE], &buf.fp[1 + IS_LE]);
918350779a2SPaul Mackerras preempt_enable();
919350779a2SPaul Mackerras reg = &buf;
920350779a2SPaul Mackerras }
921350779a2SPaul Mackerras memcpy(mem, ®->b[i], write_size);
922350779a2SPaul Mackerras if (size == 16)
923350779a2SPaul Mackerras memcpy(mem + 8, ®->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, ®s->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(®s->gpr[op->reg], ea, size, regs);
3420a53d5182SPaul Mackerras if (!err) {
3421a53d5182SPaul Mackerras if (op->type & SIGNEXT)
3422a53d5182SPaul Mackerras do_signext(®s->gpr[op->reg], size);
3423a53d5182SPaul Mackerras if ((op->type & BYTEREV) == (cross_endian ? 0 : BYTEREV))
3424a53d5182SPaul Mackerras do_byterev(®s->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