1 // SPDX-License-Identifier: GPL-2.0
3 * Disassemble s390 instructions.
5 * Copyright IBM Corp. 2007
6 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
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>
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>
29 #include <asm/cpcmd.h>
30 #include <asm/lowcore.h>
31 #include <asm/debug.h>
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) */
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. */
65 struct s390_opcode_offset
{
69 unsigned short offset
;
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 */
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
},
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_URR
] = { R_24
, R_28
, U8_16
, 0, 0, 0 },
246 [INSTR_RRF_UUFF
] = { F_24
, U4_16
, F_28
, U4_20
, 0, 0 },
247 [INSTR_RRF_UUFR
] = { F_24
, U4_16
, R_28
, U4_20
, 0, 0 },
248 [INSTR_RRF_UURF
] = { R_24
, U4_16
, F_28
, U4_20
, 0, 0 },
249 [INSTR_RRS_RRRDU
] = { R_8
, R_12
, U4_32
, D_20
, B_16
},
250 [INSTR_RR_FF
] = { F_8
, F_12
, 0, 0, 0, 0 },
251 [INSTR_RR_R0
] = { R_8
, 0, 0, 0, 0, 0 },
252 [INSTR_RR_RR
] = { R_8
, R_12
, 0, 0, 0, 0 },
253 [INSTR_RR_U0
] = { U8_8
, 0, 0, 0, 0, 0 },
254 [INSTR_RR_UR
] = { U4_8
, R_12
, 0, 0, 0, 0 },
255 [INSTR_RSI_RRP
] = { R_8
, R_12
, J16_16
, 0, 0, 0 },
256 [INSTR_RSL_LRDFU
] = { F_32
, D_20
, L8_8
, B_16
, U4_36
, 0 },
257 [INSTR_RSL_R0RD
] = { D_20
, L4_8
, B_16
, 0, 0, 0 },
258 [INSTR_RSY_AARD
] = { A_8
, A_12
, D20_20
, B_16
, 0, 0 },
259 [INSTR_RSY_CCRD
] = { C_8
, C_12
, D20_20
, B_16
, 0, 0 },
260 [INSTR_RSY_RDRU
] = { R_8
, D20_20
, B_16
, U4_12
, 0, 0 },
261 [INSTR_RSY_RRRD
] = { R_8
, R_12
, D20_20
, B_16
, 0, 0 },
262 [INSTR_RSY_RURD
] = { R_8
, U4_12
, D20_20
, B_16
, 0, 0 },
263 [INSTR_RSY_RURD2
] = { R_8
, D20_20
, B_16
, U4_12
, 0, 0 },
264 [INSTR_RS_AARD
] = { A_8
, A_12
, D_20
, B_16
, 0, 0 },
265 [INSTR_RS_CCRD
] = { C_8
, C_12
, D_20
, B_16
, 0, 0 },
266 [INSTR_RS_R0RD
] = { R_8
, D_20
, B_16
, 0, 0, 0 },
267 [INSTR_RS_RRRD
] = { R_8
, R_12
, D_20
, B_16
, 0, 0 },
268 [INSTR_RS_RURD
] = { R_8
, U4_12
, D_20
, B_16
, 0, 0 },
269 [INSTR_RXE_FRRD
] = { F_8
, D_20
, X_12
, B_16
, 0, 0 },
270 [INSTR_RXE_RRRDU
] = { R_8
, D_20
, X_12
, B_16
, U4_32
, 0 },
271 [INSTR_RXF_FRRDF
] = { F_32
, F_8
, D_20
, X_12
, B_16
, 0 },
272 [INSTR_RXY_FRRD
] = { F_8
, D20_20
, X_12
, B_16
, 0, 0 },
273 [INSTR_RXY_RRRD
] = { R_8
, D20_20
, X_12
, B_16
, 0, 0 },
274 [INSTR_RXY_URRD
] = { U4_8
, D20_20
, X_12
, B_16
, 0, 0 },
275 [INSTR_RX_FRRD
] = { F_8
, D_20
, X_12
, B_16
, 0, 0 },
276 [INSTR_RX_RRRD
] = { R_8
, D_20
, X_12
, B_16
, 0, 0 },
277 [INSTR_RX_URRD
] = { U4_8
, D_20
, X_12
, B_16
, 0, 0 },
278 [INSTR_SIL_RDI
] = { D_20
, B_16
, I16_32
, 0, 0, 0 },
279 [INSTR_SIL_RDU
] = { D_20
, B_16
, U16_32
, 0, 0, 0 },
280 [INSTR_SIY_IRD
] = { D20_20
, B_16
, I8_8
, 0, 0, 0 },
281 [INSTR_SIY_URD
] = { D20_20
, B_16
, U8_8
, 0, 0, 0 },
282 [INSTR_SI_RD
] = { D_20
, B_16
, 0, 0, 0, 0 },
283 [INSTR_SI_URD
] = { D_20
, B_16
, U8_8
, 0, 0, 0 },
284 [INSTR_SMI_U0RDP
] = { U4_8
, J16_32
, D_20
, B_16
, 0, 0 },
285 [INSTR_SSE_RDRD
] = { D_20
, B_16
, D_36
, B_32
, 0, 0 },
286 [INSTR_SSF_RRDRD
] = { D_20
, B_16
, D_36
, B_32
, R_8
, 0 },
287 [INSTR_SSF_RRDRD2
] = { R_8
, D_20
, B_16
, D_36
, B_32
, 0 },
288 [INSTR_SS_L0RDRD
] = { D_20
, L8_8
, B_16
, D_36
, B_32
, 0 },
289 [INSTR_SS_L2RDRD
] = { D_20
, B_16
, D_36
, L8_8
, B_32
, 0 },
290 [INSTR_SS_LIRDRD
] = { D_20
, L4_8
, B_16
, D_36
, B_32
, U4_12
},
291 [INSTR_SS_LLRDRD
] = { D_20
, L4_8
, B_16
, D_36
, L4_12
, B_32
},
292 [INSTR_SS_RRRDRD
] = { D_20
, R_8
, B_16
, D_36
, B_32
, R_12
},
293 [INSTR_SS_RRRDRD2
] = { R_8
, D_20
, B_16
, R_12
, D_36
, B_32
},
294 [INSTR_SS_RRRDRD3
] = { R_8
, R_12
, D_20
, B_16
, D_36
, B_32
},
295 [INSTR_S_00
] = { 0, 0, 0, 0, 0, 0 },
296 [INSTR_S_RD
] = { D_20
, B_16
, 0, 0, 0, 0 },
297 [INSTR_VRI_V0IU
] = { V_8
, I16_16
, U4_32
, 0, 0, 0 },
298 [INSTR_VRI_V0U
] = { V_8
, U16_16
, 0, 0, 0, 0 },
299 [INSTR_VRI_V0UU2
] = { V_8
, U16_16
, U4_32
, 0, 0, 0 },
300 [INSTR_VRI_V0UUU
] = { V_8
, U8_16
, U8_24
, U4_32
, 0, 0 },
301 [INSTR_VRI_VR0UU
] = { V_8
, R_12
, U8_28
, U4_24
, 0, 0 },
302 [INSTR_VRI_VVUU
] = { V_8
, V_12
, U16_16
, U4_32
, 0, 0 },
303 [INSTR_VRI_VVUUU
] = { V_8
, V_12
, U12_16
, U4_32
, U4_28
, 0 },
304 [INSTR_VRI_VVUUU2
] = { V_8
, V_12
, U8_28
, U8_16
, U4_24
, 0 },
305 [INSTR_VRI_VVV0U
] = { V_8
, V_12
, V_16
, U8_24
, 0, 0 },
306 [INSTR_VRI_VVV0UU
] = { V_8
, V_12
, V_16
, U8_24
, U4_32
, 0 },
307 [INSTR_VRI_VVV0UU2
] = { V_8
, V_12
, V_16
, U8_28
, U4_24
, 0 },
308 [INSTR_VRR_0V
] = { V_12
, 0, 0, 0, 0, 0 },
309 [INSTR_VRR_0VV0U
] = { V_12
, V_16
, U4_24
, 0, 0, 0 },
310 [INSTR_VRR_RV0UU
] = { R_8
, V_12
, U4_24
, U4_28
, 0, 0 },
311 [INSTR_VRR_VRR
] = { V_8
, R_12
, R_16
, 0, 0, 0 },
312 [INSTR_VRR_VV
] = { V_8
, V_12
, 0, 0, 0, 0 },
313 [INSTR_VRR_VV0U
] = { V_8
, V_12
, U4_32
, 0, 0, 0 },
314 [INSTR_VRR_VV0U0U
] = { V_8
, V_12
, U4_32
, U4_24
, 0, 0 },
315 [INSTR_VRR_VV0UU2
] = { V_8
, V_12
, U4_32
, U4_28
, 0, 0 },
316 [INSTR_VRR_VV0UUU
] = { V_8
, V_12
, U4_32
, U4_28
, U4_24
, 0 },
317 [INSTR_VRR_VVV
] = { V_8
, V_12
, V_16
, 0, 0, 0 },
318 [INSTR_VRR_VVV0U
] = { V_8
, V_12
, V_16
, U4_32
, 0, 0 },
319 [INSTR_VRR_VVV0U0U
] = { V_8
, V_12
, V_16
, U4_32
, U4_24
, 0 },
320 [INSTR_VRR_VVV0UU
] = { V_8
, V_12
, V_16
, U4_32
, U4_28
, 0 },
321 [INSTR_VRR_VVV0UUU
] = { V_8
, V_12
, V_16
, U4_32
, U4_28
, U4_24
},
322 [INSTR_VRR_VVV0V
] = { V_8
, V_12
, V_16
, V_32
, 0, 0 },
323 [INSTR_VRR_VVVU0UV
] = { V_8
, V_12
, V_16
, V_32
, U4_28
, U4_20
},
324 [INSTR_VRR_VVVU0V
] = { V_8
, V_12
, V_16
, V_32
, U4_20
, 0 },
325 [INSTR_VRR_VVVUU0V
] = { V_8
, V_12
, V_16
, V_32
, U4_20
, U4_24
},
326 [INSTR_VRS_RRDV
] = { V_32
, R_12
, D_20
, B_16
, 0, 0 },
327 [INSTR_VRS_RVRDU
] = { R_8
, V_12
, D_20
, B_16
, U4_32
, 0 },
328 [INSTR_VRS_VRRD
] = { V_8
, R_12
, D_20
, B_16
, 0, 0 },
329 [INSTR_VRS_VRRDU
] = { V_8
, R_12
, D_20
, B_16
, U4_32
, 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_VRRDU
] = { V_8
, D_20
, X_12
, B_16
, U4_32
, 0 },
333 [INSTR_VRX_VV
] = { V_8
, V_12
, 0, 0, 0, 0 },
334 [INSTR_VSI_URDV
] = { V_32
, D_20
, B_16
, U8_8
, 0, 0 },
337 static char long_insn_name
[][7] = LONG_INSN_INITIALIZER
;
338 static struct s390_insn opcode
[] = OPCODE_TABLE_INITIALIZER
;
339 static struct s390_opcode_offset opcode_offset
[] = OPCODE_OFFSET_INITIALIZER
;
341 /* Extracts an operand value from an instruction. */
342 static unsigned int extract_operand(unsigned char *code
,
343 const struct s390_operand
*operand
)
349 /* Extract fragments of the operand byte for byte. */
350 cp
= code
+ operand
->shift
/ 8;
351 bits
= (operand
->shift
& 7) + operand
->bits
;
355 val
|= (unsigned int) *cp
++;
359 val
&= ((1U << (operand
->bits
- 1)) << 1) - 1;
361 /* Check for special long displacement case. */
362 if (operand
->bits
== 20 && operand
->shift
== 20)
363 val
= (val
& 0xff) << 12 | (val
& 0xfff00) >> 8;
365 /* Check for register extensions bits for vector registers. */
366 if (operand
->flags
& OPERAND_VR
) {
367 if (operand
->shift
== 8)
368 val
|= (code
[4] & 8) << 1;
369 else if (operand
->shift
== 12)
370 val
|= (code
[4] & 4) << 2;
371 else if (operand
->shift
== 16)
372 val
|= (code
[4] & 2) << 3;
373 else if (operand
->shift
== 32)
374 val
|= (code
[4] & 1) << 4;
377 /* Sign extend value if the operand is signed or pc relative. */
378 if ((operand
->flags
& (OPERAND_SIGNED
| OPERAND_PCREL
)) &&
379 (val
& (1U << (operand
->bits
- 1))))
380 val
|= (-1U << (operand
->bits
- 1)) << 1;
382 /* Double value if the operand is pc relative. */
383 if (operand
->flags
& OPERAND_PCREL
)
386 /* Length x in an instructions has real length x + 1. */
387 if (operand
->flags
& OPERAND_LENGTH
)
392 struct s390_insn
*find_insn(unsigned char *code
)
394 struct s390_opcode_offset
*entry
;
395 struct s390_insn
*insn
;
396 unsigned char opfrag
;
399 /* Search the opcode offset table to find an entry which
400 * matches the beginning of the opcode. If there is no match
401 * the last entry will be used, which is the default entry for
402 * unknown instructions as well as 1-byte opcode instructions.
404 for (i
= 0; i
< ARRAY_SIZE(opcode_offset
); i
++) {
405 entry
= &opcode_offset
[i
];
406 if (entry
->opcode
== code
[0])
410 opfrag
= *(code
+ entry
->byte
) & entry
->mask
;
412 insn
= &opcode
[entry
->offset
];
413 for (i
= 0; i
< entry
->count
; i
++) {
414 if (insn
->opfrag
== opfrag
)
421 static int print_insn(char *buffer
, unsigned char *code
, unsigned long addr
)
423 struct s390_insn
*insn
;
424 const unsigned char *ops
;
425 const struct s390_operand
*operand
;
432 insn
= find_insn(code
);
435 ptr
+= sprintf(ptr
, "%.7s\t",
436 long_insn_name
[insn
->offset
]);
438 ptr
+= sprintf(ptr
, "%.5s\t", insn
->name
);
439 /* Extract the operands. */
441 for (ops
= formats
[insn
->format
], i
= 0;
442 *ops
!= 0 && i
< 6; ops
++, i
++) {
443 operand
= operands
+ *ops
;
444 value
= extract_operand(code
, operand
);
445 if ((operand
->flags
& OPERAND_INDEX
) && value
== 0)
447 if ((operand
->flags
& OPERAND_BASE
) &&
448 value
== 0 && separator
== '(') {
453 ptr
+= sprintf(ptr
, "%c", separator
);
454 if (operand
->flags
& OPERAND_GPR
)
455 ptr
+= sprintf(ptr
, "%%r%i", value
);
456 else if (operand
->flags
& OPERAND_FPR
)
457 ptr
+= sprintf(ptr
, "%%f%i", value
);
458 else if (operand
->flags
& OPERAND_AR
)
459 ptr
+= sprintf(ptr
, "%%a%i", value
);
460 else if (operand
->flags
& OPERAND_CR
)
461 ptr
+= sprintf(ptr
, "%%c%i", value
);
462 else if (operand
->flags
& OPERAND_VR
)
463 ptr
+= sprintf(ptr
, "%%v%i", value
);
464 else if (operand
->flags
& OPERAND_PCREL
)
465 ptr
+= sprintf(ptr
, "%lx", (signed int) value
467 else if (operand
->flags
& OPERAND_SIGNED
)
468 ptr
+= sprintf(ptr
, "%i", value
);
470 ptr
+= sprintf(ptr
, "%u", value
);
471 if (operand
->flags
& OPERAND_DISP
)
473 else if (operand
->flags
& OPERAND_BASE
) {
474 ptr
+= sprintf(ptr
, ")");
480 ptr
+= sprintf(ptr
, "unknown");
481 return (int) (ptr
- buffer
);
484 void show_code(struct pt_regs
*regs
)
486 char *mode
= user_mode(regs
) ? "User" : "Krnl";
487 unsigned char code
[64];
488 char buffer
[128], *ptr
;
491 int start
, end
, opsize
, hops
, i
;
493 /* Get a snapshot of the 64 bytes surrounding the fault address. */
495 set_fs(user_mode(regs
) ? USER_DS
: KERNEL_DS
);
496 for (start
= 32; start
&& regs
->psw
.addr
>= 34 - start
; start
-= 2) {
497 addr
= regs
->psw
.addr
- 34 + start
;
498 if (__copy_from_user(code
+ start
- 2,
499 (char __user
*) addr
, 2))
502 for (end
= 32; end
< 64; end
+= 2) {
503 addr
= regs
->psw
.addr
+ end
- 32;
504 if (__copy_from_user(code
+ end
,
505 (char __user
*) addr
, 2))
509 /* Code snapshot useable ? */
510 if ((regs
->psw
.addr
& 1) || start
>= end
) {
511 printk("%s Code: Bad PSW.\n", mode
);
514 /* Find a starting point for the disassembly. */
516 for (i
= 0, hops
= 0; start
+ i
< 32 && hops
< 3; hops
++) {
517 if (!find_insn(code
+ start
+ i
))
519 i
+= insn_length(code
[start
+ i
]);
522 /* Looks good, sequence ends at PSW. */
526 /* Decode the instructions. */
528 ptr
+= sprintf(ptr
, "%s Code:", mode
);
530 while (start
< end
&& hops
< 8) {
531 opsize
= insn_length(code
[start
]);
532 if (start
+ opsize
== 32)
534 else if (start
== 32)
538 addr
= regs
->psw
.addr
+ start
- 32;
539 ptr
+= sprintf(ptr
, "%016lx: ", addr
);
540 if (start
+ opsize
>= end
)
542 for (i
= 0; i
< opsize
; i
++)
543 ptr
+= sprintf(ptr
, "%02x", code
[start
+ i
]);
547 ptr
+= print_insn(ptr
, code
+ start
, addr
);
549 pr_cont("%s", buffer
);
551 ptr
+= sprintf(ptr
, "\n ");
557 void print_fn_code(unsigned char *code
, unsigned long len
)
559 char buffer
[64], *ptr
;
564 opsize
= insn_length(*code
);
567 ptr
+= sprintf(ptr
, "%p: ", code
);
568 for (i
= 0; i
< opsize
; i
++)
569 ptr
+= sprintf(ptr
, "%02x", code
[i
]);
573 ptr
+= print_insn(ptr
, code
, (unsigned long) code
);
576 printk("%s", buffer
);