1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-or-later */
2*4882a593Smuzhiyun #ifndef _ASM_POWERPC_INST_H
3*4882a593Smuzhiyun #define _ASM_POWERPC_INST_H
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun #include <asm/ppc-opcode.h>
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun /*
8*4882a593Smuzhiyun * Instruction data type for POWER
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun struct ppc_inst {
12*4882a593Smuzhiyun u32 val;
13*4882a593Smuzhiyun #ifdef CONFIG_PPC64
14*4882a593Smuzhiyun u32 suffix;
15*4882a593Smuzhiyun #endif
16*4882a593Smuzhiyun } __packed;
17*4882a593Smuzhiyun
ppc_inst_val(struct ppc_inst x)18*4882a593Smuzhiyun static inline u32 ppc_inst_val(struct ppc_inst x)
19*4882a593Smuzhiyun {
20*4882a593Smuzhiyun return x.val;
21*4882a593Smuzhiyun }
22*4882a593Smuzhiyun
ppc_inst_primary_opcode(struct ppc_inst x)23*4882a593Smuzhiyun static inline int ppc_inst_primary_opcode(struct ppc_inst x)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun return ppc_inst_val(x) >> 26;
26*4882a593Smuzhiyun }
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #ifdef CONFIG_PPC64
29*4882a593Smuzhiyun #define ppc_inst(x) ((struct ppc_inst){ .val = (x), .suffix = 0xff })
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun #define ppc_inst_prefix(x, y) ((struct ppc_inst){ .val = (x), .suffix = (y) })
32*4882a593Smuzhiyun
ppc_inst_suffix(struct ppc_inst x)33*4882a593Smuzhiyun static inline u32 ppc_inst_suffix(struct ppc_inst x)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun return x.suffix;
36*4882a593Smuzhiyun }
37*4882a593Smuzhiyun
ppc_inst_prefixed(struct ppc_inst x)38*4882a593Smuzhiyun static inline bool ppc_inst_prefixed(struct ppc_inst x)
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun return (ppc_inst_primary_opcode(x) == 1) && ppc_inst_suffix(x) != 0xff;
41*4882a593Smuzhiyun }
42*4882a593Smuzhiyun
ppc_inst_swab(struct ppc_inst x)43*4882a593Smuzhiyun static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun return ppc_inst_prefix(swab32(ppc_inst_val(x)),
46*4882a593Smuzhiyun swab32(ppc_inst_suffix(x)));
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun
ppc_inst_read(const struct ppc_inst * ptr)49*4882a593Smuzhiyun static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun u32 val, suffix;
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun val = *(u32 *)ptr;
54*4882a593Smuzhiyun if ((val >> 26) == OP_PREFIX) {
55*4882a593Smuzhiyun suffix = *((u32 *)ptr + 1);
56*4882a593Smuzhiyun return ppc_inst_prefix(val, suffix);
57*4882a593Smuzhiyun } else {
58*4882a593Smuzhiyun return ppc_inst(val);
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun
ppc_inst_equal(struct ppc_inst x,struct ppc_inst y)62*4882a593Smuzhiyun static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun return *(u64 *)&x == *(u64 *)&y;
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun #else
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun #define ppc_inst(x) ((struct ppc_inst){ .val = x })
70*4882a593Smuzhiyun
ppc_inst_prefixed(struct ppc_inst x)71*4882a593Smuzhiyun static inline bool ppc_inst_prefixed(struct ppc_inst x)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun return false;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
ppc_inst_suffix(struct ppc_inst x)76*4882a593Smuzhiyun static inline u32 ppc_inst_suffix(struct ppc_inst x)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun return 0;
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun
ppc_inst_swab(struct ppc_inst x)81*4882a593Smuzhiyun static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun return ppc_inst(swab32(ppc_inst_val(x)));
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun
ppc_inst_read(const struct ppc_inst * ptr)86*4882a593Smuzhiyun static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun return *ptr;
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun
ppc_inst_equal(struct ppc_inst x,struct ppc_inst y)91*4882a593Smuzhiyun static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun return ppc_inst_val(x) == ppc_inst_val(y);
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun #endif /* CONFIG_PPC64 */
97*4882a593Smuzhiyun
ppc_inst_len(struct ppc_inst x)98*4882a593Smuzhiyun static inline int ppc_inst_len(struct ppc_inst x)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun return ppc_inst_prefixed(x) ? 8 : 4;
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun /*
104*4882a593Smuzhiyun * Return the address of the next instruction, if the instruction @value was
105*4882a593Smuzhiyun * located at @location.
106*4882a593Smuzhiyun */
ppc_inst_next(void * location,struct ppc_inst * value)107*4882a593Smuzhiyun static inline struct ppc_inst *ppc_inst_next(void *location, struct ppc_inst *value)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun struct ppc_inst tmp;
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun tmp = ppc_inst_read(value);
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun return location + ppc_inst_len(tmp);
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun
ppc_inst_as_u64(struct ppc_inst x)116*4882a593Smuzhiyun static inline u64 ppc_inst_as_u64(struct ppc_inst x)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun #ifdef CONFIG_CPU_LITTLE_ENDIAN
119*4882a593Smuzhiyun return (u64)ppc_inst_suffix(x) << 32 | ppc_inst_val(x);
120*4882a593Smuzhiyun #else
121*4882a593Smuzhiyun return (u64)ppc_inst_val(x) << 32 | ppc_inst_suffix(x);
122*4882a593Smuzhiyun #endif
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun #define PPC_INST_STR_LEN sizeof("00000000 00000000")
126*4882a593Smuzhiyun
__ppc_inst_as_str(char str[PPC_INST_STR_LEN],struct ppc_inst x)127*4882a593Smuzhiyun static inline char *__ppc_inst_as_str(char str[PPC_INST_STR_LEN], struct ppc_inst x)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun if (ppc_inst_prefixed(x))
130*4882a593Smuzhiyun sprintf(str, "%08x %08x", ppc_inst_val(x), ppc_inst_suffix(x));
131*4882a593Smuzhiyun else
132*4882a593Smuzhiyun sprintf(str, "%08x", ppc_inst_val(x));
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun return str;
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun #define ppc_inst_as_str(x) \
138*4882a593Smuzhiyun ({ \
139*4882a593Smuzhiyun char __str[PPC_INST_STR_LEN]; \
140*4882a593Smuzhiyun __ppc_inst_as_str(__str, x); \
141*4882a593Smuzhiyun __str; \
142*4882a593Smuzhiyun })
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun int probe_user_read_inst(struct ppc_inst *inst,
145*4882a593Smuzhiyun struct ppc_inst __user *nip);
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun int probe_kernel_read_inst(struct ppc_inst *inst,
148*4882a593Smuzhiyun struct ppc_inst *src);
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun #endif /* _ASM_POWERPC_INST_H */
151