OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-binutils/] [binutils-2.19.1/] [opcodes/] [vax-dis.c] - Blame information for rev 6

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.