Add -Wshadow to the gcc command line options used when compiling the binutils.
[deliverable/binutils-gdb.git] / opcodes / s390-dis.c
1 /* s390-dis.c -- Disassemble S390 instructions
2 Copyright 2000, 2001, 2002, 2003, 2005, 2007, 2008
3 Free Software Foundation, Inc.
4 Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
5
6 This file is part of the GNU opcodes library.
7
8 This library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12
13 It is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this file; see the file COPYING. If not, write to the
20 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
22
23 #include <stdio.h>
24 #include "ansidecl.h"
25 #include "sysdep.h"
26 #include "dis-asm.h"
27 #include "opintl.h"
28 #include "opcode/s390.h"
29
30 static int init_flag = 0;
31 static int opc_index[256];
32 static int current_arch_mask = 0;
33
34 /* Set up index table for first opcode byte. */
35
36 static void
37 init_disasm (struct disassemble_info *info)
38 {
39 const struct s390_opcode *opcode;
40 const struct s390_opcode *opcode_end;
41 const char *p;
42
43 memset (opc_index, 0, sizeof (opc_index));
44 opcode_end = s390_opcodes + s390_num_opcodes;
45 for (opcode = s390_opcodes; opcode < opcode_end; opcode++)
46 {
47 opc_index[(int) opcode->opcode[0]] = opcode - s390_opcodes;
48 while ((opcode < opcode_end) &&
49 (opcode[1].opcode[0] == opcode->opcode[0]))
50 opcode++;
51 }
52
53 for (p = info->disassembler_options; p != NULL; )
54 {
55 if (CONST_STRNEQ (p, "esa"))
56 current_arch_mask = 1 << S390_OPCODE_ESA;
57 else if (CONST_STRNEQ (p, "zarch"))
58 current_arch_mask = 1 << S390_OPCODE_ZARCH;
59 else
60 fprintf (stderr, "Unknown S/390 disassembler option: %s\n", p);
61
62 p = strchr (p, ',');
63 if (p != NULL)
64 p++;
65 }
66
67 if (!current_arch_mask)
68 switch (info->mach)
69 {
70 case bfd_mach_s390_31:
71 current_arch_mask = 1 << S390_OPCODE_ESA;
72 break;
73 case bfd_mach_s390_64:
74 current_arch_mask = 1 << S390_OPCODE_ZARCH;
75 break;
76 default:
77 abort ();
78 }
79
80 init_flag = 1;
81 }
82
83 /* Extracts an operand value from an instruction. */
84 /* We do not perform the shift operation for larl-type address
85 operands here since that would lead to an overflow of the 32 bit
86 integer value. Instead the shift operation is done when printing
87 the operand in print_insn_s390. */
88
89 static inline unsigned int
90 s390_extract_operand (unsigned char *insn, const struct s390_operand *operand)
91 {
92 unsigned int val;
93 int bits;
94
95 /* Extract fragments of the operand byte for byte. */
96 insn += operand->shift / 8;
97 bits = (operand->shift & 7) + operand->bits;
98 val = 0;
99 do
100 {
101 val <<= 8;
102 val |= (unsigned int) *insn++;
103 bits -= 8;
104 }
105 while (bits > 0);
106 val >>= -bits;
107 val &= ((1U << (operand->bits - 1)) << 1) - 1;
108
109 /* Check for special long displacement case. */
110 if (operand->bits == 20 && operand->shift == 20)
111 val = (val & 0xff) << 12 | (val & 0xfff00) >> 8;
112
113 /* Sign extend value if the operand is signed or pc relative. */
114 if ((operand->flags & (S390_OPERAND_SIGNED | S390_OPERAND_PCREL))
115 && (val & (1U << (operand->bits - 1))))
116 val |= (-1U << (operand->bits - 1)) << 1;
117
118 /* Length x in an instructions has real length x + 1. */
119 if (operand->flags & S390_OPERAND_LENGTH)
120 val++;
121 return val;
122 }
123
124 /* Print a S390 instruction. */
125
126 int
127 print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
128 {
129 bfd_byte buffer[6];
130 const struct s390_opcode *opcode;
131 const struct s390_opcode *opcode_end;
132 unsigned int value;
133 int status, opsize, bufsize;
134 char separator;
135
136 if (init_flag == 0)
137 init_disasm (info);
138
139 /* The output looks better if we put 6 bytes on a line. */
140 info->bytes_per_line = 6;
141
142 /* Every S390 instruction is max 6 bytes long. */
143 memset (buffer, 0, 6);
144 status = (*info->read_memory_func) (memaddr, buffer, 6, info);
145 if (status != 0)
146 {
147 for (bufsize = 0; bufsize < 6; bufsize++)
148 if ((*info->read_memory_func) (memaddr, buffer, bufsize + 1, info) != 0)
149 break;
150 if (bufsize <= 0)
151 {
152 (*info->memory_error_func) (status, memaddr, info);
153 return -1;
154 }
155 /* Opsize calculation looks strange but it works
156 00xxxxxx -> 2 bytes, 01xxxxxx/10xxxxxx -> 4 bytes,
157 11xxxxxx -> 6 bytes. */
158 opsize = ((((buffer[0] >> 6) + 1) >> 1) + 1) << 1;
159 status = opsize > bufsize;
160 }
161 else
162 {
163 bufsize = 6;
164 opsize = ((((buffer[0] >> 6) + 1) >> 1) + 1) << 1;
165 }
166
167 if (status == 0)
168 {
169 /* Find the first match in the opcode table. */
170 opcode_end = s390_opcodes + s390_num_opcodes;
171 for (opcode = s390_opcodes + opc_index[(int) buffer[0]];
172 (opcode < opcode_end) && (buffer[0] == opcode->opcode[0]);
173 opcode++)
174 {
175 const struct s390_operand *operand;
176 const unsigned char *opindex;
177
178 /* Check architecture. */
179 if (!(opcode->modes & current_arch_mask))
180 continue;
181 /* Check signature of the opcode. */
182 if ((buffer[1] & opcode->mask[1]) != opcode->opcode[1]
183 || (buffer[2] & opcode->mask[2]) != opcode->opcode[2]
184 || (buffer[3] & opcode->mask[3]) != opcode->opcode[3]
185 || (buffer[4] & opcode->mask[4]) != opcode->opcode[4]
186 || (buffer[5] & opcode->mask[5]) != opcode->opcode[5])
187 continue;
188
189 /* The instruction is valid. */
190 if (opcode->operands[0] != 0)
191 (*info->fprintf_func) (info->stream, "%s\t", opcode->name);
192 else
193 (*info->fprintf_func) (info->stream, "%s", opcode->name);
194
195 /* Extract the operands. */
196 separator = 0;
197 for (opindex = opcode->operands; *opindex != 0; opindex++)
198 {
199 operand = s390_operands + *opindex;
200 value = s390_extract_operand (buffer, operand);
201
202 if ((operand->flags & S390_OPERAND_INDEX) && value == 0)
203 continue;
204 if ((operand->flags & S390_OPERAND_BASE) &&
205 value == 0 && separator == '(')
206 {
207 separator = ',';
208 continue;
209 }
210
211 if (separator)
212 (*info->fprintf_func) (info->stream, "%c", separator);
213
214 if (operand->flags & S390_OPERAND_GPR)
215 (*info->fprintf_func) (info->stream, "%%r%i", value);
216 else if (operand->flags & S390_OPERAND_FPR)
217 (*info->fprintf_func) (info->stream, "%%f%i", value);
218 else if (operand->flags & S390_OPERAND_AR)
219 (*info->fprintf_func) (info->stream, "%%a%i", value);
220 else if (operand->flags & S390_OPERAND_CR)
221 (*info->fprintf_func) (info->stream, "%%c%i", value);
222 else if (operand->flags & S390_OPERAND_PCREL)
223 (*info->print_address_func) (memaddr + (int)value + (int)value,
224 info);
225 else if (operand->flags & S390_OPERAND_SIGNED)
226 (*info->fprintf_func) (info->stream, "%i", (int) value);
227 else
228 (*info->fprintf_func) (info->stream, "%u", value);
229
230 if (operand->flags & S390_OPERAND_DISP)
231 {
232 separator = '(';
233 }
234 else if (operand->flags & S390_OPERAND_BASE)
235 {
236 (*info->fprintf_func) (info->stream, ")");
237 separator = ',';
238 }
239 else
240 separator = ',';
241 }
242
243 /* Found instruction, printed it, return its size. */
244 return opsize;
245 }
246 /* No matching instruction found, fall through to hex print. */
247 }
248
249 if (bufsize >= 4)
250 {
251 value = (unsigned int) buffer[0];
252 value = (value << 8) + (unsigned int) buffer[1];
253 value = (value << 8) + (unsigned int) buffer[2];
254 value = (value << 8) + (unsigned int) buffer[3];
255 (*info->fprintf_func) (info->stream, ".long\t0x%08x", value);
256 return 4;
257 }
258 else if (bufsize >= 2)
259 {
260 value = (unsigned int) buffer[0];
261 value = (value << 8) + (unsigned int) buffer[1];
262 (*info->fprintf_func) (info->stream, ".short\t0x%04x", value);
263 return 2;
264 }
265 else
266 {
267 value = (unsigned int) buffer[0];
268 (*info->fprintf_func) (info->stream, ".byte\t0x%02x", value);
269 return 1;
270 }
271 }
272
273 void
274 print_s390_disassembler_options (FILE *stream)
275 {
276 fprintf (stream, _("\n\
277 The following S/390 specific disassembler options are supported for use\n\
278 with the -M switch (multiple options should be separated by commas):\n"));
279
280 fprintf (stream, _(" esa Disassemble in ESA architecture mode\n"));
281 fprintf (stream, _(" zarch Disassemble in z/Architecture mode\n"));
282 }
This page took 0.03668 seconds and 4 git commands to generate.