Fix a use of target_mourn_inferior in windows-nat.c
[deliverable/binutils-gdb.git] / opcodes / s390-dis.c
CommitLineData
a85d7ed0 1/* s390-dis.c -- Disassemble S390 instructions
6f2750fe 2 Copyright (C) 2000-2016 Free Software Foundation, Inc.
a85d7ed0
NC
3 Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
4
9b201bb5 5 This file is part of the GNU opcodes library.
a85d7ed0 6
9b201bb5 7 This library is free software; you can redistribute it and/or modify
a85d7ed0 8 it under the terms of the GNU General Public License as published by
9b201bb5
NC
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
a85d7ed0 11
9b201bb5
NC
12 It is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
a85d7ed0
NC
16
17 You should have received a copy of the GNU General Public License
9b201bb5
NC
18 along with this file; see the file COPYING. If not, write to the
19 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
a85d7ed0 21
df7b86aa 22#include "sysdep.h"
a85d7ed0
NC
23#include <stdio.h>
24#include "ansidecl.h"
a85d7ed0 25#include "dis-asm.h"
112b7c50 26#include "opintl.h"
a85d7ed0
NC
27#include "opcode/s390.h"
28
29static int init_flag = 0;
30static int opc_index[256];
31static int current_arch_mask = 0;
b2cc3f6f 32static int option_use_insn_len_bits_p = 0;
a85d7ed0 33
44f2a95d
KH
34/* Set up index table for first opcode byte. */
35
36static void
47b0e7ad 37init_disasm (struct disassemble_info *info)
a85d7ed0 38{
9ace48f3 39 int i;
112b7c50 40 const char *p;
a85d7ed0 41
44f2a95d 42 memset (opc_index, 0, sizeof (opc_index));
9ace48f3
AA
43
44 /* Reverse order, such that each opc_index ends up pointing to the
45 first matching entry instead of the last. */
46 for (i = s390_num_opcodes; i--; )
47 opc_index[s390_opcodes[i].opcode[0]] = i;
112b7c50
AK
48
49 for (p = info->disassembler_options; p != NULL; )
44f2a95d 50 {
112b7c50
AK
51 if (CONST_STRNEQ (p, "esa"))
52 current_arch_mask = 1 << S390_OPCODE_ESA;
53 else if (CONST_STRNEQ (p, "zarch"))
54 current_arch_mask = 1 << S390_OPCODE_ZARCH;
b2cc3f6f
AK
55 else if (CONST_STRNEQ (p, "insnlength"))
56 option_use_insn_len_bits_p = 1;
112b7c50
AK
57 else
58 fprintf (stderr, "Unknown S/390 disassembler option: %s\n", p);
59
60 p = strchr (p, ',');
61 if (p != NULL)
62 p++;
44f2a95d 63 }
112b7c50
AK
64
65 if (!current_arch_mask)
7d4a7d10 66 current_arch_mask = 1 << S390_OPCODE_ZARCH;
112b7c50 67
a85d7ed0
NC
68 init_flag = 1;
69}
70
9ace48f3
AA
71/* Derive the length of an instruction from its first byte. */
72
73static inline int
74s390_insn_length (const bfd_byte *buffer)
75{
76 /* 00xxxxxx -> 2, 01xxxxxx/10xxxxxx -> 4, 11xxxxxx -> 6. */
77 return ((buffer[0] >> 6) + 3) & ~1U;
78}
79
80/* Match the instruction in BUFFER against the given OPCODE, excluding
81 the first byte. */
82
83static inline int
84s390_insn_matches_opcode (const bfd_byte *buffer,
85 const struct s390_opcode *opcode)
86{
87 return (buffer[1] & opcode->mask[1]) == opcode->opcode[1]
88 && (buffer[2] & opcode->mask[2]) == opcode->opcode[2]
89 && (buffer[3] & opcode->mask[3]) == opcode->opcode[3]
90 && (buffer[4] & opcode->mask[4]) == opcode->opcode[4]
91 && (buffer[5] & opcode->mask[5]) == opcode->opcode[5];
92}
93
94union operand_value
95{
96 int i;
97 unsigned int u;
98};
99
a85d7ed0 100/* Extracts an operand value from an instruction. */
7330f9c3
AK
101/* We do not perform the shift operation for larl-type address
102 operands here since that would lead to an overflow of the 32 bit
103 integer value. Instead the shift operation is done when printing
9ace48f3 104 the operand. */
a85d7ed0 105
9ace48f3
AA
106static inline union operand_value
107s390_extract_operand (const bfd_byte *insn,
108 const struct s390_operand *operand)
a85d7ed0 109{
9ace48f3 110 union operand_value ret;
a85d7ed0
NC
111 unsigned int val;
112 int bits;
1e2e8c52 113 const bfd_byte *orig_insn = insn;
a85d7ed0 114
44f2a95d
KH
115 /* Extract fragments of the operand byte for byte. */
116 insn += operand->shift / 8;
a85d7ed0
NC
117 bits = (operand->shift & 7) + operand->bits;
118 val = 0;
44f2a95d
KH
119 do
120 {
121 val <<= 8;
122 val |= (unsigned int) *insn++;
123 bits -= 8;
124 }
125 while (bits > 0);
a85d7ed0 126 val >>= -bits;
44f2a95d
KH
127 val &= ((1U << (operand->bits - 1)) << 1) - 1;
128
bac02689
MS
129 /* Check for special long displacement case. */
130 if (operand->bits == 20 && operand->shift == 20)
131 val = (val & 0xff) << 12 | (val & 0xfff00) >> 8;
132
9ace48f3
AA
133 /* Sign extend value if the operand is signed or pc relative. Avoid
134 integer overflows. */
135 if (operand->flags & (S390_OPERAND_SIGNED | S390_OPERAND_PCREL))
136 {
137 unsigned int m = 1U << (operand->bits - 1);
138
139 if (val >= m)
140 ret.i = (int) (val - m) - 1 - (int) (m - 1U);
141 else
142 ret.i = (int) val;
143 }
144 else if (operand->flags & S390_OPERAND_LENGTH)
145 /* Length x in an instruction has real length x + 1. */
146 ret.u = val + 1;
1e2e8c52
AK
147
148 else if (operand->flags & S390_OPERAND_VR)
149 {
150 /* Extract the extra bits for a vector register operand stored
151 in the RXB field. */
152 unsigned vr = operand->shift == 32 ? 3
153 : (unsigned) operand->shift / 4 - 2;
154
155 ret.u = val | ((orig_insn[4] & (1 << (3 - vr))) << (vr + 1));
156 }
9ace48f3
AA
157 else
158 ret.u = val;
159
160 return ret;
161}
162
163/* Print the S390 instruction in BUFFER, assuming that it matches the
164 given OPCODE. */
165
166static void
167s390_print_insn_with_opcode (bfd_vma memaddr,
168 struct disassemble_info *info,
169 const bfd_byte *buffer,
170 const struct s390_opcode *opcode)
171{
172 const unsigned char *opindex;
173 char separator;
174
175 /* Mnemonic. */
176 info->fprintf_func (info->stream, "%s", opcode->name);
177
178 /* Operands. */
179 separator = '\t';
180 for (opindex = opcode->operands; *opindex != 0; opindex++)
181 {
182 const struct s390_operand *operand = s390_operands + *opindex;
183 union operand_value val = s390_extract_operand (buffer, operand);
184 unsigned long flags = operand->flags;
185
186 if ((flags & S390_OPERAND_INDEX) && val.u == 0)
187 continue;
188 if ((flags & S390_OPERAND_BASE) &&
189 val.u == 0 && separator == '(')
190 {
191 separator = ',';
192 continue;
193 }
194
1e2e8c52
AK
195 /* For instructions with a last optional operand don't print it
196 if zero. */
197 if ((opcode->flags & S390_INSTR_FLAG_OPTPARM)
198 && val.u == 0
199 && opindex[1] == 0)
200 break;
9ace48f3
AA
201
202 if (flags & S390_OPERAND_GPR)
1e2e8c52 203 info->fprintf_func (info->stream, "%c%%r%u", separator, val.u);
9ace48f3 204 else if (flags & S390_OPERAND_FPR)
1e2e8c52
AK
205 info->fprintf_func (info->stream, "%c%%f%u", separator, val.u);
206 else if (flags & S390_OPERAND_VR)
207 info->fprintf_func (info->stream, "%c%%v%i", separator, val.u);
9ace48f3 208 else if (flags & S390_OPERAND_AR)
1e2e8c52 209 info->fprintf_func (info->stream, "%c%%a%u", separator, val.u);
9ace48f3 210 else if (flags & S390_OPERAND_CR)
1e2e8c52 211 info->fprintf_func (info->stream, "%c%%c%u", separator, val.u);
9ace48f3 212 else if (flags & S390_OPERAND_PCREL)
1e2e8c52
AK
213 {
214 info->fprintf_func (info->stream, "%c", separator);
215 info->print_address_func (memaddr + val.i + val.i, info);
216 }
9ace48f3 217 else if (flags & S390_OPERAND_SIGNED)
1e2e8c52 218 info->fprintf_func (info->stream, "%c%i", separator, val.i);
9ace48f3 219 else
1e2e8c52
AK
220 {
221 if (flags & S390_OPERAND_OR1)
222 val.u &= ~1;
223 if (flags & S390_OPERAND_OR2)
224 val.u &= ~2;
225 if (flags & S390_OPERAND_OR8)
226 val.u &= ~8;
227
228 if ((opcode->flags & S390_INSTR_FLAG_OPTPARM)
229 && val.u == 0
230 && opindex[1] == 0)
231 break;
232 info->fprintf_func (info->stream, "%c%u", separator, val.u);
233 }
9ace48f3
AA
234
235 if (flags & S390_OPERAND_DISP)
236 separator = '(';
237 else if (flags & S390_OPERAND_BASE)
238 {
239 info->fprintf_func (info->stream, ")");
240 separator = ',';
241 }
242 else
243 separator = ',';
244 }
245}
246
247/* Check whether opcode A's mask is more specific than that of B. */
44f2a95d 248
9ace48f3
AA
249static int
250opcode_mask_more_specific (const struct s390_opcode *a,
251 const struct s390_opcode *b)
252{
253 return (((int) a->mask[0] + a->mask[1] + a->mask[2]
254 + a->mask[3] + a->mask[4] + a->mask[5])
255 > ((int) b->mask[0] + b->mask[1] + b->mask[2]
256 + b->mask[3] + b->mask[4] + b->mask[5]));
a85d7ed0
NC
257}
258
259/* Print a S390 instruction. */
260
261int
47b0e7ad 262print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
a85d7ed0
NC
263{
264 bfd_byte buffer[6];
9ace48f3 265 const struct s390_opcode *opcode = NULL;
a85d7ed0 266 unsigned int value;
b2cc3f6f 267 int status, opsize, bufsize, bytes_to_dump, i;
a85d7ed0
NC
268
269 if (init_flag == 0)
44f2a95d 270 init_disasm (info);
a85d7ed0
NC
271
272 /* The output looks better if we put 6 bytes on a line. */
273 info->bytes_per_line = 6;
274
275 /* Every S390 instruction is max 6 bytes long. */
44f2a95d 276 memset (buffer, 0, 6);
9ace48f3 277 status = info->read_memory_func (memaddr, buffer, 6, info);
44f2a95d
KH
278 if (status != 0)
279 {
280 for (bufsize = 0; bufsize < 6; bufsize++)
9ace48f3 281 if (info->read_memory_func (memaddr, buffer, bufsize + 1, info) != 0)
44f2a95d
KH
282 break;
283 if (bufsize <= 0)
284 {
9ace48f3 285 info->memory_error_func (status, memaddr, info);
44f2a95d
KH
286 return -1;
287 }
9ace48f3 288 opsize = s390_insn_length (buffer);
44f2a95d
KH
289 status = opsize > bufsize;
290 }
291 else
292 {
293 bufsize = 6;
9ace48f3 294 opsize = s390_insn_length (buffer);
44f2a95d
KH
295 }
296
297 if (status == 0)
298 {
02cbf767
AK
299 const struct s390_opcode *op;
300
9ace48f3
AA
301 /* Find the "best match" in the opcode table. */
302 for (op = s390_opcodes + opc_index[buffer[0]];
303 op != s390_opcodes + s390_num_opcodes
304 && op->opcode[0] == buffer[0];
305 op++)
44f2a95d 306 {
9ace48f3
AA
307 if ((op->modes & current_arch_mask)
308 && s390_insn_matches_opcode (buffer, op)
309 && (opcode == NULL
310 || opcode_mask_more_specific (op, opcode)))
311 opcode = op;
44f2a95d 312 }
44f2a95d 313
b2cc3f6f
AK
314 if (opcode != NULL)
315 {
316 /* The instruction is valid. Print it and return its size. */
317 s390_print_insn_with_opcode (memaddr, info, buffer, opcode);
318 return opsize;
319 }
9ace48f3
AA
320 }
321
b2cc3f6f
AK
322 /* For code sections it makes sense to skip unknown instructions
323 according to their length bits. */
324 if (status == 0
325 && option_use_insn_len_bits_p
326 && info->section != NULL
327 && (info->section->flags & SEC_CODE))
328 bytes_to_dump = opsize;
329 else
330 /* By default unknown instructions are printed as .long's/.short'
331 depending on how many bytes are available. */
332 bytes_to_dump = bufsize >= 4 ? 4 : bufsize;
333
334 if (bytes_to_dump == 0)
335 return 0;
336
9ace48f3 337 /* Fall back to hex print. */
b2cc3f6f 338 switch (bytes_to_dump)
44f2a95d 339 {
b2cc3f6f 340 case 4:
44f2a95d
KH
341 value = (unsigned int) buffer[0];
342 value = (value << 8) + (unsigned int) buffer[1];
343 value = (value << 8) + (unsigned int) buffer[2];
344 value = (value << 8) + (unsigned int) buffer[3];
9ace48f3 345 info->fprintf_func (info->stream, ".long\t0x%08x", value);
44f2a95d 346 return 4;
b2cc3f6f 347 case 2:
44f2a95d
KH
348 value = (unsigned int) buffer[0];
349 value = (value << 8) + (unsigned int) buffer[1];
9ace48f3 350 info->fprintf_func (info->stream, ".short\t0x%04x", value);
44f2a95d 351 return 2;
b2cc3f6f
AK
352 default:
353 info->fprintf_func (info->stream, ".byte\t0x%02x",
354 (unsigned int) buffer[0]);
355 for (i = 1; i < bytes_to_dump; i++)
356 info->fprintf_func (info->stream, ",0x%02x",
357 (unsigned int) buffer[i]);
358 return bytes_to_dump;
a85d7ed0 359 }
b2cc3f6f 360 return 0;
a85d7ed0 361}
112b7c50
AK
362
363void
364print_s390_disassembler_options (FILE *stream)
365{
366 fprintf (stream, _("\n\
367The following S/390 specific disassembler options are supported for use\n\
368with the -M switch (multiple options should be separated by commas):\n"));
369
370 fprintf (stream, _(" esa Disassemble in ESA architecture mode\n"));
371 fprintf (stream, _(" zarch Disassemble in z/Architecture mode\n"));
b2cc3f6f
AK
372 fprintf (stream, _(" insnlength Print unknown instructions according "
373 "to length from first two bits\n"));
112b7c50 374}
This page took 1.081612 seconds and 4 git commands to generate.