xref: /linux/arch/s390/kernel/dis.c (revision ec63e2a4897075e427c121d863bd89c44578094f)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Disassemble s390 instructions.
4  *
5  * Copyright IBM Corp. 2007
6  * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
7  */
8 
9 #include <linux/sched.h>
10 #include <linux/kernel.h>
11 #include <linux/string.h>
12 #include <linux/errno.h>
13 #include <linux/ptrace.h>
14 #include <linux/timer.h>
15 #include <linux/mm.h>
16 #include <linux/smp.h>
17 #include <linux/init.h>
18 #include <linux/interrupt.h>
19 #include <linux/delay.h>
20 #include <linux/export.h>
21 #include <linux/kallsyms.h>
22 #include <linux/reboot.h>
23 #include <linux/kprobes.h>
24 #include <linux/kdebug.h>
25 #include <linux/uaccess.h>
26 #include <linux/atomic.h>
27 #include <asm/dis.h>
28 #include <asm/io.h>
29 #include <asm/cpcmd.h>
30 #include <asm/lowcore.h>
31 #include <asm/debug.h>
32 #include <asm/irq.h>
33 
34 /* Type of operand */
35 #define OPERAND_GPR	0x1	/* Operand printed as %rx */
36 #define OPERAND_FPR	0x2	/* Operand printed as %fx */
37 #define OPERAND_AR	0x4	/* Operand printed as %ax */
38 #define OPERAND_CR	0x8	/* Operand printed as %cx */
39 #define OPERAND_VR	0x10	/* Operand printed as %vx */
40 #define OPERAND_DISP	0x20	/* Operand printed as displacement */
41 #define OPERAND_BASE	0x40	/* Operand printed as base register */
42 #define OPERAND_INDEX	0x80	/* Operand printed as index register */
43 #define OPERAND_PCREL	0x100	/* Operand printed as pc-relative symbol */
44 #define OPERAND_SIGNED	0x200	/* Operand printed as signed value */
45 #define OPERAND_LENGTH	0x400	/* Operand printed as length (+1) */
46 
47 struct s390_operand {
48 	unsigned char bits;	/* The number of bits in the operand. */
49 	unsigned char shift;	/* The number of bits to shift. */
50 	unsigned short flags;	/* One bit syntax flags. */
51 };
52 
53 struct s390_insn {
54 	union {
55 		const char name[5];
56 		struct {
57 			unsigned char zero;
58 			unsigned int offset;
59 		} __packed;
60 	};
61 	unsigned char opfrag;
62 	unsigned char format;
63 };
64 
65 struct s390_opcode_offset {
66 	unsigned char opcode;
67 	unsigned char mask;
68 	unsigned char byte;
69 	unsigned short offset;
70 	unsigned short count;
71 } __packed;
72 
73 enum {
74 	UNUSED,
75 	A_8,	/* Access reg. starting at position 8 */
76 	A_12,	/* Access reg. starting at position 12 */
77 	A_24,	/* Access reg. starting at position 24 */
78 	A_28,	/* Access reg. starting at position 28 */
79 	B_16,	/* Base register starting at position 16 */
80 	B_32,	/* Base register starting at position 32 */
81 	C_8,	/* Control reg. starting at position 8 */
82 	C_12,	/* Control reg. starting at position 12 */
83 	D20_20, /* 20 bit displacement starting at 20 */
84 	D_20,	/* Displacement starting at position 20 */
85 	D_36,	/* Displacement starting at position 36 */
86 	F_8,	/* FPR starting at position 8 */
87 	F_12,	/* FPR starting at position 12 */
88 	F_16,	/* FPR starting at position 16 */
89 	F_24,	/* FPR starting at position 24 */
90 	F_28,	/* FPR starting at position 28 */
91 	F_32,	/* FPR starting at position 32 */
92 	I8_8,	/* 8 bit signed value starting at 8 */
93 	I8_32,	/* 8 bit signed value starting at 32 */
94 	I16_16, /* 16 bit signed value starting at 16 */
95 	I16_32, /* 16 bit signed value starting at 32 */
96 	I32_16, /* 32 bit signed value starting at 16 */
97 	J12_12, /* 12 bit PC relative offset at 12 */
98 	J16_16, /* 16 bit PC relative offset at 16 */
99 	J16_32, /* 16 bit PC relative offset at 32 */
100 	J24_24, /* 24 bit PC relative offset at 24 */
101 	J32_16, /* 32 bit PC relative offset at 16 */
102 	L4_8,	/* 4 bit length starting at position 8 */
103 	L4_12,	/* 4 bit length starting at position 12 */
104 	L8_8,	/* 8 bit length starting at position 8 */
105 	R_8,	/* GPR starting at position 8 */
106 	R_12,	/* GPR starting at position 12 */
107 	R_16,	/* GPR starting at position 16 */
108 	R_24,	/* GPR starting at position 24 */
109 	R_28,	/* GPR starting at position 28 */
110 	U4_8,	/* 4 bit unsigned value starting at 8 */
111 	U4_12,	/* 4 bit unsigned value starting at 12 */
112 	U4_16,	/* 4 bit unsigned value starting at 16 */
113 	U4_20,	/* 4 bit unsigned value starting at 20 */
114 	U4_24,	/* 4 bit unsigned value starting at 24 */
115 	U4_28,	/* 4 bit unsigned value starting at 28 */
116 	U4_32,	/* 4 bit unsigned value starting at 32 */
117 	U4_36,	/* 4 bit unsigned value starting at 36 */
118 	U8_8,	/* 8 bit unsigned value starting at 8 */
119 	U8_16,	/* 8 bit unsigned value starting at 16 */
120 	U8_24,	/* 8 bit unsigned value starting at 24 */
121 	U8_28,	/* 8 bit unsigned value starting at 28 */
122 	U8_32,	/* 8 bit unsigned value starting at 32 */
123 	U12_16, /* 12 bit unsigned value starting at 16 */
124 	U16_16, /* 16 bit unsigned value starting at 16 */
125 	U16_32, /* 16 bit unsigned value starting at 32 */
126 	U32_16, /* 32 bit unsigned value starting at 16 */
127 	VX_12,	/* Vector index register starting at position 12 */
128 	V_8,	/* Vector reg. starting at position 8 */
129 	V_12,	/* Vector reg. starting at position 12 */
130 	V_16,	/* Vector reg. starting at position 16 */
131 	V_32,	/* Vector reg. starting at position 32 */
132 	X_12,	/* Index register starting at position 12 */
133 };
134 
135 static const struct s390_operand operands[] = {
136 	[UNUSED] = {  0,  0, 0 },
137 	[A_8]	 = {  4,  8, OPERAND_AR },
138 	[A_12]	 = {  4, 12, OPERAND_AR },
139 	[A_24]	 = {  4, 24, OPERAND_AR },
140 	[A_28]	 = {  4, 28, OPERAND_AR },
141 	[B_16]	 = {  4, 16, OPERAND_BASE | OPERAND_GPR },
142 	[B_32]	 = {  4, 32, OPERAND_BASE | OPERAND_GPR },
143 	[C_8]	 = {  4,  8, OPERAND_CR },
144 	[C_12]	 = {  4, 12, OPERAND_CR },
145 	[D20_20] = { 20, 20, OPERAND_DISP | OPERAND_SIGNED },
146 	[D_20]	 = { 12, 20, OPERAND_DISP },
147 	[D_36]	 = { 12, 36, OPERAND_DISP },
148 	[F_8]	 = {  4,  8, OPERAND_FPR },
149 	[F_12]	 = {  4, 12, OPERAND_FPR },
150 	[F_16]	 = {  4, 16, OPERAND_FPR },
151 	[F_24]	 = {  4, 24, OPERAND_FPR },
152 	[F_28]	 = {  4, 28, OPERAND_FPR },
153 	[F_32]	 = {  4, 32, OPERAND_FPR },
154 	[I8_8]	 = {  8,  8, OPERAND_SIGNED },
155 	[I8_32]	 = {  8, 32, OPERAND_SIGNED },
156 	[I16_16] = { 16, 16, OPERAND_SIGNED },
157 	[I16_32] = { 16, 32, OPERAND_SIGNED },
158 	[I32_16] = { 32, 16, OPERAND_SIGNED },
159 	[J12_12] = { 12, 12, OPERAND_PCREL },
160 	[J16_16] = { 16, 16, OPERAND_PCREL },
161 	[J16_32] = { 16, 32, OPERAND_PCREL },
162 	[J24_24] = { 24, 24, OPERAND_PCREL },
163 	[J32_16] = { 32, 16, OPERAND_PCREL },
164 	[L4_8]	 = {  4,  8, OPERAND_LENGTH },
165 	[L4_12]	 = {  4, 12, OPERAND_LENGTH },
166 	[L8_8]	 = {  8,  8, OPERAND_LENGTH },
167 	[R_8]	 = {  4,  8, OPERAND_GPR },
168 	[R_12]	 = {  4, 12, OPERAND_GPR },
169 	[R_16]	 = {  4, 16, OPERAND_GPR },
170 	[R_24]	 = {  4, 24, OPERAND_GPR },
171 	[R_28]	 = {  4, 28, OPERAND_GPR },
172 	[U4_8]	 = {  4,  8, 0 },
173 	[U4_12]	 = {  4, 12, 0 },
174 	[U4_16]	 = {  4, 16, 0 },
175 	[U4_20]	 = {  4, 20, 0 },
176 	[U4_24]	 = {  4, 24, 0 },
177 	[U4_28]	 = {  4, 28, 0 },
178 	[U4_32]	 = {  4, 32, 0 },
179 	[U4_36]	 = {  4, 36, 0 },
180 	[U8_8]	 = {  8,  8, 0 },
181 	[U8_16]	 = {  8, 16, 0 },
182 	[U8_24]	 = {  8, 24, 0 },
183 	[U8_28]	 = {  8, 28, 0 },
184 	[U8_32]	 = {  8, 32, 0 },
185 	[U12_16] = { 12, 16, 0 },
186 	[U16_16] = { 16, 16, 0 },
187 	[U16_32] = { 16, 32, 0 },
188 	[U32_16] = { 32, 16, 0 },
189 	[VX_12]	 = {  4, 12, OPERAND_INDEX | OPERAND_VR },
190 	[V_8]	 = {  4,  8, OPERAND_VR },
191 	[V_12]	 = {  4, 12, OPERAND_VR },
192 	[V_16]	 = {  4, 16, OPERAND_VR },
193 	[V_32]	 = {  4, 32, OPERAND_VR },
194 	[X_12]	 = {  4, 12, OPERAND_INDEX | OPERAND_GPR },
195 };
196 
197 static const unsigned char formats[][6] = {
198 	[INSTR_E]	     = { 0, 0, 0, 0, 0, 0 },
199 	[INSTR_IE_UU]	     = { U4_24, U4_28, 0, 0, 0, 0 },
200 	[INSTR_MII_UPP]	     = { U4_8, J12_12, J24_24 },
201 	[INSTR_RIE_R0IU]     = { R_8, I16_16, U4_32, 0, 0, 0 },
202 	[INSTR_RIE_R0UU]     = { R_8, U16_16, U4_32, 0, 0, 0 },
203 	[INSTR_RIE_RRI0]     = { R_8, R_12, I16_16, 0, 0, 0 },
204 	[INSTR_RIE_RRP]	     = { R_8, R_12, J16_16, 0, 0, 0 },
205 	[INSTR_RIE_RRPU]     = { R_8, R_12, U4_32, J16_16, 0, 0 },
206 	[INSTR_RIE_RRUUU]    = { R_8, R_12, U8_16, U8_24, U8_32, 0 },
207 	[INSTR_RIE_RUI0]     = { R_8, I16_16, U4_12, 0, 0, 0 },
208 	[INSTR_RIE_RUPI]     = { R_8, I8_32, U4_12, J16_16, 0, 0 },
209 	[INSTR_RIE_RUPU]     = { R_8, U8_32, U4_12, J16_16, 0, 0 },
210 	[INSTR_RIL_RI]	     = { R_8, I32_16, 0, 0, 0, 0 },
211 	[INSTR_RIL_RP]	     = { R_8, J32_16, 0, 0, 0, 0 },
212 	[INSTR_RIL_RU]	     = { R_8, U32_16, 0, 0, 0, 0 },
213 	[INSTR_RIL_UP]	     = { U4_8, J32_16, 0, 0, 0, 0 },
214 	[INSTR_RIS_RURDI]    = { R_8, I8_32, U4_12, D_20, B_16, 0 },
215 	[INSTR_RIS_RURDU]    = { R_8, U8_32, U4_12, D_20, B_16, 0 },
216 	[INSTR_RI_RI]	     = { R_8, I16_16, 0, 0, 0, 0 },
217 	[INSTR_RI_RP]	     = { R_8, J16_16, 0, 0, 0, 0 },
218 	[INSTR_RI_RU]	     = { R_8, U16_16, 0, 0, 0, 0 },
219 	[INSTR_RI_UP]	     = { U4_8, J16_16, 0, 0, 0, 0 },
220 	[INSTR_RRE_00]	     = { 0, 0, 0, 0, 0, 0 },
221 	[INSTR_RRE_AA]	     = { A_24, A_28, 0, 0, 0, 0 },
222 	[INSTR_RRE_AR]	     = { A_24, R_28, 0, 0, 0, 0 },
223 	[INSTR_RRE_F0]	     = { F_24, 0, 0, 0, 0, 0 },
224 	[INSTR_RRE_FF]	     = { F_24, F_28, 0, 0, 0, 0 },
225 	[INSTR_RRE_FR]	     = { F_24, R_28, 0, 0, 0, 0 },
226 	[INSTR_RRE_R0]	     = { R_24, 0, 0, 0, 0, 0 },
227 	[INSTR_RRE_RA]	     = { R_24, A_28, 0, 0, 0, 0 },
228 	[INSTR_RRE_RF]	     = { R_24, F_28, 0, 0, 0, 0 },
229 	[INSTR_RRE_RR]	     = { R_24, R_28, 0, 0, 0, 0 },
230 	[INSTR_RRF_0UFF]     = { F_24, F_28, U4_20, 0, 0, 0 },
231 	[INSTR_RRF_0URF]     = { R_24, F_28, U4_20, 0, 0, 0 },
232 	[INSTR_RRF_F0FF]     = { F_16, F_24, F_28, 0, 0, 0 },
233 	[INSTR_RRF_F0FF2]    = { F_24, F_16, F_28, 0, 0, 0 },
234 	[INSTR_RRF_F0FR]     = { F_24, F_16, R_28, 0, 0, 0 },
235 	[INSTR_RRF_FFRU]     = { F_24, F_16, R_28, U4_20, 0, 0 },
236 	[INSTR_RRF_FUFF]     = { F_24, F_16, F_28, U4_20, 0, 0 },
237 	[INSTR_RRF_FUFF2]    = { F_24, F_28, F_16, U4_20, 0, 0 },
238 	[INSTR_RRF_R0RR]     = { R_24, R_16, R_28, 0, 0, 0 },
239 	[INSTR_RRF_R0RR2]    = { R_24, R_28, R_16, 0, 0, 0 },
240 	[INSTR_RRF_RURR]     = { R_24, R_28, R_16, U4_20, 0, 0 },
241 	[INSTR_RRF_RURR2]    = { R_24, R_16, R_28, U4_20, 0, 0 },
242 	[INSTR_RRF_U0FF]     = { F_24, U4_16, F_28, 0, 0, 0 },
243 	[INSTR_RRF_U0RF]     = { R_24, U4_16, F_28, 0, 0, 0 },
244 	[INSTR_RRF_U0RR]     = { R_24, R_28, U4_16, 0, 0, 0 },
245 	[INSTR_RRF_UUFF]     = { F_24, U4_16, F_28, U4_20, 0, 0 },
246 	[INSTR_RRF_UUFR]     = { F_24, U4_16, R_28, U4_20, 0, 0 },
247 	[INSTR_RRF_UURF]     = { R_24, U4_16, F_28, U4_20, 0, 0 },
248 	[INSTR_RRS_RRRDU]    = { R_8, R_12, U4_32, D_20, B_16 },
249 	[INSTR_RR_FF]	     = { F_8, F_12, 0, 0, 0, 0 },
250 	[INSTR_RR_R0]	     = { R_8,  0, 0, 0, 0, 0 },
251 	[INSTR_RR_RR]	     = { R_8, R_12, 0, 0, 0, 0 },
252 	[INSTR_RR_U0]	     = { U8_8,	0, 0, 0, 0, 0 },
253 	[INSTR_RR_UR]	     = { U4_8, R_12, 0, 0, 0, 0 },
254 	[INSTR_RSI_RRP]	     = { R_8, R_12, J16_16, 0, 0, 0 },
255 	[INSTR_RSL_LRDFU]    = { F_32, D_20, L8_8, B_16, U4_36, 0 },
256 	[INSTR_RSL_R0RD]     = { D_20, L4_8, B_16, 0, 0, 0 },
257 	[INSTR_RSY_AARD]     = { A_8, A_12, D20_20, B_16, 0, 0 },
258 	[INSTR_RSY_CCRD]     = { C_8, C_12, D20_20, B_16, 0, 0 },
259 	[INSTR_RSY_RDRU]     = { R_8, D20_20, B_16, U4_12, 0, 0 },
260 	[INSTR_RSY_RRRD]     = { R_8, R_12, D20_20, B_16, 0, 0 },
261 	[INSTR_RSY_RURD]     = { R_8, U4_12, D20_20, B_16, 0, 0 },
262 	[INSTR_RSY_RURD2]    = { R_8, D20_20, B_16, U4_12, 0, 0 },
263 	[INSTR_RS_AARD]	     = { A_8, A_12, D_20, B_16, 0, 0 },
264 	[INSTR_RS_CCRD]	     = { C_8, C_12, D_20, B_16, 0, 0 },
265 	[INSTR_RS_R0RD]	     = { R_8, D_20, B_16, 0, 0, 0 },
266 	[INSTR_RS_RRRD]	     = { R_8, R_12, D_20, B_16, 0, 0 },
267 	[INSTR_RS_RURD]	     = { R_8, U4_12, D_20, B_16, 0, 0 },
268 	[INSTR_RXE_FRRD]     = { F_8, D_20, X_12, B_16, 0, 0 },
269 	[INSTR_RXE_RRRDU]    = { R_8, D_20, X_12, B_16, U4_32, 0 },
270 	[INSTR_RXF_FRRDF]    = { F_32, F_8, D_20, X_12, B_16, 0 },
271 	[INSTR_RXY_FRRD]     = { F_8, D20_20, X_12, B_16, 0, 0 },
272 	[INSTR_RXY_RRRD]     = { R_8, D20_20, X_12, B_16, 0, 0 },
273 	[INSTR_RXY_URRD]     = { U4_8, D20_20, X_12, B_16, 0, 0 },
274 	[INSTR_RX_FRRD]	     = { F_8, D_20, X_12, B_16, 0, 0 },
275 	[INSTR_RX_RRRD]	     = { R_8, D_20, X_12, B_16, 0, 0 },
276 	[INSTR_RX_URRD]	     = { U4_8, D_20, X_12, B_16, 0, 0 },
277 	[INSTR_SIL_RDI]	     = { D_20, B_16, I16_32, 0, 0, 0 },
278 	[INSTR_SIL_RDU]	     = { D_20, B_16, U16_32, 0, 0, 0 },
279 	[INSTR_SIY_IRD]	     = { D20_20, B_16, I8_8, 0, 0, 0 },
280 	[INSTR_SIY_URD]	     = { D20_20, B_16, U8_8, 0, 0, 0 },
281 	[INSTR_SI_RD]	     = { D_20, B_16, 0, 0, 0, 0 },
282 	[INSTR_SI_URD]	     = { D_20, B_16, U8_8, 0, 0, 0 },
283 	[INSTR_SMI_U0RDP]    = { U4_8, J16_32, D_20, B_16, 0, 0 },
284 	[INSTR_SSE_RDRD]     = { D_20, B_16, D_36, B_32, 0, 0 },
285 	[INSTR_SSF_RRDRD]    = { D_20, B_16, D_36, B_32, R_8, 0 },
286 	[INSTR_SSF_RRDRD2]   = { R_8, D_20, B_16, D_36, B_32, 0 },
287 	[INSTR_SS_L0RDRD]    = { D_20, L8_8, B_16, D_36, B_32, 0 },
288 	[INSTR_SS_L2RDRD]    = { D_20, B_16, D_36, L8_8, B_32, 0 },
289 	[INSTR_SS_LIRDRD]    = { D_20, L4_8, B_16, D_36, B_32, U4_12 },
290 	[INSTR_SS_LLRDRD]    = { D_20, L4_8, B_16, D_36, L4_12, B_32 },
291 	[INSTR_SS_RRRDRD]    = { D_20, R_8, B_16, D_36, B_32, R_12 },
292 	[INSTR_SS_RRRDRD2]   = { R_8, D_20, B_16, R_12, D_36, B_32 },
293 	[INSTR_SS_RRRDRD3]   = { R_8, R_12, D_20, B_16, D_36, B_32 },
294 	[INSTR_S_00]	     = { 0, 0, 0, 0, 0, 0 },
295 	[INSTR_S_RD]	     = { D_20, B_16, 0, 0, 0, 0 },
296 	[INSTR_VRI_V0IU]     = { V_8, I16_16, U4_32, 0, 0, 0 },
297 	[INSTR_VRI_V0U]	     = { V_8, U16_16, 0, 0, 0, 0 },
298 	[INSTR_VRI_V0UU2]    = { V_8, U16_16, U4_32, 0, 0, 0 },
299 	[INSTR_VRI_V0UUU]    = { V_8, U8_16, U8_24, U4_32, 0, 0 },
300 	[INSTR_VRI_VR0UU]    = { V_8, R_12, U8_28, U4_24, 0, 0 },
301 	[INSTR_VRI_VVUU]     = { V_8, V_12, U16_16, U4_32, 0, 0 },
302 	[INSTR_VRI_VVUUU]    = { V_8, V_12, U12_16, U4_32, U4_28, 0 },
303 	[INSTR_VRI_VVUUU2]   = { V_8, V_12, U8_28, U8_16, U4_24, 0 },
304 	[INSTR_VRI_VVV0U]    = { V_8, V_12, V_16, U8_24, 0, 0 },
305 	[INSTR_VRI_VVV0UU]   = { V_8, V_12, V_16, U8_24, U4_32, 0 },
306 	[INSTR_VRI_VVV0UU2]  = { V_8, V_12, V_16, U8_28, U4_24, 0 },
307 	[INSTR_VRR_0V]	     = { V_12, 0, 0, 0, 0, 0 },
308 	[INSTR_VRR_0VV0U]    = { V_12, V_16, U4_24, 0, 0, 0 },
309 	[INSTR_VRR_RV0U]     = { R_8, V_12, U4_24, 0, 0, 0 },
310 	[INSTR_VRR_VRR]	     = { V_8, R_12, R_16, 0, 0, 0 },
311 	[INSTR_VRR_VV]	     = { V_8, V_12, 0, 0, 0, 0 },
312 	[INSTR_VRR_VV0U]     = { V_8, V_12, U4_32, 0, 0, 0 },
313 	[INSTR_VRR_VV0U0U]   = { V_8, V_12, U4_32, U4_24, 0, 0 },
314 	[INSTR_VRR_VV0UU2]   = { V_8, V_12, U4_32, U4_28, 0, 0 },
315 	[INSTR_VRR_VV0UUU]   = { V_8, V_12, U4_32, U4_28, U4_24, 0 },
316 	[INSTR_VRR_VVV]	     = { V_8, V_12, V_16, 0, 0, 0 },
317 	[INSTR_VRR_VVV0U]    = { V_8, V_12, V_16, U4_32, 0, 0 },
318 	[INSTR_VRR_VVV0U0U]  = { V_8, V_12, V_16, U4_32, U4_24, 0 },
319 	[INSTR_VRR_VVV0UU]   = { V_8, V_12, V_16, U4_32, U4_28, 0 },
320 	[INSTR_VRR_VVV0UUU]  = { V_8, V_12, V_16, U4_32, U4_28, U4_24 },
321 	[INSTR_VRR_VVV0V]    = { V_8, V_12, V_16, V_32, 0, 0 },
322 	[INSTR_VRR_VVVU0UV]  = { V_8, V_12, V_16, V_32, U4_28, U4_20 },
323 	[INSTR_VRR_VVVU0V]   = { V_8, V_12, V_16, V_32, U4_20, 0 },
324 	[INSTR_VRR_VVVUU0V]  = { V_8, V_12, V_16, V_32, U4_20, U4_24 },
325 	[INSTR_VRS_RRDV]     = { V_32, R_12, D_20, B_16, 0, 0 },
326 	[INSTR_VRS_RVRDU]    = { R_8, V_12, D_20, B_16, U4_32, 0 },
327 	[INSTR_VRS_VRRD]     = { V_8, R_12, D_20, B_16, 0, 0 },
328 	[INSTR_VRS_VRRDU]    = { V_8, R_12, D_20, B_16, U4_32, 0 },
329 	[INSTR_VRS_VVRD]     = { V_8, V_12, D_20, B_16, 0, 0 },
330 	[INSTR_VRS_VVRDU]    = { V_8, V_12, D_20, B_16, U4_32, 0 },
331 	[INSTR_VRV_VVXRDU]   = { V_8, D_20, VX_12, B_16, U4_32, 0 },
332 	[INSTR_VRX_VRRD]     = { V_8, D_20, X_12, B_16, 0, 0 },
333 	[INSTR_VRX_VRRDU]    = { V_8, D_20, X_12, B_16, U4_32, 0 },
334 	[INSTR_VRX_VV]	     = { V_8, V_12, 0, 0, 0, 0 },
335 	[INSTR_VSI_URDV]     = { V_32, D_20, B_16, U8_8, 0, 0 },
336 };
337 
338 static char long_insn_name[][7] = LONG_INSN_INITIALIZER;
339 static struct s390_insn opcode[] = OPCODE_TABLE_INITIALIZER;
340 static struct s390_opcode_offset opcode_offset[] = OPCODE_OFFSET_INITIALIZER;
341 
342 /* Extracts an operand value from an instruction.  */
343 static unsigned int extract_operand(unsigned char *code,
344 				    const struct s390_operand *operand)
345 {
346 	unsigned char *cp;
347 	unsigned int val;
348 	int bits;
349 
350 	/* Extract fragments of the operand byte for byte.  */
351 	cp = code + operand->shift / 8;
352 	bits = (operand->shift & 7) + operand->bits;
353 	val = 0;
354 	do {
355 		val <<= 8;
356 		val |= (unsigned int) *cp++;
357 		bits -= 8;
358 	} while (bits > 0);
359 	val >>= -bits;
360 	val &= ((1U << (operand->bits - 1)) << 1) - 1;
361 
362 	/* Check for special long displacement case.  */
363 	if (operand->bits == 20 && operand->shift == 20)
364 		val = (val & 0xff) << 12 | (val & 0xfff00) >> 8;
365 
366 	/* Check for register extensions bits for vector registers. */
367 	if (operand->flags & OPERAND_VR) {
368 		if (operand->shift == 8)
369 			val |= (code[4] & 8) << 1;
370 		else if (operand->shift == 12)
371 			val |= (code[4] & 4) << 2;
372 		else if (operand->shift == 16)
373 			val |= (code[4] & 2) << 3;
374 		else if (operand->shift == 32)
375 			val |= (code[4] & 1) << 4;
376 	}
377 
378 	/* Sign extend value if the operand is signed or pc relative.  */
379 	if ((operand->flags & (OPERAND_SIGNED | OPERAND_PCREL)) &&
380 	    (val & (1U << (operand->bits - 1))))
381 		val |= (-1U << (operand->bits - 1)) << 1;
382 
383 	/* Double value if the operand is pc relative.	*/
384 	if (operand->flags & OPERAND_PCREL)
385 		val <<= 1;
386 
387 	/* Length x in an instructions has real length x + 1.  */
388 	if (operand->flags & OPERAND_LENGTH)
389 		val++;
390 	return val;
391 }
392 
393 struct s390_insn *find_insn(unsigned char *code)
394 {
395 	struct s390_opcode_offset *entry;
396 	struct s390_insn *insn;
397 	unsigned char opfrag;
398 	int i;
399 
400 	/* Search the opcode offset table to find an entry which
401 	 * matches the beginning of the opcode. If there is no match
402 	 * the last entry will be used, which is the default entry for
403 	 * unknown instructions as well as 1-byte opcode instructions.
404 	 */
405 	for (i = 0; i < ARRAY_SIZE(opcode_offset); i++) {
406 		entry = &opcode_offset[i];
407 		if (entry->opcode == code[0])
408 			break;
409 	}
410 
411 	opfrag = *(code + entry->byte) & entry->mask;
412 
413 	insn = &opcode[entry->offset];
414 	for (i = 0; i < entry->count; i++) {
415 		if (insn->opfrag == opfrag)
416 			return insn;
417 		insn++;
418 	}
419 	return NULL;
420 }
421 
422 static int print_insn(char *buffer, unsigned char *code, unsigned long addr)
423 {
424 	struct s390_insn *insn;
425 	const unsigned char *ops;
426 	const struct s390_operand *operand;
427 	unsigned int value;
428 	char separator;
429 	char *ptr;
430 	int i;
431 
432 	ptr = buffer;
433 	insn = find_insn(code);
434 	if (insn) {
435 		if (insn->zero == 0)
436 			ptr += sprintf(ptr, "%.7s\t",
437 				       long_insn_name[insn->offset]);
438 		else
439 			ptr += sprintf(ptr, "%.5s\t", insn->name);
440 		/* Extract the operands. */
441 		separator = 0;
442 		for (ops = formats[insn->format], i = 0;
443 		     *ops != 0 && i < 6; ops++, i++) {
444 			operand = operands + *ops;
445 			value = extract_operand(code, operand);
446 			if ((operand->flags & OPERAND_INDEX)  && value == 0)
447 				continue;
448 			if ((operand->flags & OPERAND_BASE) &&
449 			    value == 0 && separator == '(') {
450 				separator = ',';
451 				continue;
452 			}
453 			if (separator)
454 				ptr += sprintf(ptr, "%c", separator);
455 			if (operand->flags & OPERAND_GPR)
456 				ptr += sprintf(ptr, "%%r%i", value);
457 			else if (operand->flags & OPERAND_FPR)
458 				ptr += sprintf(ptr, "%%f%i", value);
459 			else if (operand->flags & OPERAND_AR)
460 				ptr += sprintf(ptr, "%%a%i", value);
461 			else if (operand->flags & OPERAND_CR)
462 				ptr += sprintf(ptr, "%%c%i", value);
463 			else if (operand->flags & OPERAND_VR)
464 				ptr += sprintf(ptr, "%%v%i", value);
465 			else if (operand->flags & OPERAND_PCREL)
466 				ptr += sprintf(ptr, "%lx", (signed int) value
467 								      + addr);
468 			else if (operand->flags & OPERAND_SIGNED)
469 				ptr += sprintf(ptr, "%i", value);
470 			else
471 				ptr += sprintf(ptr, "%u", value);
472 			if (operand->flags & OPERAND_DISP)
473 				separator = '(';
474 			else if (operand->flags & OPERAND_BASE) {
475 				ptr += sprintf(ptr, ")");
476 				separator = ',';
477 			} else
478 				separator = ',';
479 		}
480 	} else
481 		ptr += sprintf(ptr, "unknown");
482 	return (int) (ptr - buffer);
483 }
484 
485 void show_code(struct pt_regs *regs)
486 {
487 	char *mode = user_mode(regs) ? "User" : "Krnl";
488 	unsigned char code[64];
489 	char buffer[128], *ptr;
490 	mm_segment_t old_fs;
491 	unsigned long addr;
492 	int start, end, opsize, hops, i;
493 
494 	/* Get a snapshot of the 64 bytes surrounding the fault address. */
495 	old_fs = get_fs();
496 	set_fs(user_mode(regs) ? USER_DS : KERNEL_DS);
497 	for (start = 32; start && regs->psw.addr >= 34 - start; start -= 2) {
498 		addr = regs->psw.addr - 34 + start;
499 		if (__copy_from_user(code + start - 2,
500 				     (char __user *) addr, 2))
501 			break;
502 	}
503 	for (end = 32; end < 64; end += 2) {
504 		addr = regs->psw.addr + end - 32;
505 		if (__copy_from_user(code + end,
506 				     (char __user *) addr, 2))
507 			break;
508 	}
509 	set_fs(old_fs);
510 	/* Code snapshot useable ? */
511 	if ((regs->psw.addr & 1) || start >= end) {
512 		printk("%s Code: Bad PSW.\n", mode);
513 		return;
514 	}
515 	/* Find a starting point for the disassembly. */
516 	while (start < 32) {
517 		for (i = 0, hops = 0; start + i < 32 && hops < 3; hops++) {
518 			if (!find_insn(code + start + i))
519 				break;
520 			i += insn_length(code[start + i]);
521 		}
522 		if (start + i == 32)
523 			/* Looks good, sequence ends at PSW. */
524 			break;
525 		start += 2;
526 	}
527 	/* Decode the instructions. */
528 	ptr = buffer;
529 	ptr += sprintf(ptr, "%s Code:", mode);
530 	hops = 0;
531 	while (start < end && hops < 8) {
532 		opsize = insn_length(code[start]);
533 		if  (start + opsize == 32)
534 			*ptr++ = '#';
535 		else if (start == 32)
536 			*ptr++ = '>';
537 		else
538 			*ptr++ = ' ';
539 		addr = regs->psw.addr + start - 32;
540 		ptr += sprintf(ptr, "%016lx: ", addr);
541 		if (start + opsize >= end)
542 			break;
543 		for (i = 0; i < opsize; i++)
544 			ptr += sprintf(ptr, "%02x", code[start + i]);
545 		*ptr++ = '\t';
546 		if (i < 6)
547 			*ptr++ = '\t';
548 		ptr += print_insn(ptr, code + start, addr);
549 		start += opsize;
550 		pr_cont("%s", buffer);
551 		ptr = buffer;
552 		ptr += sprintf(ptr, "\n          ");
553 		hops++;
554 	}
555 	pr_cont("\n");
556 }
557 
558 void print_fn_code(unsigned char *code, unsigned long len)
559 {
560 	char buffer[64], *ptr;
561 	int opsize, i;
562 
563 	while (len) {
564 		ptr = buffer;
565 		opsize = insn_length(*code);
566 		if (opsize > len)
567 			break;
568 		ptr += sprintf(ptr, "%p: ", code);
569 		for (i = 0; i < opsize; i++)
570 			ptr += sprintf(ptr, "%02x", code[i]);
571 		*ptr++ = '\t';
572 		if (i < 4)
573 			*ptr++ = '\t';
574 		ptr += print_insn(ptr, code, (unsigned long) code);
575 		*ptr++ = '\n';
576 		*ptr++ = 0;
577 		printk("%s", buffer);
578 		code += opsize;
579 		len -= opsize;
580 	}
581 }
582