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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [opcodes/] [vax-dis.c] - Blame information for rev 853

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 24 jeremybenn
/* Print VAX instructions.
2 225 jeremybenn
   Copyright 1995, 1998, 2000, 2001, 2002, 2005, 2007, 2009
3 24 jeremybenn
   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 225 jeremybenn
/* Check if the given address is a known function entry point.  This is
175
   the case if there is a symbol of the function type at this address.
176
   We also check for synthetic symbols as these are used for PLT entries
177
   (weak undefined symbols may not have the function type set).  Finally
178
   the address may have been forced to be treated as an entry point.  The
179
   latter helps in disassembling ROM images, because there's no symbol
180
   table at all.  Forced entry points can be given by supplying several
181
   -M options to objdump: -M entry:0xffbb7730.  */
182 24 jeremybenn
 
183
static bfd_boolean
184
is_function_entry (struct disassemble_info *info, bfd_vma addr)
185
{
186
  unsigned int i;
187
 
188 225 jeremybenn
  /* Check if there's a function or PLT symbol at our address.  */
189 24 jeremybenn
  if (info->symbols
190
      && info->symbols[0]
191 225 jeremybenn
      && (info->symbols[0]->flags & (BSF_FUNCTION | BSF_SYNTHETIC))
192 24 jeremybenn
      && addr == bfd_asymbol_value (info->symbols[0]))
193
    return TRUE;
194
 
195
  /* Check for forced function entry address.  */
196
  for (i = entry_addr_occupied_slots; i--;)
197
    if (entry_addr[i] == addr)
198
      return TRUE;
199
 
200
  return FALSE;
201
}
202
 
203 225 jeremybenn
/* Check if the given address is the last longword of a PLT entry.
204
   This longword is data and depending on the value it may interfere
205
   with disassembly of further PLT entries.  We make use of the fact
206
   PLT symbols are marked BSF_SYNTHETIC.  */
207
static bfd_boolean
208
is_plt_tail (struct disassemble_info *info, bfd_vma addr)
209
{
210
  if (info->symbols
211
      && info->symbols[0]
212
      && (info->symbols[0]->flags & BSF_SYNTHETIC)
213
      && addr == bfd_asymbol_value (info->symbols[0]) + 8)
214
    return TRUE;
215
 
216
  return FALSE;
217
}
218
 
219 24 jeremybenn
static int
220
print_insn_mode (const char *d,
221
                 int size,
222
                 unsigned char *p0,
223
                 bfd_vma addr,  /* PC for this arg to be relative to.  */
224
                 disassemble_info *info)
