1 /* s390-dis.c -- Disassemble S390 instructions
2 Copyright (C) 2000-2016 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. */
27 #include "opcode/s390.h"
29 static int init_flag
= 0;
30 static int opc_index
[256];
31 static int current_arch_mask
= 0;
32 static int option_use_insn_len_bits_p
= 0;
34 /* Set up index table for first opcode byte. */
37 init_disasm (struct disassemble_info
*info
)
42 memset (opc_index
, 0, sizeof (opc_index
));
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
;
49 for (p
= info
->disassembler_options
; p
!= NULL
; )
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
;
55 else if (CONST_STRNEQ (p
, "insnlength"))
56 option_use_insn_len_bits_p
= 1;
58 fprintf (stderr
, "Unknown S/390 disassembler option: %s\n", p
);
65 if (!current_arch_mask
)
66 current_arch_mask
= 1 << S390_OPCODE_ZARCH
;
71 /* Derive the length of an instruction from its first byte. */
74 s390_insn_length (const bfd_byte
*buffer
)
76 /* 00xxxxxx -> 2, 01xxxxxx/10xxxxxx -> 4, 11xxxxxx -> 6. */
77 return ((buffer
[0] >> 6) + 3) & ~1U;
80 /* Match the instruction in BUFFER against the given OPCODE, excluding
84 s390_insn_matches_opcode (const bfd_byte
*buffer
,
85 const struct s390_opcode
*opcode
)
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];
100 /* Extracts an operand value from an instruction. */
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
106 static inline union operand_value
107 s390_extract_operand (const bfd_byte
*insn
,
108 const struct s390_operand
*operand
)
110 union operand_value ret
;
113 const bfd_byte
*orig_insn
= insn
;
115 /* Extract fragments of the operand byte for byte. */
116 insn
+= operand
->shift
/ 8;
117 bits
= (operand
->shift
& 7) + operand
->bits
;
122 val
|= (unsigned int) *insn
++;
127 val
&= ((1U << (operand
->bits
- 1)) << 1) - 1;
129 /* Check for special long displacement case. */
130 if (operand
->bits
== 20 && operand
->shift
== 20)
131 val
= (val
& 0xff) << 12 | (val
& 0xfff00) >> 8;
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
))
137 unsigned int m
= 1U << (operand
->bits
- 1);
140 ret
.i
= (int) (val
- m
) - 1 - (int) (m
- 1U);
144 else if (operand
->flags
& S390_OPERAND_LENGTH
)
145 /* Length x in an instruction has real length x + 1. */
148 else if (operand
->flags
& S390_OPERAND_VR
)
150 /* Extract the extra bits for a vector register operand stored
152 unsigned vr
= operand
->shift
== 32 ? 3
153 : (unsigned) operand
->shift
/ 4 - 2;
155 ret
.u
= val
| ((orig_insn
[4] & (1 << (3 - vr
))) << (vr
+ 1));
163 /* Print the S390 instruction in BUFFER, assuming that it matches the
167 s390_print_insn_with_opcode (bfd_vma memaddr
,
168 struct disassemble_info
*info
,
169 const bfd_byte
*buffer
,
170 const struct s390_opcode
*opcode
)
172 const unsigned char *opindex
;
176 info
->fprintf_func (info
->stream
, "%s", opcode
->name
);
180 for (opindex
= opcode
->operands
; *opindex
!= 0; opindex
++)
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
;
186 if ((flags
& S390_OPERAND_INDEX
) && val
.u
== 0)
188 if ((flags
& S390_OPERAND_BASE
) &&
189 val
.u
== 0 && separator
== '(')
195 /* For instructions with a last optional operand don't print it
197 if ((opcode
->flags
& S390_INSTR_FLAG_OPTPARM
)
202 if (flags
& S390_OPERAND_GPR
)
203 info
->fprintf_func (info
->stream
, "%c%%r%u", separator
, val
.u
);
204 else if (flags
& S390_OPERAND_FPR
)
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
);
208 else if (flags
& S390_OPERAND_AR
)
209 info
->fprintf_func (info
->stream
, "%c%%a%u", separator
, val
.u
);
210 else if (flags
& S390_OPERAND_CR
)
211 info
->fprintf_func (info
->stream
, "%c%%c%u", separator
, val
.u
);
212 else if (flags
& S390_OPERAND_PCREL
)
214 info
->fprintf_func (info
->stream
, "%c", separator
);
215 info
->print_address_func (memaddr
+ val
.i
+ val
.i
, info
);
217 else if (flags
& S390_OPERAND_SIGNED
)
218 info
->fprintf_func (info
->stream
, "%c%i", separator
, val
.i
);
221 if (flags
& S390_OPERAND_OR1
)
223 if (flags
& S390_OPERAND_OR2
)
225 if (flags
& S390_OPERAND_OR8
)
228 if ((opcode
->flags
& S390_INSTR_FLAG_OPTPARM
)
232 info
->fprintf_func (info
->stream
, "%c%u", separator
, val
.u
);
235 if (flags
& S390_OPERAND_DISP
)
237 else if (flags
& S390_OPERAND_BASE
)
239 info
->fprintf_func (info
->stream
, ")");
247 /* Check whether opcode A's mask is more specific than that of B. */
250 opcode_mask_more_specific (const struct s390_opcode
*a
,
251 const struct s390_opcode
*b
)
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]));
259 /* Print a S390 instruction. */
262 print_insn_s390 (bfd_vma memaddr
, struct disassemble_info
*info
)
265 const struct s390_opcode
*opcode
= NULL
;
267 int status
, opsize
, bufsize
, bytes_to_dump
, i
;
272 /* The output looks better if we put 6 bytes on a line. */
273 info
->bytes_per_line
= 6;
275 /* Every S390 instruction is max 6 bytes long. */
276 memset (buffer
, 0, 6);
277 status
= info
->read_memory_func (memaddr
, buffer
, 6, info
);
280 for (bufsize
= 0; bufsize
< 6; bufsize
++)
281 if (info
->read_memory_func (memaddr
, buffer
, bufsize
+ 1, info
) != 0)
285 info
->memory_error_func (status
, memaddr
, info
);
288 opsize
= s390_insn_length (buffer
);
289 status
= opsize
> bufsize
;
294 opsize
= s390_insn_length (buffer
);
299 const struct s390_opcode
*op
;
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];
307 if ((op
->modes
& current_arch_mask
)
308 && s390_insn_matches_opcode (buffer
, op
)
310 || opcode_mask_more_specific (op
, opcode
)))
316 /* The instruction is valid. Print it and return its size. */
317 s390_print_insn_with_opcode (memaddr
, info
, buffer
, opcode
);
322 /* For code sections it makes sense to skip unknown instructions
323 according to their length bits. */
325 && option_use_insn_len_bits_p
326 && info
->section
!= NULL
327 && (info
->section
->flags
& SEC_CODE
))
328 bytes_to_dump
= opsize
;
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
;
334 if (bytes_to_dump
== 0)
337 /* Fall back to hex print. */
338 switch (bytes_to_dump
)
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];
345 info
->fprintf_func (info
->stream
, ".long\t0x%08x", value
);
348 value
= (unsigned int) buffer
[0];
349 value
= (value
<< 8) + (unsigned int) buffer
[1];
350 info
->fprintf_func (info
->stream
, ".short\t0x%04x", value
);
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
;
364 print_s390_disassembler_options (FILE *stream
)
366 fprintf (stream
, _("\n\
367 The following S/390 specific disassembler options are supported for use\n\
368 with the -M switch (multiple options should be separated by commas):\n"));
370 fprintf (stream
, _(" esa Disassemble in ESA architecture mode\n"));
371 fprintf (stream
, _(" zarch Disassemble in z/Architecture mode\n"));
372 fprintf (stream
, _(" insnlength Print unknown instructions according "
373 "to length from first two bits\n"));