Add VAX specific disassembler option -Mentry: to specify a function entry
[binutils.git] / opcodes / vax-dis.c
blob1300f54484dd700d293c6d5f9ee5e645fd6d7384
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>
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20 #include <setjmp.h>
21 #include <string.h>
22 #include "sysdep.h"
23 #include "opcode/vax.h"
24 #include "dis-asm.h"
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 *));
34 static char *reg_names[] =
36 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
37 "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc"
40 /* Definitions for the function entry mask bits. */
41 static char *entry_mask_bit[] =
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",
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
62 /* Get a 1 byte signed integer. */
63 #define NEXTBYTE(p) \
64 (p += 1, FETCH_DATA (info, p), \
65 COERCE_SIGNED_CHAR(p[-1]))
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]))
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])))
79 /* Maximum length of an instruction. */
80 #define MAXLEN 25
82 struct private
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;
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)))
98 static int
99 fetch_data (info, addr)
100 struct disassemble_info *info;
101 bfd_byte *addr;
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);
107 status = (*info->read_memory_func) (start,
108 priv->max_fetched,
109 addr - priv->max_fetched,
110 info);
111 if (status != 0)
113 (*info->memory_error_func) (status, start, info);
114 longjmp (priv->bailout, 1);
116 else
117 priv->max_fetched = addr;
119 return 1;
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;
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. */
131 static bfd_boolean
132 parse_disassembler_options (char * options)
134 const char * entry_switch = "entry:";
136 while ((options = strstr (options, entry_switch)))
138 options += strlen (entry_switch);
140 /* The greater-than part of the test below is paranoia. */
141 if (entry_addr_occupied_slots >= entry_addr_total_slots)
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);
147 entry_addr = realloc (entry_addr, sizeof (bfd_vma)
148 * entry_addr_total_slots);
151 if (entry_addr == NULL)
152 return FALSE;
154 entry_addr[entry_addr_occupied_slots] = bfd_scan_vma (options, NULL, 0);
155 entry_addr_occupied_slots ++;
158 return TRUE;
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. */
172 /* Free memory allocated to our entry array. */
174 static void
175 free_entry_array (void)
177 if (entry_addr)
179 free (entry_addr);
180 entry_addr = NULL;
181 entry_addr_occupied_slots = entry_addr_total_slots = 0;
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. */
191 static bfd_boolean
192 is_function_entry (struct disassemble_info *info, bfd_vma addr)
194 unsigned int i;
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;
203 /* Check for forced function entry address. */
204 for (i = entry_addr_occupied_slots; i--;)
205 if (entry_addr[i] == addr)
206 return TRUE;
208 return FALSE;
211 /* Print the vax instruction at address MEMADDR in debugged memory,
212 on INFO->STREAM. Returns length of the instruction, in bytes. */
215 print_insn_vax (memaddr, info)
216 bfd_vma memaddr;
217 disassemble_info *info;
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;
226 info->private_data = (PTR) &priv;
227 priv.max_fetched = priv.the_buffer;
228 priv.insn_start = memaddr;
230 if (! parsed_disassembler_options
231 && info->disassembler_options != NULL)
233 parse_disassembler_options (info->disassembler_options);
235 /* To avoid repeated parsing of these options. */
236 parsed_disassembler_options = TRUE;
239 if (setjmp (priv.bailout) != 0)
241 /* Error return. */
242 return -1;
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)
250 FETCH_DATA (info, buffer + 2);
252 else
254 FETCH_DATA (info, buffer + 1);
255 buffer[1] = 0;
258 /* Decode function entry mask. */
259 if (is_function_entry (info, memaddr))
261 int i = 0;
262 int register_mask = buffer[1] << 8 | buffer[0];
264 (*info->fprintf_func) (info->stream, ".word 0x%04x # Entry mask: <",
265 register_mask);
267 for (i = 15; i >= 0; i--)
268 if (register_mask & (1 << i))
269 (*info->fprintf_func) (info->stream, " %s", entry_mask_bit[i]);
271 (*info->fprintf_func) (info->stream, " >");
273 return 2;
276 for (votp = &votstrs[0]; votp->name[0]; votp++)
278 register vax_opcodeT opcode = votp->detail.code;
280 /* 2 byte codes match 2 buffer pos. */
281 if ((bfd_byte) opcode == buffer[0]
282 && (opcode >> 8 == 0 || opcode >> 8 == buffer[1]))
284 argp = votp->detail.args;
285 break;
288 if (argp == NULL)
290 /* Handle undefined instructions. */
291 (*info->fprintf_func) (info->stream, ".word 0x%x",
292 (buffer[0] << 8) + buffer[1]);
293 return 2;
296 /* Point at first byte of argument data, and at descriptor for first
297 argument. */
298 arg = buffer + ((votp->detail.code >> 8) ? 2 : 1);
300 /* Make sure we have it in mem */
301 FETCH_DATA (info, arg);
303 (*info->fprintf_func) (info->stream, "%s", votp->name);
304 if (*argp)
305 (*info->fprintf_func) (info->stream, " ");
307 while (*argp)
309 arg += print_insn_arg (argp, arg, memaddr + arg - buffer, info);
310 argp += 2;
311 if (*argp)
312 (*info->fprintf_func) (info->stream, ",");
315 return arg - buffer;
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. */
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;
329 int arg_len;
331 /* check validity of addressing length */
332 switch (d[1])
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();
346 /* branches have no mode byte */
347 if (d[0] == 'b')
349 unsigned char *p = p0;
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);
356 return p - p0;
359 return print_insn_mode (d, arg_len, p0, addr, info);
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;
370 unsigned char *p = p0;
371 unsigned char mode, reg;
373 /* fetch and interpret mode byte */
374 mode = (unsigned char) NEXTBYTE (p);
375 reg = mode & 0xF;
376 switch (mode & 0xF0)
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;
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')
409 int float_word;
411 float_word = p[0] | (p[1] << 8);
412 if ((d[1] == 'd' || d[1] == 'f')
413 && (float_word & 0xff80) == 0x8000)
415 (*info->fprintf_func) (info->stream, "[invalid %c-float]",
416 d[1]);
418 else
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]);
426 else
428 for (i = 0; i < size; i++)
429 (*info->fprintf_func) (info->stream, "%02x", p[size - i - 1]);
431 p += size;
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;
471 return p - p0;