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