18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
28c2ecf20Sopenharmony_ci#ifndef _ASM_POWERPC_INST_H
38c2ecf20Sopenharmony_ci#define _ASM_POWERPC_INST_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <asm/ppc-opcode.h>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci/*
88c2ecf20Sopenharmony_ci * Instruction data type for POWER
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_cistruct ppc_inst {
128c2ecf20Sopenharmony_ci	u32 val;
138c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC64
148c2ecf20Sopenharmony_ci	u32 suffix;
158c2ecf20Sopenharmony_ci#endif
168c2ecf20Sopenharmony_ci} __packed;
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_cistatic inline u32 ppc_inst_val(struct ppc_inst x)
198c2ecf20Sopenharmony_ci{
208c2ecf20Sopenharmony_ci	return x.val;
218c2ecf20Sopenharmony_ci}
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_cistatic inline int ppc_inst_primary_opcode(struct ppc_inst x)
248c2ecf20Sopenharmony_ci{
258c2ecf20Sopenharmony_ci	return ppc_inst_val(x) >> 26;
268c2ecf20Sopenharmony_ci}
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC64
298c2ecf20Sopenharmony_ci#define ppc_inst(x) ((struct ppc_inst){ .val = (x), .suffix = 0xff })
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#define ppc_inst_prefix(x, y) ((struct ppc_inst){ .val = (x), .suffix = (y) })
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_cistatic inline u32 ppc_inst_suffix(struct ppc_inst x)
348c2ecf20Sopenharmony_ci{
358c2ecf20Sopenharmony_ci	return x.suffix;
368c2ecf20Sopenharmony_ci}
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_cistatic inline bool ppc_inst_prefixed(struct ppc_inst x)
398c2ecf20Sopenharmony_ci{
408c2ecf20Sopenharmony_ci	return (ppc_inst_primary_opcode(x) == 1) && ppc_inst_suffix(x) != 0xff;
418c2ecf20Sopenharmony_ci}
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_cistatic inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
448c2ecf20Sopenharmony_ci{
458c2ecf20Sopenharmony_ci	return ppc_inst_prefix(swab32(ppc_inst_val(x)),
468c2ecf20Sopenharmony_ci			       swab32(ppc_inst_suffix(x)));
478c2ecf20Sopenharmony_ci}
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistatic inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
508c2ecf20Sopenharmony_ci{
518c2ecf20Sopenharmony_ci	u32 val, suffix;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	val = *(u32 *)ptr;
548c2ecf20Sopenharmony_ci	if ((val >> 26) == OP_PREFIX) {
558c2ecf20Sopenharmony_ci		suffix = *((u32 *)ptr + 1);
568c2ecf20Sopenharmony_ci		return ppc_inst_prefix(val, suffix);
578c2ecf20Sopenharmony_ci	} else {
588c2ecf20Sopenharmony_ci		return ppc_inst(val);
598c2ecf20Sopenharmony_ci	}
608c2ecf20Sopenharmony_ci}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cistatic inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
638c2ecf20Sopenharmony_ci{
648c2ecf20Sopenharmony_ci	return *(u64 *)&x == *(u64 *)&y;
658c2ecf20Sopenharmony_ci}
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci#else
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci#define ppc_inst(x) ((struct ppc_inst){ .val = x })
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistatic inline bool ppc_inst_prefixed(struct ppc_inst x)
728c2ecf20Sopenharmony_ci{
738c2ecf20Sopenharmony_ci	return false;
748c2ecf20Sopenharmony_ci}
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_cistatic inline u32 ppc_inst_suffix(struct ppc_inst x)
778c2ecf20Sopenharmony_ci{
788c2ecf20Sopenharmony_ci	return 0;
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistatic inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
828c2ecf20Sopenharmony_ci{
838c2ecf20Sopenharmony_ci	return ppc_inst(swab32(ppc_inst_val(x)));
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_cistatic inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
878c2ecf20Sopenharmony_ci{
888c2ecf20Sopenharmony_ci	return *ptr;
898c2ecf20Sopenharmony_ci}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistatic inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
928c2ecf20Sopenharmony_ci{
938c2ecf20Sopenharmony_ci	return ppc_inst_val(x) == ppc_inst_val(y);
948c2ecf20Sopenharmony_ci}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC64 */
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistatic inline int ppc_inst_len(struct ppc_inst x)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	return ppc_inst_prefixed(x) ? 8 : 4;
1018c2ecf20Sopenharmony_ci}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci/*
1048c2ecf20Sopenharmony_ci * Return the address of the next instruction, if the instruction @value was
1058c2ecf20Sopenharmony_ci * located at @location.
1068c2ecf20Sopenharmony_ci */
1078c2ecf20Sopenharmony_cistatic inline struct ppc_inst *ppc_inst_next(void *location, struct ppc_inst *value)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	struct ppc_inst tmp;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	tmp = ppc_inst_read(value);
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	return location + ppc_inst_len(tmp);
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_cistatic inline u64 ppc_inst_as_u64(struct ppc_inst x)
1178c2ecf20Sopenharmony_ci{
1188c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_LITTLE_ENDIAN
1198c2ecf20Sopenharmony_ci	return (u64)ppc_inst_suffix(x) << 32 | ppc_inst_val(x);
1208c2ecf20Sopenharmony_ci#else
1218c2ecf20Sopenharmony_ci	return (u64)ppc_inst_val(x) << 32 | ppc_inst_suffix(x);
1228c2ecf20Sopenharmony_ci#endif
1238c2ecf20Sopenharmony_ci}
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci#define PPC_INST_STR_LEN sizeof("00000000 00000000")
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cistatic inline char *__ppc_inst_as_str(char str[PPC_INST_STR_LEN], struct ppc_inst x)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	if (ppc_inst_prefixed(x))
1308c2ecf20Sopenharmony_ci		sprintf(str, "%08x %08x", ppc_inst_val(x), ppc_inst_suffix(x));
1318c2ecf20Sopenharmony_ci	else
1328c2ecf20Sopenharmony_ci		sprintf(str, "%08x", ppc_inst_val(x));
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	return str;
1358c2ecf20Sopenharmony_ci}
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci#define ppc_inst_as_str(x)		\
1388c2ecf20Sopenharmony_ci({					\
1398c2ecf20Sopenharmony_ci	char __str[PPC_INST_STR_LEN];	\
1408c2ecf20Sopenharmony_ci	__ppc_inst_as_str(__str, x);	\
1418c2ecf20Sopenharmony_ci	__str;				\
1428c2ecf20Sopenharmony_ci})
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ciint probe_user_read_inst(struct ppc_inst *inst,
1458c2ecf20Sopenharmony_ci			 struct ppc_inst __user *nip);
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ciint probe_kernel_read_inst(struct ppc_inst *inst,
1488c2ecf20Sopenharmony_ci			   struct ppc_inst *src);
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci#endif /* _ASM_POWERPC_INST_H */
151