162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Single-step support.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2004 Paul Mackerras <paulus@au.ibm.com>, IBM
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci#include <linux/kernel.h>
862306a36Sopenharmony_ci#include <linux/kprobes.h>
962306a36Sopenharmony_ci#include <linux/ptrace.h>
1062306a36Sopenharmony_ci#include <linux/prefetch.h>
1162306a36Sopenharmony_ci#include <asm/sstep.h>
1262306a36Sopenharmony_ci#include <asm/processor.h>
1362306a36Sopenharmony_ci#include <linux/uaccess.h>
1462306a36Sopenharmony_ci#include <asm/cpu_has_feature.h>
1562306a36Sopenharmony_ci#include <asm/cputable.h>
1662306a36Sopenharmony_ci#include <asm/disassemble.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#ifdef CONFIG_PPC64
1962306a36Sopenharmony_ci/* Bits in SRR1 that are copied from MSR */
2062306a36Sopenharmony_ci#define MSR_MASK	0xffffffff87c0ffffUL
2162306a36Sopenharmony_ci#else
2262306a36Sopenharmony_ci#define MSR_MASK	0x87c0ffff
2362306a36Sopenharmony_ci#endif
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci/* Bits in XER */
2662306a36Sopenharmony_ci#define XER_SO		0x80000000U
2762306a36Sopenharmony_ci#define XER_OV		0x40000000U
2862306a36Sopenharmony_ci#define XER_CA		0x20000000U
2962306a36Sopenharmony_ci#define XER_OV32	0x00080000U
3062306a36Sopenharmony_ci#define XER_CA32	0x00040000U
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#ifdef CONFIG_VSX
3362306a36Sopenharmony_ci#define VSX_REGISTER_XTP(rd)   ((((rd) & 1) << 5) | ((rd) & 0xfe))
3462306a36Sopenharmony_ci#endif
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#ifdef CONFIG_PPC_FPU
3762306a36Sopenharmony_ci/*
3862306a36Sopenharmony_ci * Functions in ldstfp.S
3962306a36Sopenharmony_ci */
4062306a36Sopenharmony_ciextern void get_fpr(int rn, double *p);
4162306a36Sopenharmony_ciextern void put_fpr(int rn, const double *p);
4262306a36Sopenharmony_ciextern void get_vr(int rn, __vector128 *p);
4362306a36Sopenharmony_ciextern void put_vr(int rn, __vector128 *p);
4462306a36Sopenharmony_ciextern void load_vsrn(int vsr, const void *p);
4562306a36Sopenharmony_ciextern void store_vsrn(int vsr, void *p);
4662306a36Sopenharmony_ciextern void conv_sp_to_dp(const float *sp, double *dp);
4762306a36Sopenharmony_ciextern void conv_dp_to_sp(const double *dp, float *sp);
4862306a36Sopenharmony_ci#endif
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci#ifdef __powerpc64__
5162306a36Sopenharmony_ci/*
5262306a36Sopenharmony_ci * Functions in quad.S
5362306a36Sopenharmony_ci */
5462306a36Sopenharmony_ciextern int do_lq(unsigned long ea, unsigned long *regs);
5562306a36Sopenharmony_ciextern int do_stq(unsigned long ea, unsigned long val0, unsigned long val1);
5662306a36Sopenharmony_ciextern int do_lqarx(unsigned long ea, unsigned long *regs);
5762306a36Sopenharmony_ciextern int do_stqcx(unsigned long ea, unsigned long val0, unsigned long val1,
5862306a36Sopenharmony_ci		    unsigned int *crp);
5962306a36Sopenharmony_ci#endif
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci#ifdef __LITTLE_ENDIAN__
6262306a36Sopenharmony_ci#define IS_LE	1
6362306a36Sopenharmony_ci#define IS_BE	0
6462306a36Sopenharmony_ci#else
6562306a36Sopenharmony_ci#define IS_LE	0
6662306a36Sopenharmony_ci#define IS_BE	1
6762306a36Sopenharmony_ci#endif
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci/*
7062306a36Sopenharmony_ci * Emulate the truncation of 64 bit values in 32-bit mode.
7162306a36Sopenharmony_ci */
7262306a36Sopenharmony_cistatic nokprobe_inline unsigned long truncate_if_32bit(unsigned long msr,
7362306a36Sopenharmony_ci							unsigned long val)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	if ((msr & MSR_64BIT) == 0)
7662306a36Sopenharmony_ci		val &= 0xffffffffUL;
7762306a36Sopenharmony_ci	return val;
7862306a36Sopenharmony_ci}
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci/*
8162306a36Sopenharmony_ci * Determine whether a conditional branch instruction would branch.
8262306a36Sopenharmony_ci */
8362306a36Sopenharmony_cistatic nokprobe_inline int branch_taken(unsigned int instr,
8462306a36Sopenharmony_ci					const struct pt_regs *regs,
8562306a36Sopenharmony_ci					struct instruction_op *op)
8662306a36Sopenharmony_ci{
8762306a36Sopenharmony_ci	unsigned int bo = (instr >> 21) & 0x1f;
8862306a36Sopenharmony_ci	unsigned int bi;
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	if ((bo & 4) == 0) {
9162306a36Sopenharmony_ci		/* decrement counter */
9262306a36Sopenharmony_ci		op->type |= DECCTR;
9362306a36Sopenharmony_ci		if (((bo >> 1) & 1) ^ (regs->ctr == 1))
9462306a36Sopenharmony_ci			return 0;
9562306a36Sopenharmony_ci	}
9662306a36Sopenharmony_ci	if ((bo & 0x10) == 0) {
9762306a36Sopenharmony_ci		/* check bit from CR */
9862306a36Sopenharmony_ci		bi = (instr >> 16) & 0x1f;
9962306a36Sopenharmony_ci		if (((regs->ccr >> (31 - bi)) & 1) != ((bo >> 3) & 1))
10062306a36Sopenharmony_ci			return 0;
10162306a36Sopenharmony_ci	}
10262306a36Sopenharmony_ci	return 1;
10362306a36Sopenharmony_ci}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cistatic nokprobe_inline long address_ok(struct pt_regs *regs,
10662306a36Sopenharmony_ci				       unsigned long ea, int nb)
10762306a36Sopenharmony_ci{
10862306a36Sopenharmony_ci	if (!user_mode(regs))
10962306a36Sopenharmony_ci		return 1;
11062306a36Sopenharmony_ci	if (access_ok((void __user *)ea, nb))
11162306a36Sopenharmony_ci		return 1;
11262306a36Sopenharmony_ci	if (access_ok((void __user *)ea, 1))
11362306a36Sopenharmony_ci		/* Access overlaps the end of the user region */
11462306a36Sopenharmony_ci		regs->dar = TASK_SIZE_MAX - 1;
11562306a36Sopenharmony_ci	else
11662306a36Sopenharmony_ci		regs->dar = ea;
11762306a36Sopenharmony_ci	return 0;
11862306a36Sopenharmony_ci}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci/*
12162306a36Sopenharmony_ci * Calculate effective address for a D-form instruction
12262306a36Sopenharmony_ci */
12362306a36Sopenharmony_cistatic nokprobe_inline unsigned long dform_ea(unsigned int instr,
12462306a36Sopenharmony_ci					      const struct pt_regs *regs)
12562306a36Sopenharmony_ci{
12662306a36Sopenharmony_ci	int ra;
12762306a36Sopenharmony_ci	unsigned long ea;
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	ra = (instr >> 16) & 0x1f;
13062306a36Sopenharmony_ci	ea = (signed short) instr;		/* sign-extend */
13162306a36Sopenharmony_ci	if (ra)
13262306a36Sopenharmony_ci		ea += regs->gpr[ra];
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	return ea;
13562306a36Sopenharmony_ci}
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci#ifdef __powerpc64__
13862306a36Sopenharmony_ci/*
13962306a36Sopenharmony_ci * Calculate effective address for a DS-form instruction
14062306a36Sopenharmony_ci */
14162306a36Sopenharmony_cistatic nokprobe_inline unsigned long dsform_ea(unsigned int instr,
14262306a36Sopenharmony_ci					       const struct pt_regs *regs)
14362306a36Sopenharmony_ci{
14462306a36Sopenharmony_ci	int ra;
14562306a36Sopenharmony_ci	unsigned long ea;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	ra = (instr >> 16) & 0x1f;
14862306a36Sopenharmony_ci	ea = (signed short) (instr & ~3);	/* sign-extend */
14962306a36Sopenharmony_ci	if (ra)
15062306a36Sopenharmony_ci		ea += regs->gpr[ra];
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	return ea;
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci/*
15662306a36Sopenharmony_ci * Calculate effective address for a DQ-form instruction
15762306a36Sopenharmony_ci */
15862306a36Sopenharmony_cistatic nokprobe_inline unsigned long dqform_ea(unsigned int instr,
15962306a36Sopenharmony_ci					       const struct pt_regs *regs)
16062306a36Sopenharmony_ci{
16162306a36Sopenharmony_ci	int ra;
16262306a36Sopenharmony_ci	unsigned long ea;
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	ra = (instr >> 16) & 0x1f;
16562306a36Sopenharmony_ci	ea = (signed short) (instr & ~0xf);	/* sign-extend */
16662306a36Sopenharmony_ci	if (ra)
16762306a36Sopenharmony_ci		ea += regs->gpr[ra];
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	return ea;
17062306a36Sopenharmony_ci}
17162306a36Sopenharmony_ci#endif /* __powerpc64 */
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci/*
17462306a36Sopenharmony_ci * Calculate effective address for an X-form instruction
17562306a36Sopenharmony_ci */
17662306a36Sopenharmony_cistatic nokprobe_inline unsigned long xform_ea(unsigned int instr,
17762306a36Sopenharmony_ci					      const struct pt_regs *regs)
17862306a36Sopenharmony_ci{
17962306a36Sopenharmony_ci	int ra, rb;
18062306a36Sopenharmony_ci	unsigned long ea;
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	ra = (instr >> 16) & 0x1f;
18362306a36Sopenharmony_ci	rb = (instr >> 11) & 0x1f;
18462306a36Sopenharmony_ci	ea = regs->gpr[rb];
18562306a36Sopenharmony_ci	if (ra)
18662306a36Sopenharmony_ci		ea += regs->gpr[ra];
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	return ea;
18962306a36Sopenharmony_ci}
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci/*
19262306a36Sopenharmony_ci * Calculate effective address for a MLS:D-form / 8LS:D-form
19362306a36Sopenharmony_ci * prefixed instruction
19462306a36Sopenharmony_ci */
19562306a36Sopenharmony_cistatic nokprobe_inline unsigned long mlsd_8lsd_ea(unsigned int instr,
19662306a36Sopenharmony_ci						  unsigned int suffix,
19762306a36Sopenharmony_ci						  const struct pt_regs *regs)
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci	int ra, prefix_r;
20062306a36Sopenharmony_ci	unsigned int  dd;
20162306a36Sopenharmony_ci	unsigned long ea, d0, d1, d;
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	prefix_r = GET_PREFIX_R(instr);
20462306a36Sopenharmony_ci	ra = GET_PREFIX_RA(suffix);
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	d0 = instr & 0x3ffff;
20762306a36Sopenharmony_ci	d1 = suffix & 0xffff;
20862306a36Sopenharmony_ci	d = (d0 << 16) | d1;
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	/*
21162306a36Sopenharmony_ci	 * sign extend a 34 bit number
21262306a36Sopenharmony_ci	 */
21362306a36Sopenharmony_ci	dd = (unsigned int)(d >> 2);
21462306a36Sopenharmony_ci	ea = (signed int)dd;
21562306a36Sopenharmony_ci	ea = (ea << 2) | (d & 0x3);
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	if (!prefix_r && ra)
21862306a36Sopenharmony_ci		ea += regs->gpr[ra];
21962306a36Sopenharmony_ci	else if (!prefix_r && !ra)
22062306a36Sopenharmony_ci		; /* Leave ea as is */
22162306a36Sopenharmony_ci	else if (prefix_r)
22262306a36Sopenharmony_ci		ea += regs->nip;
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	/*
22562306a36Sopenharmony_ci	 * (prefix_r && ra) is an invalid form. Should already be
22662306a36Sopenharmony_ci	 * checked for by caller!
22762306a36Sopenharmony_ci	 */
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	return ea;
23062306a36Sopenharmony_ci}
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci/*
23362306a36Sopenharmony_ci * Return the largest power of 2, not greater than sizeof(unsigned long),
23462306a36Sopenharmony_ci * such that x is a multiple of it.
23562306a36Sopenharmony_ci */
23662306a36Sopenharmony_cistatic nokprobe_inline unsigned long max_align(unsigned long x)
23762306a36Sopenharmony_ci{
23862306a36Sopenharmony_ci	x |= sizeof(unsigned long);
23962306a36Sopenharmony_ci	return x & -x;		/* isolates rightmost bit */
24062306a36Sopenharmony_ci}
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_cistatic nokprobe_inline unsigned long byterev_2(unsigned long x)
24362306a36Sopenharmony_ci{
24462306a36Sopenharmony_ci	return ((x >> 8) & 0xff) | ((x & 0xff) << 8);
24562306a36Sopenharmony_ci}
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_cistatic nokprobe_inline unsigned long byterev_4(unsigned long x)
24862306a36Sopenharmony_ci{
24962306a36Sopenharmony_ci	return ((x >> 24) & 0xff) | ((x >> 8) & 0xff00) |
25062306a36Sopenharmony_ci		((x & 0xff00) << 8) | ((x & 0xff) << 24);
25162306a36Sopenharmony_ci}
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci#ifdef __powerpc64__
25462306a36Sopenharmony_cistatic nokprobe_inline unsigned long byterev_8(unsigned long x)
25562306a36Sopenharmony_ci{
25662306a36Sopenharmony_ci	return (byterev_4(x) << 32) | byterev_4(x >> 32);
25762306a36Sopenharmony_ci}
25862306a36Sopenharmony_ci#endif
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_cistatic nokprobe_inline void do_byte_reverse(void *ptr, int nb)
26162306a36Sopenharmony_ci{
26262306a36Sopenharmony_ci	switch (nb) {
26362306a36Sopenharmony_ci	case 2:
26462306a36Sopenharmony_ci		*(u16 *)ptr = byterev_2(*(u16 *)ptr);
26562306a36Sopenharmony_ci		break;
26662306a36Sopenharmony_ci	case 4:
26762306a36Sopenharmony_ci		*(u32 *)ptr = byterev_4(*(u32 *)ptr);
26862306a36Sopenharmony_ci		break;
26962306a36Sopenharmony_ci#ifdef __powerpc64__
27062306a36Sopenharmony_ci	case 8:
27162306a36Sopenharmony_ci		*(unsigned long *)ptr = byterev_8(*(unsigned long *)ptr);
27262306a36Sopenharmony_ci		break;
27362306a36Sopenharmony_ci	case 16: {
27462306a36Sopenharmony_ci		unsigned long *up = (unsigned long *)ptr;
27562306a36Sopenharmony_ci		unsigned long tmp;
27662306a36Sopenharmony_ci		tmp = byterev_8(up[0]);
27762306a36Sopenharmony_ci		up[0] = byterev_8(up[1]);
27862306a36Sopenharmony_ci		up[1] = tmp;
27962306a36Sopenharmony_ci		break;
28062306a36Sopenharmony_ci	}
28162306a36Sopenharmony_ci	case 32: {
28262306a36Sopenharmony_ci		unsigned long *up = (unsigned long *)ptr;
28362306a36Sopenharmony_ci		unsigned long tmp;
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci		tmp = byterev_8(up[0]);
28662306a36Sopenharmony_ci		up[0] = byterev_8(up[3]);
28762306a36Sopenharmony_ci		up[3] = tmp;
28862306a36Sopenharmony_ci		tmp = byterev_8(up[2]);
28962306a36Sopenharmony_ci		up[2] = byterev_8(up[1]);
29062306a36Sopenharmony_ci		up[1] = tmp;
29162306a36Sopenharmony_ci		break;
29262306a36Sopenharmony_ci	}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci#endif
29562306a36Sopenharmony_ci	default:
29662306a36Sopenharmony_ci		WARN_ON_ONCE(1);
29762306a36Sopenharmony_ci	}
29862306a36Sopenharmony_ci}
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_cistatic __always_inline int
30162306a36Sopenharmony_ci__read_mem_aligned(unsigned long *dest, unsigned long ea, int nb, struct pt_regs *regs)
30262306a36Sopenharmony_ci{
30362306a36Sopenharmony_ci	unsigned long x = 0;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	switch (nb) {
30662306a36Sopenharmony_ci	case 1:
30762306a36Sopenharmony_ci		unsafe_get_user(x, (unsigned char __user *)ea, Efault);
30862306a36Sopenharmony_ci		break;
30962306a36Sopenharmony_ci	case 2:
31062306a36Sopenharmony_ci		unsafe_get_user(x, (unsigned short __user *)ea, Efault);
31162306a36Sopenharmony_ci		break;
31262306a36Sopenharmony_ci	case 4:
31362306a36Sopenharmony_ci		unsafe_get_user(x, (unsigned int __user *)ea, Efault);
31462306a36Sopenharmony_ci		break;
31562306a36Sopenharmony_ci#ifdef __powerpc64__
31662306a36Sopenharmony_ci	case 8:
31762306a36Sopenharmony_ci		unsafe_get_user(x, (unsigned long __user *)ea, Efault);
31862306a36Sopenharmony_ci		break;
31962306a36Sopenharmony_ci#endif
32062306a36Sopenharmony_ci	}
32162306a36Sopenharmony_ci	*dest = x;
32262306a36Sopenharmony_ci	return 0;
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ciEfault:
32562306a36Sopenharmony_ci	regs->dar = ea;
32662306a36Sopenharmony_ci	return -EFAULT;
32762306a36Sopenharmony_ci}
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_cistatic nokprobe_inline int
33062306a36Sopenharmony_ciread_mem_aligned(unsigned long *dest, unsigned long ea, int nb, struct pt_regs *regs)
33162306a36Sopenharmony_ci{
33262306a36Sopenharmony_ci	int err;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	if (is_kernel_addr(ea))
33562306a36Sopenharmony_ci		return __read_mem_aligned(dest, ea, nb, regs);
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	if (user_read_access_begin((void __user *)ea, nb)) {
33862306a36Sopenharmony_ci		err = __read_mem_aligned(dest, ea, nb, regs);
33962306a36Sopenharmony_ci		user_read_access_end();
34062306a36Sopenharmony_ci	} else {
34162306a36Sopenharmony_ci		err = -EFAULT;
34262306a36Sopenharmony_ci		regs->dar = ea;
34362306a36Sopenharmony_ci	}
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	return err;
34662306a36Sopenharmony_ci}
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci/*
34962306a36Sopenharmony_ci * Copy from userspace to a buffer, using the largest possible
35062306a36Sopenharmony_ci * aligned accesses, up to sizeof(long).
35162306a36Sopenharmony_ci */
35262306a36Sopenharmony_cistatic __always_inline int __copy_mem_in(u8 *dest, unsigned long ea, int nb, struct pt_regs *regs)
35362306a36Sopenharmony_ci{
35462306a36Sopenharmony_ci	int c;
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci	for (; nb > 0; nb -= c) {
35762306a36Sopenharmony_ci		c = max_align(ea);
35862306a36Sopenharmony_ci		if (c > nb)
35962306a36Sopenharmony_ci			c = max_align(nb);
36062306a36Sopenharmony_ci		switch (c) {
36162306a36Sopenharmony_ci		case 1:
36262306a36Sopenharmony_ci			unsafe_get_user(*dest, (u8 __user *)ea, Efault);
36362306a36Sopenharmony_ci			break;
36462306a36Sopenharmony_ci		case 2:
36562306a36Sopenharmony_ci			unsafe_get_user(*(u16 *)dest, (u16 __user *)ea, Efault);
36662306a36Sopenharmony_ci			break;
36762306a36Sopenharmony_ci		case 4:
36862306a36Sopenharmony_ci			unsafe_get_user(*(u32 *)dest, (u32 __user *)ea, Efault);
36962306a36Sopenharmony_ci			break;
37062306a36Sopenharmony_ci#ifdef __powerpc64__
37162306a36Sopenharmony_ci		case 8:
37262306a36Sopenharmony_ci			unsafe_get_user(*(u64 *)dest, (u64 __user *)ea, Efault);
37362306a36Sopenharmony_ci			break;
37462306a36Sopenharmony_ci#endif
37562306a36Sopenharmony_ci		}
37662306a36Sopenharmony_ci		dest += c;
37762306a36Sopenharmony_ci		ea += c;
37862306a36Sopenharmony_ci	}
37962306a36Sopenharmony_ci	return 0;
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ciEfault:
38262306a36Sopenharmony_ci	regs->dar = ea;
38362306a36Sopenharmony_ci	return -EFAULT;
38462306a36Sopenharmony_ci}
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_cistatic nokprobe_inline int copy_mem_in(u8 *dest, unsigned long ea, int nb, struct pt_regs *regs)
38762306a36Sopenharmony_ci{
38862306a36Sopenharmony_ci	int err;
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	if (is_kernel_addr(ea))
39162306a36Sopenharmony_ci		return __copy_mem_in(dest, ea, nb, regs);
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	if (user_read_access_begin((void __user *)ea, nb)) {
39462306a36Sopenharmony_ci		err = __copy_mem_in(dest, ea, nb, regs);
39562306a36Sopenharmony_ci		user_read_access_end();
39662306a36Sopenharmony_ci	} else {
39762306a36Sopenharmony_ci		err = -EFAULT;
39862306a36Sopenharmony_ci		regs->dar = ea;
39962306a36Sopenharmony_ci	}
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	return err;
40262306a36Sopenharmony_ci}
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_cistatic nokprobe_inline int read_mem_unaligned(unsigned long *dest,
40562306a36Sopenharmony_ci					      unsigned long ea, int nb,
40662306a36Sopenharmony_ci					      struct pt_regs *regs)
40762306a36Sopenharmony_ci{
40862306a36Sopenharmony_ci	union {
40962306a36Sopenharmony_ci		unsigned long ul;
41062306a36Sopenharmony_ci		u8 b[sizeof(unsigned long)];
41162306a36Sopenharmony_ci	} u;
41262306a36Sopenharmony_ci	int i;
41362306a36Sopenharmony_ci	int err;
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	u.ul = 0;
41662306a36Sopenharmony_ci	i = IS_BE ? sizeof(unsigned long) - nb : 0;
41762306a36Sopenharmony_ci	err = copy_mem_in(&u.b[i], ea, nb, regs);
41862306a36Sopenharmony_ci	if (!err)
41962306a36Sopenharmony_ci		*dest = u.ul;
42062306a36Sopenharmony_ci	return err;
42162306a36Sopenharmony_ci}
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci/*
42462306a36Sopenharmony_ci * Read memory at address ea for nb bytes, return 0 for success
42562306a36Sopenharmony_ci * or -EFAULT if an error occurred.  N.B. nb must be 1, 2, 4 or 8.
42662306a36Sopenharmony_ci * If nb < sizeof(long), the result is right-justified on BE systems.
42762306a36Sopenharmony_ci */
42862306a36Sopenharmony_cistatic int read_mem(unsigned long *dest, unsigned long ea, int nb,
42962306a36Sopenharmony_ci			      struct pt_regs *regs)
43062306a36Sopenharmony_ci{
43162306a36Sopenharmony_ci	if (!address_ok(regs, ea, nb))
43262306a36Sopenharmony_ci		return -EFAULT;
43362306a36Sopenharmony_ci	if ((ea & (nb - 1)) == 0)
43462306a36Sopenharmony_ci		return read_mem_aligned(dest, ea, nb, regs);
43562306a36Sopenharmony_ci	return read_mem_unaligned(dest, ea, nb, regs);
43662306a36Sopenharmony_ci}
43762306a36Sopenharmony_ciNOKPROBE_SYMBOL(read_mem);
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_cistatic __always_inline int
44062306a36Sopenharmony_ci__write_mem_aligned(unsigned long val, unsigned long ea, int nb, struct pt_regs *regs)
44162306a36Sopenharmony_ci{
44262306a36Sopenharmony_ci	switch (nb) {
44362306a36Sopenharmony_ci	case 1:
44462306a36Sopenharmony_ci		unsafe_put_user(val, (unsigned char __user *)ea, Efault);
44562306a36Sopenharmony_ci		break;
44662306a36Sopenharmony_ci	case 2:
44762306a36Sopenharmony_ci		unsafe_put_user(val, (unsigned short __user *)ea, Efault);
44862306a36Sopenharmony_ci		break;
44962306a36Sopenharmony_ci	case 4:
45062306a36Sopenharmony_ci		unsafe_put_user(val, (unsigned int __user *)ea, Efault);
45162306a36Sopenharmony_ci		break;
45262306a36Sopenharmony_ci#ifdef __powerpc64__
45362306a36Sopenharmony_ci	case 8:
45462306a36Sopenharmony_ci		unsafe_put_user(val, (unsigned long __user *)ea, Efault);
45562306a36Sopenharmony_ci		break;
45662306a36Sopenharmony_ci#endif
45762306a36Sopenharmony_ci	}
45862306a36Sopenharmony_ci	return 0;
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ciEfault:
46162306a36Sopenharmony_ci	regs->dar = ea;
46262306a36Sopenharmony_ci	return -EFAULT;
46362306a36Sopenharmony_ci}
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_cistatic nokprobe_inline int
46662306a36Sopenharmony_ciwrite_mem_aligned(unsigned long val, unsigned long ea, int nb, struct pt_regs *regs)
46762306a36Sopenharmony_ci{
46862306a36Sopenharmony_ci	int err;
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci	if (is_kernel_addr(ea))
47162306a36Sopenharmony_ci		return __write_mem_aligned(val, ea, nb, regs);
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	if (user_write_access_begin((void __user *)ea, nb)) {
47462306a36Sopenharmony_ci		err = __write_mem_aligned(val, ea, nb, regs);
47562306a36Sopenharmony_ci		user_write_access_end();
47662306a36Sopenharmony_ci	} else {
47762306a36Sopenharmony_ci		err = -EFAULT;
47862306a36Sopenharmony_ci		regs->dar = ea;
47962306a36Sopenharmony_ci	}
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	return err;
48262306a36Sopenharmony_ci}
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci/*
48562306a36Sopenharmony_ci * Copy from a buffer to userspace, using the largest possible
48662306a36Sopenharmony_ci * aligned accesses, up to sizeof(long).
48762306a36Sopenharmony_ci */
48862306a36Sopenharmony_cistatic __always_inline int __copy_mem_out(u8 *dest, unsigned long ea, int nb, struct pt_regs *regs)
48962306a36Sopenharmony_ci{
49062306a36Sopenharmony_ci	int c;
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	for (; nb > 0; nb -= c) {
49362306a36Sopenharmony_ci		c = max_align(ea);
49462306a36Sopenharmony_ci		if (c > nb)
49562306a36Sopenharmony_ci			c = max_align(nb);
49662306a36Sopenharmony_ci		switch (c) {
49762306a36Sopenharmony_ci		case 1:
49862306a36Sopenharmony_ci			unsafe_put_user(*dest, (u8 __user *)ea, Efault);
49962306a36Sopenharmony_ci			break;
50062306a36Sopenharmony_ci		case 2:
50162306a36Sopenharmony_ci			unsafe_put_user(*(u16 *)dest, (u16 __user *)ea, Efault);
50262306a36Sopenharmony_ci			break;
50362306a36Sopenharmony_ci		case 4:
50462306a36Sopenharmony_ci			unsafe_put_user(*(u32 *)dest, (u32 __user *)ea, Efault);
50562306a36Sopenharmony_ci			break;
50662306a36Sopenharmony_ci#ifdef __powerpc64__
50762306a36Sopenharmony_ci		case 8:
50862306a36Sopenharmony_ci			unsafe_put_user(*(u64 *)dest, (u64 __user *)ea, Efault);
50962306a36Sopenharmony_ci			break;
51062306a36Sopenharmony_ci#endif
51162306a36Sopenharmony_ci		}
51262306a36Sopenharmony_ci		dest += c;
51362306a36Sopenharmony_ci		ea += c;
51462306a36Sopenharmony_ci	}
51562306a36Sopenharmony_ci	return 0;
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ciEfault:
51862306a36Sopenharmony_ci	regs->dar = ea;
51962306a36Sopenharmony_ci	return -EFAULT;
52062306a36Sopenharmony_ci}
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_cistatic nokprobe_inline int copy_mem_out(u8 *dest, unsigned long ea, int nb, struct pt_regs *regs)
52362306a36Sopenharmony_ci{
52462306a36Sopenharmony_ci	int err;
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci	if (is_kernel_addr(ea))
52762306a36Sopenharmony_ci		return __copy_mem_out(dest, ea, nb, regs);
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	if (user_write_access_begin((void __user *)ea, nb)) {
53062306a36Sopenharmony_ci		err = __copy_mem_out(dest, ea, nb, regs);
53162306a36Sopenharmony_ci		user_write_access_end();
53262306a36Sopenharmony_ci	} else {
53362306a36Sopenharmony_ci		err = -EFAULT;
53462306a36Sopenharmony_ci		regs->dar = ea;
53562306a36Sopenharmony_ci	}
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_ci	return err;
53862306a36Sopenharmony_ci}
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_cistatic nokprobe_inline int write_mem_unaligned(unsigned long val,
54162306a36Sopenharmony_ci					       unsigned long ea, int nb,
54262306a36Sopenharmony_ci					       struct pt_regs *regs)
54362306a36Sopenharmony_ci{
54462306a36Sopenharmony_ci	union {
54562306a36Sopenharmony_ci		unsigned long ul;
54662306a36Sopenharmony_ci		u8 b[sizeof(unsigned long)];
54762306a36Sopenharmony_ci	} u;
54862306a36Sopenharmony_ci	int i;
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	u.ul = val;
55162306a36Sopenharmony_ci	i = IS_BE ? sizeof(unsigned long) - nb : 0;
55262306a36Sopenharmony_ci	return copy_mem_out(&u.b[i], ea, nb, regs);
55362306a36Sopenharmony_ci}
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci/*
55662306a36Sopenharmony_ci * Write memory at address ea for nb bytes, return 0 for success
55762306a36Sopenharmony_ci * or -EFAULT if an error occurred.  N.B. nb must be 1, 2, 4 or 8.
55862306a36Sopenharmony_ci */
55962306a36Sopenharmony_cistatic int write_mem(unsigned long val, unsigned long ea, int nb,
56062306a36Sopenharmony_ci			       struct pt_regs *regs)
56162306a36Sopenharmony_ci{
56262306a36Sopenharmony_ci	if (!address_ok(regs, ea, nb))
56362306a36Sopenharmony_ci		return -EFAULT;
56462306a36Sopenharmony_ci	if ((ea & (nb - 1)) == 0)
56562306a36Sopenharmony_ci		return write_mem_aligned(val, ea, nb, regs);
56662306a36Sopenharmony_ci	return write_mem_unaligned(val, ea, nb, regs);
56762306a36Sopenharmony_ci}
56862306a36Sopenharmony_ciNOKPROBE_SYMBOL(write_mem);
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci#ifdef CONFIG_PPC_FPU
57162306a36Sopenharmony_ci/*
57262306a36Sopenharmony_ci * These access either the real FP register or the image in the
57362306a36Sopenharmony_ci * thread_struct, depending on regs->msr & MSR_FP.
57462306a36Sopenharmony_ci */
57562306a36Sopenharmony_cistatic int do_fp_load(struct instruction_op *op, unsigned long ea,
57662306a36Sopenharmony_ci		      struct pt_regs *regs, bool cross_endian)
57762306a36Sopenharmony_ci{
57862306a36Sopenharmony_ci	int err, rn, nb;
57962306a36Sopenharmony_ci	union {
58062306a36Sopenharmony_ci		int i;
58162306a36Sopenharmony_ci		unsigned int u;
58262306a36Sopenharmony_ci		float f;
58362306a36Sopenharmony_ci		double d[2];
58462306a36Sopenharmony_ci		unsigned long l[2];
58562306a36Sopenharmony_ci		u8 b[2 * sizeof(double)];
58662306a36Sopenharmony_ci	} u;
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci	nb = GETSIZE(op->type);
58962306a36Sopenharmony_ci	if (nb > sizeof(u))
59062306a36Sopenharmony_ci		return -EINVAL;
59162306a36Sopenharmony_ci	if (!address_ok(regs, ea, nb))
59262306a36Sopenharmony_ci		return -EFAULT;
59362306a36Sopenharmony_ci	rn = op->reg;
59462306a36Sopenharmony_ci	err = copy_mem_in(u.b, ea, nb, regs);
59562306a36Sopenharmony_ci	if (err)
59662306a36Sopenharmony_ci		return err;
59762306a36Sopenharmony_ci	if (unlikely(cross_endian)) {
59862306a36Sopenharmony_ci		do_byte_reverse(u.b, min(nb, 8));
59962306a36Sopenharmony_ci		if (nb == 16)
60062306a36Sopenharmony_ci			do_byte_reverse(&u.b[8], 8);
60162306a36Sopenharmony_ci	}
60262306a36Sopenharmony_ci	preempt_disable();
60362306a36Sopenharmony_ci	if (nb == 4) {
60462306a36Sopenharmony_ci		if (op->type & FPCONV)
60562306a36Sopenharmony_ci			conv_sp_to_dp(&u.f, &u.d[0]);
60662306a36Sopenharmony_ci		else if (op->type & SIGNEXT)
60762306a36Sopenharmony_ci			u.l[0] = u.i;
60862306a36Sopenharmony_ci		else
60962306a36Sopenharmony_ci			u.l[0] = u.u;
61062306a36Sopenharmony_ci	}
61162306a36Sopenharmony_ci	if (regs->msr & MSR_FP)
61262306a36Sopenharmony_ci		put_fpr(rn, &u.d[0]);
61362306a36Sopenharmony_ci	else
61462306a36Sopenharmony_ci		current->thread.TS_FPR(rn) = u.l[0];
61562306a36Sopenharmony_ci	if (nb == 16) {
61662306a36Sopenharmony_ci		/* lfdp */
61762306a36Sopenharmony_ci		rn |= 1;
61862306a36Sopenharmony_ci		if (regs->msr & MSR_FP)
61962306a36Sopenharmony_ci			put_fpr(rn, &u.d[1]);
62062306a36Sopenharmony_ci		else
62162306a36Sopenharmony_ci			current->thread.TS_FPR(rn) = u.l[1];
62262306a36Sopenharmony_ci	}
62362306a36Sopenharmony_ci	preempt_enable();
62462306a36Sopenharmony_ci	return 0;
62562306a36Sopenharmony_ci}
62662306a36Sopenharmony_ciNOKPROBE_SYMBOL(do_fp_load);
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_cistatic int do_fp_store(struct instruction_op *op, unsigned long ea,
62962306a36Sopenharmony_ci		       struct pt_regs *regs, bool cross_endian)
63062306a36Sopenharmony_ci{
63162306a36Sopenharmony_ci	int rn, nb;
63262306a36Sopenharmony_ci	union {
63362306a36Sopenharmony_ci		unsigned int u;
63462306a36Sopenharmony_ci		float f;
63562306a36Sopenharmony_ci		double d[2];
63662306a36Sopenharmony_ci		unsigned long l[2];
63762306a36Sopenharmony_ci		u8 b[2 * sizeof(double)];
63862306a36Sopenharmony_ci	} u;
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci	nb = GETSIZE(op->type);
64162306a36Sopenharmony_ci	if (nb > sizeof(u))
64262306a36Sopenharmony_ci		return -EINVAL;
64362306a36Sopenharmony_ci	if (!address_ok(regs, ea, nb))
64462306a36Sopenharmony_ci		return -EFAULT;
64562306a36Sopenharmony_ci	rn = op->reg;
64662306a36Sopenharmony_ci	preempt_disable();
64762306a36Sopenharmony_ci	if (regs->msr & MSR_FP)
64862306a36Sopenharmony_ci		get_fpr(rn, &u.d[0]);
64962306a36Sopenharmony_ci	else
65062306a36Sopenharmony_ci		u.l[0] = current->thread.TS_FPR(rn);
65162306a36Sopenharmony_ci	if (nb == 4) {
65262306a36Sopenharmony_ci		if (op->type & FPCONV)
65362306a36Sopenharmony_ci			conv_dp_to_sp(&u.d[0], &u.f);
65462306a36Sopenharmony_ci		else
65562306a36Sopenharmony_ci			u.u = u.l[0];
65662306a36Sopenharmony_ci	}
65762306a36Sopenharmony_ci	if (nb == 16) {
65862306a36Sopenharmony_ci		rn |= 1;
65962306a36Sopenharmony_ci		if (regs->msr & MSR_FP)
66062306a36Sopenharmony_ci			get_fpr(rn, &u.d[1]);
66162306a36Sopenharmony_ci		else
66262306a36Sopenharmony_ci			u.l[1] = current->thread.TS_FPR(rn);
66362306a36Sopenharmony_ci	}
66462306a36Sopenharmony_ci	preempt_enable();
66562306a36Sopenharmony_ci	if (unlikely(cross_endian)) {
66662306a36Sopenharmony_ci		do_byte_reverse(u.b, min(nb, 8));
66762306a36Sopenharmony_ci		if (nb == 16)
66862306a36Sopenharmony_ci			do_byte_reverse(&u.b[8], 8);
66962306a36Sopenharmony_ci	}
67062306a36Sopenharmony_ci	return copy_mem_out(u.b, ea, nb, regs);
67162306a36Sopenharmony_ci}
67262306a36Sopenharmony_ciNOKPROBE_SYMBOL(do_fp_store);
67362306a36Sopenharmony_ci#endif
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci#ifdef CONFIG_ALTIVEC
67662306a36Sopenharmony_ci/* For Altivec/VMX, no need to worry about alignment */
67762306a36Sopenharmony_cistatic nokprobe_inline int do_vec_load(int rn, unsigned long ea,
67862306a36Sopenharmony_ci				       int size, struct pt_regs *regs,
67962306a36Sopenharmony_ci				       bool cross_endian)
68062306a36Sopenharmony_ci{
68162306a36Sopenharmony_ci	int err;
68262306a36Sopenharmony_ci	union {
68362306a36Sopenharmony_ci		__vector128 v;
68462306a36Sopenharmony_ci		u8 b[sizeof(__vector128)];
68562306a36Sopenharmony_ci	} u = {};
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci	if (size > sizeof(u))
68862306a36Sopenharmony_ci		return -EINVAL;
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci	if (!address_ok(regs, ea & ~0xfUL, 16))
69162306a36Sopenharmony_ci		return -EFAULT;
69262306a36Sopenharmony_ci	/* align to multiple of size */
69362306a36Sopenharmony_ci	ea &= ~(size - 1);
69462306a36Sopenharmony_ci	err = copy_mem_in(&u.b[ea & 0xf], ea, size, regs);
69562306a36Sopenharmony_ci	if (err)
69662306a36Sopenharmony_ci		return err;
69762306a36Sopenharmony_ci	if (unlikely(cross_endian))
69862306a36Sopenharmony_ci		do_byte_reverse(&u.b[ea & 0xf], size);
69962306a36Sopenharmony_ci	preempt_disable();
70062306a36Sopenharmony_ci	if (regs->msr & MSR_VEC)
70162306a36Sopenharmony_ci		put_vr(rn, &u.v);
70262306a36Sopenharmony_ci	else
70362306a36Sopenharmony_ci		current->thread.vr_state.vr[rn] = u.v;
70462306a36Sopenharmony_ci	preempt_enable();
70562306a36Sopenharmony_ci	return 0;
70662306a36Sopenharmony_ci}
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_cistatic nokprobe_inline int do_vec_store(int rn, unsigned long ea,
70962306a36Sopenharmony_ci					int size, struct pt_regs *regs,
71062306a36Sopenharmony_ci					bool cross_endian)
71162306a36Sopenharmony_ci{
71262306a36Sopenharmony_ci	union {
71362306a36Sopenharmony_ci		__vector128 v;
71462306a36Sopenharmony_ci		u8 b[sizeof(__vector128)];
71562306a36Sopenharmony_ci	} u;
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_ci	if (size > sizeof(u))
71862306a36Sopenharmony_ci		return -EINVAL;
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_ci	if (!address_ok(regs, ea & ~0xfUL, 16))
72162306a36Sopenharmony_ci		return -EFAULT;
72262306a36Sopenharmony_ci	/* align to multiple of size */
72362306a36Sopenharmony_ci	ea &= ~(size - 1);
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_ci	preempt_disable();
72662306a36Sopenharmony_ci	if (regs->msr & MSR_VEC)
72762306a36Sopenharmony_ci		get_vr(rn, &u.v);
72862306a36Sopenharmony_ci	else
72962306a36Sopenharmony_ci		u.v = current->thread.vr_state.vr[rn];
73062306a36Sopenharmony_ci	preempt_enable();
73162306a36Sopenharmony_ci	if (unlikely(cross_endian))
73262306a36Sopenharmony_ci		do_byte_reverse(&u.b[ea & 0xf], size);
73362306a36Sopenharmony_ci	return copy_mem_out(&u.b[ea & 0xf], ea, size, regs);
73462306a36Sopenharmony_ci}
73562306a36Sopenharmony_ci#endif /* CONFIG_ALTIVEC */
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci#ifdef __powerpc64__
73862306a36Sopenharmony_cistatic nokprobe_inline int emulate_lq(struct pt_regs *regs, unsigned long ea,
73962306a36Sopenharmony_ci				      int reg, bool cross_endian)
74062306a36Sopenharmony_ci{
74162306a36Sopenharmony_ci	int err;
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci	if (!address_ok(regs, ea, 16))
74462306a36Sopenharmony_ci		return -EFAULT;
74562306a36Sopenharmony_ci	/* if aligned, should be atomic */
74662306a36Sopenharmony_ci	if ((ea & 0xf) == 0) {
74762306a36Sopenharmony_ci		err = do_lq(ea, &regs->gpr[reg]);
74862306a36Sopenharmony_ci	} else {
74962306a36Sopenharmony_ci		err = read_mem(&regs->gpr[reg + IS_LE], ea, 8, regs);
75062306a36Sopenharmony_ci		if (!err)
75162306a36Sopenharmony_ci			err = read_mem(&regs->gpr[reg + IS_BE], ea + 8, 8, regs);
75262306a36Sopenharmony_ci	}
75362306a36Sopenharmony_ci	if (!err && unlikely(cross_endian))
75462306a36Sopenharmony_ci		do_byte_reverse(&regs->gpr[reg], 16);
75562306a36Sopenharmony_ci	return err;
75662306a36Sopenharmony_ci}
75762306a36Sopenharmony_ci
75862306a36Sopenharmony_cistatic nokprobe_inline int emulate_stq(struct pt_regs *regs, unsigned long ea,
75962306a36Sopenharmony_ci				       int reg, bool cross_endian)
76062306a36Sopenharmony_ci{
76162306a36Sopenharmony_ci	int err;
76262306a36Sopenharmony_ci	unsigned long vals[2];
76362306a36Sopenharmony_ci
76462306a36Sopenharmony_ci	if (!address_ok(regs, ea, 16))
76562306a36Sopenharmony_ci		return -EFAULT;
76662306a36Sopenharmony_ci	vals[0] = regs->gpr[reg];
76762306a36Sopenharmony_ci	vals[1] = regs->gpr[reg + 1];
76862306a36Sopenharmony_ci	if (unlikely(cross_endian))
76962306a36Sopenharmony_ci		do_byte_reverse(vals, 16);
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci	/* if aligned, should be atomic */
77262306a36Sopenharmony_ci	if ((ea & 0xf) == 0)
77362306a36Sopenharmony_ci		return do_stq(ea, vals[0], vals[1]);
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_ci	err = write_mem(vals[IS_LE], ea, 8, regs);
77662306a36Sopenharmony_ci	if (!err)
77762306a36Sopenharmony_ci		err = write_mem(vals[IS_BE], ea + 8, 8, regs);
77862306a36Sopenharmony_ci	return err;
77962306a36Sopenharmony_ci}
78062306a36Sopenharmony_ci#endif /* __powerpc64 */
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci#ifdef CONFIG_VSX
78362306a36Sopenharmony_civoid emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg,
78462306a36Sopenharmony_ci		      const void *mem, bool rev)
78562306a36Sopenharmony_ci{
78662306a36Sopenharmony_ci	int size, read_size;
78762306a36Sopenharmony_ci	int i, j;
78862306a36Sopenharmony_ci	const unsigned int *wp;
78962306a36Sopenharmony_ci	const unsigned short *hp;
79062306a36Sopenharmony_ci	const unsigned char *bp;
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci	size = GETSIZE(op->type);
79362306a36Sopenharmony_ci	reg->d[0] = reg->d[1] = 0;
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci	switch (op->element_size) {
79662306a36Sopenharmony_ci	case 32:
79762306a36Sopenharmony_ci		/* [p]lxvp[x] */
79862306a36Sopenharmony_ci	case 16:
79962306a36Sopenharmony_ci		/* whole vector; lxv[x] or lxvl[l] */
80062306a36Sopenharmony_ci		if (size == 0)
80162306a36Sopenharmony_ci			break;
80262306a36Sopenharmony_ci		memcpy(reg, mem, size);
80362306a36Sopenharmony_ci		if (IS_LE && (op->vsx_flags & VSX_LDLEFT))
80462306a36Sopenharmony_ci			rev = !rev;
80562306a36Sopenharmony_ci		if (rev)
80662306a36Sopenharmony_ci			do_byte_reverse(reg, size);
80762306a36Sopenharmony_ci		break;
80862306a36Sopenharmony_ci	case 8:
80962306a36Sopenharmony_ci		/* scalar loads, lxvd2x, lxvdsx */
81062306a36Sopenharmony_ci		read_size = (size >= 8) ? 8 : size;
81162306a36Sopenharmony_ci		i = IS_LE ? 8 : 8 - read_size;
81262306a36Sopenharmony_ci		memcpy(&reg->b[i], mem, read_size);
81362306a36Sopenharmony_ci		if (rev)
81462306a36Sopenharmony_ci			do_byte_reverse(&reg->b[i], 8);
81562306a36Sopenharmony_ci		if (size < 8) {
81662306a36Sopenharmony_ci			if (op->type & SIGNEXT) {
81762306a36Sopenharmony_ci				/* size == 4 is the only case here */
81862306a36Sopenharmony_ci				reg->d[IS_LE] = (signed int) reg->d[IS_LE];
81962306a36Sopenharmony_ci			} else if (op->vsx_flags & VSX_FPCONV) {
82062306a36Sopenharmony_ci				preempt_disable();
82162306a36Sopenharmony_ci				conv_sp_to_dp(&reg->fp[1 + IS_LE],
82262306a36Sopenharmony_ci					      &reg->dp[IS_LE]);
82362306a36Sopenharmony_ci				preempt_enable();
82462306a36Sopenharmony_ci			}
82562306a36Sopenharmony_ci		} else {
82662306a36Sopenharmony_ci			if (size == 16) {
82762306a36Sopenharmony_ci				unsigned long v = *(unsigned long *)(mem + 8);
82862306a36Sopenharmony_ci				reg->d[IS_BE] = !rev ? v : byterev_8(v);
82962306a36Sopenharmony_ci			} else if (op->vsx_flags & VSX_SPLAT)
83062306a36Sopenharmony_ci				reg->d[IS_BE] = reg->d[IS_LE];
83162306a36Sopenharmony_ci		}
83262306a36Sopenharmony_ci		break;
83362306a36Sopenharmony_ci	case 4:
83462306a36Sopenharmony_ci		/* lxvw4x, lxvwsx */
83562306a36Sopenharmony_ci		wp = mem;
83662306a36Sopenharmony_ci		for (j = 0; j < size / 4; ++j) {
83762306a36Sopenharmony_ci			i = IS_LE ? 3 - j : j;
83862306a36Sopenharmony_ci			reg->w[i] = !rev ? *wp++ : byterev_4(*wp++);
83962306a36Sopenharmony_ci		}
84062306a36Sopenharmony_ci		if (op->vsx_flags & VSX_SPLAT) {
84162306a36Sopenharmony_ci			u32 val = reg->w[IS_LE ? 3 : 0];
84262306a36Sopenharmony_ci			for (; j < 4; ++j) {
84362306a36Sopenharmony_ci				i = IS_LE ? 3 - j : j;
84462306a36Sopenharmony_ci				reg->w[i] = val;
84562306a36Sopenharmony_ci			}
84662306a36Sopenharmony_ci		}
84762306a36Sopenharmony_ci		break;
84862306a36Sopenharmony_ci	case 2:
84962306a36Sopenharmony_ci		/* lxvh8x */
85062306a36Sopenharmony_ci		hp = mem;
85162306a36Sopenharmony_ci		for (j = 0; j < size / 2; ++j) {
85262306a36Sopenharmony_ci			i = IS_LE ? 7 - j : j;
85362306a36Sopenharmony_ci			reg->h[i] = !rev ? *hp++ : byterev_2(*hp++);
85462306a36Sopenharmony_ci		}
85562306a36Sopenharmony_ci		break;
85662306a36Sopenharmony_ci	case 1:
85762306a36Sopenharmony_ci		/* lxvb16x */
85862306a36Sopenharmony_ci		bp = mem;
85962306a36Sopenharmony_ci		for (j = 0; j < size; ++j) {
86062306a36Sopenharmony_ci			i = IS_LE ? 15 - j : j;
86162306a36Sopenharmony_ci			reg->b[i] = *bp++;
86262306a36Sopenharmony_ci		}
86362306a36Sopenharmony_ci		break;
86462306a36Sopenharmony_ci	}
86562306a36Sopenharmony_ci}
86662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(emulate_vsx_load);
86762306a36Sopenharmony_ciNOKPROBE_SYMBOL(emulate_vsx_load);
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_civoid emulate_vsx_store(struct instruction_op *op, const union vsx_reg *reg,
87062306a36Sopenharmony_ci		       void *mem, bool rev)
87162306a36Sopenharmony_ci{
87262306a36Sopenharmony_ci	int size, write_size;
87362306a36Sopenharmony_ci	int i, j;
87462306a36Sopenharmony_ci	union vsx_reg buf;
87562306a36Sopenharmony_ci	unsigned int *wp;
87662306a36Sopenharmony_ci	unsigned short *hp;
87762306a36Sopenharmony_ci	unsigned char *bp;
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci	size = GETSIZE(op->type);
88062306a36Sopenharmony_ci
88162306a36Sopenharmony_ci	switch (op->element_size) {
88262306a36Sopenharmony_ci	case 32:
88362306a36Sopenharmony_ci		/* [p]stxvp[x] */
88462306a36Sopenharmony_ci		if (size == 0)
88562306a36Sopenharmony_ci			break;
88662306a36Sopenharmony_ci		if (rev) {
88762306a36Sopenharmony_ci			/* reverse 32 bytes */
88862306a36Sopenharmony_ci			union vsx_reg buf32[2];
88962306a36Sopenharmony_ci			buf32[0].d[0] = byterev_8(reg[1].d[1]);
89062306a36Sopenharmony_ci			buf32[0].d[1] = byterev_8(reg[1].d[0]);
89162306a36Sopenharmony_ci			buf32[1].d[0] = byterev_8(reg[0].d[1]);
89262306a36Sopenharmony_ci			buf32[1].d[1] = byterev_8(reg[0].d[0]);
89362306a36Sopenharmony_ci			memcpy(mem, buf32, size);
89462306a36Sopenharmony_ci		} else {
89562306a36Sopenharmony_ci			memcpy(mem, reg, size);
89662306a36Sopenharmony_ci		}
89762306a36Sopenharmony_ci		break;
89862306a36Sopenharmony_ci	case 16:
89962306a36Sopenharmony_ci		/* stxv, stxvx, stxvl, stxvll */
90062306a36Sopenharmony_ci		if (size == 0)
90162306a36Sopenharmony_ci			break;
90262306a36Sopenharmony_ci		if (IS_LE && (op->vsx_flags & VSX_LDLEFT))
90362306a36Sopenharmony_ci			rev = !rev;
90462306a36Sopenharmony_ci		if (rev) {
90562306a36Sopenharmony_ci			/* reverse 16 bytes */
90662306a36Sopenharmony_ci			buf.d[0] = byterev_8(reg->d[1]);
90762306a36Sopenharmony_ci			buf.d[1] = byterev_8(reg->d[0]);
90862306a36Sopenharmony_ci			reg = &buf;
90962306a36Sopenharmony_ci		}
91062306a36Sopenharmony_ci		memcpy(mem, reg, size);
91162306a36Sopenharmony_ci		break;
91262306a36Sopenharmony_ci	case 8:
91362306a36Sopenharmony_ci		/* scalar stores, stxvd2x */
91462306a36Sopenharmony_ci		write_size = (size >= 8) ? 8 : size;
91562306a36Sopenharmony_ci		i = IS_LE ? 8 : 8 - write_size;
91662306a36Sopenharmony_ci		if (size < 8 && op->vsx_flags & VSX_FPCONV) {
91762306a36Sopenharmony_ci			buf.d[0] = buf.d[1] = 0;
91862306a36Sopenharmony_ci			preempt_disable();
91962306a36Sopenharmony_ci			conv_dp_to_sp(&reg->dp[IS_LE], &buf.fp[1 + IS_LE]);
92062306a36Sopenharmony_ci			preempt_enable();
92162306a36Sopenharmony_ci			reg = &buf;
92262306a36Sopenharmony_ci		}
92362306a36Sopenharmony_ci		memcpy(mem, &reg->b[i], write_size);
92462306a36Sopenharmony_ci		if (size == 16)
92562306a36Sopenharmony_ci			memcpy(mem + 8, &reg->d[IS_BE], 8);
92662306a36Sopenharmony_ci		if (unlikely(rev)) {
92762306a36Sopenharmony_ci			do_byte_reverse(mem, write_size);
92862306a36Sopenharmony_ci			if (size == 16)
92962306a36Sopenharmony_ci				do_byte_reverse(mem + 8, 8);
93062306a36Sopenharmony_ci		}
93162306a36Sopenharmony_ci		break;
93262306a36Sopenharmony_ci	case 4:
93362306a36Sopenharmony_ci		/* stxvw4x */
93462306a36Sopenharmony_ci		wp = mem;
93562306a36Sopenharmony_ci		for (j = 0; j < size / 4; ++j) {
93662306a36Sopenharmony_ci			i = IS_LE ? 3 - j : j;
93762306a36Sopenharmony_ci			*wp++ = !rev ? reg->w[i] : byterev_4(reg->w[i]);
93862306a36Sopenharmony_ci		}
93962306a36Sopenharmony_ci		break;
94062306a36Sopenharmony_ci	case 2:
94162306a36Sopenharmony_ci		/* stxvh8x */
94262306a36Sopenharmony_ci		hp = mem;
94362306a36Sopenharmony_ci		for (j = 0; j < size / 2; ++j) {
94462306a36Sopenharmony_ci			i = IS_LE ? 7 - j : j;
94562306a36Sopenharmony_ci			*hp++ = !rev ? reg->h[i] : byterev_2(reg->h[i]);
94662306a36Sopenharmony_ci		}
94762306a36Sopenharmony_ci		break;
94862306a36Sopenharmony_ci	case 1:
94962306a36Sopenharmony_ci		/* stvxb16x */
95062306a36Sopenharmony_ci		bp = mem;
95162306a36Sopenharmony_ci		for (j = 0; j < size; ++j) {
95262306a36Sopenharmony_ci			i = IS_LE ? 15 - j : j;
95362306a36Sopenharmony_ci			*bp++ = reg->b[i];
95462306a36Sopenharmony_ci		}
95562306a36Sopenharmony_ci		break;
95662306a36Sopenharmony_ci	}
95762306a36Sopenharmony_ci}
95862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(emulate_vsx_store);
95962306a36Sopenharmony_ciNOKPROBE_SYMBOL(emulate_vsx_store);
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_cistatic nokprobe_inline int do_vsx_load(struct instruction_op *op,
96262306a36Sopenharmony_ci				       unsigned long ea, struct pt_regs *regs,
96362306a36Sopenharmony_ci				       bool cross_endian)
96462306a36Sopenharmony_ci{
96562306a36Sopenharmony_ci	int reg = op->reg;
96662306a36Sopenharmony_ci	int i, j, nr_vsx_regs;
96762306a36Sopenharmony_ci	u8 mem[32];
96862306a36Sopenharmony_ci	union vsx_reg buf[2];
96962306a36Sopenharmony_ci	int size = GETSIZE(op->type);
97062306a36Sopenharmony_ci
97162306a36Sopenharmony_ci	if (!address_ok(regs, ea, size) || copy_mem_in(mem, ea, size, regs))
97262306a36Sopenharmony_ci		return -EFAULT;
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_ci	nr_vsx_regs = max(1ul, size / sizeof(__vector128));
97562306a36Sopenharmony_ci	emulate_vsx_load(op, buf, mem, cross_endian);
97662306a36Sopenharmony_ci	preempt_disable();
97762306a36Sopenharmony_ci	if (reg < 32) {
97862306a36Sopenharmony_ci		/* FP regs + extensions */
97962306a36Sopenharmony_ci		if (regs->msr & MSR_FP) {
98062306a36Sopenharmony_ci			for (i = 0; i < nr_vsx_regs; i++) {
98162306a36Sopenharmony_ci				j = IS_LE ? nr_vsx_regs - i - 1 : i;
98262306a36Sopenharmony_ci				load_vsrn(reg + i, &buf[j].v);
98362306a36Sopenharmony_ci			}
98462306a36Sopenharmony_ci		} else {
98562306a36Sopenharmony_ci			for (i = 0; i < nr_vsx_regs; i++) {
98662306a36Sopenharmony_ci				j = IS_LE ? nr_vsx_regs - i - 1 : i;
98762306a36Sopenharmony_ci				current->thread.fp_state.fpr[reg + i][0] = buf[j].d[0];
98862306a36Sopenharmony_ci				current->thread.fp_state.fpr[reg + i][1] = buf[j].d[1];
98962306a36Sopenharmony_ci			}
99062306a36Sopenharmony_ci		}
99162306a36Sopenharmony_ci	} else {
99262306a36Sopenharmony_ci		if (regs->msr & MSR_VEC) {
99362306a36Sopenharmony_ci			for (i = 0; i < nr_vsx_regs; i++) {
99462306a36Sopenharmony_ci				j = IS_LE ? nr_vsx_regs - i - 1 : i;
99562306a36Sopenharmony_ci				load_vsrn(reg + i, &buf[j].v);
99662306a36Sopenharmony_ci			}
99762306a36Sopenharmony_ci		} else {
99862306a36Sopenharmony_ci			for (i = 0; i < nr_vsx_regs; i++) {
99962306a36Sopenharmony_ci				j = IS_LE ? nr_vsx_regs - i - 1 : i;
100062306a36Sopenharmony_ci				current->thread.vr_state.vr[reg - 32 + i] = buf[j].v;
100162306a36Sopenharmony_ci			}
100262306a36Sopenharmony_ci		}
100362306a36Sopenharmony_ci	}
100462306a36Sopenharmony_ci	preempt_enable();
100562306a36Sopenharmony_ci	return 0;
100662306a36Sopenharmony_ci}
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_cistatic nokprobe_inline int do_vsx_store(struct instruction_op *op,
100962306a36Sopenharmony_ci					unsigned long ea, struct pt_regs *regs,
101062306a36Sopenharmony_ci					bool cross_endian)
101162306a36Sopenharmony_ci{
101262306a36Sopenharmony_ci	int reg = op->reg;
101362306a36Sopenharmony_ci	int i, j, nr_vsx_regs;
101462306a36Sopenharmony_ci	u8 mem[32];
101562306a36Sopenharmony_ci	union vsx_reg buf[2];
101662306a36Sopenharmony_ci	int size = GETSIZE(op->type);
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	if (!address_ok(regs, ea, size))
101962306a36Sopenharmony_ci		return -EFAULT;
102062306a36Sopenharmony_ci
102162306a36Sopenharmony_ci	nr_vsx_regs = max(1ul, size / sizeof(__vector128));
102262306a36Sopenharmony_ci	preempt_disable();
102362306a36Sopenharmony_ci	if (reg < 32) {
102462306a36Sopenharmony_ci		/* FP regs + extensions */
102562306a36Sopenharmony_ci		if (regs->msr & MSR_FP) {
102662306a36Sopenharmony_ci			for (i = 0; i < nr_vsx_regs; i++) {
102762306a36Sopenharmony_ci				j = IS_LE ? nr_vsx_regs - i - 1 : i;
102862306a36Sopenharmony_ci				store_vsrn(reg + i, &buf[j].v);
102962306a36Sopenharmony_ci			}
103062306a36Sopenharmony_ci		} else {
103162306a36Sopenharmony_ci			for (i = 0; i < nr_vsx_regs; i++) {
103262306a36Sopenharmony_ci				j = IS_LE ? nr_vsx_regs - i - 1 : i;
103362306a36Sopenharmony_ci				buf[j].d[0] = current->thread.fp_state.fpr[reg + i][0];
103462306a36Sopenharmony_ci				buf[j].d[1] = current->thread.fp_state.fpr[reg + i][1];
103562306a36Sopenharmony_ci			}
103662306a36Sopenharmony_ci		}
103762306a36Sopenharmony_ci	} else {
103862306a36Sopenharmony_ci		if (regs->msr & MSR_VEC) {
103962306a36Sopenharmony_ci			for (i = 0; i < nr_vsx_regs; i++) {
104062306a36Sopenharmony_ci				j = IS_LE ? nr_vsx_regs - i - 1 : i;
104162306a36Sopenharmony_ci				store_vsrn(reg + i, &buf[j].v);
104262306a36Sopenharmony_ci			}
104362306a36Sopenharmony_ci		} else {
104462306a36Sopenharmony_ci			for (i = 0; i < nr_vsx_regs; i++) {
104562306a36Sopenharmony_ci				j = IS_LE ? nr_vsx_regs - i - 1 : i;
104662306a36Sopenharmony_ci				buf[j].v = current->thread.vr_state.vr[reg - 32 + i];
104762306a36Sopenharmony_ci			}
104862306a36Sopenharmony_ci		}
104962306a36Sopenharmony_ci	}
105062306a36Sopenharmony_ci	preempt_enable();
105162306a36Sopenharmony_ci	emulate_vsx_store(op, buf, mem, cross_endian);
105262306a36Sopenharmony_ci	return  copy_mem_out(mem, ea, size, regs);
105362306a36Sopenharmony_ci}
105462306a36Sopenharmony_ci#endif /* CONFIG_VSX */
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_cistatic __always_inline int __emulate_dcbz(unsigned long ea)
105762306a36Sopenharmony_ci{
105862306a36Sopenharmony_ci	unsigned long i;
105962306a36Sopenharmony_ci	unsigned long size = l1_dcache_bytes();
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_ci	for (i = 0; i < size; i += sizeof(long))
106262306a36Sopenharmony_ci		unsafe_put_user(0, (unsigned long __user *)(ea + i), Efault);
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci	return 0;
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ciEfault:
106762306a36Sopenharmony_ci	return -EFAULT;
106862306a36Sopenharmony_ci}
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ciint emulate_dcbz(unsigned long ea, struct pt_regs *regs)
107162306a36Sopenharmony_ci{
107262306a36Sopenharmony_ci	int err;
107362306a36Sopenharmony_ci	unsigned long size = l1_dcache_bytes();
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci	ea = truncate_if_32bit(regs->msr, ea);
107662306a36Sopenharmony_ci	ea &= ~(size - 1);
107762306a36Sopenharmony_ci	if (!address_ok(regs, ea, size))
107862306a36Sopenharmony_ci		return -EFAULT;
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	if (is_kernel_addr(ea)) {
108162306a36Sopenharmony_ci		err = __emulate_dcbz(ea);
108262306a36Sopenharmony_ci	} else if (user_write_access_begin((void __user *)ea, size)) {
108362306a36Sopenharmony_ci		err = __emulate_dcbz(ea);
108462306a36Sopenharmony_ci		user_write_access_end();
108562306a36Sopenharmony_ci	} else {
108662306a36Sopenharmony_ci		err = -EFAULT;
108762306a36Sopenharmony_ci	}
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_ci	if (err)
109062306a36Sopenharmony_ci		regs->dar = ea;
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci	return err;
109462306a36Sopenharmony_ci}
109562306a36Sopenharmony_ciNOKPROBE_SYMBOL(emulate_dcbz);
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_ci#define __put_user_asmx(x, addr, err, op, cr)		\
109862306a36Sopenharmony_ci	__asm__ __volatile__(				\
109962306a36Sopenharmony_ci		".machine push\n"			\
110062306a36Sopenharmony_ci		".machine power8\n"			\
110162306a36Sopenharmony_ci		"1:	" op " %2,0,%3\n"		\
110262306a36Sopenharmony_ci		".machine pop\n"			\
110362306a36Sopenharmony_ci		"	mfcr	%1\n"			\
110462306a36Sopenharmony_ci		"2:\n"					\
110562306a36Sopenharmony_ci		".section .fixup,\"ax\"\n"		\
110662306a36Sopenharmony_ci		"3:	li	%0,%4\n"		\
110762306a36Sopenharmony_ci		"	b	2b\n"			\
110862306a36Sopenharmony_ci		".previous\n"				\
110962306a36Sopenharmony_ci		EX_TABLE(1b, 3b)			\
111062306a36Sopenharmony_ci		: "=r" (err), "=r" (cr)			\
111162306a36Sopenharmony_ci		: "r" (x), "r" (addr), "i" (-EFAULT), "0" (err))
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci#define __get_user_asmx(x, addr, err, op)		\
111462306a36Sopenharmony_ci	__asm__ __volatile__(				\
111562306a36Sopenharmony_ci		".machine push\n"			\
111662306a36Sopenharmony_ci		".machine power8\n"			\
111762306a36Sopenharmony_ci		"1:	"op" %1,0,%2\n"			\
111862306a36Sopenharmony_ci		".machine pop\n"			\
111962306a36Sopenharmony_ci		"2:\n"					\
112062306a36Sopenharmony_ci		".section .fixup,\"ax\"\n"		\
112162306a36Sopenharmony_ci		"3:	li	%0,%3\n"		\
112262306a36Sopenharmony_ci		"	b	2b\n"			\
112362306a36Sopenharmony_ci		".previous\n"				\
112462306a36Sopenharmony_ci		EX_TABLE(1b, 3b)			\
112562306a36Sopenharmony_ci		: "=r" (err), "=r" (x)			\
112662306a36Sopenharmony_ci		: "r" (addr), "i" (-EFAULT), "0" (err))
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci#define __cacheop_user_asmx(addr, err, op)		\
112962306a36Sopenharmony_ci	__asm__ __volatile__(				\
113062306a36Sopenharmony_ci		"1:	"op" 0,%1\n"			\
113162306a36Sopenharmony_ci		"2:\n"					\
113262306a36Sopenharmony_ci		".section .fixup,\"ax\"\n"		\
113362306a36Sopenharmony_ci		"3:	li	%0,%3\n"		\
113462306a36Sopenharmony_ci		"	b	2b\n"			\
113562306a36Sopenharmony_ci		".previous\n"				\
113662306a36Sopenharmony_ci		EX_TABLE(1b, 3b)			\
113762306a36Sopenharmony_ci		: "=r" (err)				\
113862306a36Sopenharmony_ci		: "r" (addr), "i" (-EFAULT), "0" (err))
113962306a36Sopenharmony_ci
114062306a36Sopenharmony_cistatic nokprobe_inline void set_cr0(const struct pt_regs *regs,
114162306a36Sopenharmony_ci				    struct instruction_op *op)
114262306a36Sopenharmony_ci{
114362306a36Sopenharmony_ci	long val = op->val;
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_ci	op->type |= SETCC;
114662306a36Sopenharmony_ci	op->ccval = (regs->ccr & 0x0fffffff) | ((regs->xer >> 3) & 0x10000000);
114762306a36Sopenharmony_ci	if (!(regs->msr & MSR_64BIT))
114862306a36Sopenharmony_ci		val = (int) val;
114962306a36Sopenharmony_ci	if (val < 0)
115062306a36Sopenharmony_ci		op->ccval |= 0x80000000;
115162306a36Sopenharmony_ci	else if (val > 0)
115262306a36Sopenharmony_ci		op->ccval |= 0x40000000;
115362306a36Sopenharmony_ci	else
115462306a36Sopenharmony_ci		op->ccval |= 0x20000000;
115562306a36Sopenharmony_ci}
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_cistatic nokprobe_inline void set_ca32(struct instruction_op *op, bool val)
115862306a36Sopenharmony_ci{
115962306a36Sopenharmony_ci	if (cpu_has_feature(CPU_FTR_ARCH_300)) {
116062306a36Sopenharmony_ci		if (val)
116162306a36Sopenharmony_ci			op->xerval |= XER_CA32;
116262306a36Sopenharmony_ci		else
116362306a36Sopenharmony_ci			op->xerval &= ~XER_CA32;
116462306a36Sopenharmony_ci	}
116562306a36Sopenharmony_ci}
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_cistatic nokprobe_inline void add_with_carry(const struct pt_regs *regs,
116862306a36Sopenharmony_ci				     struct instruction_op *op, int rd,
116962306a36Sopenharmony_ci				     unsigned long val1, unsigned long val2,
117062306a36Sopenharmony_ci				     unsigned long carry_in)
117162306a36Sopenharmony_ci{
117262306a36Sopenharmony_ci	unsigned long val = val1 + val2;
117362306a36Sopenharmony_ci
117462306a36Sopenharmony_ci	if (carry_in)
117562306a36Sopenharmony_ci		++val;
117662306a36Sopenharmony_ci	op->type = COMPUTE | SETREG | SETXER;
117762306a36Sopenharmony_ci	op->reg = rd;
117862306a36Sopenharmony_ci	op->val = val;
117962306a36Sopenharmony_ci	val = truncate_if_32bit(regs->msr, val);
118062306a36Sopenharmony_ci	val1 = truncate_if_32bit(regs->msr, val1);
118162306a36Sopenharmony_ci	op->xerval = regs->xer;
118262306a36Sopenharmony_ci	if (val < val1 || (carry_in && val == val1))
118362306a36Sopenharmony_ci		op->xerval |= XER_CA;
118462306a36Sopenharmony_ci	else
118562306a36Sopenharmony_ci		op->xerval &= ~XER_CA;
118662306a36Sopenharmony_ci
118762306a36Sopenharmony_ci	set_ca32(op, (unsigned int)val < (unsigned int)val1 ||
118862306a36Sopenharmony_ci			(carry_in && (unsigned int)val == (unsigned int)val1));
118962306a36Sopenharmony_ci}
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_cistatic nokprobe_inline void do_cmp_signed(const struct pt_regs *regs,
119262306a36Sopenharmony_ci					  struct instruction_op *op,
119362306a36Sopenharmony_ci					  long v1, long v2, int crfld)
119462306a36Sopenharmony_ci{
119562306a36Sopenharmony_ci	unsigned int crval, shift;
119662306a36Sopenharmony_ci
119762306a36Sopenharmony_ci	op->type = COMPUTE | SETCC;
119862306a36Sopenharmony_ci	crval = (regs->xer >> 31) & 1;		/* get SO bit */
119962306a36Sopenharmony_ci	if (v1 < v2)
120062306a36Sopenharmony_ci		crval |= 8;
120162306a36Sopenharmony_ci	else if (v1 > v2)
120262306a36Sopenharmony_ci		crval |= 4;
120362306a36Sopenharmony_ci	else
120462306a36Sopenharmony_ci		crval |= 2;
120562306a36Sopenharmony_ci	shift = (7 - crfld) * 4;
120662306a36Sopenharmony_ci	op->ccval = (regs->ccr & ~(0xf << shift)) | (crval << shift);
120762306a36Sopenharmony_ci}
120862306a36Sopenharmony_ci
120962306a36Sopenharmony_cistatic nokprobe_inline void do_cmp_unsigned(const struct pt_regs *regs,
121062306a36Sopenharmony_ci					    struct instruction_op *op,
121162306a36Sopenharmony_ci					    unsigned long v1,
121262306a36Sopenharmony_ci					    unsigned long v2, int crfld)
121362306a36Sopenharmony_ci{
121462306a36Sopenharmony_ci	unsigned int crval, shift;
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_ci	op->type = COMPUTE | SETCC;
121762306a36Sopenharmony_ci	crval = (regs->xer >> 31) & 1;		/* get SO bit */
121862306a36Sopenharmony_ci	if (v1 < v2)
121962306a36Sopenharmony_ci		crval |= 8;
122062306a36Sopenharmony_ci	else if (v1 > v2)
122162306a36Sopenharmony_ci		crval |= 4;
122262306a36Sopenharmony_ci	else
122362306a36Sopenharmony_ci		crval |= 2;
122462306a36Sopenharmony_ci	shift = (7 - crfld) * 4;
122562306a36Sopenharmony_ci	op->ccval = (regs->ccr & ~(0xf << shift)) | (crval << shift);
122662306a36Sopenharmony_ci}
122762306a36Sopenharmony_ci
122862306a36Sopenharmony_cistatic nokprobe_inline void do_cmpb(const struct pt_regs *regs,
122962306a36Sopenharmony_ci				    struct instruction_op *op,
123062306a36Sopenharmony_ci				    unsigned long v1, unsigned long v2)
123162306a36Sopenharmony_ci{
123262306a36Sopenharmony_ci	unsigned long long out_val, mask;
123362306a36Sopenharmony_ci	int i;
123462306a36Sopenharmony_ci
123562306a36Sopenharmony_ci	out_val = 0;
123662306a36Sopenharmony_ci	for (i = 0; i < 8; i++) {
123762306a36Sopenharmony_ci		mask = 0xffUL << (i * 8);
123862306a36Sopenharmony_ci		if ((v1 & mask) == (v2 & mask))
123962306a36Sopenharmony_ci			out_val |= mask;
124062306a36Sopenharmony_ci	}
124162306a36Sopenharmony_ci	op->val = out_val;
124262306a36Sopenharmony_ci}
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_ci/*
124562306a36Sopenharmony_ci * The size parameter is used to adjust the equivalent popcnt instruction.
124662306a36Sopenharmony_ci * popcntb = 8, popcntw = 32, popcntd = 64
124762306a36Sopenharmony_ci */
124862306a36Sopenharmony_cistatic nokprobe_inline void do_popcnt(const struct pt_regs *regs,
124962306a36Sopenharmony_ci				      struct instruction_op *op,
125062306a36Sopenharmony_ci				      unsigned long v1, int size)
125162306a36Sopenharmony_ci{
125262306a36Sopenharmony_ci	unsigned long long out = v1;
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_ci	out -= (out >> 1) & 0x5555555555555555ULL;
125562306a36Sopenharmony_ci	out = (0x3333333333333333ULL & out) +
125662306a36Sopenharmony_ci	      (0x3333333333333333ULL & (out >> 2));
125762306a36Sopenharmony_ci	out = (out + (out >> 4)) & 0x0f0f0f0f0f0f0f0fULL;
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_ci	if (size == 8) {	/* popcntb */
126062306a36Sopenharmony_ci		op->val = out;
126162306a36Sopenharmony_ci		return;
126262306a36Sopenharmony_ci	}
126362306a36Sopenharmony_ci	out += out >> 8;
126462306a36Sopenharmony_ci	out += out >> 16;
126562306a36Sopenharmony_ci	if (size == 32) {	/* popcntw */
126662306a36Sopenharmony_ci		op->val = out & 0x0000003f0000003fULL;
126762306a36Sopenharmony_ci		return;
126862306a36Sopenharmony_ci	}
126962306a36Sopenharmony_ci
127062306a36Sopenharmony_ci	out = (out + (out >> 32)) & 0x7f;
127162306a36Sopenharmony_ci	op->val = out;	/* popcntd */
127262306a36Sopenharmony_ci}
127362306a36Sopenharmony_ci
127462306a36Sopenharmony_ci#ifdef CONFIG_PPC64
127562306a36Sopenharmony_cistatic nokprobe_inline void do_bpermd(const struct pt_regs *regs,
127662306a36Sopenharmony_ci				      struct instruction_op *op,
127762306a36Sopenharmony_ci				      unsigned long v1, unsigned long v2)
127862306a36Sopenharmony_ci{
127962306a36Sopenharmony_ci	unsigned char perm, idx;
128062306a36Sopenharmony_ci	unsigned int i;
128162306a36Sopenharmony_ci
128262306a36Sopenharmony_ci	perm = 0;
128362306a36Sopenharmony_ci	for (i = 0; i < 8; i++) {
128462306a36Sopenharmony_ci		idx = (v1 >> (i * 8)) & 0xff;
128562306a36Sopenharmony_ci		if (idx < 64)
128662306a36Sopenharmony_ci			if (v2 & PPC_BIT(idx))
128762306a36Sopenharmony_ci				perm |= 1 << i;
128862306a36Sopenharmony_ci	}
128962306a36Sopenharmony_ci	op->val = perm;
129062306a36Sopenharmony_ci}
129162306a36Sopenharmony_ci#endif /* CONFIG_PPC64 */
129262306a36Sopenharmony_ci/*
129362306a36Sopenharmony_ci * The size parameter adjusts the equivalent prty instruction.
129462306a36Sopenharmony_ci * prtyw = 32, prtyd = 64
129562306a36Sopenharmony_ci */
129662306a36Sopenharmony_cistatic nokprobe_inline void do_prty(const struct pt_regs *regs,
129762306a36Sopenharmony_ci				    struct instruction_op *op,
129862306a36Sopenharmony_ci				    unsigned long v, int size)
129962306a36Sopenharmony_ci{
130062306a36Sopenharmony_ci	unsigned long long res = v ^ (v >> 8);
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci	res ^= res >> 16;
130362306a36Sopenharmony_ci	if (size == 32) {		/* prtyw */
130462306a36Sopenharmony_ci		op->val = res & 0x0000000100000001ULL;
130562306a36Sopenharmony_ci		return;
130662306a36Sopenharmony_ci	}
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ci	res ^= res >> 32;
130962306a36Sopenharmony_ci	op->val = res & 1;	/*prtyd */
131062306a36Sopenharmony_ci}
131162306a36Sopenharmony_ci
131262306a36Sopenharmony_cistatic nokprobe_inline int trap_compare(long v1, long v2)
131362306a36Sopenharmony_ci{
131462306a36Sopenharmony_ci	int ret = 0;
131562306a36Sopenharmony_ci
131662306a36Sopenharmony_ci	if (v1 < v2)
131762306a36Sopenharmony_ci		ret |= 0x10;
131862306a36Sopenharmony_ci	else if (v1 > v2)
131962306a36Sopenharmony_ci		ret |= 0x08;
132062306a36Sopenharmony_ci	else
132162306a36Sopenharmony_ci		ret |= 0x04;
132262306a36Sopenharmony_ci	if ((unsigned long)v1 < (unsigned long)v2)
132362306a36Sopenharmony_ci		ret |= 0x02;
132462306a36Sopenharmony_ci	else if ((unsigned long)v1 > (unsigned long)v2)
132562306a36Sopenharmony_ci		ret |= 0x01;
132662306a36Sopenharmony_ci	return ret;
132762306a36Sopenharmony_ci}
132862306a36Sopenharmony_ci
132962306a36Sopenharmony_ci/*
133062306a36Sopenharmony_ci * Elements of 32-bit rotate and mask instructions.
133162306a36Sopenharmony_ci */
133262306a36Sopenharmony_ci#define MASK32(mb, me)	((0xffffffffUL >> (mb)) + \
133362306a36Sopenharmony_ci			 ((signed long)-0x80000000L >> (me)) + ((me) >= (mb)))
133462306a36Sopenharmony_ci#ifdef __powerpc64__
133562306a36Sopenharmony_ci#define MASK64_L(mb)	(~0UL >> (mb))
133662306a36Sopenharmony_ci#define MASK64_R(me)	((signed long)-0x8000000000000000L >> (me))
133762306a36Sopenharmony_ci#define MASK64(mb, me)	(MASK64_L(mb) + MASK64_R(me) + ((me) >= (mb)))
133862306a36Sopenharmony_ci#define DATA32(x)	(((x) & 0xffffffffUL) | (((x) & 0xffffffffUL) << 32))
133962306a36Sopenharmony_ci#else
134062306a36Sopenharmony_ci#define DATA32(x)	(x)
134162306a36Sopenharmony_ci#endif
134262306a36Sopenharmony_ci#define ROTATE(x, n)	((n) ? (((x) << (n)) | ((x) >> (8 * sizeof(long) - (n)))) : (x))
134362306a36Sopenharmony_ci
134462306a36Sopenharmony_ci/*
134562306a36Sopenharmony_ci * Decode an instruction, and return information about it in *op
134662306a36Sopenharmony_ci * without changing *regs.
134762306a36Sopenharmony_ci * Integer arithmetic and logical instructions, branches, and barrier
134862306a36Sopenharmony_ci * instructions can be emulated just using the information in *op.
134962306a36Sopenharmony_ci *
135062306a36Sopenharmony_ci * Return value is 1 if the instruction can be emulated just by
135162306a36Sopenharmony_ci * updating *regs with the information in *op, -1 if we need the
135262306a36Sopenharmony_ci * GPRs but *regs doesn't contain the full register set, or 0
135362306a36Sopenharmony_ci * otherwise.
135462306a36Sopenharmony_ci */
135562306a36Sopenharmony_ciint analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
135662306a36Sopenharmony_ci		  ppc_inst_t instr)
135762306a36Sopenharmony_ci{
135862306a36Sopenharmony_ci#ifdef CONFIG_PPC64
135962306a36Sopenharmony_ci	unsigned int suffixopcode, prefixtype, prefix_r;
136062306a36Sopenharmony_ci#endif
136162306a36Sopenharmony_ci	unsigned int opcode, ra, rb, rc, rd, spr, u;
136262306a36Sopenharmony_ci	unsigned long int imm;
136362306a36Sopenharmony_ci	unsigned long int val, val2;
136462306a36Sopenharmony_ci	unsigned int mb, me, sh;
136562306a36Sopenharmony_ci	unsigned int word, suffix;
136662306a36Sopenharmony_ci	long ival;
136762306a36Sopenharmony_ci
136862306a36Sopenharmony_ci	word = ppc_inst_val(instr);
136962306a36Sopenharmony_ci	suffix = ppc_inst_suffix(instr);
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_ci	op->type = COMPUTE;
137262306a36Sopenharmony_ci
137362306a36Sopenharmony_ci	opcode = ppc_inst_primary_opcode(instr);
137462306a36Sopenharmony_ci	switch (opcode) {
137562306a36Sopenharmony_ci	case 16:	/* bc */
137662306a36Sopenharmony_ci		op->type = BRANCH;
137762306a36Sopenharmony_ci		imm = (signed short)(word & 0xfffc);
137862306a36Sopenharmony_ci		if ((word & 2) == 0)
137962306a36Sopenharmony_ci			imm += regs->nip;
138062306a36Sopenharmony_ci		op->val = truncate_if_32bit(regs->msr, imm);
138162306a36Sopenharmony_ci		if (word & 1)
138262306a36Sopenharmony_ci			op->type |= SETLK;
138362306a36Sopenharmony_ci		if (branch_taken(word, regs, op))
138462306a36Sopenharmony_ci			op->type |= BRTAKEN;
138562306a36Sopenharmony_ci		return 1;
138662306a36Sopenharmony_ci	case 17:	/* sc */
138762306a36Sopenharmony_ci		if ((word & 0xfe2) == 2)
138862306a36Sopenharmony_ci			op->type = SYSCALL;
138962306a36Sopenharmony_ci		else if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) &&
139062306a36Sopenharmony_ci				(word & 0xfe3) == 1) {	/* scv */
139162306a36Sopenharmony_ci			op->type = SYSCALL_VECTORED_0;
139262306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
139362306a36Sopenharmony_ci				goto unknown_opcode;
139462306a36Sopenharmony_ci		} else
139562306a36Sopenharmony_ci			op->type = UNKNOWN;
139662306a36Sopenharmony_ci		return 0;
139762306a36Sopenharmony_ci	case 18:	/* b */
139862306a36Sopenharmony_ci		op->type = BRANCH | BRTAKEN;
139962306a36Sopenharmony_ci		imm = word & 0x03fffffc;
140062306a36Sopenharmony_ci		if (imm & 0x02000000)
140162306a36Sopenharmony_ci			imm -= 0x04000000;
140262306a36Sopenharmony_ci		if ((word & 2) == 0)
140362306a36Sopenharmony_ci			imm += regs->nip;
140462306a36Sopenharmony_ci		op->val = truncate_if_32bit(regs->msr, imm);
140562306a36Sopenharmony_ci		if (word & 1)
140662306a36Sopenharmony_ci			op->type |= SETLK;
140762306a36Sopenharmony_ci		return 1;
140862306a36Sopenharmony_ci	case 19:
140962306a36Sopenharmony_ci		switch ((word >> 1) & 0x3ff) {
141062306a36Sopenharmony_ci		case 0:		/* mcrf */
141162306a36Sopenharmony_ci			op->type = COMPUTE + SETCC;
141262306a36Sopenharmony_ci			rd = 7 - ((word >> 23) & 0x7);
141362306a36Sopenharmony_ci			ra = 7 - ((word >> 18) & 0x7);
141462306a36Sopenharmony_ci			rd *= 4;
141562306a36Sopenharmony_ci			ra *= 4;
141662306a36Sopenharmony_ci			val = (regs->ccr >> ra) & 0xf;
141762306a36Sopenharmony_ci			op->ccval = (regs->ccr & ~(0xfUL << rd)) | (val << rd);
141862306a36Sopenharmony_ci			return 1;
141962306a36Sopenharmony_ci
142062306a36Sopenharmony_ci		case 16:	/* bclr */
142162306a36Sopenharmony_ci		case 528:	/* bcctr */
142262306a36Sopenharmony_ci			op->type = BRANCH;
142362306a36Sopenharmony_ci			imm = (word & 0x400)? regs->ctr: regs->link;
142462306a36Sopenharmony_ci			op->val = truncate_if_32bit(regs->msr, imm);
142562306a36Sopenharmony_ci			if (word & 1)
142662306a36Sopenharmony_ci				op->type |= SETLK;
142762306a36Sopenharmony_ci			if (branch_taken(word, regs, op))
142862306a36Sopenharmony_ci				op->type |= BRTAKEN;
142962306a36Sopenharmony_ci			return 1;
143062306a36Sopenharmony_ci
143162306a36Sopenharmony_ci		case 18:	/* rfid, scary */
143262306a36Sopenharmony_ci			if (regs->msr & MSR_PR)
143362306a36Sopenharmony_ci				goto priv;
143462306a36Sopenharmony_ci			op->type = RFI;
143562306a36Sopenharmony_ci			return 0;
143662306a36Sopenharmony_ci
143762306a36Sopenharmony_ci		case 150:	/* isync */
143862306a36Sopenharmony_ci			op->type = BARRIER | BARRIER_ISYNC;
143962306a36Sopenharmony_ci			return 1;
144062306a36Sopenharmony_ci
144162306a36Sopenharmony_ci		case 33:	/* crnor */
144262306a36Sopenharmony_ci		case 129:	/* crandc */
144362306a36Sopenharmony_ci		case 193:	/* crxor */
144462306a36Sopenharmony_ci		case 225:	/* crnand */
144562306a36Sopenharmony_ci		case 257:	/* crand */
144662306a36Sopenharmony_ci		case 289:	/* creqv */
144762306a36Sopenharmony_ci		case 417:	/* crorc */
144862306a36Sopenharmony_ci		case 449:	/* cror */
144962306a36Sopenharmony_ci			op->type = COMPUTE + SETCC;
145062306a36Sopenharmony_ci			ra = (word >> 16) & 0x1f;
145162306a36Sopenharmony_ci			rb = (word >> 11) & 0x1f;
145262306a36Sopenharmony_ci			rd = (word >> 21) & 0x1f;
145362306a36Sopenharmony_ci			ra = (regs->ccr >> (31 - ra)) & 1;
145462306a36Sopenharmony_ci			rb = (regs->ccr >> (31 - rb)) & 1;
145562306a36Sopenharmony_ci			val = (word >> (6 + ra * 2 + rb)) & 1;
145662306a36Sopenharmony_ci			op->ccval = (regs->ccr & ~(1UL << (31 - rd))) |
145762306a36Sopenharmony_ci				(val << (31 - rd));
145862306a36Sopenharmony_ci			return 1;
145962306a36Sopenharmony_ci		}
146062306a36Sopenharmony_ci		break;
146162306a36Sopenharmony_ci	case 31:
146262306a36Sopenharmony_ci		switch ((word >> 1) & 0x3ff) {
146362306a36Sopenharmony_ci		case 598:	/* sync */
146462306a36Sopenharmony_ci			op->type = BARRIER + BARRIER_SYNC;
146562306a36Sopenharmony_ci#ifdef __powerpc64__
146662306a36Sopenharmony_ci			switch ((word >> 21) & 3) {
146762306a36Sopenharmony_ci			case 1:		/* lwsync */
146862306a36Sopenharmony_ci				op->type = BARRIER + BARRIER_LWSYNC;
146962306a36Sopenharmony_ci				break;
147062306a36Sopenharmony_ci			case 2:		/* ptesync */
147162306a36Sopenharmony_ci				op->type = BARRIER + BARRIER_PTESYNC;
147262306a36Sopenharmony_ci				break;
147362306a36Sopenharmony_ci			}
147462306a36Sopenharmony_ci#endif
147562306a36Sopenharmony_ci			return 1;
147662306a36Sopenharmony_ci
147762306a36Sopenharmony_ci		case 854:	/* eieio */
147862306a36Sopenharmony_ci			op->type = BARRIER + BARRIER_EIEIO;
147962306a36Sopenharmony_ci			return 1;
148062306a36Sopenharmony_ci		}
148162306a36Sopenharmony_ci		break;
148262306a36Sopenharmony_ci	}
148362306a36Sopenharmony_ci
148462306a36Sopenharmony_ci	rd = (word >> 21) & 0x1f;
148562306a36Sopenharmony_ci	ra = (word >> 16) & 0x1f;
148662306a36Sopenharmony_ci	rb = (word >> 11) & 0x1f;
148762306a36Sopenharmony_ci	rc = (word >> 6) & 0x1f;
148862306a36Sopenharmony_ci
148962306a36Sopenharmony_ci	switch (opcode) {
149062306a36Sopenharmony_ci#ifdef __powerpc64__
149162306a36Sopenharmony_ci	case 1:
149262306a36Sopenharmony_ci		if (!cpu_has_feature(CPU_FTR_ARCH_31))
149362306a36Sopenharmony_ci			goto unknown_opcode;
149462306a36Sopenharmony_ci
149562306a36Sopenharmony_ci		prefix_r = GET_PREFIX_R(word);
149662306a36Sopenharmony_ci		ra = GET_PREFIX_RA(suffix);
149762306a36Sopenharmony_ci		rd = (suffix >> 21) & 0x1f;
149862306a36Sopenharmony_ci		op->reg = rd;
149962306a36Sopenharmony_ci		op->val = regs->gpr[rd];
150062306a36Sopenharmony_ci		suffixopcode = get_op(suffix);
150162306a36Sopenharmony_ci		prefixtype = (word >> 24) & 0x3;
150262306a36Sopenharmony_ci		switch (prefixtype) {
150362306a36Sopenharmony_ci		case 2:
150462306a36Sopenharmony_ci			if (prefix_r && ra)
150562306a36Sopenharmony_ci				return 0;
150662306a36Sopenharmony_ci			switch (suffixopcode) {
150762306a36Sopenharmony_ci			case 14:	/* paddi */
150862306a36Sopenharmony_ci				op->type = COMPUTE | PREFIXED;
150962306a36Sopenharmony_ci				op->val = mlsd_8lsd_ea(word, suffix, regs);
151062306a36Sopenharmony_ci				goto compute_done;
151162306a36Sopenharmony_ci			}
151262306a36Sopenharmony_ci		}
151362306a36Sopenharmony_ci		break;
151462306a36Sopenharmony_ci	case 2:		/* tdi */
151562306a36Sopenharmony_ci		if (rd & trap_compare(regs->gpr[ra], (short) word))
151662306a36Sopenharmony_ci			goto trap;
151762306a36Sopenharmony_ci		return 1;
151862306a36Sopenharmony_ci#endif
151962306a36Sopenharmony_ci	case 3:		/* twi */
152062306a36Sopenharmony_ci		if (rd & trap_compare((int)regs->gpr[ra], (short) word))
152162306a36Sopenharmony_ci			goto trap;
152262306a36Sopenharmony_ci		return 1;
152362306a36Sopenharmony_ci
152462306a36Sopenharmony_ci#ifdef __powerpc64__
152562306a36Sopenharmony_ci	case 4:
152662306a36Sopenharmony_ci		/*
152762306a36Sopenharmony_ci		 * There are very many instructions with this primary opcode
152862306a36Sopenharmony_ci		 * introduced in the ISA as early as v2.03. However, the ones
152962306a36Sopenharmony_ci		 * we currently emulate were all introduced with ISA 3.0
153062306a36Sopenharmony_ci		 */
153162306a36Sopenharmony_ci		if (!cpu_has_feature(CPU_FTR_ARCH_300))
153262306a36Sopenharmony_ci			goto unknown_opcode;
153362306a36Sopenharmony_ci
153462306a36Sopenharmony_ci		switch (word & 0x3f) {
153562306a36Sopenharmony_ci		case 48:	/* maddhd */
153662306a36Sopenharmony_ci			asm volatile(PPC_MADDHD(%0, %1, %2, %3) :
153762306a36Sopenharmony_ci				     "=r" (op->val) : "r" (regs->gpr[ra]),
153862306a36Sopenharmony_ci				     "r" (regs->gpr[rb]), "r" (regs->gpr[rc]));
153962306a36Sopenharmony_ci			goto compute_done;
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_ci		case 49:	/* maddhdu */
154262306a36Sopenharmony_ci			asm volatile(PPC_MADDHDU(%0, %1, %2, %3) :
154362306a36Sopenharmony_ci				     "=r" (op->val) : "r" (regs->gpr[ra]),
154462306a36Sopenharmony_ci				     "r" (regs->gpr[rb]), "r" (regs->gpr[rc]));
154562306a36Sopenharmony_ci			goto compute_done;
154662306a36Sopenharmony_ci
154762306a36Sopenharmony_ci		case 51:	/* maddld */
154862306a36Sopenharmony_ci			asm volatile(PPC_MADDLD(%0, %1, %2, %3) :
154962306a36Sopenharmony_ci				     "=r" (op->val) : "r" (regs->gpr[ra]),
155062306a36Sopenharmony_ci				     "r" (regs->gpr[rb]), "r" (regs->gpr[rc]));
155162306a36Sopenharmony_ci			goto compute_done;
155262306a36Sopenharmony_ci		}
155362306a36Sopenharmony_ci
155462306a36Sopenharmony_ci		/*
155562306a36Sopenharmony_ci		 * There are other instructions from ISA 3.0 with the same
155662306a36Sopenharmony_ci		 * primary opcode which do not have emulation support yet.
155762306a36Sopenharmony_ci		 */
155862306a36Sopenharmony_ci		goto unknown_opcode;
155962306a36Sopenharmony_ci#endif
156062306a36Sopenharmony_ci
156162306a36Sopenharmony_ci	case 7:		/* mulli */
156262306a36Sopenharmony_ci		op->val = regs->gpr[ra] * (short) word;
156362306a36Sopenharmony_ci		goto compute_done;
156462306a36Sopenharmony_ci
156562306a36Sopenharmony_ci	case 8:		/* subfic */
156662306a36Sopenharmony_ci		imm = (short) word;
156762306a36Sopenharmony_ci		add_with_carry(regs, op, rd, ~regs->gpr[ra], imm, 1);
156862306a36Sopenharmony_ci		return 1;
156962306a36Sopenharmony_ci
157062306a36Sopenharmony_ci	case 10:	/* cmpli */
157162306a36Sopenharmony_ci		imm = (unsigned short) word;
157262306a36Sopenharmony_ci		val = regs->gpr[ra];
157362306a36Sopenharmony_ci#ifdef __powerpc64__
157462306a36Sopenharmony_ci		if ((rd & 1) == 0)
157562306a36Sopenharmony_ci			val = (unsigned int) val;
157662306a36Sopenharmony_ci#endif
157762306a36Sopenharmony_ci		do_cmp_unsigned(regs, op, val, imm, rd >> 2);
157862306a36Sopenharmony_ci		return 1;
157962306a36Sopenharmony_ci
158062306a36Sopenharmony_ci	case 11:	/* cmpi */
158162306a36Sopenharmony_ci		imm = (short) word;
158262306a36Sopenharmony_ci		val = regs->gpr[ra];
158362306a36Sopenharmony_ci#ifdef __powerpc64__
158462306a36Sopenharmony_ci		if ((rd & 1) == 0)
158562306a36Sopenharmony_ci			val = (int) val;
158662306a36Sopenharmony_ci#endif
158762306a36Sopenharmony_ci		do_cmp_signed(regs, op, val, imm, rd >> 2);
158862306a36Sopenharmony_ci		return 1;
158962306a36Sopenharmony_ci
159062306a36Sopenharmony_ci	case 12:	/* addic */
159162306a36Sopenharmony_ci		imm = (short) word;
159262306a36Sopenharmony_ci		add_with_carry(regs, op, rd, regs->gpr[ra], imm, 0);
159362306a36Sopenharmony_ci		return 1;
159462306a36Sopenharmony_ci
159562306a36Sopenharmony_ci	case 13:	/* addic. */
159662306a36Sopenharmony_ci		imm = (short) word;
159762306a36Sopenharmony_ci		add_with_carry(regs, op, rd, regs->gpr[ra], imm, 0);
159862306a36Sopenharmony_ci		set_cr0(regs, op);
159962306a36Sopenharmony_ci		return 1;
160062306a36Sopenharmony_ci
160162306a36Sopenharmony_ci	case 14:	/* addi */
160262306a36Sopenharmony_ci		imm = (short) word;
160362306a36Sopenharmony_ci		if (ra)
160462306a36Sopenharmony_ci			imm += regs->gpr[ra];
160562306a36Sopenharmony_ci		op->val = imm;
160662306a36Sopenharmony_ci		goto compute_done;
160762306a36Sopenharmony_ci
160862306a36Sopenharmony_ci	case 15:	/* addis */
160962306a36Sopenharmony_ci		imm = ((short) word) << 16;
161062306a36Sopenharmony_ci		if (ra)
161162306a36Sopenharmony_ci			imm += regs->gpr[ra];
161262306a36Sopenharmony_ci		op->val = imm;
161362306a36Sopenharmony_ci		goto compute_done;
161462306a36Sopenharmony_ci
161562306a36Sopenharmony_ci	case 19:
161662306a36Sopenharmony_ci		if (((word >> 1) & 0x1f) == 2) {
161762306a36Sopenharmony_ci			/* addpcis */
161862306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
161962306a36Sopenharmony_ci				goto unknown_opcode;
162062306a36Sopenharmony_ci			imm = (short) (word & 0xffc1);	/* d0 + d2 fields */
162162306a36Sopenharmony_ci			imm |= (word >> 15) & 0x3e;	/* d1 field */
162262306a36Sopenharmony_ci			op->val = regs->nip + (imm << 16) + 4;
162362306a36Sopenharmony_ci			goto compute_done;
162462306a36Sopenharmony_ci		}
162562306a36Sopenharmony_ci		op->type = UNKNOWN;
162662306a36Sopenharmony_ci		return 0;
162762306a36Sopenharmony_ci
162862306a36Sopenharmony_ci	case 20:	/* rlwimi */
162962306a36Sopenharmony_ci		mb = (word >> 6) & 0x1f;
163062306a36Sopenharmony_ci		me = (word >> 1) & 0x1f;
163162306a36Sopenharmony_ci		val = DATA32(regs->gpr[rd]);
163262306a36Sopenharmony_ci		imm = MASK32(mb, me);
163362306a36Sopenharmony_ci		op->val = (regs->gpr[ra] & ~imm) | (ROTATE(val, rb) & imm);
163462306a36Sopenharmony_ci		goto logical_done;
163562306a36Sopenharmony_ci
163662306a36Sopenharmony_ci	case 21:	/* rlwinm */
163762306a36Sopenharmony_ci		mb = (word >> 6) & 0x1f;
163862306a36Sopenharmony_ci		me = (word >> 1) & 0x1f;
163962306a36Sopenharmony_ci		val = DATA32(regs->gpr[rd]);
164062306a36Sopenharmony_ci		op->val = ROTATE(val, rb) & MASK32(mb, me);
164162306a36Sopenharmony_ci		goto logical_done;
164262306a36Sopenharmony_ci
164362306a36Sopenharmony_ci	case 23:	/* rlwnm */
164462306a36Sopenharmony_ci		mb = (word >> 6) & 0x1f;
164562306a36Sopenharmony_ci		me = (word >> 1) & 0x1f;
164662306a36Sopenharmony_ci		rb = regs->gpr[rb] & 0x1f;
164762306a36Sopenharmony_ci		val = DATA32(regs->gpr[rd]);
164862306a36Sopenharmony_ci		op->val = ROTATE(val, rb) & MASK32(mb, me);
164962306a36Sopenharmony_ci		goto logical_done;
165062306a36Sopenharmony_ci
165162306a36Sopenharmony_ci	case 24:	/* ori */
165262306a36Sopenharmony_ci		op->val = regs->gpr[rd] | (unsigned short) word;
165362306a36Sopenharmony_ci		goto logical_done_nocc;
165462306a36Sopenharmony_ci
165562306a36Sopenharmony_ci	case 25:	/* oris */
165662306a36Sopenharmony_ci		imm = (unsigned short) word;
165762306a36Sopenharmony_ci		op->val = regs->gpr[rd] | (imm << 16);
165862306a36Sopenharmony_ci		goto logical_done_nocc;
165962306a36Sopenharmony_ci
166062306a36Sopenharmony_ci	case 26:	/* xori */
166162306a36Sopenharmony_ci		op->val = regs->gpr[rd] ^ (unsigned short) word;
166262306a36Sopenharmony_ci		goto logical_done_nocc;
166362306a36Sopenharmony_ci
166462306a36Sopenharmony_ci	case 27:	/* xoris */
166562306a36Sopenharmony_ci		imm = (unsigned short) word;
166662306a36Sopenharmony_ci		op->val = regs->gpr[rd] ^ (imm << 16);
166762306a36Sopenharmony_ci		goto logical_done_nocc;
166862306a36Sopenharmony_ci
166962306a36Sopenharmony_ci	case 28:	/* andi. */
167062306a36Sopenharmony_ci		op->val = regs->gpr[rd] & (unsigned short) word;
167162306a36Sopenharmony_ci		set_cr0(regs, op);
167262306a36Sopenharmony_ci		goto logical_done_nocc;
167362306a36Sopenharmony_ci
167462306a36Sopenharmony_ci	case 29:	/* andis. */
167562306a36Sopenharmony_ci		imm = (unsigned short) word;
167662306a36Sopenharmony_ci		op->val = regs->gpr[rd] & (imm << 16);
167762306a36Sopenharmony_ci		set_cr0(regs, op);
167862306a36Sopenharmony_ci		goto logical_done_nocc;
167962306a36Sopenharmony_ci
168062306a36Sopenharmony_ci#ifdef __powerpc64__
168162306a36Sopenharmony_ci	case 30:	/* rld* */
168262306a36Sopenharmony_ci		mb = ((word >> 6) & 0x1f) | (word & 0x20);
168362306a36Sopenharmony_ci		val = regs->gpr[rd];
168462306a36Sopenharmony_ci		if ((word & 0x10) == 0) {
168562306a36Sopenharmony_ci			sh = rb | ((word & 2) << 4);
168662306a36Sopenharmony_ci			val = ROTATE(val, sh);
168762306a36Sopenharmony_ci			switch ((word >> 2) & 3) {
168862306a36Sopenharmony_ci			case 0:		/* rldicl */
168962306a36Sopenharmony_ci				val &= MASK64_L(mb);
169062306a36Sopenharmony_ci				break;
169162306a36Sopenharmony_ci			case 1:		/* rldicr */
169262306a36Sopenharmony_ci				val &= MASK64_R(mb);
169362306a36Sopenharmony_ci				break;
169462306a36Sopenharmony_ci			case 2:		/* rldic */
169562306a36Sopenharmony_ci				val &= MASK64(mb, 63 - sh);
169662306a36Sopenharmony_ci				break;
169762306a36Sopenharmony_ci			case 3:		/* rldimi */
169862306a36Sopenharmony_ci				imm = MASK64(mb, 63 - sh);
169962306a36Sopenharmony_ci				val = (regs->gpr[ra] & ~imm) |
170062306a36Sopenharmony_ci					(val & imm);
170162306a36Sopenharmony_ci			}
170262306a36Sopenharmony_ci			op->val = val;
170362306a36Sopenharmony_ci			goto logical_done;
170462306a36Sopenharmony_ci		} else {
170562306a36Sopenharmony_ci			sh = regs->gpr[rb] & 0x3f;
170662306a36Sopenharmony_ci			val = ROTATE(val, sh);
170762306a36Sopenharmony_ci			switch ((word >> 1) & 7) {
170862306a36Sopenharmony_ci			case 0:		/* rldcl */
170962306a36Sopenharmony_ci				op->val = val & MASK64_L(mb);
171062306a36Sopenharmony_ci				goto logical_done;
171162306a36Sopenharmony_ci			case 1:		/* rldcr */
171262306a36Sopenharmony_ci				op->val = val & MASK64_R(mb);
171362306a36Sopenharmony_ci				goto logical_done;
171462306a36Sopenharmony_ci			}
171562306a36Sopenharmony_ci		}
171662306a36Sopenharmony_ci#endif
171762306a36Sopenharmony_ci		op->type = UNKNOWN;	/* illegal instruction */
171862306a36Sopenharmony_ci		return 0;
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_ci	case 31:
172162306a36Sopenharmony_ci		/* isel occupies 32 minor opcodes */
172262306a36Sopenharmony_ci		if (((word >> 1) & 0x1f) == 15) {
172362306a36Sopenharmony_ci			mb = (word >> 6) & 0x1f; /* bc field */
172462306a36Sopenharmony_ci			val = (regs->ccr >> (31 - mb)) & 1;
172562306a36Sopenharmony_ci			val2 = (ra) ? regs->gpr[ra] : 0;
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_ci			op->val = (val) ? val2 : regs->gpr[rb];
172862306a36Sopenharmony_ci			goto compute_done;
172962306a36Sopenharmony_ci		}
173062306a36Sopenharmony_ci
173162306a36Sopenharmony_ci		switch ((word >> 1) & 0x3ff) {
173262306a36Sopenharmony_ci		case 4:		/* tw */
173362306a36Sopenharmony_ci			if (rd == 0x1f ||
173462306a36Sopenharmony_ci			    (rd & trap_compare((int)regs->gpr[ra],
173562306a36Sopenharmony_ci					       (int)regs->gpr[rb])))
173662306a36Sopenharmony_ci				goto trap;
173762306a36Sopenharmony_ci			return 1;
173862306a36Sopenharmony_ci#ifdef __powerpc64__
173962306a36Sopenharmony_ci		case 68:	/* td */
174062306a36Sopenharmony_ci			if (rd & trap_compare(regs->gpr[ra], regs->gpr[rb]))
174162306a36Sopenharmony_ci				goto trap;
174262306a36Sopenharmony_ci			return 1;
174362306a36Sopenharmony_ci#endif
174462306a36Sopenharmony_ci		case 83:	/* mfmsr */
174562306a36Sopenharmony_ci			if (regs->msr & MSR_PR)
174662306a36Sopenharmony_ci				goto priv;
174762306a36Sopenharmony_ci			op->type = MFMSR;
174862306a36Sopenharmony_ci			op->reg = rd;
174962306a36Sopenharmony_ci			return 0;
175062306a36Sopenharmony_ci		case 146:	/* mtmsr */
175162306a36Sopenharmony_ci			if (regs->msr & MSR_PR)
175262306a36Sopenharmony_ci				goto priv;
175362306a36Sopenharmony_ci			op->type = MTMSR;
175462306a36Sopenharmony_ci			op->reg = rd;
175562306a36Sopenharmony_ci			op->val = 0xffffffff & ~(MSR_ME | MSR_LE);
175662306a36Sopenharmony_ci			return 0;
175762306a36Sopenharmony_ci#ifdef CONFIG_PPC64
175862306a36Sopenharmony_ci		case 178:	/* mtmsrd */
175962306a36Sopenharmony_ci			if (regs->msr & MSR_PR)
176062306a36Sopenharmony_ci				goto priv;
176162306a36Sopenharmony_ci			op->type = MTMSR;
176262306a36Sopenharmony_ci			op->reg = rd;
176362306a36Sopenharmony_ci			/* only MSR_EE and MSR_RI get changed if bit 15 set */
176462306a36Sopenharmony_ci			/* mtmsrd doesn't change MSR_HV, MSR_ME or MSR_LE */
176562306a36Sopenharmony_ci			imm = (word & 0x10000)? 0x8002: 0xefffffffffffeffeUL;
176662306a36Sopenharmony_ci			op->val = imm;
176762306a36Sopenharmony_ci			return 0;
176862306a36Sopenharmony_ci#endif
176962306a36Sopenharmony_ci
177062306a36Sopenharmony_ci		case 19:	/* mfcr */
177162306a36Sopenharmony_ci			imm = 0xffffffffUL;
177262306a36Sopenharmony_ci			if ((word >> 20) & 1) {
177362306a36Sopenharmony_ci				imm = 0xf0000000UL;
177462306a36Sopenharmony_ci				for (sh = 0; sh < 8; ++sh) {
177562306a36Sopenharmony_ci					if (word & (0x80000 >> sh))
177662306a36Sopenharmony_ci						break;
177762306a36Sopenharmony_ci					imm >>= 4;
177862306a36Sopenharmony_ci				}
177962306a36Sopenharmony_ci			}
178062306a36Sopenharmony_ci			op->val = regs->ccr & imm;
178162306a36Sopenharmony_ci			goto compute_done;
178262306a36Sopenharmony_ci
178362306a36Sopenharmony_ci		case 128:	/* setb */
178462306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
178562306a36Sopenharmony_ci				goto unknown_opcode;
178662306a36Sopenharmony_ci			/*
178762306a36Sopenharmony_ci			 * 'ra' encodes the CR field number (bfa) in the top 3 bits.
178862306a36Sopenharmony_ci			 * Since each CR field is 4 bits,
178962306a36Sopenharmony_ci			 * we can simply mask off the bottom two bits (bfa * 4)
179062306a36Sopenharmony_ci			 * to yield the first bit in the CR field.
179162306a36Sopenharmony_ci			 */
179262306a36Sopenharmony_ci			ra = ra & ~0x3;
179362306a36Sopenharmony_ci			/* 'val' stores bits of the CR field (bfa) */
179462306a36Sopenharmony_ci			val = regs->ccr >> (CR0_SHIFT - ra);
179562306a36Sopenharmony_ci			/* checks if the LT bit of CR field (bfa) is set */
179662306a36Sopenharmony_ci			if (val & 8)
179762306a36Sopenharmony_ci				op->val = -1;
179862306a36Sopenharmony_ci			/* checks if the GT bit of CR field (bfa) is set */
179962306a36Sopenharmony_ci			else if (val & 4)
180062306a36Sopenharmony_ci				op->val = 1;
180162306a36Sopenharmony_ci			else
180262306a36Sopenharmony_ci				op->val = 0;
180362306a36Sopenharmony_ci			goto compute_done;
180462306a36Sopenharmony_ci
180562306a36Sopenharmony_ci		case 144:	/* mtcrf */
180662306a36Sopenharmony_ci			op->type = COMPUTE + SETCC;
180762306a36Sopenharmony_ci			imm = 0xf0000000UL;
180862306a36Sopenharmony_ci			val = regs->gpr[rd];
180962306a36Sopenharmony_ci			op->ccval = regs->ccr;
181062306a36Sopenharmony_ci			for (sh = 0; sh < 8; ++sh) {
181162306a36Sopenharmony_ci				if (word & (0x80000 >> sh))
181262306a36Sopenharmony_ci					op->ccval = (op->ccval & ~imm) |
181362306a36Sopenharmony_ci						(val & imm);
181462306a36Sopenharmony_ci				imm >>= 4;
181562306a36Sopenharmony_ci			}
181662306a36Sopenharmony_ci			return 1;
181762306a36Sopenharmony_ci
181862306a36Sopenharmony_ci		case 339:	/* mfspr */
181962306a36Sopenharmony_ci			spr = ((word >> 16) & 0x1f) | ((word >> 6) & 0x3e0);
182062306a36Sopenharmony_ci			op->type = MFSPR;
182162306a36Sopenharmony_ci			op->reg = rd;
182262306a36Sopenharmony_ci			op->spr = spr;
182362306a36Sopenharmony_ci			if (spr == SPRN_XER || spr == SPRN_LR ||
182462306a36Sopenharmony_ci			    spr == SPRN_CTR)
182562306a36Sopenharmony_ci				return 1;
182662306a36Sopenharmony_ci			return 0;
182762306a36Sopenharmony_ci
182862306a36Sopenharmony_ci		case 467:	/* mtspr */
182962306a36Sopenharmony_ci			spr = ((word >> 16) & 0x1f) | ((word >> 6) & 0x3e0);
183062306a36Sopenharmony_ci			op->type = MTSPR;
183162306a36Sopenharmony_ci			op->val = regs->gpr[rd];
183262306a36Sopenharmony_ci			op->spr = spr;
183362306a36Sopenharmony_ci			if (spr == SPRN_XER || spr == SPRN_LR ||
183462306a36Sopenharmony_ci			    spr == SPRN_CTR)
183562306a36Sopenharmony_ci				return 1;
183662306a36Sopenharmony_ci			return 0;
183762306a36Sopenharmony_ci
183862306a36Sopenharmony_ci/*
183962306a36Sopenharmony_ci * Compare instructions
184062306a36Sopenharmony_ci */
184162306a36Sopenharmony_ci		case 0:	/* cmp */
184262306a36Sopenharmony_ci			val = regs->gpr[ra];
184362306a36Sopenharmony_ci			val2 = regs->gpr[rb];
184462306a36Sopenharmony_ci#ifdef __powerpc64__
184562306a36Sopenharmony_ci			if ((rd & 1) == 0) {
184662306a36Sopenharmony_ci				/* word (32-bit) compare */
184762306a36Sopenharmony_ci				val = (int) val;
184862306a36Sopenharmony_ci				val2 = (int) val2;
184962306a36Sopenharmony_ci			}
185062306a36Sopenharmony_ci#endif
185162306a36Sopenharmony_ci			do_cmp_signed(regs, op, val, val2, rd >> 2);
185262306a36Sopenharmony_ci			return 1;
185362306a36Sopenharmony_ci
185462306a36Sopenharmony_ci		case 32:	/* cmpl */
185562306a36Sopenharmony_ci			val = regs->gpr[ra];
185662306a36Sopenharmony_ci			val2 = regs->gpr[rb];
185762306a36Sopenharmony_ci#ifdef __powerpc64__
185862306a36Sopenharmony_ci			if ((rd & 1) == 0) {
185962306a36Sopenharmony_ci				/* word (32-bit) compare */
186062306a36Sopenharmony_ci				val = (unsigned int) val;
186162306a36Sopenharmony_ci				val2 = (unsigned int) val2;
186262306a36Sopenharmony_ci			}
186362306a36Sopenharmony_ci#endif
186462306a36Sopenharmony_ci			do_cmp_unsigned(regs, op, val, val2, rd >> 2);
186562306a36Sopenharmony_ci			return 1;
186662306a36Sopenharmony_ci
186762306a36Sopenharmony_ci		case 508: /* cmpb */
186862306a36Sopenharmony_ci			do_cmpb(regs, op, regs->gpr[rd], regs->gpr[rb]);
186962306a36Sopenharmony_ci			goto logical_done_nocc;
187062306a36Sopenharmony_ci
187162306a36Sopenharmony_ci/*
187262306a36Sopenharmony_ci * Arithmetic instructions
187362306a36Sopenharmony_ci */
187462306a36Sopenharmony_ci		case 8:	/* subfc */
187562306a36Sopenharmony_ci			add_with_carry(regs, op, rd, ~regs->gpr[ra],
187662306a36Sopenharmony_ci				       regs->gpr[rb], 1);
187762306a36Sopenharmony_ci			goto arith_done;
187862306a36Sopenharmony_ci#ifdef __powerpc64__
187962306a36Sopenharmony_ci		case 9:	/* mulhdu */
188062306a36Sopenharmony_ci			asm("mulhdu %0,%1,%2" : "=r" (op->val) :
188162306a36Sopenharmony_ci			    "r" (regs->gpr[ra]), "r" (regs->gpr[rb]));
188262306a36Sopenharmony_ci			goto arith_done;
188362306a36Sopenharmony_ci#endif
188462306a36Sopenharmony_ci		case 10:	/* addc */
188562306a36Sopenharmony_ci			add_with_carry(regs, op, rd, regs->gpr[ra],
188662306a36Sopenharmony_ci				       regs->gpr[rb], 0);
188762306a36Sopenharmony_ci			goto arith_done;
188862306a36Sopenharmony_ci
188962306a36Sopenharmony_ci		case 11:	/* mulhwu */
189062306a36Sopenharmony_ci			asm("mulhwu %0,%1,%2" : "=r" (op->val) :
189162306a36Sopenharmony_ci			    "r" (regs->gpr[ra]), "r" (regs->gpr[rb]));
189262306a36Sopenharmony_ci			goto arith_done;
189362306a36Sopenharmony_ci
189462306a36Sopenharmony_ci		case 40:	/* subf */
189562306a36Sopenharmony_ci			op->val = regs->gpr[rb] - regs->gpr[ra];
189662306a36Sopenharmony_ci			goto arith_done;
189762306a36Sopenharmony_ci#ifdef __powerpc64__
189862306a36Sopenharmony_ci		case 73:	/* mulhd */
189962306a36Sopenharmony_ci			asm("mulhd %0,%1,%2" : "=r" (op->val) :
190062306a36Sopenharmony_ci			    "r" (regs->gpr[ra]), "r" (regs->gpr[rb]));
190162306a36Sopenharmony_ci			goto arith_done;
190262306a36Sopenharmony_ci#endif
190362306a36Sopenharmony_ci		case 75:	/* mulhw */
190462306a36Sopenharmony_ci			asm("mulhw %0,%1,%2" : "=r" (op->val) :
190562306a36Sopenharmony_ci			    "r" (regs->gpr[ra]), "r" (regs->gpr[rb]));
190662306a36Sopenharmony_ci			goto arith_done;
190762306a36Sopenharmony_ci
190862306a36Sopenharmony_ci		case 104:	/* neg */
190962306a36Sopenharmony_ci			op->val = -regs->gpr[ra];
191062306a36Sopenharmony_ci			goto arith_done;
191162306a36Sopenharmony_ci
191262306a36Sopenharmony_ci		case 136:	/* subfe */
191362306a36Sopenharmony_ci			add_with_carry(regs, op, rd, ~regs->gpr[ra],
191462306a36Sopenharmony_ci				       regs->gpr[rb], regs->xer & XER_CA);
191562306a36Sopenharmony_ci			goto arith_done;
191662306a36Sopenharmony_ci
191762306a36Sopenharmony_ci		case 138:	/* adde */
191862306a36Sopenharmony_ci			add_with_carry(regs, op, rd, regs->gpr[ra],
191962306a36Sopenharmony_ci				       regs->gpr[rb], regs->xer & XER_CA);
192062306a36Sopenharmony_ci			goto arith_done;
192162306a36Sopenharmony_ci
192262306a36Sopenharmony_ci		case 200:	/* subfze */
192362306a36Sopenharmony_ci			add_with_carry(regs, op, rd, ~regs->gpr[ra], 0L,
192462306a36Sopenharmony_ci				       regs->xer & XER_CA);
192562306a36Sopenharmony_ci			goto arith_done;
192662306a36Sopenharmony_ci
192762306a36Sopenharmony_ci		case 202:	/* addze */
192862306a36Sopenharmony_ci			add_with_carry(regs, op, rd, regs->gpr[ra], 0L,
192962306a36Sopenharmony_ci				       regs->xer & XER_CA);
193062306a36Sopenharmony_ci			goto arith_done;
193162306a36Sopenharmony_ci
193262306a36Sopenharmony_ci		case 232:	/* subfme */
193362306a36Sopenharmony_ci			add_with_carry(regs, op, rd, ~regs->gpr[ra], -1L,
193462306a36Sopenharmony_ci				       regs->xer & XER_CA);
193562306a36Sopenharmony_ci			goto arith_done;
193662306a36Sopenharmony_ci#ifdef __powerpc64__
193762306a36Sopenharmony_ci		case 233:	/* mulld */
193862306a36Sopenharmony_ci			op->val = regs->gpr[ra] * regs->gpr[rb];
193962306a36Sopenharmony_ci			goto arith_done;
194062306a36Sopenharmony_ci#endif
194162306a36Sopenharmony_ci		case 234:	/* addme */
194262306a36Sopenharmony_ci			add_with_carry(regs, op, rd, regs->gpr[ra], -1L,
194362306a36Sopenharmony_ci				       regs->xer & XER_CA);
194462306a36Sopenharmony_ci			goto arith_done;
194562306a36Sopenharmony_ci
194662306a36Sopenharmony_ci		case 235:	/* mullw */
194762306a36Sopenharmony_ci			op->val = (long)(int) regs->gpr[ra] *
194862306a36Sopenharmony_ci				(int) regs->gpr[rb];
194962306a36Sopenharmony_ci
195062306a36Sopenharmony_ci			goto arith_done;
195162306a36Sopenharmony_ci#ifdef __powerpc64__
195262306a36Sopenharmony_ci		case 265:	/* modud */
195362306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
195462306a36Sopenharmony_ci				goto unknown_opcode;
195562306a36Sopenharmony_ci			op->val = regs->gpr[ra] % regs->gpr[rb];
195662306a36Sopenharmony_ci			goto compute_done;
195762306a36Sopenharmony_ci#endif
195862306a36Sopenharmony_ci		case 266:	/* add */
195962306a36Sopenharmony_ci			op->val = regs->gpr[ra] + regs->gpr[rb];
196062306a36Sopenharmony_ci			goto arith_done;
196162306a36Sopenharmony_ci
196262306a36Sopenharmony_ci		case 267:	/* moduw */
196362306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
196462306a36Sopenharmony_ci				goto unknown_opcode;
196562306a36Sopenharmony_ci			op->val = (unsigned int) regs->gpr[ra] %
196662306a36Sopenharmony_ci				(unsigned int) regs->gpr[rb];
196762306a36Sopenharmony_ci			goto compute_done;
196862306a36Sopenharmony_ci#ifdef __powerpc64__
196962306a36Sopenharmony_ci		case 457:	/* divdu */
197062306a36Sopenharmony_ci			op->val = regs->gpr[ra] / regs->gpr[rb];
197162306a36Sopenharmony_ci			goto arith_done;
197262306a36Sopenharmony_ci#endif
197362306a36Sopenharmony_ci		case 459:	/* divwu */
197462306a36Sopenharmony_ci			op->val = (unsigned int) regs->gpr[ra] /
197562306a36Sopenharmony_ci				(unsigned int) regs->gpr[rb];
197662306a36Sopenharmony_ci			goto arith_done;
197762306a36Sopenharmony_ci#ifdef __powerpc64__
197862306a36Sopenharmony_ci		case 489:	/* divd */
197962306a36Sopenharmony_ci			op->val = (long int) regs->gpr[ra] /
198062306a36Sopenharmony_ci				(long int) regs->gpr[rb];
198162306a36Sopenharmony_ci			goto arith_done;
198262306a36Sopenharmony_ci#endif
198362306a36Sopenharmony_ci		case 491:	/* divw */
198462306a36Sopenharmony_ci			op->val = (int) regs->gpr[ra] /
198562306a36Sopenharmony_ci				(int) regs->gpr[rb];
198662306a36Sopenharmony_ci			goto arith_done;
198762306a36Sopenharmony_ci#ifdef __powerpc64__
198862306a36Sopenharmony_ci		case 425:	/* divde[.] */
198962306a36Sopenharmony_ci			asm volatile(PPC_DIVDE(%0, %1, %2) :
199062306a36Sopenharmony_ci				"=r" (op->val) : "r" (regs->gpr[ra]),
199162306a36Sopenharmony_ci				"r" (regs->gpr[rb]));
199262306a36Sopenharmony_ci			goto arith_done;
199362306a36Sopenharmony_ci		case 393:	/* divdeu[.] */
199462306a36Sopenharmony_ci			asm volatile(PPC_DIVDEU(%0, %1, %2) :
199562306a36Sopenharmony_ci				"=r" (op->val) : "r" (regs->gpr[ra]),
199662306a36Sopenharmony_ci				"r" (regs->gpr[rb]));
199762306a36Sopenharmony_ci			goto arith_done;
199862306a36Sopenharmony_ci#endif
199962306a36Sopenharmony_ci		case 755:	/* darn */
200062306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
200162306a36Sopenharmony_ci				goto unknown_opcode;
200262306a36Sopenharmony_ci			switch (ra & 0x3) {
200362306a36Sopenharmony_ci			case 0:
200462306a36Sopenharmony_ci				/* 32-bit conditioned */
200562306a36Sopenharmony_ci				asm volatile(PPC_DARN(%0, 0) : "=r" (op->val));
200662306a36Sopenharmony_ci				goto compute_done;
200762306a36Sopenharmony_ci
200862306a36Sopenharmony_ci			case 1:
200962306a36Sopenharmony_ci				/* 64-bit conditioned */
201062306a36Sopenharmony_ci				asm volatile(PPC_DARN(%0, 1) : "=r" (op->val));
201162306a36Sopenharmony_ci				goto compute_done;
201262306a36Sopenharmony_ci
201362306a36Sopenharmony_ci			case 2:
201462306a36Sopenharmony_ci				/* 64-bit raw */
201562306a36Sopenharmony_ci				asm volatile(PPC_DARN(%0, 2) : "=r" (op->val));
201662306a36Sopenharmony_ci				goto compute_done;
201762306a36Sopenharmony_ci			}
201862306a36Sopenharmony_ci
201962306a36Sopenharmony_ci			goto unknown_opcode;
202062306a36Sopenharmony_ci#ifdef __powerpc64__
202162306a36Sopenharmony_ci		case 777:	/* modsd */
202262306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
202362306a36Sopenharmony_ci				goto unknown_opcode;
202462306a36Sopenharmony_ci			op->val = (long int) regs->gpr[ra] %
202562306a36Sopenharmony_ci				(long int) regs->gpr[rb];
202662306a36Sopenharmony_ci			goto compute_done;
202762306a36Sopenharmony_ci#endif
202862306a36Sopenharmony_ci		case 779:	/* modsw */
202962306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
203062306a36Sopenharmony_ci				goto unknown_opcode;
203162306a36Sopenharmony_ci			op->val = (int) regs->gpr[ra] %
203262306a36Sopenharmony_ci				(int) regs->gpr[rb];
203362306a36Sopenharmony_ci			goto compute_done;
203462306a36Sopenharmony_ci
203562306a36Sopenharmony_ci
203662306a36Sopenharmony_ci/*
203762306a36Sopenharmony_ci * Logical instructions
203862306a36Sopenharmony_ci */
203962306a36Sopenharmony_ci		case 26:	/* cntlzw */
204062306a36Sopenharmony_ci			val = (unsigned int) regs->gpr[rd];
204162306a36Sopenharmony_ci			op->val = ( val ? __builtin_clz(val) : 32 );
204262306a36Sopenharmony_ci			goto logical_done;
204362306a36Sopenharmony_ci#ifdef __powerpc64__
204462306a36Sopenharmony_ci		case 58:	/* cntlzd */
204562306a36Sopenharmony_ci			val = regs->gpr[rd];
204662306a36Sopenharmony_ci			op->val = ( val ? __builtin_clzl(val) : 64 );
204762306a36Sopenharmony_ci			goto logical_done;
204862306a36Sopenharmony_ci#endif
204962306a36Sopenharmony_ci		case 28:	/* and */
205062306a36Sopenharmony_ci			op->val = regs->gpr[rd] & regs->gpr[rb];
205162306a36Sopenharmony_ci			goto logical_done;
205262306a36Sopenharmony_ci
205362306a36Sopenharmony_ci		case 60:	/* andc */
205462306a36Sopenharmony_ci			op->val = regs->gpr[rd] & ~regs->gpr[rb];
205562306a36Sopenharmony_ci			goto logical_done;
205662306a36Sopenharmony_ci
205762306a36Sopenharmony_ci		case 122:	/* popcntb */
205862306a36Sopenharmony_ci			do_popcnt(regs, op, regs->gpr[rd], 8);
205962306a36Sopenharmony_ci			goto logical_done_nocc;
206062306a36Sopenharmony_ci
206162306a36Sopenharmony_ci		case 124:	/* nor */
206262306a36Sopenharmony_ci			op->val = ~(regs->gpr[rd] | regs->gpr[rb]);
206362306a36Sopenharmony_ci			goto logical_done;
206462306a36Sopenharmony_ci
206562306a36Sopenharmony_ci		case 154:	/* prtyw */
206662306a36Sopenharmony_ci			do_prty(regs, op, regs->gpr[rd], 32);
206762306a36Sopenharmony_ci			goto logical_done_nocc;
206862306a36Sopenharmony_ci
206962306a36Sopenharmony_ci		case 186:	/* prtyd */
207062306a36Sopenharmony_ci			do_prty(regs, op, regs->gpr[rd], 64);
207162306a36Sopenharmony_ci			goto logical_done_nocc;
207262306a36Sopenharmony_ci#ifdef CONFIG_PPC64
207362306a36Sopenharmony_ci		case 252:	/* bpermd */
207462306a36Sopenharmony_ci			do_bpermd(regs, op, regs->gpr[rd], regs->gpr[rb]);
207562306a36Sopenharmony_ci			goto logical_done_nocc;
207662306a36Sopenharmony_ci#endif
207762306a36Sopenharmony_ci		case 284:	/* xor */
207862306a36Sopenharmony_ci			op->val = ~(regs->gpr[rd] ^ regs->gpr[rb]);
207962306a36Sopenharmony_ci			goto logical_done;
208062306a36Sopenharmony_ci
208162306a36Sopenharmony_ci		case 316:	/* xor */
208262306a36Sopenharmony_ci			op->val = regs->gpr[rd] ^ regs->gpr[rb];
208362306a36Sopenharmony_ci			goto logical_done;
208462306a36Sopenharmony_ci
208562306a36Sopenharmony_ci		case 378:	/* popcntw */
208662306a36Sopenharmony_ci			do_popcnt(regs, op, regs->gpr[rd], 32);
208762306a36Sopenharmony_ci			goto logical_done_nocc;
208862306a36Sopenharmony_ci
208962306a36Sopenharmony_ci		case 412:	/* orc */
209062306a36Sopenharmony_ci			op->val = regs->gpr[rd] | ~regs->gpr[rb];
209162306a36Sopenharmony_ci			goto logical_done;
209262306a36Sopenharmony_ci
209362306a36Sopenharmony_ci		case 444:	/* or */
209462306a36Sopenharmony_ci			op->val = regs->gpr[rd] | regs->gpr[rb];
209562306a36Sopenharmony_ci			goto logical_done;
209662306a36Sopenharmony_ci
209762306a36Sopenharmony_ci		case 476:	/* nand */
209862306a36Sopenharmony_ci			op->val = ~(regs->gpr[rd] & regs->gpr[rb]);
209962306a36Sopenharmony_ci			goto logical_done;
210062306a36Sopenharmony_ci#ifdef CONFIG_PPC64
210162306a36Sopenharmony_ci		case 506:	/* popcntd */
210262306a36Sopenharmony_ci			do_popcnt(regs, op, regs->gpr[rd], 64);
210362306a36Sopenharmony_ci			goto logical_done_nocc;
210462306a36Sopenharmony_ci#endif
210562306a36Sopenharmony_ci		case 538:	/* cnttzw */
210662306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
210762306a36Sopenharmony_ci				goto unknown_opcode;
210862306a36Sopenharmony_ci			val = (unsigned int) regs->gpr[rd];
210962306a36Sopenharmony_ci			op->val = (val ? __builtin_ctz(val) : 32);
211062306a36Sopenharmony_ci			goto logical_done;
211162306a36Sopenharmony_ci#ifdef __powerpc64__
211262306a36Sopenharmony_ci		case 570:	/* cnttzd */
211362306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
211462306a36Sopenharmony_ci				goto unknown_opcode;
211562306a36Sopenharmony_ci			val = regs->gpr[rd];
211662306a36Sopenharmony_ci			op->val = (val ? __builtin_ctzl(val) : 64);
211762306a36Sopenharmony_ci			goto logical_done;
211862306a36Sopenharmony_ci#endif
211962306a36Sopenharmony_ci		case 922:	/* extsh */
212062306a36Sopenharmony_ci			op->val = (signed short) regs->gpr[rd];
212162306a36Sopenharmony_ci			goto logical_done;
212262306a36Sopenharmony_ci
212362306a36Sopenharmony_ci		case 954:	/* extsb */
212462306a36Sopenharmony_ci			op->val = (signed char) regs->gpr[rd];
212562306a36Sopenharmony_ci			goto logical_done;
212662306a36Sopenharmony_ci#ifdef __powerpc64__
212762306a36Sopenharmony_ci		case 986:	/* extsw */
212862306a36Sopenharmony_ci			op->val = (signed int) regs->gpr[rd];
212962306a36Sopenharmony_ci			goto logical_done;
213062306a36Sopenharmony_ci#endif
213162306a36Sopenharmony_ci
213262306a36Sopenharmony_ci/*
213362306a36Sopenharmony_ci * Shift instructions
213462306a36Sopenharmony_ci */
213562306a36Sopenharmony_ci		case 24:	/* slw */
213662306a36Sopenharmony_ci			sh = regs->gpr[rb] & 0x3f;
213762306a36Sopenharmony_ci			if (sh < 32)
213862306a36Sopenharmony_ci				op->val = (regs->gpr[rd] << sh) & 0xffffffffUL;
213962306a36Sopenharmony_ci			else
214062306a36Sopenharmony_ci				op->val = 0;
214162306a36Sopenharmony_ci			goto logical_done;
214262306a36Sopenharmony_ci
214362306a36Sopenharmony_ci		case 536:	/* srw */
214462306a36Sopenharmony_ci			sh = regs->gpr[rb] & 0x3f;
214562306a36Sopenharmony_ci			if (sh < 32)
214662306a36Sopenharmony_ci				op->val = (regs->gpr[rd] & 0xffffffffUL) >> sh;
214762306a36Sopenharmony_ci			else
214862306a36Sopenharmony_ci				op->val = 0;
214962306a36Sopenharmony_ci			goto logical_done;
215062306a36Sopenharmony_ci
215162306a36Sopenharmony_ci		case 792:	/* sraw */
215262306a36Sopenharmony_ci			op->type = COMPUTE + SETREG + SETXER;
215362306a36Sopenharmony_ci			sh = regs->gpr[rb] & 0x3f;
215462306a36Sopenharmony_ci			ival = (signed int) regs->gpr[rd];
215562306a36Sopenharmony_ci			op->val = ival >> (sh < 32 ? sh : 31);
215662306a36Sopenharmony_ci			op->xerval = regs->xer;
215762306a36Sopenharmony_ci			if (ival < 0 && (sh >= 32 || (ival & ((1ul << sh) - 1)) != 0))
215862306a36Sopenharmony_ci				op->xerval |= XER_CA;
215962306a36Sopenharmony_ci			else
216062306a36Sopenharmony_ci				op->xerval &= ~XER_CA;
216162306a36Sopenharmony_ci			set_ca32(op, op->xerval & XER_CA);
216262306a36Sopenharmony_ci			goto logical_done;
216362306a36Sopenharmony_ci
216462306a36Sopenharmony_ci		case 824:	/* srawi */
216562306a36Sopenharmony_ci			op->type = COMPUTE + SETREG + SETXER;
216662306a36Sopenharmony_ci			sh = rb;
216762306a36Sopenharmony_ci			ival = (signed int) regs->gpr[rd];
216862306a36Sopenharmony_ci			op->val = ival >> sh;
216962306a36Sopenharmony_ci			op->xerval = regs->xer;
217062306a36Sopenharmony_ci			if (ival < 0 && (ival & ((1ul << sh) - 1)) != 0)
217162306a36Sopenharmony_ci				op->xerval |= XER_CA;
217262306a36Sopenharmony_ci			else
217362306a36Sopenharmony_ci				op->xerval &= ~XER_CA;
217462306a36Sopenharmony_ci			set_ca32(op, op->xerval & XER_CA);
217562306a36Sopenharmony_ci			goto logical_done;
217662306a36Sopenharmony_ci
217762306a36Sopenharmony_ci#ifdef __powerpc64__
217862306a36Sopenharmony_ci		case 27:	/* sld */
217962306a36Sopenharmony_ci			sh = regs->gpr[rb] & 0x7f;
218062306a36Sopenharmony_ci			if (sh < 64)
218162306a36Sopenharmony_ci				op->val = regs->gpr[rd] << sh;
218262306a36Sopenharmony_ci			else
218362306a36Sopenharmony_ci				op->val = 0;
218462306a36Sopenharmony_ci			goto logical_done;
218562306a36Sopenharmony_ci
218662306a36Sopenharmony_ci		case 539:	/* srd */
218762306a36Sopenharmony_ci			sh = regs->gpr[rb] & 0x7f;
218862306a36Sopenharmony_ci			if (sh < 64)
218962306a36Sopenharmony_ci				op->val = regs->gpr[rd] >> sh;
219062306a36Sopenharmony_ci			else
219162306a36Sopenharmony_ci				op->val = 0;
219262306a36Sopenharmony_ci			goto logical_done;
219362306a36Sopenharmony_ci
219462306a36Sopenharmony_ci		case 794:	/* srad */
219562306a36Sopenharmony_ci			op->type = COMPUTE + SETREG + SETXER;
219662306a36Sopenharmony_ci			sh = regs->gpr[rb] & 0x7f;
219762306a36Sopenharmony_ci			ival = (signed long int) regs->gpr[rd];
219862306a36Sopenharmony_ci			op->val = ival >> (sh < 64 ? sh : 63);
219962306a36Sopenharmony_ci			op->xerval = regs->xer;
220062306a36Sopenharmony_ci			if (ival < 0 && (sh >= 64 || (ival & ((1ul << sh) - 1)) != 0))
220162306a36Sopenharmony_ci				op->xerval |= XER_CA;
220262306a36Sopenharmony_ci			else
220362306a36Sopenharmony_ci				op->xerval &= ~XER_CA;
220462306a36Sopenharmony_ci			set_ca32(op, op->xerval & XER_CA);
220562306a36Sopenharmony_ci			goto logical_done;
220662306a36Sopenharmony_ci
220762306a36Sopenharmony_ci		case 826:	/* sradi with sh_5 = 0 */
220862306a36Sopenharmony_ci		case 827:	/* sradi with sh_5 = 1 */
220962306a36Sopenharmony_ci			op->type = COMPUTE + SETREG + SETXER;
221062306a36Sopenharmony_ci			sh = rb | ((word & 2) << 4);
221162306a36Sopenharmony_ci			ival = (signed long int) regs->gpr[rd];
221262306a36Sopenharmony_ci			op->val = ival >> sh;
221362306a36Sopenharmony_ci			op->xerval = regs->xer;
221462306a36Sopenharmony_ci			if (ival < 0 && (ival & ((1ul << sh) - 1)) != 0)
221562306a36Sopenharmony_ci				op->xerval |= XER_CA;
221662306a36Sopenharmony_ci			else
221762306a36Sopenharmony_ci				op->xerval &= ~XER_CA;
221862306a36Sopenharmony_ci			set_ca32(op, op->xerval & XER_CA);
221962306a36Sopenharmony_ci			goto logical_done;
222062306a36Sopenharmony_ci
222162306a36Sopenharmony_ci		case 890:	/* extswsli with sh_5 = 0 */
222262306a36Sopenharmony_ci		case 891:	/* extswsli with sh_5 = 1 */
222362306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
222462306a36Sopenharmony_ci				goto unknown_opcode;
222562306a36Sopenharmony_ci			op->type = COMPUTE + SETREG;
222662306a36Sopenharmony_ci			sh = rb | ((word & 2) << 4);
222762306a36Sopenharmony_ci			val = (signed int) regs->gpr[rd];
222862306a36Sopenharmony_ci			if (sh)
222962306a36Sopenharmony_ci				op->val = ROTATE(val, sh) & MASK64(0, 63 - sh);
223062306a36Sopenharmony_ci			else
223162306a36Sopenharmony_ci				op->val = val;
223262306a36Sopenharmony_ci			goto logical_done;
223362306a36Sopenharmony_ci
223462306a36Sopenharmony_ci#endif /* __powerpc64__ */
223562306a36Sopenharmony_ci
223662306a36Sopenharmony_ci/*
223762306a36Sopenharmony_ci * Cache instructions
223862306a36Sopenharmony_ci */
223962306a36Sopenharmony_ci		case 54:	/* dcbst */
224062306a36Sopenharmony_ci			op->type = MKOP(CACHEOP, DCBST, 0);
224162306a36Sopenharmony_ci			op->ea = xform_ea(word, regs);
224262306a36Sopenharmony_ci			return 0;
224362306a36Sopenharmony_ci
224462306a36Sopenharmony_ci		case 86:	/* dcbf */
224562306a36Sopenharmony_ci			op->type = MKOP(CACHEOP, DCBF, 0);
224662306a36Sopenharmony_ci			op->ea = xform_ea(word, regs);
224762306a36Sopenharmony_ci			return 0;
224862306a36Sopenharmony_ci
224962306a36Sopenharmony_ci		case 246:	/* dcbtst */
225062306a36Sopenharmony_ci			op->type = MKOP(CACHEOP, DCBTST, 0);
225162306a36Sopenharmony_ci			op->ea = xform_ea(word, regs);
225262306a36Sopenharmony_ci			op->reg = rd;
225362306a36Sopenharmony_ci			return 0;
225462306a36Sopenharmony_ci
225562306a36Sopenharmony_ci		case 278:	/* dcbt */
225662306a36Sopenharmony_ci			op->type = MKOP(CACHEOP, DCBTST, 0);
225762306a36Sopenharmony_ci			op->ea = xform_ea(word, regs);
225862306a36Sopenharmony_ci			op->reg = rd;
225962306a36Sopenharmony_ci			return 0;
226062306a36Sopenharmony_ci
226162306a36Sopenharmony_ci		case 982:	/* icbi */
226262306a36Sopenharmony_ci			op->type = MKOP(CACHEOP, ICBI, 0);
226362306a36Sopenharmony_ci			op->ea = xform_ea(word, regs);
226462306a36Sopenharmony_ci			return 0;
226562306a36Sopenharmony_ci
226662306a36Sopenharmony_ci		case 1014:	/* dcbz */
226762306a36Sopenharmony_ci			op->type = MKOP(CACHEOP, DCBZ, 0);
226862306a36Sopenharmony_ci			op->ea = xform_ea(word, regs);
226962306a36Sopenharmony_ci			return 0;
227062306a36Sopenharmony_ci		}
227162306a36Sopenharmony_ci		break;
227262306a36Sopenharmony_ci	}
227362306a36Sopenharmony_ci
227462306a36Sopenharmony_ci/*
227562306a36Sopenharmony_ci * Loads and stores.
227662306a36Sopenharmony_ci */
227762306a36Sopenharmony_ci	op->type = UNKNOWN;
227862306a36Sopenharmony_ci	op->update_reg = ra;
227962306a36Sopenharmony_ci	op->reg = rd;
228062306a36Sopenharmony_ci	op->val = regs->gpr[rd];
228162306a36Sopenharmony_ci	u = (word >> 20) & UPDATE;
228262306a36Sopenharmony_ci	op->vsx_flags = 0;
228362306a36Sopenharmony_ci
228462306a36Sopenharmony_ci	switch (opcode) {
228562306a36Sopenharmony_ci	case 31:
228662306a36Sopenharmony_ci		u = word & UPDATE;
228762306a36Sopenharmony_ci		op->ea = xform_ea(word, regs);
228862306a36Sopenharmony_ci		switch ((word >> 1) & 0x3ff) {
228962306a36Sopenharmony_ci		case 20:	/* lwarx */
229062306a36Sopenharmony_ci			op->type = MKOP(LARX, 0, 4);
229162306a36Sopenharmony_ci			break;
229262306a36Sopenharmony_ci
229362306a36Sopenharmony_ci		case 150:	/* stwcx. */
229462306a36Sopenharmony_ci			op->type = MKOP(STCX, 0, 4);
229562306a36Sopenharmony_ci			break;
229662306a36Sopenharmony_ci
229762306a36Sopenharmony_ci#ifdef CONFIG_PPC_HAS_LBARX_LHARX
229862306a36Sopenharmony_ci		case 52:	/* lbarx */
229962306a36Sopenharmony_ci			op->type = MKOP(LARX, 0, 1);
230062306a36Sopenharmony_ci			break;
230162306a36Sopenharmony_ci
230262306a36Sopenharmony_ci		case 694:	/* stbcx. */
230362306a36Sopenharmony_ci			op->type = MKOP(STCX, 0, 1);
230462306a36Sopenharmony_ci			break;
230562306a36Sopenharmony_ci
230662306a36Sopenharmony_ci		case 116:	/* lharx */
230762306a36Sopenharmony_ci			op->type = MKOP(LARX, 0, 2);
230862306a36Sopenharmony_ci			break;
230962306a36Sopenharmony_ci
231062306a36Sopenharmony_ci		case 726:	/* sthcx. */
231162306a36Sopenharmony_ci			op->type = MKOP(STCX, 0, 2);
231262306a36Sopenharmony_ci			break;
231362306a36Sopenharmony_ci#endif
231462306a36Sopenharmony_ci#ifdef __powerpc64__
231562306a36Sopenharmony_ci		case 84:	/* ldarx */
231662306a36Sopenharmony_ci			op->type = MKOP(LARX, 0, 8);
231762306a36Sopenharmony_ci			break;
231862306a36Sopenharmony_ci
231962306a36Sopenharmony_ci		case 214:	/* stdcx. */
232062306a36Sopenharmony_ci			op->type = MKOP(STCX, 0, 8);
232162306a36Sopenharmony_ci			break;
232262306a36Sopenharmony_ci
232362306a36Sopenharmony_ci		case 276:	/* lqarx */
232462306a36Sopenharmony_ci			if (!((rd & 1) || rd == ra || rd == rb))
232562306a36Sopenharmony_ci				op->type = MKOP(LARX, 0, 16);
232662306a36Sopenharmony_ci			break;
232762306a36Sopenharmony_ci
232862306a36Sopenharmony_ci		case 182:	/* stqcx. */
232962306a36Sopenharmony_ci			if (!(rd & 1))
233062306a36Sopenharmony_ci				op->type = MKOP(STCX, 0, 16);
233162306a36Sopenharmony_ci			break;
233262306a36Sopenharmony_ci#endif
233362306a36Sopenharmony_ci
233462306a36Sopenharmony_ci		case 23:	/* lwzx */
233562306a36Sopenharmony_ci		case 55:	/* lwzux */
233662306a36Sopenharmony_ci			op->type = MKOP(LOAD, u, 4);
233762306a36Sopenharmony_ci			break;
233862306a36Sopenharmony_ci
233962306a36Sopenharmony_ci		case 87:	/* lbzx */
234062306a36Sopenharmony_ci		case 119:	/* lbzux */
234162306a36Sopenharmony_ci			op->type = MKOP(LOAD, u, 1);
234262306a36Sopenharmony_ci			break;
234362306a36Sopenharmony_ci
234462306a36Sopenharmony_ci#ifdef CONFIG_ALTIVEC
234562306a36Sopenharmony_ci		/*
234662306a36Sopenharmony_ci		 * Note: for the load/store vector element instructions,
234762306a36Sopenharmony_ci		 * bits of the EA say which field of the VMX register to use.
234862306a36Sopenharmony_ci		 */
234962306a36Sopenharmony_ci		case 7:		/* lvebx */
235062306a36Sopenharmony_ci			op->type = MKOP(LOAD_VMX, 0, 1);
235162306a36Sopenharmony_ci			op->element_size = 1;
235262306a36Sopenharmony_ci			break;
235362306a36Sopenharmony_ci
235462306a36Sopenharmony_ci		case 39:	/* lvehx */
235562306a36Sopenharmony_ci			op->type = MKOP(LOAD_VMX, 0, 2);
235662306a36Sopenharmony_ci			op->element_size = 2;
235762306a36Sopenharmony_ci			break;
235862306a36Sopenharmony_ci
235962306a36Sopenharmony_ci		case 71:	/* lvewx */
236062306a36Sopenharmony_ci			op->type = MKOP(LOAD_VMX, 0, 4);
236162306a36Sopenharmony_ci			op->element_size = 4;
236262306a36Sopenharmony_ci			break;
236362306a36Sopenharmony_ci
236462306a36Sopenharmony_ci		case 103:	/* lvx */
236562306a36Sopenharmony_ci		case 359:	/* lvxl */
236662306a36Sopenharmony_ci			op->type = MKOP(LOAD_VMX, 0, 16);
236762306a36Sopenharmony_ci			op->element_size = 16;
236862306a36Sopenharmony_ci			break;
236962306a36Sopenharmony_ci
237062306a36Sopenharmony_ci		case 135:	/* stvebx */
237162306a36Sopenharmony_ci			op->type = MKOP(STORE_VMX, 0, 1);
237262306a36Sopenharmony_ci			op->element_size = 1;
237362306a36Sopenharmony_ci			break;
237462306a36Sopenharmony_ci
237562306a36Sopenharmony_ci		case 167:	/* stvehx */
237662306a36Sopenharmony_ci			op->type = MKOP(STORE_VMX, 0, 2);
237762306a36Sopenharmony_ci			op->element_size = 2;
237862306a36Sopenharmony_ci			break;
237962306a36Sopenharmony_ci
238062306a36Sopenharmony_ci		case 199:	/* stvewx */
238162306a36Sopenharmony_ci			op->type = MKOP(STORE_VMX, 0, 4);
238262306a36Sopenharmony_ci			op->element_size = 4;
238362306a36Sopenharmony_ci			break;
238462306a36Sopenharmony_ci
238562306a36Sopenharmony_ci		case 231:	/* stvx */
238662306a36Sopenharmony_ci		case 487:	/* stvxl */
238762306a36Sopenharmony_ci			op->type = MKOP(STORE_VMX, 0, 16);
238862306a36Sopenharmony_ci			break;
238962306a36Sopenharmony_ci#endif /* CONFIG_ALTIVEC */
239062306a36Sopenharmony_ci
239162306a36Sopenharmony_ci#ifdef __powerpc64__
239262306a36Sopenharmony_ci		case 21:	/* ldx */
239362306a36Sopenharmony_ci		case 53:	/* ldux */
239462306a36Sopenharmony_ci			op->type = MKOP(LOAD, u, 8);
239562306a36Sopenharmony_ci			break;
239662306a36Sopenharmony_ci
239762306a36Sopenharmony_ci		case 149:	/* stdx */
239862306a36Sopenharmony_ci		case 181:	/* stdux */
239962306a36Sopenharmony_ci			op->type = MKOP(STORE, u, 8);
240062306a36Sopenharmony_ci			break;
240162306a36Sopenharmony_ci#endif
240262306a36Sopenharmony_ci
240362306a36Sopenharmony_ci		case 151:	/* stwx */
240462306a36Sopenharmony_ci		case 183:	/* stwux */
240562306a36Sopenharmony_ci			op->type = MKOP(STORE, u, 4);
240662306a36Sopenharmony_ci			break;
240762306a36Sopenharmony_ci
240862306a36Sopenharmony_ci		case 215:	/* stbx */
240962306a36Sopenharmony_ci		case 247:	/* stbux */
241062306a36Sopenharmony_ci			op->type = MKOP(STORE, u, 1);
241162306a36Sopenharmony_ci			break;
241262306a36Sopenharmony_ci
241362306a36Sopenharmony_ci		case 279:	/* lhzx */
241462306a36Sopenharmony_ci		case 311:	/* lhzux */
241562306a36Sopenharmony_ci			op->type = MKOP(LOAD, u, 2);
241662306a36Sopenharmony_ci			break;
241762306a36Sopenharmony_ci
241862306a36Sopenharmony_ci#ifdef __powerpc64__
241962306a36Sopenharmony_ci		case 341:	/* lwax */
242062306a36Sopenharmony_ci		case 373:	/* lwaux */
242162306a36Sopenharmony_ci			op->type = MKOP(LOAD, SIGNEXT | u, 4);
242262306a36Sopenharmony_ci			break;
242362306a36Sopenharmony_ci#endif
242462306a36Sopenharmony_ci
242562306a36Sopenharmony_ci		case 343:	/* lhax */
242662306a36Sopenharmony_ci		case 375:	/* lhaux */
242762306a36Sopenharmony_ci			op->type = MKOP(LOAD, SIGNEXT | u, 2);
242862306a36Sopenharmony_ci			break;
242962306a36Sopenharmony_ci
243062306a36Sopenharmony_ci		case 407:	/* sthx */
243162306a36Sopenharmony_ci		case 439:	/* sthux */
243262306a36Sopenharmony_ci			op->type = MKOP(STORE, u, 2);
243362306a36Sopenharmony_ci			break;
243462306a36Sopenharmony_ci
243562306a36Sopenharmony_ci#ifdef __powerpc64__
243662306a36Sopenharmony_ci		case 532:	/* ldbrx */
243762306a36Sopenharmony_ci			op->type = MKOP(LOAD, BYTEREV, 8);
243862306a36Sopenharmony_ci			break;
243962306a36Sopenharmony_ci
244062306a36Sopenharmony_ci#endif
244162306a36Sopenharmony_ci		case 533:	/* lswx */
244262306a36Sopenharmony_ci			op->type = MKOP(LOAD_MULTI, 0, regs->xer & 0x7f);
244362306a36Sopenharmony_ci			break;
244462306a36Sopenharmony_ci
244562306a36Sopenharmony_ci		case 534:	/* lwbrx */
244662306a36Sopenharmony_ci			op->type = MKOP(LOAD, BYTEREV, 4);
244762306a36Sopenharmony_ci			break;
244862306a36Sopenharmony_ci
244962306a36Sopenharmony_ci		case 597:	/* lswi */
245062306a36Sopenharmony_ci			if (rb == 0)
245162306a36Sopenharmony_ci				rb = 32;	/* # bytes to load */
245262306a36Sopenharmony_ci			op->type = MKOP(LOAD_MULTI, 0, rb);
245362306a36Sopenharmony_ci			op->ea = ra ? regs->gpr[ra] : 0;
245462306a36Sopenharmony_ci			break;
245562306a36Sopenharmony_ci
245662306a36Sopenharmony_ci#ifdef CONFIG_PPC_FPU
245762306a36Sopenharmony_ci		case 535:	/* lfsx */
245862306a36Sopenharmony_ci		case 567:	/* lfsux */
245962306a36Sopenharmony_ci			op->type = MKOP(LOAD_FP, u | FPCONV, 4);
246062306a36Sopenharmony_ci			break;
246162306a36Sopenharmony_ci
246262306a36Sopenharmony_ci		case 599:	/* lfdx */
246362306a36Sopenharmony_ci		case 631:	/* lfdux */
246462306a36Sopenharmony_ci			op->type = MKOP(LOAD_FP, u, 8);
246562306a36Sopenharmony_ci			break;
246662306a36Sopenharmony_ci
246762306a36Sopenharmony_ci		case 663:	/* stfsx */
246862306a36Sopenharmony_ci		case 695:	/* stfsux */
246962306a36Sopenharmony_ci			op->type = MKOP(STORE_FP, u | FPCONV, 4);
247062306a36Sopenharmony_ci			break;
247162306a36Sopenharmony_ci
247262306a36Sopenharmony_ci		case 727:	/* stfdx */
247362306a36Sopenharmony_ci		case 759:	/* stfdux */
247462306a36Sopenharmony_ci			op->type = MKOP(STORE_FP, u, 8);
247562306a36Sopenharmony_ci			break;
247662306a36Sopenharmony_ci
247762306a36Sopenharmony_ci#ifdef __powerpc64__
247862306a36Sopenharmony_ci		case 791:	/* lfdpx */
247962306a36Sopenharmony_ci			op->type = MKOP(LOAD_FP, 0, 16);
248062306a36Sopenharmony_ci			break;
248162306a36Sopenharmony_ci
248262306a36Sopenharmony_ci		case 855:	/* lfiwax */
248362306a36Sopenharmony_ci			op->type = MKOP(LOAD_FP, SIGNEXT, 4);
248462306a36Sopenharmony_ci			break;
248562306a36Sopenharmony_ci
248662306a36Sopenharmony_ci		case 887:	/* lfiwzx */
248762306a36Sopenharmony_ci			op->type = MKOP(LOAD_FP, 0, 4);
248862306a36Sopenharmony_ci			break;
248962306a36Sopenharmony_ci
249062306a36Sopenharmony_ci		case 919:	/* stfdpx */
249162306a36Sopenharmony_ci			op->type = MKOP(STORE_FP, 0, 16);
249262306a36Sopenharmony_ci			break;
249362306a36Sopenharmony_ci
249462306a36Sopenharmony_ci		case 983:	/* stfiwx */
249562306a36Sopenharmony_ci			op->type = MKOP(STORE_FP, 0, 4);
249662306a36Sopenharmony_ci			break;
249762306a36Sopenharmony_ci#endif /* __powerpc64 */
249862306a36Sopenharmony_ci#endif /* CONFIG_PPC_FPU */
249962306a36Sopenharmony_ci
250062306a36Sopenharmony_ci#ifdef __powerpc64__
250162306a36Sopenharmony_ci		case 660:	/* stdbrx */
250262306a36Sopenharmony_ci			op->type = MKOP(STORE, BYTEREV, 8);
250362306a36Sopenharmony_ci			op->val = byterev_8(regs->gpr[rd]);
250462306a36Sopenharmony_ci			break;
250562306a36Sopenharmony_ci
250662306a36Sopenharmony_ci#endif
250762306a36Sopenharmony_ci		case 661:	/* stswx */
250862306a36Sopenharmony_ci			op->type = MKOP(STORE_MULTI, 0, regs->xer & 0x7f);
250962306a36Sopenharmony_ci			break;
251062306a36Sopenharmony_ci
251162306a36Sopenharmony_ci		case 662:	/* stwbrx */
251262306a36Sopenharmony_ci			op->type = MKOP(STORE, BYTEREV, 4);
251362306a36Sopenharmony_ci			op->val = byterev_4(regs->gpr[rd]);
251462306a36Sopenharmony_ci			break;
251562306a36Sopenharmony_ci
251662306a36Sopenharmony_ci		case 725:	/* stswi */
251762306a36Sopenharmony_ci			if (rb == 0)
251862306a36Sopenharmony_ci				rb = 32;	/* # bytes to store */
251962306a36Sopenharmony_ci			op->type = MKOP(STORE_MULTI, 0, rb);
252062306a36Sopenharmony_ci			op->ea = ra ? regs->gpr[ra] : 0;
252162306a36Sopenharmony_ci			break;
252262306a36Sopenharmony_ci
252362306a36Sopenharmony_ci		case 790:	/* lhbrx */
252462306a36Sopenharmony_ci			op->type = MKOP(LOAD, BYTEREV, 2);
252562306a36Sopenharmony_ci			break;
252662306a36Sopenharmony_ci
252762306a36Sopenharmony_ci		case 918:	/* sthbrx */
252862306a36Sopenharmony_ci			op->type = MKOP(STORE, BYTEREV, 2);
252962306a36Sopenharmony_ci			op->val = byterev_2(regs->gpr[rd]);
253062306a36Sopenharmony_ci			break;
253162306a36Sopenharmony_ci
253262306a36Sopenharmony_ci#ifdef CONFIG_VSX
253362306a36Sopenharmony_ci		case 12:	/* lxsiwzx */
253462306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
253562306a36Sopenharmony_ci			op->type = MKOP(LOAD_VSX, 0, 4);
253662306a36Sopenharmony_ci			op->element_size = 8;
253762306a36Sopenharmony_ci			break;
253862306a36Sopenharmony_ci
253962306a36Sopenharmony_ci		case 76:	/* lxsiwax */
254062306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
254162306a36Sopenharmony_ci			op->type = MKOP(LOAD_VSX, SIGNEXT, 4);
254262306a36Sopenharmony_ci			op->element_size = 8;
254362306a36Sopenharmony_ci			break;
254462306a36Sopenharmony_ci
254562306a36Sopenharmony_ci		case 140:	/* stxsiwx */
254662306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
254762306a36Sopenharmony_ci			op->type = MKOP(STORE_VSX, 0, 4);
254862306a36Sopenharmony_ci			op->element_size = 8;
254962306a36Sopenharmony_ci			break;
255062306a36Sopenharmony_ci
255162306a36Sopenharmony_ci		case 268:	/* lxvx */
255262306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
255362306a36Sopenharmony_ci				goto unknown_opcode;
255462306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
255562306a36Sopenharmony_ci			op->type = MKOP(LOAD_VSX, 0, 16);
255662306a36Sopenharmony_ci			op->element_size = 16;
255762306a36Sopenharmony_ci			op->vsx_flags = VSX_CHECK_VEC;
255862306a36Sopenharmony_ci			break;
255962306a36Sopenharmony_ci
256062306a36Sopenharmony_ci		case 269:	/* lxvl */
256162306a36Sopenharmony_ci		case 301: {	/* lxvll */
256262306a36Sopenharmony_ci			int nb;
256362306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
256462306a36Sopenharmony_ci				goto unknown_opcode;
256562306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
256662306a36Sopenharmony_ci			op->ea = ra ? regs->gpr[ra] : 0;
256762306a36Sopenharmony_ci			nb = regs->gpr[rb] & 0xff;
256862306a36Sopenharmony_ci			if (nb > 16)
256962306a36Sopenharmony_ci				nb = 16;
257062306a36Sopenharmony_ci			op->type = MKOP(LOAD_VSX, 0, nb);
257162306a36Sopenharmony_ci			op->element_size = 16;
257262306a36Sopenharmony_ci			op->vsx_flags = ((word & 0x20) ? VSX_LDLEFT : 0) |
257362306a36Sopenharmony_ci				VSX_CHECK_VEC;
257462306a36Sopenharmony_ci			break;
257562306a36Sopenharmony_ci		}
257662306a36Sopenharmony_ci		case 332:	/* lxvdsx */
257762306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
257862306a36Sopenharmony_ci			op->type = MKOP(LOAD_VSX, 0, 8);
257962306a36Sopenharmony_ci			op->element_size = 8;
258062306a36Sopenharmony_ci			op->vsx_flags = VSX_SPLAT;
258162306a36Sopenharmony_ci			break;
258262306a36Sopenharmony_ci
258362306a36Sopenharmony_ci		case 333:       /* lxvpx */
258462306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_31))
258562306a36Sopenharmony_ci				goto unknown_opcode;
258662306a36Sopenharmony_ci			op->reg = VSX_REGISTER_XTP(rd);
258762306a36Sopenharmony_ci			op->type = MKOP(LOAD_VSX, 0, 32);
258862306a36Sopenharmony_ci			op->element_size = 32;
258962306a36Sopenharmony_ci			break;
259062306a36Sopenharmony_ci
259162306a36Sopenharmony_ci		case 364:	/* lxvwsx */
259262306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
259362306a36Sopenharmony_ci				goto unknown_opcode;
259462306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
259562306a36Sopenharmony_ci			op->type = MKOP(LOAD_VSX, 0, 4);
259662306a36Sopenharmony_ci			op->element_size = 4;
259762306a36Sopenharmony_ci			op->vsx_flags = VSX_SPLAT | VSX_CHECK_VEC;
259862306a36Sopenharmony_ci			break;
259962306a36Sopenharmony_ci
260062306a36Sopenharmony_ci		case 396:	/* stxvx */
260162306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
260262306a36Sopenharmony_ci				goto unknown_opcode;
260362306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
260462306a36Sopenharmony_ci			op->type = MKOP(STORE_VSX, 0, 16);
260562306a36Sopenharmony_ci			op->element_size = 16;
260662306a36Sopenharmony_ci			op->vsx_flags = VSX_CHECK_VEC;
260762306a36Sopenharmony_ci			break;
260862306a36Sopenharmony_ci
260962306a36Sopenharmony_ci		case 397:	/* stxvl */
261062306a36Sopenharmony_ci		case 429: {	/* stxvll */
261162306a36Sopenharmony_ci			int nb;
261262306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
261362306a36Sopenharmony_ci				goto unknown_opcode;
261462306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
261562306a36Sopenharmony_ci			op->ea = ra ? regs->gpr[ra] : 0;
261662306a36Sopenharmony_ci			nb = regs->gpr[rb] & 0xff;
261762306a36Sopenharmony_ci			if (nb > 16)
261862306a36Sopenharmony_ci				nb = 16;
261962306a36Sopenharmony_ci			op->type = MKOP(STORE_VSX, 0, nb);
262062306a36Sopenharmony_ci			op->element_size = 16;
262162306a36Sopenharmony_ci			op->vsx_flags = ((word & 0x20) ? VSX_LDLEFT : 0) |
262262306a36Sopenharmony_ci				VSX_CHECK_VEC;
262362306a36Sopenharmony_ci			break;
262462306a36Sopenharmony_ci		}
262562306a36Sopenharmony_ci		case 461:       /* stxvpx */
262662306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_31))
262762306a36Sopenharmony_ci				goto unknown_opcode;
262862306a36Sopenharmony_ci			op->reg = VSX_REGISTER_XTP(rd);
262962306a36Sopenharmony_ci			op->type = MKOP(STORE_VSX, 0, 32);
263062306a36Sopenharmony_ci			op->element_size = 32;
263162306a36Sopenharmony_ci			break;
263262306a36Sopenharmony_ci		case 524:	/* lxsspx */
263362306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
263462306a36Sopenharmony_ci			op->type = MKOP(LOAD_VSX, 0, 4);
263562306a36Sopenharmony_ci			op->element_size = 8;
263662306a36Sopenharmony_ci			op->vsx_flags = VSX_FPCONV;
263762306a36Sopenharmony_ci			break;
263862306a36Sopenharmony_ci
263962306a36Sopenharmony_ci		case 588:	/* lxsdx */
264062306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
264162306a36Sopenharmony_ci			op->type = MKOP(LOAD_VSX, 0, 8);
264262306a36Sopenharmony_ci			op->element_size = 8;
264362306a36Sopenharmony_ci			break;
264462306a36Sopenharmony_ci
264562306a36Sopenharmony_ci		case 652:	/* stxsspx */
264662306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
264762306a36Sopenharmony_ci			op->type = MKOP(STORE_VSX, 0, 4);
264862306a36Sopenharmony_ci			op->element_size = 8;
264962306a36Sopenharmony_ci			op->vsx_flags = VSX_FPCONV;
265062306a36Sopenharmony_ci			break;
265162306a36Sopenharmony_ci
265262306a36Sopenharmony_ci		case 716:	/* stxsdx */
265362306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
265462306a36Sopenharmony_ci			op->type = MKOP(STORE_VSX, 0, 8);
265562306a36Sopenharmony_ci			op->element_size = 8;
265662306a36Sopenharmony_ci			break;
265762306a36Sopenharmony_ci
265862306a36Sopenharmony_ci		case 780:	/* lxvw4x */
265962306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
266062306a36Sopenharmony_ci			op->type = MKOP(LOAD_VSX, 0, 16);
266162306a36Sopenharmony_ci			op->element_size = 4;
266262306a36Sopenharmony_ci			break;
266362306a36Sopenharmony_ci
266462306a36Sopenharmony_ci		case 781:	/* lxsibzx */
266562306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
266662306a36Sopenharmony_ci				goto unknown_opcode;
266762306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
266862306a36Sopenharmony_ci			op->type = MKOP(LOAD_VSX, 0, 1);
266962306a36Sopenharmony_ci			op->element_size = 8;
267062306a36Sopenharmony_ci			op->vsx_flags = VSX_CHECK_VEC;
267162306a36Sopenharmony_ci			break;
267262306a36Sopenharmony_ci
267362306a36Sopenharmony_ci		case 812:	/* lxvh8x */
267462306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
267562306a36Sopenharmony_ci				goto unknown_opcode;
267662306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
267762306a36Sopenharmony_ci			op->type = MKOP(LOAD_VSX, 0, 16);
267862306a36Sopenharmony_ci			op->element_size = 2;
267962306a36Sopenharmony_ci			op->vsx_flags = VSX_CHECK_VEC;
268062306a36Sopenharmony_ci			break;
268162306a36Sopenharmony_ci
268262306a36Sopenharmony_ci		case 813:	/* lxsihzx */
268362306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
268462306a36Sopenharmony_ci				goto unknown_opcode;
268562306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
268662306a36Sopenharmony_ci			op->type = MKOP(LOAD_VSX, 0, 2);
268762306a36Sopenharmony_ci			op->element_size = 8;
268862306a36Sopenharmony_ci			op->vsx_flags = VSX_CHECK_VEC;
268962306a36Sopenharmony_ci			break;
269062306a36Sopenharmony_ci
269162306a36Sopenharmony_ci		case 844:	/* lxvd2x */
269262306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
269362306a36Sopenharmony_ci			op->type = MKOP(LOAD_VSX, 0, 16);
269462306a36Sopenharmony_ci			op->element_size = 8;
269562306a36Sopenharmony_ci			break;
269662306a36Sopenharmony_ci
269762306a36Sopenharmony_ci		case 876:	/* lxvb16x */
269862306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
269962306a36Sopenharmony_ci				goto unknown_opcode;
270062306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
270162306a36Sopenharmony_ci			op->type = MKOP(LOAD_VSX, 0, 16);
270262306a36Sopenharmony_ci			op->element_size = 1;
270362306a36Sopenharmony_ci			op->vsx_flags = VSX_CHECK_VEC;
270462306a36Sopenharmony_ci			break;
270562306a36Sopenharmony_ci
270662306a36Sopenharmony_ci		case 908:	/* stxvw4x */
270762306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
270862306a36Sopenharmony_ci			op->type = MKOP(STORE_VSX, 0, 16);
270962306a36Sopenharmony_ci			op->element_size = 4;
271062306a36Sopenharmony_ci			break;
271162306a36Sopenharmony_ci
271262306a36Sopenharmony_ci		case 909:	/* stxsibx */
271362306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
271462306a36Sopenharmony_ci				goto unknown_opcode;
271562306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
271662306a36Sopenharmony_ci			op->type = MKOP(STORE_VSX, 0, 1);
271762306a36Sopenharmony_ci			op->element_size = 8;
271862306a36Sopenharmony_ci			op->vsx_flags = VSX_CHECK_VEC;
271962306a36Sopenharmony_ci			break;
272062306a36Sopenharmony_ci
272162306a36Sopenharmony_ci		case 940:	/* stxvh8x */
272262306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
272362306a36Sopenharmony_ci				goto unknown_opcode;
272462306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
272562306a36Sopenharmony_ci			op->type = MKOP(STORE_VSX, 0, 16);
272662306a36Sopenharmony_ci			op->element_size = 2;
272762306a36Sopenharmony_ci			op->vsx_flags = VSX_CHECK_VEC;
272862306a36Sopenharmony_ci			break;
272962306a36Sopenharmony_ci
273062306a36Sopenharmony_ci		case 941:	/* stxsihx */
273162306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
273262306a36Sopenharmony_ci				goto unknown_opcode;
273362306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
273462306a36Sopenharmony_ci			op->type = MKOP(STORE_VSX, 0, 2);
273562306a36Sopenharmony_ci			op->element_size = 8;
273662306a36Sopenharmony_ci			op->vsx_flags = VSX_CHECK_VEC;
273762306a36Sopenharmony_ci			break;
273862306a36Sopenharmony_ci
273962306a36Sopenharmony_ci		case 972:	/* stxvd2x */
274062306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
274162306a36Sopenharmony_ci			op->type = MKOP(STORE_VSX, 0, 16);
274262306a36Sopenharmony_ci			op->element_size = 8;
274362306a36Sopenharmony_ci			break;
274462306a36Sopenharmony_ci
274562306a36Sopenharmony_ci		case 1004:	/* stxvb16x */
274662306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
274762306a36Sopenharmony_ci				goto unknown_opcode;
274862306a36Sopenharmony_ci			op->reg = rd | ((word & 1) << 5);
274962306a36Sopenharmony_ci			op->type = MKOP(STORE_VSX, 0, 16);
275062306a36Sopenharmony_ci			op->element_size = 1;
275162306a36Sopenharmony_ci			op->vsx_flags = VSX_CHECK_VEC;
275262306a36Sopenharmony_ci			break;
275362306a36Sopenharmony_ci
275462306a36Sopenharmony_ci#endif /* CONFIG_VSX */
275562306a36Sopenharmony_ci		}
275662306a36Sopenharmony_ci		break;
275762306a36Sopenharmony_ci
275862306a36Sopenharmony_ci	case 32:	/* lwz */
275962306a36Sopenharmony_ci	case 33:	/* lwzu */
276062306a36Sopenharmony_ci		op->type = MKOP(LOAD, u, 4);
276162306a36Sopenharmony_ci		op->ea = dform_ea(word, regs);
276262306a36Sopenharmony_ci		break;
276362306a36Sopenharmony_ci
276462306a36Sopenharmony_ci	case 34:	/* lbz */
276562306a36Sopenharmony_ci	case 35:	/* lbzu */
276662306a36Sopenharmony_ci		op->type = MKOP(LOAD, u, 1);
276762306a36Sopenharmony_ci		op->ea = dform_ea(word, regs);
276862306a36Sopenharmony_ci		break;
276962306a36Sopenharmony_ci
277062306a36Sopenharmony_ci	case 36:	/* stw */
277162306a36Sopenharmony_ci	case 37:	/* stwu */
277262306a36Sopenharmony_ci		op->type = MKOP(STORE, u, 4);
277362306a36Sopenharmony_ci		op->ea = dform_ea(word, regs);
277462306a36Sopenharmony_ci		break;
277562306a36Sopenharmony_ci
277662306a36Sopenharmony_ci	case 38:	/* stb */
277762306a36Sopenharmony_ci	case 39:	/* stbu */
277862306a36Sopenharmony_ci		op->type = MKOP(STORE, u, 1);
277962306a36Sopenharmony_ci		op->ea = dform_ea(word, regs);
278062306a36Sopenharmony_ci		break;
278162306a36Sopenharmony_ci
278262306a36Sopenharmony_ci	case 40:	/* lhz */
278362306a36Sopenharmony_ci	case 41:	/* lhzu */
278462306a36Sopenharmony_ci		op->type = MKOP(LOAD, u, 2);
278562306a36Sopenharmony_ci		op->ea = dform_ea(word, regs);
278662306a36Sopenharmony_ci		break;
278762306a36Sopenharmony_ci
278862306a36Sopenharmony_ci	case 42:	/* lha */
278962306a36Sopenharmony_ci	case 43:	/* lhau */
279062306a36Sopenharmony_ci		op->type = MKOP(LOAD, SIGNEXT | u, 2);
279162306a36Sopenharmony_ci		op->ea = dform_ea(word, regs);
279262306a36Sopenharmony_ci		break;
279362306a36Sopenharmony_ci
279462306a36Sopenharmony_ci	case 44:	/* sth */
279562306a36Sopenharmony_ci	case 45:	/* sthu */
279662306a36Sopenharmony_ci		op->type = MKOP(STORE, u, 2);
279762306a36Sopenharmony_ci		op->ea = dform_ea(word, regs);
279862306a36Sopenharmony_ci		break;
279962306a36Sopenharmony_ci
280062306a36Sopenharmony_ci	case 46:	/* lmw */
280162306a36Sopenharmony_ci		if (ra >= rd)
280262306a36Sopenharmony_ci			break;		/* invalid form, ra in range to load */
280362306a36Sopenharmony_ci		op->type = MKOP(LOAD_MULTI, 0, 4 * (32 - rd));
280462306a36Sopenharmony_ci		op->ea = dform_ea(word, regs);
280562306a36Sopenharmony_ci		break;
280662306a36Sopenharmony_ci
280762306a36Sopenharmony_ci	case 47:	/* stmw */
280862306a36Sopenharmony_ci		op->type = MKOP(STORE_MULTI, 0, 4 * (32 - rd));
280962306a36Sopenharmony_ci		op->ea = dform_ea(word, regs);
281062306a36Sopenharmony_ci		break;
281162306a36Sopenharmony_ci
281262306a36Sopenharmony_ci#ifdef CONFIG_PPC_FPU
281362306a36Sopenharmony_ci	case 48:	/* lfs */
281462306a36Sopenharmony_ci	case 49:	/* lfsu */
281562306a36Sopenharmony_ci		op->type = MKOP(LOAD_FP, u | FPCONV, 4);
281662306a36Sopenharmony_ci		op->ea = dform_ea(word, regs);
281762306a36Sopenharmony_ci		break;
281862306a36Sopenharmony_ci
281962306a36Sopenharmony_ci	case 50:	/* lfd */
282062306a36Sopenharmony_ci	case 51:	/* lfdu */
282162306a36Sopenharmony_ci		op->type = MKOP(LOAD_FP, u, 8);
282262306a36Sopenharmony_ci		op->ea = dform_ea(word, regs);
282362306a36Sopenharmony_ci		break;
282462306a36Sopenharmony_ci
282562306a36Sopenharmony_ci	case 52:	/* stfs */
282662306a36Sopenharmony_ci	case 53:	/* stfsu */
282762306a36Sopenharmony_ci		op->type = MKOP(STORE_FP, u | FPCONV, 4);
282862306a36Sopenharmony_ci		op->ea = dform_ea(word, regs);
282962306a36Sopenharmony_ci		break;
283062306a36Sopenharmony_ci
283162306a36Sopenharmony_ci	case 54:	/* stfd */
283262306a36Sopenharmony_ci	case 55:	/* stfdu */
283362306a36Sopenharmony_ci		op->type = MKOP(STORE_FP, u, 8);
283462306a36Sopenharmony_ci		op->ea = dform_ea(word, regs);
283562306a36Sopenharmony_ci		break;
283662306a36Sopenharmony_ci#endif
283762306a36Sopenharmony_ci
283862306a36Sopenharmony_ci#ifdef __powerpc64__
283962306a36Sopenharmony_ci	case 56:	/* lq */
284062306a36Sopenharmony_ci		if (!((rd & 1) || (rd == ra)))
284162306a36Sopenharmony_ci			op->type = MKOP(LOAD, 0, 16);
284262306a36Sopenharmony_ci		op->ea = dqform_ea(word, regs);
284362306a36Sopenharmony_ci		break;
284462306a36Sopenharmony_ci#endif
284562306a36Sopenharmony_ci
284662306a36Sopenharmony_ci#ifdef CONFIG_VSX
284762306a36Sopenharmony_ci	case 57:	/* lfdp, lxsd, lxssp */
284862306a36Sopenharmony_ci		op->ea = dsform_ea(word, regs);
284962306a36Sopenharmony_ci		switch (word & 3) {
285062306a36Sopenharmony_ci		case 0:		/* lfdp */
285162306a36Sopenharmony_ci			if (rd & 1)
285262306a36Sopenharmony_ci				break;		/* reg must be even */
285362306a36Sopenharmony_ci			op->type = MKOP(LOAD_FP, 0, 16);
285462306a36Sopenharmony_ci			break;
285562306a36Sopenharmony_ci		case 2:		/* lxsd */
285662306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
285762306a36Sopenharmony_ci				goto unknown_opcode;
285862306a36Sopenharmony_ci			op->reg = rd + 32;
285962306a36Sopenharmony_ci			op->type = MKOP(LOAD_VSX, 0, 8);
286062306a36Sopenharmony_ci			op->element_size = 8;
286162306a36Sopenharmony_ci			op->vsx_flags = VSX_CHECK_VEC;
286262306a36Sopenharmony_ci			break;
286362306a36Sopenharmony_ci		case 3:		/* lxssp */
286462306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
286562306a36Sopenharmony_ci				goto unknown_opcode;
286662306a36Sopenharmony_ci			op->reg = rd + 32;
286762306a36Sopenharmony_ci			op->type = MKOP(LOAD_VSX, 0, 4);
286862306a36Sopenharmony_ci			op->element_size = 8;
286962306a36Sopenharmony_ci			op->vsx_flags = VSX_FPCONV | VSX_CHECK_VEC;
287062306a36Sopenharmony_ci			break;
287162306a36Sopenharmony_ci		}
287262306a36Sopenharmony_ci		break;
287362306a36Sopenharmony_ci#endif /* CONFIG_VSX */
287462306a36Sopenharmony_ci
287562306a36Sopenharmony_ci#ifdef __powerpc64__
287662306a36Sopenharmony_ci	case 58:	/* ld[u], lwa */
287762306a36Sopenharmony_ci		op->ea = dsform_ea(word, regs);
287862306a36Sopenharmony_ci		switch (word & 3) {
287962306a36Sopenharmony_ci		case 0:		/* ld */
288062306a36Sopenharmony_ci			op->type = MKOP(LOAD, 0, 8);
288162306a36Sopenharmony_ci			break;
288262306a36Sopenharmony_ci		case 1:		/* ldu */
288362306a36Sopenharmony_ci			op->type = MKOP(LOAD, UPDATE, 8);
288462306a36Sopenharmony_ci			break;
288562306a36Sopenharmony_ci		case 2:		/* lwa */
288662306a36Sopenharmony_ci			op->type = MKOP(LOAD, SIGNEXT, 4);
288762306a36Sopenharmony_ci			break;
288862306a36Sopenharmony_ci		}
288962306a36Sopenharmony_ci		break;
289062306a36Sopenharmony_ci#endif
289162306a36Sopenharmony_ci
289262306a36Sopenharmony_ci#ifdef CONFIG_VSX
289362306a36Sopenharmony_ci	case 6:
289462306a36Sopenharmony_ci		if (!cpu_has_feature(CPU_FTR_ARCH_31))
289562306a36Sopenharmony_ci			goto unknown_opcode;
289662306a36Sopenharmony_ci		op->ea = dqform_ea(word, regs);
289762306a36Sopenharmony_ci		op->reg = VSX_REGISTER_XTP(rd);
289862306a36Sopenharmony_ci		op->element_size = 32;
289962306a36Sopenharmony_ci		switch (word & 0xf) {
290062306a36Sopenharmony_ci		case 0:         /* lxvp */
290162306a36Sopenharmony_ci			op->type = MKOP(LOAD_VSX, 0, 32);
290262306a36Sopenharmony_ci			break;
290362306a36Sopenharmony_ci		case 1:         /* stxvp */
290462306a36Sopenharmony_ci			op->type = MKOP(STORE_VSX, 0, 32);
290562306a36Sopenharmony_ci			break;
290662306a36Sopenharmony_ci		}
290762306a36Sopenharmony_ci		break;
290862306a36Sopenharmony_ci
290962306a36Sopenharmony_ci	case 61:	/* stfdp, lxv, stxsd, stxssp, stxv */
291062306a36Sopenharmony_ci		switch (word & 7) {
291162306a36Sopenharmony_ci		case 0:		/* stfdp with LSB of DS field = 0 */
291262306a36Sopenharmony_ci		case 4:		/* stfdp with LSB of DS field = 1 */
291362306a36Sopenharmony_ci			op->ea = dsform_ea(word, regs);
291462306a36Sopenharmony_ci			op->type = MKOP(STORE_FP, 0, 16);
291562306a36Sopenharmony_ci			break;
291662306a36Sopenharmony_ci
291762306a36Sopenharmony_ci		case 1:		/* lxv */
291862306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
291962306a36Sopenharmony_ci				goto unknown_opcode;
292062306a36Sopenharmony_ci			op->ea = dqform_ea(word, regs);
292162306a36Sopenharmony_ci			if (word & 8)
292262306a36Sopenharmony_ci				op->reg = rd + 32;
292362306a36Sopenharmony_ci			op->type = MKOP(LOAD_VSX, 0, 16);
292462306a36Sopenharmony_ci			op->element_size = 16;
292562306a36Sopenharmony_ci			op->vsx_flags = VSX_CHECK_VEC;
292662306a36Sopenharmony_ci			break;
292762306a36Sopenharmony_ci
292862306a36Sopenharmony_ci		case 2:		/* stxsd with LSB of DS field = 0 */
292962306a36Sopenharmony_ci		case 6:		/* stxsd with LSB of DS field = 1 */
293062306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
293162306a36Sopenharmony_ci				goto unknown_opcode;
293262306a36Sopenharmony_ci			op->ea = dsform_ea(word, regs);
293362306a36Sopenharmony_ci			op->reg = rd + 32;
293462306a36Sopenharmony_ci			op->type = MKOP(STORE_VSX, 0, 8);
293562306a36Sopenharmony_ci			op->element_size = 8;
293662306a36Sopenharmony_ci			op->vsx_flags = VSX_CHECK_VEC;
293762306a36Sopenharmony_ci			break;
293862306a36Sopenharmony_ci
293962306a36Sopenharmony_ci		case 3:		/* stxssp with LSB of DS field = 0 */
294062306a36Sopenharmony_ci		case 7:		/* stxssp with LSB of DS field = 1 */
294162306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
294262306a36Sopenharmony_ci				goto unknown_opcode;
294362306a36Sopenharmony_ci			op->ea = dsform_ea(word, regs);
294462306a36Sopenharmony_ci			op->reg = rd + 32;
294562306a36Sopenharmony_ci			op->type = MKOP(STORE_VSX, 0, 4);
294662306a36Sopenharmony_ci			op->element_size = 8;
294762306a36Sopenharmony_ci			op->vsx_flags = VSX_FPCONV | VSX_CHECK_VEC;
294862306a36Sopenharmony_ci			break;
294962306a36Sopenharmony_ci
295062306a36Sopenharmony_ci		case 5:		/* stxv */
295162306a36Sopenharmony_ci			if (!cpu_has_feature(CPU_FTR_ARCH_300))
295262306a36Sopenharmony_ci				goto unknown_opcode;
295362306a36Sopenharmony_ci			op->ea = dqform_ea(word, regs);
295462306a36Sopenharmony_ci			if (word & 8)
295562306a36Sopenharmony_ci				op->reg = rd + 32;
295662306a36Sopenharmony_ci			op->type = MKOP(STORE_VSX, 0, 16);
295762306a36Sopenharmony_ci			op->element_size = 16;
295862306a36Sopenharmony_ci			op->vsx_flags = VSX_CHECK_VEC;
295962306a36Sopenharmony_ci			break;
296062306a36Sopenharmony_ci		}
296162306a36Sopenharmony_ci		break;
296262306a36Sopenharmony_ci#endif /* CONFIG_VSX */
296362306a36Sopenharmony_ci
296462306a36Sopenharmony_ci#ifdef __powerpc64__
296562306a36Sopenharmony_ci	case 62:	/* std[u] */
296662306a36Sopenharmony_ci		op->ea = dsform_ea(word, regs);
296762306a36Sopenharmony_ci		switch (word & 3) {
296862306a36Sopenharmony_ci		case 0:		/* std */
296962306a36Sopenharmony_ci			op->type = MKOP(STORE, 0, 8);
297062306a36Sopenharmony_ci			break;
297162306a36Sopenharmony_ci		case 1:		/* stdu */
297262306a36Sopenharmony_ci			op->type = MKOP(STORE, UPDATE, 8);
297362306a36Sopenharmony_ci			break;
297462306a36Sopenharmony_ci		case 2:		/* stq */
297562306a36Sopenharmony_ci			if (!(rd & 1))
297662306a36Sopenharmony_ci				op->type = MKOP(STORE, 0, 16);
297762306a36Sopenharmony_ci			break;
297862306a36Sopenharmony_ci		}
297962306a36Sopenharmony_ci		break;
298062306a36Sopenharmony_ci	case 1: /* Prefixed instructions */
298162306a36Sopenharmony_ci		if (!cpu_has_feature(CPU_FTR_ARCH_31))
298262306a36Sopenharmony_ci			goto unknown_opcode;
298362306a36Sopenharmony_ci
298462306a36Sopenharmony_ci		prefix_r = GET_PREFIX_R(word);
298562306a36Sopenharmony_ci		ra = GET_PREFIX_RA(suffix);
298662306a36Sopenharmony_ci		op->update_reg = ra;
298762306a36Sopenharmony_ci		rd = (suffix >> 21) & 0x1f;
298862306a36Sopenharmony_ci		op->reg = rd;
298962306a36Sopenharmony_ci		op->val = regs->gpr[rd];
299062306a36Sopenharmony_ci
299162306a36Sopenharmony_ci		suffixopcode = get_op(suffix);
299262306a36Sopenharmony_ci		prefixtype = (word >> 24) & 0x3;
299362306a36Sopenharmony_ci		switch (prefixtype) {
299462306a36Sopenharmony_ci		case 0: /* Type 00  Eight-Byte Load/Store */
299562306a36Sopenharmony_ci			if (prefix_r && ra)
299662306a36Sopenharmony_ci				break;
299762306a36Sopenharmony_ci			op->ea = mlsd_8lsd_ea(word, suffix, regs);
299862306a36Sopenharmony_ci			switch (suffixopcode) {
299962306a36Sopenharmony_ci			case 41:	/* plwa */
300062306a36Sopenharmony_ci				op->type = MKOP(LOAD, PREFIXED | SIGNEXT, 4);
300162306a36Sopenharmony_ci				break;
300262306a36Sopenharmony_ci#ifdef CONFIG_VSX
300362306a36Sopenharmony_ci			case 42:        /* plxsd */
300462306a36Sopenharmony_ci				op->reg = rd + 32;
300562306a36Sopenharmony_ci				op->type = MKOP(LOAD_VSX, PREFIXED, 8);
300662306a36Sopenharmony_ci				op->element_size = 8;
300762306a36Sopenharmony_ci				op->vsx_flags = VSX_CHECK_VEC;
300862306a36Sopenharmony_ci				break;
300962306a36Sopenharmony_ci			case 43:	/* plxssp */
301062306a36Sopenharmony_ci				op->reg = rd + 32;
301162306a36Sopenharmony_ci				op->type = MKOP(LOAD_VSX, PREFIXED, 4);
301262306a36Sopenharmony_ci				op->element_size = 8;
301362306a36Sopenharmony_ci				op->vsx_flags = VSX_FPCONV | VSX_CHECK_VEC;
301462306a36Sopenharmony_ci				break;
301562306a36Sopenharmony_ci			case 46:	/* pstxsd */
301662306a36Sopenharmony_ci				op->reg = rd + 32;
301762306a36Sopenharmony_ci				op->type = MKOP(STORE_VSX, PREFIXED, 8);
301862306a36Sopenharmony_ci				op->element_size = 8;
301962306a36Sopenharmony_ci				op->vsx_flags = VSX_CHECK_VEC;
302062306a36Sopenharmony_ci				break;
302162306a36Sopenharmony_ci			case 47:	/* pstxssp */
302262306a36Sopenharmony_ci				op->reg = rd + 32;
302362306a36Sopenharmony_ci				op->type = MKOP(STORE_VSX, PREFIXED, 4);
302462306a36Sopenharmony_ci				op->element_size = 8;
302562306a36Sopenharmony_ci				op->vsx_flags = VSX_FPCONV | VSX_CHECK_VEC;
302662306a36Sopenharmony_ci				break;
302762306a36Sopenharmony_ci			case 51:	/* plxv1 */
302862306a36Sopenharmony_ci				op->reg += 32;
302962306a36Sopenharmony_ci				fallthrough;
303062306a36Sopenharmony_ci			case 50:	/* plxv0 */
303162306a36Sopenharmony_ci				op->type = MKOP(LOAD_VSX, PREFIXED, 16);
303262306a36Sopenharmony_ci				op->element_size = 16;
303362306a36Sopenharmony_ci				op->vsx_flags = VSX_CHECK_VEC;
303462306a36Sopenharmony_ci				break;
303562306a36Sopenharmony_ci			case 55:	/* pstxv1 */
303662306a36Sopenharmony_ci				op->reg = rd + 32;
303762306a36Sopenharmony_ci				fallthrough;
303862306a36Sopenharmony_ci			case 54:	/* pstxv0 */
303962306a36Sopenharmony_ci				op->type = MKOP(STORE_VSX, PREFIXED, 16);
304062306a36Sopenharmony_ci				op->element_size = 16;
304162306a36Sopenharmony_ci				op->vsx_flags = VSX_CHECK_VEC;
304262306a36Sopenharmony_ci				break;
304362306a36Sopenharmony_ci#endif /* CONFIG_VSX */
304462306a36Sopenharmony_ci			case 56:        /* plq */
304562306a36Sopenharmony_ci				op->type = MKOP(LOAD, PREFIXED, 16);
304662306a36Sopenharmony_ci				break;
304762306a36Sopenharmony_ci			case 57:	/* pld */
304862306a36Sopenharmony_ci				op->type = MKOP(LOAD, PREFIXED, 8);
304962306a36Sopenharmony_ci				break;
305062306a36Sopenharmony_ci#ifdef CONFIG_VSX
305162306a36Sopenharmony_ci			case 58:        /* plxvp */
305262306a36Sopenharmony_ci				op->reg = VSX_REGISTER_XTP(rd);
305362306a36Sopenharmony_ci				op->type = MKOP(LOAD_VSX, PREFIXED, 32);
305462306a36Sopenharmony_ci				op->element_size = 32;
305562306a36Sopenharmony_ci				break;
305662306a36Sopenharmony_ci#endif /* CONFIG_VSX */
305762306a36Sopenharmony_ci			case 60:        /* pstq */
305862306a36Sopenharmony_ci				op->type = MKOP(STORE, PREFIXED, 16);
305962306a36Sopenharmony_ci				break;
306062306a36Sopenharmony_ci			case 61:	/* pstd */
306162306a36Sopenharmony_ci				op->type = MKOP(STORE, PREFIXED, 8);
306262306a36Sopenharmony_ci				break;
306362306a36Sopenharmony_ci#ifdef CONFIG_VSX
306462306a36Sopenharmony_ci			case 62:        /* pstxvp */
306562306a36Sopenharmony_ci				op->reg = VSX_REGISTER_XTP(rd);
306662306a36Sopenharmony_ci				op->type = MKOP(STORE_VSX, PREFIXED, 32);
306762306a36Sopenharmony_ci				op->element_size = 32;
306862306a36Sopenharmony_ci				break;
306962306a36Sopenharmony_ci#endif /* CONFIG_VSX */
307062306a36Sopenharmony_ci			}
307162306a36Sopenharmony_ci			break;
307262306a36Sopenharmony_ci		case 1: /* Type 01 Eight-Byte Register-to-Register */
307362306a36Sopenharmony_ci			break;
307462306a36Sopenharmony_ci		case 2: /* Type 10 Modified Load/Store */
307562306a36Sopenharmony_ci			if (prefix_r && ra)
307662306a36Sopenharmony_ci				break;
307762306a36Sopenharmony_ci			op->ea = mlsd_8lsd_ea(word, suffix, regs);
307862306a36Sopenharmony_ci			switch (suffixopcode) {
307962306a36Sopenharmony_ci			case 32:	/* plwz */
308062306a36Sopenharmony_ci				op->type = MKOP(LOAD, PREFIXED, 4);
308162306a36Sopenharmony_ci				break;
308262306a36Sopenharmony_ci			case 34:	/* plbz */
308362306a36Sopenharmony_ci				op->type = MKOP(LOAD, PREFIXED, 1);
308462306a36Sopenharmony_ci				break;
308562306a36Sopenharmony_ci			case 36:	/* pstw */
308662306a36Sopenharmony_ci				op->type = MKOP(STORE, PREFIXED, 4);
308762306a36Sopenharmony_ci				break;
308862306a36Sopenharmony_ci			case 38:	/* pstb */
308962306a36Sopenharmony_ci				op->type = MKOP(STORE, PREFIXED, 1);
309062306a36Sopenharmony_ci				break;
309162306a36Sopenharmony_ci			case 40:	/* plhz */
309262306a36Sopenharmony_ci				op->type = MKOP(LOAD, PREFIXED, 2);
309362306a36Sopenharmony_ci				break;
309462306a36Sopenharmony_ci			case 42:	/* plha */
309562306a36Sopenharmony_ci				op->type = MKOP(LOAD, PREFIXED | SIGNEXT, 2);
309662306a36Sopenharmony_ci				break;
309762306a36Sopenharmony_ci			case 44:	/* psth */
309862306a36Sopenharmony_ci				op->type = MKOP(STORE, PREFIXED, 2);
309962306a36Sopenharmony_ci				break;
310062306a36Sopenharmony_ci			case 48:        /* plfs */
310162306a36Sopenharmony_ci				op->type = MKOP(LOAD_FP, PREFIXED | FPCONV, 4);
310262306a36Sopenharmony_ci				break;
310362306a36Sopenharmony_ci			case 50:        /* plfd */
310462306a36Sopenharmony_ci				op->type = MKOP(LOAD_FP, PREFIXED, 8);
310562306a36Sopenharmony_ci				break;
310662306a36Sopenharmony_ci			case 52:        /* pstfs */
310762306a36Sopenharmony_ci				op->type = MKOP(STORE_FP, PREFIXED | FPCONV, 4);
310862306a36Sopenharmony_ci				break;
310962306a36Sopenharmony_ci			case 54:        /* pstfd */
311062306a36Sopenharmony_ci				op->type = MKOP(STORE_FP, PREFIXED, 8);
311162306a36Sopenharmony_ci				break;
311262306a36Sopenharmony_ci			}
311362306a36Sopenharmony_ci			break;
311462306a36Sopenharmony_ci		case 3: /* Type 11 Modified Register-to-Register */
311562306a36Sopenharmony_ci			break;
311662306a36Sopenharmony_ci		}
311762306a36Sopenharmony_ci#endif /* __powerpc64__ */
311862306a36Sopenharmony_ci
311962306a36Sopenharmony_ci	}
312062306a36Sopenharmony_ci
312162306a36Sopenharmony_ci	if (OP_IS_LOAD_STORE(op->type) && (op->type & UPDATE)) {
312262306a36Sopenharmony_ci		switch (GETTYPE(op->type)) {
312362306a36Sopenharmony_ci		case LOAD:
312462306a36Sopenharmony_ci			if (ra == rd)
312562306a36Sopenharmony_ci				goto unknown_opcode;
312662306a36Sopenharmony_ci			fallthrough;
312762306a36Sopenharmony_ci		case STORE:
312862306a36Sopenharmony_ci		case LOAD_FP:
312962306a36Sopenharmony_ci		case STORE_FP:
313062306a36Sopenharmony_ci			if (ra == 0)
313162306a36Sopenharmony_ci				goto unknown_opcode;
313262306a36Sopenharmony_ci		}
313362306a36Sopenharmony_ci	}
313462306a36Sopenharmony_ci
313562306a36Sopenharmony_ci#ifdef CONFIG_VSX
313662306a36Sopenharmony_ci	if ((GETTYPE(op->type) == LOAD_VSX ||
313762306a36Sopenharmony_ci	     GETTYPE(op->type) == STORE_VSX) &&
313862306a36Sopenharmony_ci	    !cpu_has_feature(CPU_FTR_VSX)) {
313962306a36Sopenharmony_ci		return -1;
314062306a36Sopenharmony_ci	}
314162306a36Sopenharmony_ci#endif /* CONFIG_VSX */
314262306a36Sopenharmony_ci
314362306a36Sopenharmony_ci	return 0;
314462306a36Sopenharmony_ci
314562306a36Sopenharmony_ci unknown_opcode:
314662306a36Sopenharmony_ci	op->type = UNKNOWN;
314762306a36Sopenharmony_ci	return 0;
314862306a36Sopenharmony_ci
314962306a36Sopenharmony_ci logical_done:
315062306a36Sopenharmony_ci	if (word & 1)
315162306a36Sopenharmony_ci		set_cr0(regs, op);
315262306a36Sopenharmony_ci logical_done_nocc:
315362306a36Sopenharmony_ci	op->reg = ra;
315462306a36Sopenharmony_ci	op->type |= SETREG;
315562306a36Sopenharmony_ci	return 1;
315662306a36Sopenharmony_ci
315762306a36Sopenharmony_ci arith_done:
315862306a36Sopenharmony_ci	if (word & 1)
315962306a36Sopenharmony_ci		set_cr0(regs, op);
316062306a36Sopenharmony_ci compute_done:
316162306a36Sopenharmony_ci	op->reg = rd;
316262306a36Sopenharmony_ci	op->type |= SETREG;
316362306a36Sopenharmony_ci	return 1;
316462306a36Sopenharmony_ci
316562306a36Sopenharmony_ci priv:
316662306a36Sopenharmony_ci	op->type = INTERRUPT | 0x700;
316762306a36Sopenharmony_ci	op->val = SRR1_PROGPRIV;
316862306a36Sopenharmony_ci	return 0;
316962306a36Sopenharmony_ci
317062306a36Sopenharmony_ci trap:
317162306a36Sopenharmony_ci	op->type = INTERRUPT | 0x700;
317262306a36Sopenharmony_ci	op->val = SRR1_PROGTRAP;
317362306a36Sopenharmony_ci	return 0;
317462306a36Sopenharmony_ci}
317562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(analyse_instr);
317662306a36Sopenharmony_ciNOKPROBE_SYMBOL(analyse_instr);
317762306a36Sopenharmony_ci
317862306a36Sopenharmony_ci/*
317962306a36Sopenharmony_ci * For PPC32 we always use stwu with r1 to change the stack pointer.
318062306a36Sopenharmony_ci * So this emulated store may corrupt the exception frame, now we
318162306a36Sopenharmony_ci * have to provide the exception frame trampoline, which is pushed
318262306a36Sopenharmony_ci * below the kprobed function stack. So we only update gpr[1] but
318362306a36Sopenharmony_ci * don't emulate the real store operation. We will do real store
318462306a36Sopenharmony_ci * operation safely in exception return code by checking this flag.
318562306a36Sopenharmony_ci */
318662306a36Sopenharmony_cistatic nokprobe_inline int handle_stack_update(unsigned long ea, struct pt_regs *regs)
318762306a36Sopenharmony_ci{
318862306a36Sopenharmony_ci	/*
318962306a36Sopenharmony_ci	 * Check if we already set since that means we'll
319062306a36Sopenharmony_ci	 * lose the previous value.
319162306a36Sopenharmony_ci	 */
319262306a36Sopenharmony_ci	WARN_ON(test_thread_flag(TIF_EMULATE_STACK_STORE));
319362306a36Sopenharmony_ci	set_thread_flag(TIF_EMULATE_STACK_STORE);
319462306a36Sopenharmony_ci	return 0;
319562306a36Sopenharmony_ci}
319662306a36Sopenharmony_ci
319762306a36Sopenharmony_cistatic nokprobe_inline void do_signext(unsigned long *valp, int size)
319862306a36Sopenharmony_ci{
319962306a36Sopenharmony_ci	switch (size) {
320062306a36Sopenharmony_ci	case 2:
320162306a36Sopenharmony_ci		*valp = (signed short) *valp;
320262306a36Sopenharmony_ci		break;
320362306a36Sopenharmony_ci	case 4:
320462306a36Sopenharmony_ci		*valp = (signed int) *valp;
320562306a36Sopenharmony_ci		break;
320662306a36Sopenharmony_ci	}
320762306a36Sopenharmony_ci}
320862306a36Sopenharmony_ci
320962306a36Sopenharmony_cistatic nokprobe_inline void do_byterev(unsigned long *valp, int size)
321062306a36Sopenharmony_ci{
321162306a36Sopenharmony_ci	switch (size) {
321262306a36Sopenharmony_ci	case 2:
321362306a36Sopenharmony_ci		*valp = byterev_2(*valp);
321462306a36Sopenharmony_ci		break;
321562306a36Sopenharmony_ci	case 4:
321662306a36Sopenharmony_ci		*valp = byterev_4(*valp);
321762306a36Sopenharmony_ci		break;
321862306a36Sopenharmony_ci#ifdef __powerpc64__
321962306a36Sopenharmony_ci	case 8:
322062306a36Sopenharmony_ci		*valp = byterev_8(*valp);
322162306a36Sopenharmony_ci		break;
322262306a36Sopenharmony_ci#endif
322362306a36Sopenharmony_ci	}
322462306a36Sopenharmony_ci}
322562306a36Sopenharmony_ci
322662306a36Sopenharmony_ci/*
322762306a36Sopenharmony_ci * Emulate an instruction that can be executed just by updating
322862306a36Sopenharmony_ci * fields in *regs.
322962306a36Sopenharmony_ci */
323062306a36Sopenharmony_civoid emulate_update_regs(struct pt_regs *regs, struct instruction_op *op)
323162306a36Sopenharmony_ci{
323262306a36Sopenharmony_ci	unsigned long next_pc;
323362306a36Sopenharmony_ci
323462306a36Sopenharmony_ci	next_pc = truncate_if_32bit(regs->msr, regs->nip + GETLENGTH(op->type));
323562306a36Sopenharmony_ci	switch (GETTYPE(op->type)) {
323662306a36Sopenharmony_ci	case COMPUTE:
323762306a36Sopenharmony_ci		if (op->type & SETREG)
323862306a36Sopenharmony_ci			regs->gpr[op->reg] = op->val;
323962306a36Sopenharmony_ci		if (op->type & SETCC)
324062306a36Sopenharmony_ci			regs->ccr = op->ccval;
324162306a36Sopenharmony_ci		if (op->type & SETXER)
324262306a36Sopenharmony_ci			regs->xer = op->xerval;
324362306a36Sopenharmony_ci		break;
324462306a36Sopenharmony_ci
324562306a36Sopenharmony_ci	case BRANCH:
324662306a36Sopenharmony_ci		if (op->type & SETLK)
324762306a36Sopenharmony_ci			regs->link = next_pc;
324862306a36Sopenharmony_ci		if (op->type & BRTAKEN)
324962306a36Sopenharmony_ci			next_pc = op->val;
325062306a36Sopenharmony_ci		if (op->type & DECCTR)
325162306a36Sopenharmony_ci			--regs->ctr;
325262306a36Sopenharmony_ci		break;
325362306a36Sopenharmony_ci
325462306a36Sopenharmony_ci	case BARRIER:
325562306a36Sopenharmony_ci		switch (op->type & BARRIER_MASK) {
325662306a36Sopenharmony_ci		case BARRIER_SYNC:
325762306a36Sopenharmony_ci			mb();
325862306a36Sopenharmony_ci			break;
325962306a36Sopenharmony_ci		case BARRIER_ISYNC:
326062306a36Sopenharmony_ci			isync();
326162306a36Sopenharmony_ci			break;
326262306a36Sopenharmony_ci		case BARRIER_EIEIO:
326362306a36Sopenharmony_ci			eieio();
326462306a36Sopenharmony_ci			break;
326562306a36Sopenharmony_ci#ifdef CONFIG_PPC64
326662306a36Sopenharmony_ci		case BARRIER_LWSYNC:
326762306a36Sopenharmony_ci			asm volatile("lwsync" : : : "memory");
326862306a36Sopenharmony_ci			break;
326962306a36Sopenharmony_ci		case BARRIER_PTESYNC:
327062306a36Sopenharmony_ci			asm volatile("ptesync" : : : "memory");
327162306a36Sopenharmony_ci			break;
327262306a36Sopenharmony_ci#endif
327362306a36Sopenharmony_ci		}
327462306a36Sopenharmony_ci		break;
327562306a36Sopenharmony_ci
327662306a36Sopenharmony_ci	case MFSPR:
327762306a36Sopenharmony_ci		switch (op->spr) {
327862306a36Sopenharmony_ci		case SPRN_XER:
327962306a36Sopenharmony_ci			regs->gpr[op->reg] = regs->xer & 0xffffffffUL;
328062306a36Sopenharmony_ci			break;
328162306a36Sopenharmony_ci		case SPRN_LR:
328262306a36Sopenharmony_ci			regs->gpr[op->reg] = regs->link;
328362306a36Sopenharmony_ci			break;
328462306a36Sopenharmony_ci		case SPRN_CTR:
328562306a36Sopenharmony_ci			regs->gpr[op->reg] = regs->ctr;
328662306a36Sopenharmony_ci			break;
328762306a36Sopenharmony_ci		default:
328862306a36Sopenharmony_ci			WARN_ON_ONCE(1);
328962306a36Sopenharmony_ci		}
329062306a36Sopenharmony_ci		break;
329162306a36Sopenharmony_ci
329262306a36Sopenharmony_ci	case MTSPR:
329362306a36Sopenharmony_ci		switch (op->spr) {
329462306a36Sopenharmony_ci		case SPRN_XER:
329562306a36Sopenharmony_ci			regs->xer = op->val & 0xffffffffUL;
329662306a36Sopenharmony_ci			break;
329762306a36Sopenharmony_ci		case SPRN_LR:
329862306a36Sopenharmony_ci			regs->link = op->val;
329962306a36Sopenharmony_ci			break;
330062306a36Sopenharmony_ci		case SPRN_CTR:
330162306a36Sopenharmony_ci			regs->ctr = op->val;
330262306a36Sopenharmony_ci			break;
330362306a36Sopenharmony_ci		default:
330462306a36Sopenharmony_ci			WARN_ON_ONCE(1);
330562306a36Sopenharmony_ci		}
330662306a36Sopenharmony_ci		break;
330762306a36Sopenharmony_ci
330862306a36Sopenharmony_ci	default:
330962306a36Sopenharmony_ci		WARN_ON_ONCE(1);
331062306a36Sopenharmony_ci	}
331162306a36Sopenharmony_ci	regs_set_return_ip(regs, next_pc);
331262306a36Sopenharmony_ci}
331362306a36Sopenharmony_ciNOKPROBE_SYMBOL(emulate_update_regs);
331462306a36Sopenharmony_ci
331562306a36Sopenharmony_ci/*
331662306a36Sopenharmony_ci * Emulate a previously-analysed load or store instruction.
331762306a36Sopenharmony_ci * Return values are:
331862306a36Sopenharmony_ci * 0 = instruction emulated successfully
331962306a36Sopenharmony_ci * -EFAULT = address out of range or access faulted (regs->dar
332062306a36Sopenharmony_ci *	     contains the faulting address)
332162306a36Sopenharmony_ci * -EACCES = misaligned access, instruction requires alignment
332262306a36Sopenharmony_ci * -EINVAL = unknown operation in *op
332362306a36Sopenharmony_ci */
332462306a36Sopenharmony_ciint emulate_loadstore(struct pt_regs *regs, struct instruction_op *op)
332562306a36Sopenharmony_ci{
332662306a36Sopenharmony_ci	int err, size, type;
332762306a36Sopenharmony_ci	int i, rd, nb;
332862306a36Sopenharmony_ci	unsigned int cr;
332962306a36Sopenharmony_ci	unsigned long val;
333062306a36Sopenharmony_ci	unsigned long ea;
333162306a36Sopenharmony_ci	bool cross_endian;
333262306a36Sopenharmony_ci
333362306a36Sopenharmony_ci	err = 0;
333462306a36Sopenharmony_ci	size = GETSIZE(op->type);
333562306a36Sopenharmony_ci	type = GETTYPE(op->type);
333662306a36Sopenharmony_ci	cross_endian = (regs->msr & MSR_LE) != (MSR_KERNEL & MSR_LE);
333762306a36Sopenharmony_ci	ea = truncate_if_32bit(regs->msr, op->ea);
333862306a36Sopenharmony_ci
333962306a36Sopenharmony_ci	switch (type) {
334062306a36Sopenharmony_ci	case LARX:
334162306a36Sopenharmony_ci		if (ea & (size - 1))
334262306a36Sopenharmony_ci			return -EACCES;		/* can't handle misaligned */
334362306a36Sopenharmony_ci		if (!address_ok(regs, ea, size))
334462306a36Sopenharmony_ci			return -EFAULT;
334562306a36Sopenharmony_ci		err = 0;
334662306a36Sopenharmony_ci		val = 0;
334762306a36Sopenharmony_ci		switch (size) {
334862306a36Sopenharmony_ci#ifdef CONFIG_PPC_HAS_LBARX_LHARX
334962306a36Sopenharmony_ci		case 1:
335062306a36Sopenharmony_ci			__get_user_asmx(val, ea, err, "lbarx");
335162306a36Sopenharmony_ci			break;
335262306a36Sopenharmony_ci		case 2:
335362306a36Sopenharmony_ci			__get_user_asmx(val, ea, err, "lharx");
335462306a36Sopenharmony_ci			break;
335562306a36Sopenharmony_ci#endif
335662306a36Sopenharmony_ci		case 4:
335762306a36Sopenharmony_ci			__get_user_asmx(val, ea, err, "lwarx");
335862306a36Sopenharmony_ci			break;
335962306a36Sopenharmony_ci#ifdef __powerpc64__
336062306a36Sopenharmony_ci		case 8:
336162306a36Sopenharmony_ci			__get_user_asmx(val, ea, err, "ldarx");
336262306a36Sopenharmony_ci			break;
336362306a36Sopenharmony_ci		case 16:
336462306a36Sopenharmony_ci			err = do_lqarx(ea, &regs->gpr[op->reg]);
336562306a36Sopenharmony_ci			break;
336662306a36Sopenharmony_ci#endif
336762306a36Sopenharmony_ci		default:
336862306a36Sopenharmony_ci			return -EINVAL;
336962306a36Sopenharmony_ci		}
337062306a36Sopenharmony_ci		if (err) {
337162306a36Sopenharmony_ci			regs->dar = ea;
337262306a36Sopenharmony_ci			break;
337362306a36Sopenharmony_ci		}
337462306a36Sopenharmony_ci		if (size < 16)
337562306a36Sopenharmony_ci			regs->gpr[op->reg] = val;
337662306a36Sopenharmony_ci		break;
337762306a36Sopenharmony_ci
337862306a36Sopenharmony_ci	case STCX:
337962306a36Sopenharmony_ci		if (ea & (size - 1))
338062306a36Sopenharmony_ci			return -EACCES;		/* can't handle misaligned */
338162306a36Sopenharmony_ci		if (!address_ok(regs, ea, size))
338262306a36Sopenharmony_ci			return -EFAULT;
338362306a36Sopenharmony_ci		err = 0;
338462306a36Sopenharmony_ci		switch (size) {
338562306a36Sopenharmony_ci#ifdef __powerpc64__
338662306a36Sopenharmony_ci		case 1:
338762306a36Sopenharmony_ci			__put_user_asmx(op->val, ea, err, "stbcx.", cr);
338862306a36Sopenharmony_ci			break;
338962306a36Sopenharmony_ci		case 2:
339062306a36Sopenharmony_ci			__put_user_asmx(op->val, ea, err, "sthcx.", cr);
339162306a36Sopenharmony_ci			break;
339262306a36Sopenharmony_ci#endif
339362306a36Sopenharmony_ci		case 4:
339462306a36Sopenharmony_ci			__put_user_asmx(op->val, ea, err, "stwcx.", cr);
339562306a36Sopenharmony_ci			break;
339662306a36Sopenharmony_ci#ifdef __powerpc64__
339762306a36Sopenharmony_ci		case 8:
339862306a36Sopenharmony_ci			__put_user_asmx(op->val, ea, err, "stdcx.", cr);
339962306a36Sopenharmony_ci			break;
340062306a36Sopenharmony_ci		case 16:
340162306a36Sopenharmony_ci			err = do_stqcx(ea, regs->gpr[op->reg],
340262306a36Sopenharmony_ci				       regs->gpr[op->reg + 1], &cr);
340362306a36Sopenharmony_ci			break;
340462306a36Sopenharmony_ci#endif
340562306a36Sopenharmony_ci		default:
340662306a36Sopenharmony_ci			return -EINVAL;
340762306a36Sopenharmony_ci		}
340862306a36Sopenharmony_ci		if (!err)
340962306a36Sopenharmony_ci			regs->ccr = (regs->ccr & 0x0fffffff) |
341062306a36Sopenharmony_ci				(cr & 0xe0000000) |
341162306a36Sopenharmony_ci				((regs->xer >> 3) & 0x10000000);
341262306a36Sopenharmony_ci		else
341362306a36Sopenharmony_ci			regs->dar = ea;
341462306a36Sopenharmony_ci		break;
341562306a36Sopenharmony_ci
341662306a36Sopenharmony_ci	case LOAD:
341762306a36Sopenharmony_ci#ifdef __powerpc64__
341862306a36Sopenharmony_ci		if (size == 16) {
341962306a36Sopenharmony_ci			err = emulate_lq(regs, ea, op->reg, cross_endian);
342062306a36Sopenharmony_ci			break;
342162306a36Sopenharmony_ci		}
342262306a36Sopenharmony_ci#endif
342362306a36Sopenharmony_ci		err = read_mem(&regs->gpr[op->reg], ea, size, regs);
342462306a36Sopenharmony_ci		if (!err) {
342562306a36Sopenharmony_ci			if (op->type & SIGNEXT)
342662306a36Sopenharmony_ci				do_signext(&regs->gpr[op->reg], size);
342762306a36Sopenharmony_ci			if ((op->type & BYTEREV) == (cross_endian ? 0 : BYTEREV))
342862306a36Sopenharmony_ci				do_byterev(&regs->gpr[op->reg], size);
342962306a36Sopenharmony_ci		}
343062306a36Sopenharmony_ci		break;
343162306a36Sopenharmony_ci
343262306a36Sopenharmony_ci#ifdef CONFIG_PPC_FPU
343362306a36Sopenharmony_ci	case LOAD_FP:
343462306a36Sopenharmony_ci		/*
343562306a36Sopenharmony_ci		 * If the instruction is in userspace, we can emulate it even
343662306a36Sopenharmony_ci		 * if the VMX state is not live, because we have the state
343762306a36Sopenharmony_ci		 * stored in the thread_struct.  If the instruction is in
343862306a36Sopenharmony_ci		 * the kernel, we must not touch the state in the thread_struct.
343962306a36Sopenharmony_ci		 */
344062306a36Sopenharmony_ci		if (!(regs->msr & MSR_PR) && !(regs->msr & MSR_FP))
344162306a36Sopenharmony_ci			return 0;
344262306a36Sopenharmony_ci		err = do_fp_load(op, ea, regs, cross_endian);
344362306a36Sopenharmony_ci		break;
344462306a36Sopenharmony_ci#endif
344562306a36Sopenharmony_ci#ifdef CONFIG_ALTIVEC
344662306a36Sopenharmony_ci	case LOAD_VMX:
344762306a36Sopenharmony_ci		if (!(regs->msr & MSR_PR) && !(regs->msr & MSR_VEC))
344862306a36Sopenharmony_ci			return 0;
344962306a36Sopenharmony_ci		err = do_vec_load(op->reg, ea, size, regs, cross_endian);
345062306a36Sopenharmony_ci		break;
345162306a36Sopenharmony_ci#endif
345262306a36Sopenharmony_ci#ifdef CONFIG_VSX
345362306a36Sopenharmony_ci	case LOAD_VSX: {
345462306a36Sopenharmony_ci		unsigned long msrbit = MSR_VSX;
345562306a36Sopenharmony_ci
345662306a36Sopenharmony_ci		/*
345762306a36Sopenharmony_ci		 * Some VSX instructions check the MSR_VEC bit rather than MSR_VSX
345862306a36Sopenharmony_ci		 * when the target of the instruction is a vector register.
345962306a36Sopenharmony_ci		 */
346062306a36Sopenharmony_ci		if (op->reg >= 32 && (op->vsx_flags & VSX_CHECK_VEC))
346162306a36Sopenharmony_ci			msrbit = MSR_VEC;
346262306a36Sopenharmony_ci		if (!(regs->msr & MSR_PR) && !(regs->msr & msrbit))
346362306a36Sopenharmony_ci			return 0;
346462306a36Sopenharmony_ci		err = do_vsx_load(op, ea, regs, cross_endian);
346562306a36Sopenharmony_ci		break;
346662306a36Sopenharmony_ci	}
346762306a36Sopenharmony_ci#endif
346862306a36Sopenharmony_ci	case LOAD_MULTI:
346962306a36Sopenharmony_ci		if (!address_ok(regs, ea, size))
347062306a36Sopenharmony_ci			return -EFAULT;
347162306a36Sopenharmony_ci		rd = op->reg;
347262306a36Sopenharmony_ci		for (i = 0; i < size; i += 4) {
347362306a36Sopenharmony_ci			unsigned int v32 = 0;
347462306a36Sopenharmony_ci
347562306a36Sopenharmony_ci			nb = size - i;
347662306a36Sopenharmony_ci			if (nb > 4)
347762306a36Sopenharmony_ci				nb = 4;
347862306a36Sopenharmony_ci			err = copy_mem_in((u8 *) &v32, ea, nb, regs);
347962306a36Sopenharmony_ci			if (err)
348062306a36Sopenharmony_ci				break;
348162306a36Sopenharmony_ci			if (unlikely(cross_endian))
348262306a36Sopenharmony_ci				v32 = byterev_4(v32);
348362306a36Sopenharmony_ci			regs->gpr[rd] = v32;
348462306a36Sopenharmony_ci			ea += 4;
348562306a36Sopenharmony_ci			/* reg number wraps from 31 to 0 for lsw[ix] */
348662306a36Sopenharmony_ci			rd = (rd + 1) & 0x1f;
348762306a36Sopenharmony_ci		}
348862306a36Sopenharmony_ci		break;
348962306a36Sopenharmony_ci
349062306a36Sopenharmony_ci	case STORE:
349162306a36Sopenharmony_ci#ifdef __powerpc64__
349262306a36Sopenharmony_ci		if (size == 16) {
349362306a36Sopenharmony_ci			err = emulate_stq(regs, ea, op->reg, cross_endian);
349462306a36Sopenharmony_ci			break;
349562306a36Sopenharmony_ci		}
349662306a36Sopenharmony_ci#endif
349762306a36Sopenharmony_ci		if ((op->type & UPDATE) && size == sizeof(long) &&
349862306a36Sopenharmony_ci		    op->reg == 1 && op->update_reg == 1 &&
349962306a36Sopenharmony_ci		    !(regs->msr & MSR_PR) &&
350062306a36Sopenharmony_ci		    ea >= regs->gpr[1] - STACK_INT_FRAME_SIZE) {
350162306a36Sopenharmony_ci			err = handle_stack_update(ea, regs);
350262306a36Sopenharmony_ci			break;
350362306a36Sopenharmony_ci		}
350462306a36Sopenharmony_ci		if (unlikely(cross_endian))
350562306a36Sopenharmony_ci			do_byterev(&op->val, size);
350662306a36Sopenharmony_ci		err = write_mem(op->val, ea, size, regs);
350762306a36Sopenharmony_ci		break;
350862306a36Sopenharmony_ci
350962306a36Sopenharmony_ci#ifdef CONFIG_PPC_FPU
351062306a36Sopenharmony_ci	case STORE_FP:
351162306a36Sopenharmony_ci		if (!(regs->msr & MSR_PR) && !(regs->msr & MSR_FP))
351262306a36Sopenharmony_ci			return 0;
351362306a36Sopenharmony_ci		err = do_fp_store(op, ea, regs, cross_endian);
351462306a36Sopenharmony_ci		break;
351562306a36Sopenharmony_ci#endif
351662306a36Sopenharmony_ci#ifdef CONFIG_ALTIVEC
351762306a36Sopenharmony_ci	case STORE_VMX:
351862306a36Sopenharmony_ci		if (!(regs->msr & MSR_PR) && !(regs->msr & MSR_VEC))
351962306a36Sopenharmony_ci			return 0;
352062306a36Sopenharmony_ci		err = do_vec_store(op->reg, ea, size, regs, cross_endian);
352162306a36Sopenharmony_ci		break;
352262306a36Sopenharmony_ci#endif
352362306a36Sopenharmony_ci#ifdef CONFIG_VSX
352462306a36Sopenharmony_ci	case STORE_VSX: {
352562306a36Sopenharmony_ci		unsigned long msrbit = MSR_VSX;
352662306a36Sopenharmony_ci
352762306a36Sopenharmony_ci		/*
352862306a36Sopenharmony_ci		 * Some VSX instructions check the MSR_VEC bit rather than MSR_VSX
352962306a36Sopenharmony_ci		 * when the target of the instruction is a vector register.
353062306a36Sopenharmony_ci		 */
353162306a36Sopenharmony_ci		if (op->reg >= 32 && (op->vsx_flags & VSX_CHECK_VEC))
353262306a36Sopenharmony_ci			msrbit = MSR_VEC;
353362306a36Sopenharmony_ci		if (!(regs->msr & MSR_PR) && !(regs->msr & msrbit))
353462306a36Sopenharmony_ci			return 0;
353562306a36Sopenharmony_ci		err = do_vsx_store(op, ea, regs, cross_endian);
353662306a36Sopenharmony_ci		break;
353762306a36Sopenharmony_ci	}
353862306a36Sopenharmony_ci#endif
353962306a36Sopenharmony_ci	case STORE_MULTI:
354062306a36Sopenharmony_ci		if (!address_ok(regs, ea, size))
354162306a36Sopenharmony_ci			return -EFAULT;
354262306a36Sopenharmony_ci		rd = op->reg;
354362306a36Sopenharmony_ci		for (i = 0; i < size; i += 4) {
354462306a36Sopenharmony_ci			unsigned int v32 = regs->gpr[rd];
354562306a36Sopenharmony_ci
354662306a36Sopenharmony_ci			nb = size - i;
354762306a36Sopenharmony_ci			if (nb > 4)
354862306a36Sopenharmony_ci				nb = 4;
354962306a36Sopenharmony_ci			if (unlikely(cross_endian))
355062306a36Sopenharmony_ci				v32 = byterev_4(v32);
355162306a36Sopenharmony_ci			err = copy_mem_out((u8 *) &v32, ea, nb, regs);
355262306a36Sopenharmony_ci			if (err)
355362306a36Sopenharmony_ci				break;
355462306a36Sopenharmony_ci			ea += 4;
355562306a36Sopenharmony_ci			/* reg number wraps from 31 to 0 for stsw[ix] */
355662306a36Sopenharmony_ci			rd = (rd + 1) & 0x1f;
355762306a36Sopenharmony_ci		}
355862306a36Sopenharmony_ci		break;
355962306a36Sopenharmony_ci
356062306a36Sopenharmony_ci	default:
356162306a36Sopenharmony_ci		return -EINVAL;
356262306a36Sopenharmony_ci	}
356362306a36Sopenharmony_ci
356462306a36Sopenharmony_ci	if (err)
356562306a36Sopenharmony_ci		return err;
356662306a36Sopenharmony_ci
356762306a36Sopenharmony_ci	if (op->type & UPDATE)
356862306a36Sopenharmony_ci		regs->gpr[op->update_reg] = op->ea;
356962306a36Sopenharmony_ci
357062306a36Sopenharmony_ci	return 0;
357162306a36Sopenharmony_ci}
357262306a36Sopenharmony_ciNOKPROBE_SYMBOL(emulate_loadstore);
357362306a36Sopenharmony_ci
357462306a36Sopenharmony_ci/*
357562306a36Sopenharmony_ci * Emulate instructions that cause a transfer of control,
357662306a36Sopenharmony_ci * loads and stores, and a few other instructions.
357762306a36Sopenharmony_ci * Returns 1 if the step was emulated, 0 if not,
357862306a36Sopenharmony_ci * or -1 if the instruction is one that should not be stepped,
357962306a36Sopenharmony_ci * such as an rfid, or a mtmsrd that would clear MSR_RI.
358062306a36Sopenharmony_ci */
358162306a36Sopenharmony_ciint emulate_step(struct pt_regs *regs, ppc_inst_t instr)
358262306a36Sopenharmony_ci{
358362306a36Sopenharmony_ci	struct instruction_op op;
358462306a36Sopenharmony_ci	int r, err, type;
358562306a36Sopenharmony_ci	unsigned long val;
358662306a36Sopenharmony_ci	unsigned long ea;
358762306a36Sopenharmony_ci
358862306a36Sopenharmony_ci	r = analyse_instr(&op, regs, instr);
358962306a36Sopenharmony_ci	if (r < 0)
359062306a36Sopenharmony_ci		return r;
359162306a36Sopenharmony_ci	if (r > 0) {
359262306a36Sopenharmony_ci		emulate_update_regs(regs, &op);
359362306a36Sopenharmony_ci		return 1;
359462306a36Sopenharmony_ci	}
359562306a36Sopenharmony_ci
359662306a36Sopenharmony_ci	err = 0;
359762306a36Sopenharmony_ci	type = GETTYPE(op.type);
359862306a36Sopenharmony_ci
359962306a36Sopenharmony_ci	if (OP_IS_LOAD_STORE(type)) {
360062306a36Sopenharmony_ci		err = emulate_loadstore(regs, &op);
360162306a36Sopenharmony_ci		if (err)
360262306a36Sopenharmony_ci			return 0;
360362306a36Sopenharmony_ci		goto instr_done;
360462306a36Sopenharmony_ci	}
360562306a36Sopenharmony_ci
360662306a36Sopenharmony_ci	switch (type) {
360762306a36Sopenharmony_ci	case CACHEOP:
360862306a36Sopenharmony_ci		ea = truncate_if_32bit(regs->msr, op.ea);
360962306a36Sopenharmony_ci		if (!address_ok(regs, ea, 8))
361062306a36Sopenharmony_ci			return 0;
361162306a36Sopenharmony_ci		switch (op.type & CACHEOP_MASK) {
361262306a36Sopenharmony_ci		case DCBST:
361362306a36Sopenharmony_ci			__cacheop_user_asmx(ea, err, "dcbst");
361462306a36Sopenharmony_ci			break;
361562306a36Sopenharmony_ci		case DCBF:
361662306a36Sopenharmony_ci			__cacheop_user_asmx(ea, err, "dcbf");
361762306a36Sopenharmony_ci			break;
361862306a36Sopenharmony_ci		case DCBTST:
361962306a36Sopenharmony_ci			if (op.reg == 0)
362062306a36Sopenharmony_ci				prefetchw((void *) ea);
362162306a36Sopenharmony_ci			break;
362262306a36Sopenharmony_ci		case DCBT:
362362306a36Sopenharmony_ci			if (op.reg == 0)
362462306a36Sopenharmony_ci				prefetch((void *) ea);
362562306a36Sopenharmony_ci			break;
362662306a36Sopenharmony_ci		case ICBI:
362762306a36Sopenharmony_ci			__cacheop_user_asmx(ea, err, "icbi");
362862306a36Sopenharmony_ci			break;
362962306a36Sopenharmony_ci		case DCBZ:
363062306a36Sopenharmony_ci			err = emulate_dcbz(ea, regs);
363162306a36Sopenharmony_ci			break;
363262306a36Sopenharmony_ci		}
363362306a36Sopenharmony_ci		if (err) {
363462306a36Sopenharmony_ci			regs->dar = ea;
363562306a36Sopenharmony_ci			return 0;
363662306a36Sopenharmony_ci		}
363762306a36Sopenharmony_ci		goto instr_done;
363862306a36Sopenharmony_ci
363962306a36Sopenharmony_ci	case MFMSR:
364062306a36Sopenharmony_ci		regs->gpr[op.reg] = regs->msr & MSR_MASK;
364162306a36Sopenharmony_ci		goto instr_done;
364262306a36Sopenharmony_ci
364362306a36Sopenharmony_ci	case MTMSR:
364462306a36Sopenharmony_ci		val = regs->gpr[op.reg];
364562306a36Sopenharmony_ci		if ((val & MSR_RI) == 0)
364662306a36Sopenharmony_ci			/* can't step mtmsr[d] that would clear MSR_RI */
364762306a36Sopenharmony_ci			return -1;
364862306a36Sopenharmony_ci		/* here op.val is the mask of bits to change */
364962306a36Sopenharmony_ci		regs_set_return_msr(regs, (regs->msr & ~op.val) | (val & op.val));
365062306a36Sopenharmony_ci		goto instr_done;
365162306a36Sopenharmony_ci
365262306a36Sopenharmony_ci	case SYSCALL:	/* sc */
365362306a36Sopenharmony_ci		/*
365462306a36Sopenharmony_ci		 * Per ISA v3.1, section 7.5.15 'Trace Interrupt', we can't
365562306a36Sopenharmony_ci		 * single step a system call instruction:
365662306a36Sopenharmony_ci		 *
365762306a36Sopenharmony_ci		 *   Successful completion for an instruction means that the
365862306a36Sopenharmony_ci		 *   instruction caused no other interrupt. Thus a Trace
365962306a36Sopenharmony_ci		 *   interrupt never occurs for a System Call or System Call
366062306a36Sopenharmony_ci		 *   Vectored instruction, or for a Trap instruction that
366162306a36Sopenharmony_ci		 *   traps.
366262306a36Sopenharmony_ci		 */
366362306a36Sopenharmony_ci		return -1;
366462306a36Sopenharmony_ci	case SYSCALL_VECTORED_0:	/* scv 0 */
366562306a36Sopenharmony_ci		return -1;
366662306a36Sopenharmony_ci	case RFI:
366762306a36Sopenharmony_ci		return -1;
366862306a36Sopenharmony_ci	}
366962306a36Sopenharmony_ci	return 0;
367062306a36Sopenharmony_ci
367162306a36Sopenharmony_ci instr_done:
367262306a36Sopenharmony_ci	regs_set_return_ip(regs,
367362306a36Sopenharmony_ci		truncate_if_32bit(regs->msr, regs->nip + GETLENGTH(op.type)));
367462306a36Sopenharmony_ci	return 1;
367562306a36Sopenharmony_ci}
367662306a36Sopenharmony_ciNOKPROBE_SYMBOL(emulate_step);
3677