225
{
226
  unsigned char *p = p0;
227
  unsigned char mode, reg;
228
 
229
  /* Fetch and interpret mode byte.  */
230
  mode = (unsigned char) NEXTBYTE (p);
231
  reg = mode & 0xF;
232
  switch (mode & 0xF0)
233
    {
234
    case 0x00:
235
    case 0x10:
236
    case 0x20:
237
    case 0x30: /* Literal mode                  $number.  */
238
      if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
239
        (*info->fprintf_func) (info->stream, "$0x%x [%c-float]", mode, d[1]);
240
      else
241
        (*info->fprintf_func) (info->stream, "$0x%x", mode);
242
      break;
243
    case 0x40: /* Index:                        base-addr[Rn] */
244
      p += print_insn_mode (d, size, p0 + 1, addr + 1, info);
245
      (*info->fprintf_func) (info->stream, "[%s]", reg_names[reg]);
246
      break;
247
    case 0x50: /* Register:                     Rn */
248
      (*info->fprintf_func) (info->stream, "%s", reg_names[reg]);
249
      break;
250
    case 0x60: /* Register deferred:            (Rn) */
251
      (*info->fprintf_func) (info->stream, "(%s)", reg_names[reg]);
252
      break;
253
    case 0x70: /* Autodecrement:                -(Rn) */
254
      (*info->fprintf_func) (info->stream, "-(%s)", reg_names[reg]);
255
      break;
256
    case 0x80: /* Autoincrement:                (Rn)+ */
257
      if (reg == 0xF)
258
        {       /* Immediate?  */
259
          int i;
260
 
261
          FETCH_DATA (info, p + size);
262
          (*info->fprintf_func) (info->stream, "$0x");
263
          if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
264
            {
265
              int float_word;
266
 
267
              float_word = p[0] | (p[1] << 8);
268
              if ((d[1] == 'd' || d[1] == 'f')
269
                  && (float_word & 0xff80) == 0x8000)
270
                {
271
                  (*info->fprintf_func) (info->stream, "[invalid %c-float]",
272
                                         d[1]);
273
                }
274
              else
275
                {
276
                  for (i = 0; i < size; i++)
277
                    (*info->fprintf_func) (info->stream, "%02x",
278
                                           p[size - i - 1]);
279
                  (*info->fprintf_func) (info->stream, " [%c-float]", d[1]);
280
                }
281
            }
282
          else
283
            {
284
              for (i = 0; i < size; i++)
285
                (*info->fprintf_func) (info->stream, "%02x", p[size - i - 1]);
286
            }
287
          p += size;
288
        }
289
      else
290
        (*info->fprintf_func) (info->stream, "(%s)+", reg_names[reg]);
291
      break;
292
    case 0x90: /* Autoincrement deferred:       @(Rn)+ */
293
      if (reg == 0xF)
294
        (*info->fprintf_func) (info->stream, "*0x%x", NEXTLONG (p));
295
      else
296
        (*info->fprintf_func) (info->stream, "@(%s)+", reg_names[reg]);
297
      break;
298
    case 0xB0: /* Displacement byte deferred:   *displ(Rn).  */
299
      (*info->fprintf_func) (info->stream, "*");
300
    case 0xA0: /* Displacement byte:            displ(Rn).  */
301
      if (reg == 0xF)
302
        (*info->print_address_func) (addr + 2 + NEXTBYTE (p), info);
303
      else
304
        (*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTBYTE (p),
305
                               reg_names[reg]);
306
      break;
307
    case 0xD0: /* Displacement word deferred:   *displ(Rn).  */
308
      (*info->fprintf_func) (info->stream, "*");
309
    case 0xC0: /* Displacement word:            displ(Rn).  */
310
      if (reg == 0xF)
311
        (*info->print_address_func) (addr + 3 + NEXTWORD (p), info);
312
      else
313
        (*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTWORD (p),
314
                               reg_names[reg]);
315
      break;
316
    case 0xF0: /* Displacement long deferred:   *displ(Rn).  */
317
      (*info->fprintf_func) (info->stream, "*");
318
    case 0xE0: /* Displacement long:            displ(Rn).  */
319
      if (reg == 0xF)
320
        (*info->print_address_func) (addr + 5 + NEXTLONG (p), info);
321
      else
322
        (*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTLONG (p),
323
                               reg_names[reg]);
324
      break;
325
    }
326
 
327
  return p - p0;
328
}
329
 
330
/* Returns number of bytes "eaten" by the operand, or return -1 if an
331
   invalid operand was found, or -2 if an opcode tabel error was
332
   found. */
333
 
334
static int
335
print_insn_arg (const char *d,
336
                unsigned char *p0,
337
                bfd_vma addr,   /* PC for this arg to be relative to.  */
338
                disassemble_info *info)
339
{
340
  int arg_len;
341
 
342
  /* Check validity of addressing length.  */
343
  switch (d[1])
344
    {
345
    case 'b' : arg_len = 1;     break;
346
    case 'd' : arg_len = 8;     break;
347
    case 'f' : arg_len = 4;     break;
348
    case 'g' : arg_len = 8;     break;
349
    case 'h' : arg_len = 16;    break;
350
    case 'l' : arg_len = 4;     break;
351
    case 'o' : arg_len = 16;    break;
352
    case 'w' : arg_len = 2;     break;
353
    case 'q' : arg_len = 8;     break;
354
    default  : abort ();
355
    }
356
 
357
  /* Branches have no mode byte.  */
358
  if (d[0] == 'b')
359
    {
360
      unsigned char *p = p0;
361
 
362
      if (arg_len == 1)
363
        (*info->print_address_func) (addr + 1 + NEXTBYTE (p), info);
364
      else
365
        (*info->print_address_func) (addr + 2 + NEXTWORD (p), info);
366
 
367
      return p - p0;
368
    }
369
 
370
  return print_insn_mode (d, arg_len, p0, addr, info);
371
}
372
 
