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