]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/s390-dis.c
value_from_pointer: remove call to resolve_dynamic_type
[thirdparty/binutils-gdb.git] / opcodes / s390-dis.c
CommitLineData
a85d7ed0 1/* s390-dis.c -- Disassemble S390 instructions
4b95cf5c 2 Copyright (C) 2000-2014 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
NC
37{
38 const struct s390_opcode *opcode;
39 const struct s390_opcode *opcode_end;
112b7c50 40 const char *p;
a85d7ed0 41
44f2a95d 42 memset (opc_index, 0, sizeof (opc_index));
a85d7ed0 43 opcode_end = s390_opcodes + s390_num_opcodes;
44f2a95d
KH
44 for (opcode = s390_opcodes; opcode < opcode_end; opcode++)
45 {
46 opc_index[(int) opcode->opcode[0]] = opcode - s390_opcodes;
47 while ((opcode < opcode_end) &&
48 (opcode[1].opcode[0] == opcode->opcode[0]))
49 opcode++;
50 }
112b7c50
AK
51
52 for (p = info->disassembler_options; p != NULL; )
44f2a95d 53 {
112b7c50
AK
54 if (CONST_STRNEQ (p, "esa"))
55 current_arch_mask = 1 << S390_OPCODE_ESA;
56 else if (CONST_STRNEQ (p, "zarch"))
57 current_arch_mask = 1 << S390_OPCODE_ZARCH;
58 else
59 fprintf (stderr, "Unknown S/390 disassembler option: %s\n", p);
60
61 p = strchr (p, ',');
62 if (p != NULL)
63 p++;
44f2a95d 64 }
112b7c50
AK
65
66 if (!current_arch_mask)
7d4a7d10 67 current_arch_mask = 1 << S390_OPCODE_ZARCH;
112b7c50 68
a85d7ed0
NC
69 init_flag = 1;
70}
71
72/* Extracts an operand value from an instruction. */
7330f9c3
AK
73/* We do not perform the shift operation for larl-type address
74 operands here since that would lead to an overflow of the 32 bit
75 integer value. Instead the shift operation is done when printing
76 the operand in print_insn_s390. */
a85d7ed0
NC
77
78static inline unsigned int
47b0e7ad 79s390_extract_operand (unsigned char *insn, const struct s390_operand *operand)
a85d7ed0
NC
80{
81 unsigned int val;
82 int bits;
83
44f2a95d
KH
84 /* Extract fragments of the operand byte for byte. */
85 insn += operand->shift / 8;
a85d7ed0
NC
86 bits = (operand->shift & 7) + operand->bits;
87 val = 0;
44f2a95d
KH
88 do
89 {
90 val <<= 8;
91 val |= (unsigned int) *insn++;
92 bits -= 8;
93 }
94 while (bits > 0);
a85d7ed0 95 val >>= -bits;
44f2a95d
KH
96 val &= ((1U << (operand->bits - 1)) << 1) - 1;
97
bac02689
MS
98 /* Check for special long displacement case. */
99 if (operand->bits == 20 && operand->shift == 20)
100 val = (val & 0xff) << 12 | (val & 0xfff00) >> 8;
101
44f2a95d
KH
102 /* Sign extend value if the operand is signed or pc relative. */
103 if ((operand->flags & (S390_OPERAND_SIGNED | S390_OPERAND_PCREL))
104 && (val & (1U << (operand->bits - 1))))
105 val |= (-1U << (operand->bits - 1)) << 1;
106
47b0e7ad 107 /* Length x in an instructions has real length x + 1. */
a85d7ed0
NC
108 if (operand->flags & S390_OPERAND_LENGTH)
109 val++;
110 return val;
111}
112
113/* Print a S390 instruction. */
114
115int
47b0e7ad 116print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
a85d7ed0
NC
117{
118 bfd_byte buffer[6];
119 const struct s390_opcode *opcode;
120 const struct s390_opcode *opcode_end;
121 unsigned int value;
122 int status, opsize, bufsize;
123 char separator;
124
125 if (init_flag == 0)
44f2a95d 126 init_disasm (info);
a85d7ed0
NC
127
128 /* The output looks better if we put 6 bytes on a line. */
129 info->bytes_per_line = 6;
130
131 /* Every S390 instruction is max 6 bytes long. */
44f2a95d 132 memset (buffer, 0, 6);
a85d7ed0 133 status = (*info->read_memory_func) (memaddr, buffer, 6, info);
44f2a95d
KH
134 if (status != 0)
135 {
136 for (bufsize = 0; bufsize < 6; bufsize++)
137 if ((*info->read_memory_func) (memaddr, buffer, bufsize + 1, info) != 0)
138 break;
139 if (bufsize <= 0)
140 {
141 (*info->memory_error_func) (status, memaddr, info);
142 return -1;
143 }
144 /* Opsize calculation looks strange but it works
145 00xxxxxx -> 2 bytes, 01xxxxxx/10xxxxxx -> 4 bytes,
146 11xxxxxx -> 6 bytes. */
147 opsize = ((((buffer[0] >> 6) + 1) >> 1) + 1) << 1;
148 status = opsize > bufsize;
149 }
150 else
151 {
152 bufsize = 6;
153 opsize = ((((buffer[0] >> 6) + 1) >> 1) + 1) << 1;
154 }
155
156 if (status == 0)
157 {
02cbf767
AK
158 const struct s390_opcode *op;
159
44f2a95d
KH
160 /* Find the first match in the opcode table. */
161 opcode_end = s390_opcodes + s390_num_opcodes;
162 for (opcode = s390_opcodes + opc_index[(int) buffer[0]];
163 (opcode < opcode_end) && (buffer[0] == opcode->opcode[0]);
164 opcode++)
165 {
166 const struct s390_operand *operand;
167 const unsigned char *opindex;
168
169 /* Check architecture. */
af169f23 170 if (!(opcode->modes & current_arch_mask))
44f2a95d 171 continue;
02cbf767 172
44f2a95d
KH
173 /* Check signature of the opcode. */
174 if ((buffer[1] & opcode->mask[1]) != opcode->opcode[1]
175 || (buffer[2] & opcode->mask[2]) != opcode->opcode[2]
176 || (buffer[3] & opcode->mask[3]) != opcode->opcode[3]
177 || (buffer[4] & opcode->mask[4]) != opcode->opcode[4]
178 || (buffer[5] & opcode->mask[5]) != opcode->opcode[5])
179 continue;
180
02cbf767
AK
181 /* Advance to an opcode with a more specific mask. */
182 for (op = opcode + 1; op < opcode_end; op++)
183 {
184 if ((buffer[0] & op->mask[0]) != op->opcode[0])
185 break;
186
187 if ((buffer[1] & op->mask[1]) != op->opcode[1]
188 || (buffer[2] & op->mask[2]) != op->opcode[2]
189 || (buffer[3] & op->mask[3]) != op->opcode[3]
190 || (buffer[4] & op->mask[4]) != op->opcode[4]
191 || (buffer[5] & op->mask[5]) != op->opcode[5])
192 continue;
193
194 if (((int)opcode->mask[0] + opcode->mask[1] +
195 opcode->mask[2] + opcode->mask[3] +
196 opcode->mask[4] + opcode->mask[5]) <
197 ((int)op->mask[0] + op->mask[1] +
198 op->mask[2] + op->mask[3] +
199 op->mask[4] + op->mask[5]))
200 opcode = op;
201 }
202
44f2a95d
KH
203 /* The instruction is valid. */
204 if (opcode->operands[0] != 0)
205 (*info->fprintf_func) (info->stream, "%s\t", opcode->name);
206 else
207 (*info->fprintf_func) (info->stream, "%s", opcode->name);
208
209 /* Extract the operands. */
210 separator = 0;
211 for (opindex = opcode->operands; *opindex != 0; opindex++)
212 {
44f2a95d
KH
213 operand = s390_operands + *opindex;
214 value = s390_extract_operand (buffer, operand);
215
216 if ((operand->flags & S390_OPERAND_INDEX) && value == 0)
217 continue;
218 if ((operand->flags & S390_OPERAND_BASE) &&
219 value == 0 && separator == '(')
220 {
221 separator = ',';
222 continue;
223 }
224
225 if (separator)
226 (*info->fprintf_func) (info->stream, "%c", separator);
227
228 if (operand->flags & S390_OPERAND_GPR)
229 (*info->fprintf_func) (info->stream, "%%r%i", value);
230 else if (operand->flags & S390_OPERAND_FPR)
231 (*info->fprintf_func) (info->stream, "%%f%i", value);
232 else if (operand->flags & S390_OPERAND_AR)
233 (*info->fprintf_func) (info->stream, "%%a%i", value);
234 else if (operand->flags & S390_OPERAND_CR)
235 (*info->fprintf_func) (info->stream, "%%c%i", value);
236 else if (operand->flags & S390_OPERAND_PCREL)
c8676ae4
AK
237 (*info->print_address_func) (memaddr + (int)value + (int)value,
238 info);
44f2a95d
KH
239 else if (operand->flags & S390_OPERAND_SIGNED)
240 (*info->fprintf_func) (info->stream, "%i", (int) value);
241 else
ad101263 242 (*info->fprintf_func) (info->stream, "%u", value);
44f2a95d
KH
243
244 if (operand->flags & S390_OPERAND_DISP)
245 {
246 separator = '(';
247 }
248 else if (operand->flags & S390_OPERAND_BASE)
249 {
250 (*info->fprintf_func) (info->stream, ")");
251 separator = ',';
252 }
253 else
254 separator = ',';
255 }
256
257 /* Found instruction, printed it, return its size. */
258 return opsize;
259 }
260 /* No matching instruction found, fall through to hex print. */
261 }
262
263 if (bufsize >= 4)
264 {
265 value = (unsigned int) buffer[0];
266 value = (value << 8) + (unsigned int) buffer[1];
267 value = (value << 8) + (unsigned int) buffer[2];
268 value = (value << 8) + (unsigned int) buffer[3];
269 (*info->fprintf_func) (info->stream, ".long\t0x%08x", value);
270 return 4;
271 }
272 else if (bufsize >= 2)
273 {
274 value = (unsigned int) buffer[0];
275 value = (value << 8) + (unsigned int) buffer[1];
276 (*info->fprintf_func) (info->stream, ".short\t0x%04x", value);
277 return 2;
a85d7ed0 278 }
44f2a95d
KH
279 else
280 {
281 value = (unsigned int) buffer[0];
282 (*info->fprintf_func) (info->stream, ".byte\t0x%02x", value);
283 return 1;
a85d7ed0 284 }
a85d7ed0 285}
112b7c50
AK
286
287void
288print_s390_disassembler_options (FILE *stream)
289{
290 fprintf (stream, _("\n\
291The following S/390 specific disassembler options are supported for use\n\
292with the -M switch (multiple options should be separated by commas):\n"));
293
294 fprintf (stream, _(" esa Disassemble in ESA architecture mode\n"));
295 fprintf (stream, _(" zarch Disassemble in z/Architecture mode\n"));
296}