373
/* Print the vax instruction at address MEMADDR in debugged memory,
374
   on INFO->STREAM.  Returns length of the instruction, in bytes.  */
375
 
376
int
377
print_insn_vax (bfd_vma memaddr, disassemble_info *info)
378
{
379
  static bfd_boolean parsed_disassembler_options = FALSE;
380
  const struct vot *votp;
381
  const char *argp;
382
  unsigned char *arg;
383
  struct private priv;
384
  bfd_byte *buffer = priv.the_buffer;
385
 
386
  info->private_data = & priv;
387
  priv.max_fetched = priv.the_buffer;
388
  priv.insn_start = memaddr;
389
 
390
  if (! parsed_disassembler_options
391
      && info->disassembler_options != NULL)
392
    {
393
      parse_disassembler_options (info->disassembler_options);
394
 
395
      /* To avoid repeated parsing of these options.  */
396
      parsed_disassembler_options = TRUE;
397
    }
398
 
399
  if (setjmp (priv.bailout) != 0)
400
    /* Error return.  */
401
    return -1;
402
 
403
  argp = NULL;
404
  /* Check if the info buffer has more than one byte left since
405
     the last opcode might be a single byte with no argument data.  */
406
  if (info->buffer_length - (memaddr - info->buffer_vma) > 1)
407
    {
408
      FETCH_DATA (info, buffer + 2);
409
    }
410
  else
411
    {
412
      FETCH_DATA (info, buffer + 1);
413
      buffer[1] = 0;
414
    }
415
 
416
  /* Decode function entry mask.  */
417
  if (is_function_entry (info, memaddr))
418
    {
419
      int i = 0;
420
      int register_mask = buffer[1] << 8 | buffer[0];
421
 
422
      (*info->fprintf_func) (info->stream, ".word 0x%04x # Entry mask: <",
423
                             register_mask);
424
 
425
      for (i = 15; i >= 0; i--)
426
        if (register_mask & (1 << i))
427
          (*info->fprintf_func) (info->stream, " %s", entry_mask_bit[i]);
428
 
429
      (*info->fprintf_func) (info->stream, " >");
430
 
431
      return 2;
432
    }
433
 
434 225 jeremybenn
  /* Decode PLT entry offset longword.  */
435
  if (is_plt_tail (info, memaddr))
436
    {
437
      int offset;
438
 
439
      FETCH_DATA (info, buffer + 4);
440
      offset = buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];
441
      (*info->fprintf_func) (info->stream, ".long 0x%08x", offset);
442
 
443
      return 4;
444
    }
445
 
446 24 jeremybenn
  for (votp = &votstrs[0]; votp->name[0]; votp++)
447
    {
448
      vax_opcodeT opcode = votp->detail.code;
449
 
450
      /* 2 byte codes match 2 buffer pos. */
451
      if ((bfd_byte) opcode == buffer[0]
452
          && (opcode >> 8 == 0 || opcode >> 8 == buffer[1]))
453
        {
454
          argp = votp->detail.args;
455
          break;
456
        }
457
    }
458
  if (argp == NULL)
459
    {
460
      /* Handle undefined instructions. */
461
      (*info->fprintf_func) (info->stream, ".word 0x%x",
462
                             (buffer[0] << 8) + buffer[1]);
463
      return 2;
464
    }
465
 
466
  /* Point at first byte of argument data, and at descriptor for first
467
     argument.  */
468
  arg = buffer + ((votp->detail.code >> 8) ? 2 : 1);
469
 
470
  /* Make sure we have it in mem */
471
  FETCH_DATA (info, arg);
472
 
473
  (*info->fprintf_func) (info->stream, "%s", votp->name);
474
  if (*argp)
475
    (*info->fprintf_func) (info->stream, " ");
476
 
477
  while (*argp)
478
    {
479
      arg += print_insn_arg (argp, arg, memaddr + arg - buffer, info);
480
      argp += 2;
481
      if (*argp)
482
        (*info->fprintf_func) (info->stream, ",");
483
    }
484
 
485
  return arg - buffer;
486
}
487
 

powered by: WebSVN 2.1.0

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