Update the address and phone number of the FSF
[deliverable/binutils-gdb.git] / opcodes / vax-dis.c
1 /* Print VAX instructions.
2 Copyright 1995, 1998, 2000, 2001, 2002, 2005
3 Free Software Foundation, Inc.
4 Contributed by Pauline Middelink <middelin@polyware.iaf.nl>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
19
20 #include <setjmp.h>
21 #include <string.h>
22 #include "sysdep.h"
23 #include "opcode/vax.h"
24 #include "dis-asm.h"
25
26 /* Local function prototypes */
27 static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
28 static int print_insn_arg
29 PARAMS ((const char *, unsigned char *, bfd_vma, disassemble_info *));
30 static int print_insn_mode
31 PARAMS ((const char *, int, unsigned char *, bfd_vma, disassemble_info *));
32
33
34 static char *reg_names[] =
35 {
36 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
37 "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc"
38 };
39
40 /* Definitions for the function entry mask bits. */
41 static char *entry_mask_bit[] =
42 {
43 /* Registers 0 and 1 shall not be saved, since they're used to pass back
44 a function's result to its caller... */
45 "~r0~", "~r1~",
46 /* Registers 2 .. 11 are normal registers. */
47 "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
48 /* Registers 12 and 13 are argument and frame pointer and must not
49 be saved by using the entry mask. */
50 "~ap~", "~fp~",
51 /* Bits 14 and 15 control integer and decimal overflow. */
52 "IntOvfl", "DecOvfl",
53 };
54
55 /* Sign-extend an (unsigned char). */
56 #if __STDC__ == 1
57 #define COERCE_SIGNED_CHAR(ch) ((signed char)(ch))
58 #else
59 #define COERCE_SIGNED_CHAR(ch) ((int)(((ch) ^ 0x80) & 0xFF) - 128)
60 #endif
61
62 /* Get a 1 byte signed integer. */
63 #define NEXTBYTE(p) \
64 (p += 1, FETCH_DATA (info, p), \
65 COERCE_SIGNED_CHAR(p[-1]))
66
67 /* Get a 2 byte signed integer. */
68 #define COERCE16(x) ((int) (((x) ^ 0x8000) - 0x8000))
69 #define NEXTWORD(p) \
70 (p += 2, FETCH_DATA (info, p), \
71 COERCE16 ((p[-1] << 8) + p[-2]))
72
73 /* Get a 4 byte signed integer. */
74 #define COERCE32(x) ((int) (((x) ^ 0x80000000) - 0x80000000))
75 #define NEXTLONG(p) \
76 (p += 4, FETCH_DATA (info, p), \
77 (COERCE32 ((((((p[-1] << 8) + p[-2]) << 8) + p[-3]) << 8) + p[-4])))
78
79 /* Maximum length of an instruction. */
80 #define MAXLEN 25
81
82 struct private
83 {
84 /* Points to first byte not fetched. */
85 bfd_byte * max_fetched;
86 bfd_byte the_buffer[MAXLEN];
87 bfd_vma insn_start;
88 jmp_buf bailout;
89 };
90
91 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
92 to ADDR (exclusive) are valid. Returns 1 for success, longjmps
93 on error. */
94 #define FETCH_DATA(info, addr) \
95 ((addr) <= ((struct private *)(info->private_data))->max_fetched \
96 ? 1 : fetch_data ((info), (addr)))
97
98 static int
99 fetch_data (info, addr)
100 struct disassemble_info *info;
101 bfd_byte *addr;
102 {
103 int status;
104 struct private *priv = (struct private *) info->private_data;
105 bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
106
107 status = (*info->read_memory_func) (start,
108 priv->max_fetched,
109 addr - priv->max_fetched,
110 info);
111 if (status != 0)
112 {
113 (*info->memory_error_func) (status, start, info);
114 longjmp (priv->bailout, 1);
115 }
116 else
117 priv->max_fetched = addr;
118
119 return 1;
120 }
121
122 /* Entry mask handling. */
123 static unsigned int entry_addr_occupied_slots = 0;
124 static unsigned int entry_addr_total_slots = 0;
125 static bfd_vma * entry_addr = NULL;
126
127 /* Parse the VAX specific disassembler options. These contain function
128 entry addresses, which can be useful to disassemble ROM images, since
129 there's no symbol table. Returns TRUE upon success, FALSE otherwise. */
130
131 static bfd_boolean
132 parse_disassembler_options (char * options)
133 {
134 const char * entry_switch = "entry:";
135
136 while ((options = strstr (options, entry_switch)))
137 {
138 options += strlen (entry_switch);
139
140 /* The greater-than part of the test below is paranoia. */
141 if (entry_addr_occupied_slots >= entry_addr_total_slots)
142 {
143 /* A guesstimate of the number of entries we will have to create. */
144 entry_addr_total_slots +=
145 strlen (options) / (strlen (entry_switch) + 5);
146
147 entry_addr = realloc (entry_addr, sizeof (bfd_vma)
148 * entry_addr_total_slots);
149 }
150
151 if (entry_addr == NULL)
152 return FALSE;
153
154 entry_addr[entry_addr_occupied_slots] = bfd_scan_vma (options, NULL, 0);
155 entry_addr_occupied_slots ++;
156 }
157
158 return TRUE;
159 }
160
161 #if 0 /* FIXME: Ideally the disassembler should have target specific
162 initialisation and termination function pointers. Then
163 parse_disassembler_options could be the init function and
164 free_entry_array (below) could be the termination routine.
165 Until then there is no way for the disassembler to tell us
166 that it has finished and that we no longer need the entry
167 array, so this routine is suppressed for now. It does mean
168 that we leak memory, but only to the extent that we do not
169 free it just before the disassembler is about to terminate
170 anyway. */
171
172 /* Free memory allocated to our entry array. */
173
174 static void
175 free_entry_array (void)
176 {
177 if (entry_addr)
178 {
179 free (entry_addr);
180 entry_addr = NULL;
181 entry_addr_occupied_slots = entry_addr_total_slots = 0;
182 }
183 }
184 #endif
185 /* Check if the given address is a known function entry. Either there must
186 be a symbol of function type at this address, or the address must be
187 a forced entry point. The later helps in disassembling ROM images, because
188 there's no symbol table at all. Forced entry points can be given by
189 supplying several -M options to objdump: -M entry:0xffbb7730. */
190
191 static bfd_boolean
192 is_function_entry (struct disassemble_info *info, bfd_vma addr)
193 {
194 unsigned int i;
195
196 /* Check if there's a BSF_FUNCTION symbol at our address. */
197 if (info->symbols
198 && info->symbols[0]
199 && (info->symbols[0]->flags & BSF_FUNCTION)
200 && addr == bfd_asymbol_value (info->symbols[0]))
201 return TRUE;
202
203 /* Check for forced function entry address. */
204 for (i = entry_addr_occupied_slots; i--;)
205 if (entry_addr[i] == addr)
206 return TRUE;
207
208 return FALSE;
209 }
210
211 /* Print the vax instruction at address MEMADDR in debugged memory,
212 on INFO->STREAM. Returns length of the instruction, in bytes. */
213
214 int
215 print_insn_vax (memaddr, info)
216 bfd_vma memaddr;
217 disassemble_info *info;
218 {
219 static bfd_boolean parsed_disassembler_options = FALSE;
220 const struct vot *votp;
221 const char *argp;
222 unsigned char *arg;
223 struct private priv;
224 bfd_byte *buffer = priv.the_buffer;
225
226 info->private_data = (PTR) &priv;
227 priv.max_fetched = priv.the_buffer;
228 priv.insn_start = memaddr;
229
230 if (! parsed_disassembler_options
231 && info->disassembler_options != NULL)
232 {
233 parse_disassembler_options (info->disassembler_options);
234
235 /* To avoid repeated parsing of these options. */
236 parsed_disassembler_options = TRUE;
237 }
238
239 if (setjmp (priv.bailout) != 0)
240 {
241 /* Error return. */
242 return -1;
243 }
244
245 argp = NULL;
246 /* Check if the info buffer has more than one byte left since
247 the last opcode might be a single byte with no argument data. */
248 if (info->buffer_length - (memaddr - info->buffer_vma) > 1)
249 {
250 FETCH_DATA (info, buffer + 2);
251 }
252 else
253 {
254 FETCH_DATA (info, buffer + 1);
255 buffer[1] = 0;
256 }
257
258 /* Decode function entry mask. */
259 if (is_function_entry (info, memaddr))
260 {
261 int i = 0;
262 int register_mask = buffer[1] << 8 | buffer[0];
263
264 (*info->fprintf_func) (info->stream, ".word 0x%04x # Entry mask: <",
265 register_mask);
266
267 for (i = 15; i >= 0; i--)
268 if (register_mask & (1 << i))
269 (*info->fprintf_func) (info->stream, " %s", entry_mask_bit[i]);
270
271 (*info->fprintf_func) (info->stream, " >");
272
273 return 2;
274 }
275
276 for (votp = &votstrs[0]; votp->name[0]; votp++)
277 {
278 register vax_opcodeT opcode = votp->detail.code;
279
280 /* 2 byte codes match 2 buffer pos. */
281 if ((bfd_byte) opcode == buffer[0]
282 && (opcode >> 8 == 0 || opcode >> 8 == buffer[1]))
283 {
284 argp = votp->detail.args;
285 break;
286 }
287 }
288 if (argp == NULL)
289 {
290 /* Handle undefined instructions. */
291 (*info->fprintf_func) (info->stream, ".word 0x%x",
292 (buffer[0] << 8) + buffer[1]);
293 return 2;
294 }
295
296 /* Point at first byte of argument data, and at descriptor for first
297 argument. */
298 arg = buffer + ((votp->detail.code >> 8) ? 2 : 1);
299
300 /* Make sure we have it in mem */
301 FETCH_DATA (info, arg);
302
303 (*info->fprintf_func) (info->stream, "%s", votp->name);
304 if (*argp)
305 (*info->fprintf_func) (info->stream, " ");
306
307 while (*argp)
308 {
309 arg += print_insn_arg (argp, arg, memaddr + arg - buffer, info);
310 argp += 2;
311 if (*argp)
312 (*info->fprintf_func) (info->stream, ",");
313 }
314
315 return arg - buffer;
316 }
317
318 /* Returns number of bytes "eaten" by the operand, or return -1 if an
319 invalid operand was found, or -2 if an opcode tabel error was
320 found. */
321
322 static int
323 print_insn_arg (d, p0, addr, info)
324 const char *d;
325 unsigned char *p0;
326 bfd_vma addr; /* PC for this arg to be relative to */
327 disassemble_info *info;
328 {
329 int arg_len;
330
331 /* check validity of addressing length */
332 switch (d[1])
333 {
334 case 'b' : arg_len = 1; break;
335 case 'd' : arg_len = 8; break;
336 case 'f' : arg_len = 4; break;
337 case 'g' : arg_len = 8; break;
338 case 'h' : arg_len = 16; break;
339 case 'l' : arg_len = 4; break;
340 case 'o' : arg_len = 16; break;
341 case 'w' : arg_len = 2; break;
342 case 'q' : arg_len = 8; break;
343 default : abort();
344 }
345
346 /* branches have no mode byte */
347 if (d[0] == 'b')
348 {
349 unsigned char *p = p0;
350
351 if (arg_len == 1)
352 (*info->print_address_func) (addr + 1 + NEXTBYTE (p), info);
353 else
354 (*info->print_address_func) (addr + 2 + NEXTWORD (p), info);
355
356 return p - p0;
357 }
358
359 return print_insn_mode (d, arg_len, p0, addr, info);
360 }
361
362 static int
363 print_insn_mode (d, size, p0, addr, info)
364 const char *d;
365 int size;
366 unsigned char *p0;
367 bfd_vma addr; /* PC for this arg to be relative to */
368 disassemble_info *info;
369 {
370 unsigned char *p = p0;
371 unsigned char mode, reg;
372
373 /* fetch and interpret mode byte */
374 mode = (unsigned char) NEXTBYTE (p);
375 reg = mode & 0xF;
376 switch (mode & 0xF0)
377 {
378 case 0x00:
379 case 0x10:
380 case 0x20:
381 case 0x30: /* literal mode $number */
382 if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
383 (*info->fprintf_func) (info->stream, "$0x%x [%c-float]", mode, d[1]);
384 else
385 (*info->fprintf_func) (info->stream, "$0x%x", mode);
386 break;
387 case 0x40: /* index: base-addr[Rn] */
388 p += print_insn_mode (d, size, p0 + 1, addr + 1, info);
389 (*info->fprintf_func) (info->stream, "[%s]", reg_names[reg]);
390 break;
391 case 0x50: /* register: Rn */
392 (*info->fprintf_func) (info->stream, "%s", reg_names[reg]);
393 break;
394 case 0x60: /* register deferred: (Rn) */
395 (*info->fprintf_func) (info->stream, "(%s)", reg_names[reg]);
396 break;
397 case 0x70: /* autodecrement: -(Rn) */
398 (*info->fprintf_func) (info->stream, "-(%s)", reg_names[reg]);
399 break;
400 case 0x80: /* autoincrement: (Rn)+ */
401 if (reg == 0xF)
402 { /* immediate? */
403 int i;
404
405 FETCH_DATA (info, p + size);
406 (*info->fprintf_func) (info->stream, "$0x");
407 if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
408 {
409 int float_word;
410
411 float_word = p[0] | (p[1] << 8);
412 if ((d[1] == 'd' || d[1] == 'f')
413 && (float_word & 0xff80) == 0x8000)
414 {
415 (*info->fprintf_func) (info->stream, "[invalid %c-float]",
416 d[1]);
417 }
418 else
419 {
420 for (i = 0; i < size; i++)
421 (*info->fprintf_func) (info->stream, "%02x",
422 p[size - i - 1]);
423 (*info->fprintf_func) (info->stream, " [%c-float]", d[1]);
424 }
425 }
426 else
427 {
428 for (i = 0; i < size; i++)
429 (*info->fprintf_func) (info->stream, "%02x", p[size - i - 1]);
430 }
431 p += size;
432 }
433 else
434 (*info->fprintf_func) (info->stream, "(%s)+", reg_names[reg]);
435 break;
436 case 0x90: /* autoincrement deferred: @(Rn)+ */
437 if (reg == 0xF)
438 (*info->fprintf_func) (info->stream, "*0x%x", NEXTLONG (p));
439 else
440 (*info->fprintf_func) (info->stream, "@(%s)+", reg_names[reg]);
441 break;
442 case 0xB0: /* displacement byte deferred: *displ(Rn) */
443 (*info->fprintf_func) (info->stream, "*");
444 case 0xA0: /* displacement byte: displ(Rn) */
445 if (reg == 0xF)
446 (*info->print_address_func) (addr + 2 + NEXTBYTE (p), info);
447 else
448 (*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTBYTE (p),
449 reg_names[reg]);
450 break;
451 case 0xD0: /* displacement word deferred: *displ(Rn) */
452 (*info->fprintf_func) (info->stream, "*");
453 case 0xC0: /* displacement word: displ(Rn) */
454 if (reg == 0xF)
455 (*info->print_address_func) (addr + 3 + NEXTWORD (p), info);
456 else
457 (*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTWORD (p),
458 reg_names[reg]);
459 break;
460 case 0xF0: /* displacement long deferred: *displ(Rn) */
461 (*info->fprintf_func) (info->stream, "*");
462 case 0xE0: /* displacement long: displ(Rn) */
463 if (reg == 0xF)
464 (*info->print_address_func) (addr + 5 + NEXTLONG (p), info);
465 else
466 (*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTLONG (p),
467 reg_names[reg]);
468 break;
469 }
470
471 return p - p0;
472 }
This page took 0.040721 seconds and 5 git commands to generate.