1 /* s390-dis.c -- Disassemble S390 instructions
2 Copyright (C) 2000-2017 Free Software Foundation, Inc.
3 Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
5 This file is part of the GNU opcodes library.
7 This library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
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.
17 You should have received a copy of the GNU General Public License
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. */
25 #include "disassemble.h"
27 #include "opcode/s390.h"
28 #include "libiberty.h"
30 static int opc_index[256];
31 static int current_arch_mask = 0;
32 static int option_use_insn_len_bits_p = 0;
37 const char *description;
40 static const s390_options_t options[] =
42 { "esa" , N_("Disassemble in ESA architecture mode") },
43 { "zarch", N_("Disassemble in z/Architecture mode") },
44 { "insnlength", N_("Print unknown instructions according to "
45 "length from first two bits") }
48 /* Set up index table for first opcode byte. */
51 disassemble_init_s390 (struct disassemble_info *info)
56 memset (opc_index, 0, sizeof (opc_index));
58 /* Reverse order, such that each opc_index ends up pointing to the
59 first matching entry instead of the last. */
60 for (i = s390_num_opcodes; i--; )
61 opc_index[s390_opcodes[i].opcode[0]] = i;
63 current_arch_mask = 1 << S390_OPCODE_ZARCH;
64 option_use_insn_len_bits_p = 0;
66 for (p = info->disassembler_options; p != NULL; )
68 if (CONST_STRNEQ (p, "esa"))
69 current_arch_mask = 1 << S390_OPCODE_ESA;
70 else if (CONST_STRNEQ (p, "zarch"))
71 current_arch_mask = 1 << S390_OPCODE_ZARCH;
72 else if (CONST_STRNEQ (p, "insnlength"))
73 option_use_insn_len_bits_p = 1;
75 fprintf (stderr, "Unknown S/390 disassembler option: %s\n", p);
83 /* Derive the length of an instruction from its first byte. */
86 s390_insn_length (const bfd_byte *buffer)
88 /* 00xxxxxx -> 2, 01xxxxxx/10xxxxxx -> 4, 11xxxxxx -> 6. */
89 return ((buffer[0] >> 6) + 3) & ~1U;
92 /* Match the instruction in BUFFER against the given OPCODE, excluding
96 s390_insn_matches_opcode (const bfd_byte *buffer,
97 const struct s390_opcode *opcode)
99 return (buffer[1] & opcode->mask[1]) == opcode->opcode[1]
100 && (buffer[2] & opcode->mask[2]) == opcode->opcode[2]
101 && (buffer[3] & opcode->mask[3]) == opcode->opcode[3]
102 && (buffer[4] & opcode->mask[4]) == opcode->opcode[4]
103 && (buffer[5] & opcode->mask[5]) == opcode->opcode[5];
112 /* Extracts an operand value from an instruction. */
113 /* We do not perform the shift operation for larl-type address
114 operands here since that would lead to an overflow of the 32 bit
115 integer value. Instead the shift operation is done when printing
118 static inline union operand_value
119 s390_extract_operand (const bfd_byte *insn,
120 const struct s390_operand *operand)
122 union operand_value ret;
125 const bfd_byte *orig_insn = insn;
127 /* Extract fragments of the operand byte for byte. */
128 insn += operand->shift / 8;
129 bits = (operand->shift & 7) + operand->bits;
134 val |= (unsigned int) *insn++;
139 val &= ((1U << (operand->bits - 1)) << 1) - 1;
141 /* Check for special long displacement case. */
142 if (operand->bits == 20 && operand->shift == 20)
143 val = (val & 0xff) << 12 | (val & 0xfff00) >> 8;
145 /* Sign extend value if the operand is signed or pc relative. Avoid
146 integer overflows. */
147 if (operand->flags & (S390_OPERAND_SIGNED | S390_OPERAND_PCREL))
149 unsigned int m = 1U << (operand->bits - 1);
152 ret.i = (int) (val - m) - 1 - (int) (m - 1U);
156 else if (operand->flags & S390_OPERAND_LENGTH)
157 /* Length x in an instruction has real length x + 1. */
160 else if (operand->flags & S390_OPERAND_VR)
162 /* Extract the extra bits for a vector register operand stored
164 unsigned vr = operand->shift == 32 ? 3
165 : (unsigned) operand->shift / 4 - 2;
167 ret.u = val | ((orig_insn[4] & (1 << (3 - vr))) << (vr + 1));
175 /* Print the S390 instruction in BUFFER, assuming that it matches the
179 s390_print_insn_with_opcode (bfd_vma memaddr,
180 struct disassemble_info *info,
181 const bfd_byte *buffer,
182 const struct s390_opcode *opcode)
184 const unsigned char *opindex;
188 info->fprintf_func (info->stream, "%s", opcode->name);
192 for (opindex = opcode->operands; *opindex != 0; opindex++)
194 const struct s390_operand *operand = s390_operands + *opindex;
195 union operand_value val = s390_extract_operand (buffer, operand);
196 unsigned long flags = operand->flags;
198 if ((flags & S390_OPERAND_INDEX) && val.u == 0)
200 if ((flags & S390_OPERAND_BASE) &&
201 val.u == 0 && separator == '(')
207 /* For instructions with a last optional operand don't print it
209 if ((opcode->flags & S390_INSTR_FLAG_OPTPARM)
214 if (flags & S390_OPERAND_GPR)
215 info->fprintf_func (info->stream, "%c%%r%u", separator, val.u);
216 else if (flags & S390_OPERAND_FPR)
217 info->fprintf_func (info->stream, "%c%%f%u", separator, val.u);
218 else if (flags & S390_OPERAND_VR)
219 info->fprintf_func (info->stream, "%c%%v%i", separator, val.u);
220 else if (flags & S390_OPERAND_AR)
221 info->fprintf_func (info->stream, "%c%%a%u", separator, val.u);
222 else if (flags & S390_OPERAND_CR)
223 info->fprintf_func (info->stream, "%c%%c%u", separator, val.u);
224 else if (flags & S390_OPERAND_PCREL)
226 info->fprintf_func (info->stream, "%c", separator);
227 info->print_address_func (memaddr + val.i + val.i, info);
229 else if (flags & S390_OPERAND_SIGNED)
230 info->fprintf_func (info->stream, "%c%i", separator, val.i);
233 if (flags & S390_OPERAND_OR1)
235 if (flags & S390_OPERAND_OR2)
237 if (flags & S390_OPERAND_OR8)
240 if ((opcode->flags & S390_INSTR_FLAG_OPTPARM)
244 info->fprintf_func (info->stream, "%c%u", separator, val.u);
247 if (flags & S390_OPERAND_DISP)
249 else if (flags & S390_OPERAND_BASE)
251 info->fprintf_func (info->stream, ")");
259 /* Check whether opcode A's mask is more specific than that of B. */
262 opcode_mask_more_specific (const struct s390_opcode *a,
263 const struct s390_opcode *b)
265 return (((int) a->mask[0] + a->mask[1] + a->mask[2]
266 + a->mask[3] + a->mask[4] + a->mask[5])
267 > ((int) b->mask[0] + b->mask[1] + b->mask[2]
268 + b->mask[3] + b->mask[4] + b->mask[5]));
271 /* Print a S390 instruction. */
274 print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
277 const struct s390_opcode *opcode = NULL;
279 int status, opsize, bufsize, bytes_to_dump, i;
281 /* The output looks better if we put 6 bytes on a line. */
282 info->bytes_per_line = 6;
284 /* Every S390 instruction is max 6 bytes long. */
285 memset (buffer, 0, 6);
286 status = info->read_memory_func (memaddr, buffer, 6, info);
289 for (bufsize = 0; bufsize < 6; bufsize++)
290 if (info->read_memory_func (memaddr, buffer, bufsize + 1, info) != 0)
294 info->memory_error_func (status, memaddr, info);
297 opsize = s390_insn_length (buffer);
298 status = opsize > bufsize;
303 opsize = s390_insn_length (buffer);
308 const struct s390_opcode *op;
310 /* Find the "best match" in the opcode table. */
311 for (op = s390_opcodes + opc_index[buffer[0]];
312 op != s390_opcodes + s390_num_opcodes
313 && op->opcode[0] == buffer[0];
316 if ((op->modes & current_arch_mask)
317 && s390_insn_matches_opcode (buffer, op)
319 || opcode_mask_more_specific (op, opcode)))
325 /* The instruction is valid. Print it and return its size. */
326 s390_print_insn_with_opcode (memaddr, info, buffer, opcode);
331 /* For code sections it makes sense to skip unknown instructions
332 according to their length bits. */
334 && option_use_insn_len_bits_p
335 && info->section != NULL
336 && (info->section->flags & SEC_CODE))
337 bytes_to_dump = opsize;
339 /* By default unknown instructions are printed as .long's/.short'
340 depending on how many bytes are available. */
341 bytes_to_dump = bufsize >= 4 ? 4 : bufsize;
343 if (bytes_to_dump == 0)
346 /* Fall back to hex print. */
347 switch (bytes_to_dump)
350 value = (unsigned int) buffer[0];
351 value = (value << 8) + (unsigned int) buffer[1];
352 value = (value << 8) + (unsigned int) buffer[2];
353 value = (value << 8) + (unsigned int) buffer[3];
354 info->fprintf_func (info->stream, ".long\t0x%08x", value);
357 value = (unsigned int) buffer[0];
358 value = (value << 8) + (unsigned int) buffer[1];
359 info->fprintf_func (info->stream, ".short\t0x%04x", value);
362 info->fprintf_func (info->stream, ".byte\t0x%02x",
363 (unsigned int) buffer[0]);
364 for (i = 1; i < bytes_to_dump; i++)
365 info->fprintf_func (info->stream, ",0x%02x",
366 (unsigned int) buffer[i]);
367 return bytes_to_dump;
372 const disasm_options_t *
373 disassembler_options_s390 (void)
375 static disasm_options_t *opts = NULL;
379 size_t i, num_options = ARRAY_SIZE (options);
380 opts = XNEW (disasm_options_t);
381 opts->name = XNEWVEC (const char *, num_options + 1);
382 opts->description = XNEWVEC (const char *, num_options + 1);
383 for (i = 0; i < num_options; i++)
385 opts->name[i] = options[i].name;
386 opts->description[i] = _(options[i].description);
388 /* The array we return must be NULL terminated. */
389 opts->name[i] = NULL;
390 opts->description[i] = NULL;
397 print_s390_disassembler_options (FILE *stream)
399 unsigned int i, max_len = 0;
400 fprintf (stream, _("\n\
401 The following S/390 specific disassembler options are supported for use\n\
402 with the -M switch (multiple options should be separated by commas):\n"));
404 for (i = 0; i < ARRAY_SIZE (options); i++)
406 unsigned int len = strlen (options[i].name);
411 for (i = 0, max_len++; i < ARRAY_SIZE (options); i++)
412 fprintf (stream, " %s%*c %s\n",
414 (int)(max_len - strlen (options[i].name)), ' ',
415 _(options[i].description));