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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [opcodes/] [vax-dis.c] - Diff between revs 834 and 842

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 834 Rev 842
/* Print VAX instructions.
/* Print VAX instructions.
   Copyright 1995, 1998, 2000, 2001, 2002, 2005, 2007, 2009
   Copyright 1995, 1998, 2000, 2001, 2002, 2005, 2007, 2009
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
   Contributed by Pauline Middelink <middelin@polyware.iaf.nl>
   Contributed by Pauline Middelink <middelin@polyware.iaf.nl>
 
 
   This file is part of the GNU opcodes library.
   This file is part of the GNU opcodes library.
 
 
   This library is free software; you can redistribute it and/or modify
   This library is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   the Free Software Foundation; either version 3, or (at your option)
   any later version.
   any later version.
 
 
   It is distributed in the hope that it will be useful, but WITHOUT
   It is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
   License for more details.
   License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
   MA 02110-1301, USA.  */
   MA 02110-1301, USA.  */
 
 
#include <setjmp.h>
#include <setjmp.h>
#include <string.h>
#include <string.h>
#include "sysdep.h"
#include "sysdep.h"
#include "opcode/vax.h"
#include "opcode/vax.h"
#include "dis-asm.h"
#include "dis-asm.h"
 
 
static char *reg_names[] =
static char *reg_names[] =
{
{
  "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
  "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
  "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc"
  "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc"
};
};
 
 
/* Definitions for the function entry mask bits.  */
/* Definitions for the function entry mask bits.  */
static char *entry_mask_bit[] =
static char *entry_mask_bit[] =
{
{
  /* Registers 0 and 1 shall not be saved, since they're used to pass back
  /* Registers 0 and 1 shall not be saved, since they're used to pass back
     a function's result to its caller...  */
     a function's result to its caller...  */
  "~r0~", "~r1~",
  "~r0~", "~r1~",
  /* Registers 2 .. 11 are normal registers.  */
  /* Registers 2 .. 11 are normal registers.  */
  "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
  "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
  /* Registers 12 and 13 are argument and frame pointer and must not
  /* Registers 12 and 13 are argument and frame pointer and must not
     be saved by using the entry mask.  */
     be saved by using the entry mask.  */
  "~ap~", "~fp~",
  "~ap~", "~fp~",
  /* Bits 14 and 15 control integer and decimal overflow.  */
  /* Bits 14 and 15 control integer and decimal overflow.  */
  "IntOvfl", "DecOvfl",
  "IntOvfl", "DecOvfl",
};
};
 
 
/* Sign-extend an (unsigned char). */
/* Sign-extend an (unsigned char). */
#define COERCE_SIGNED_CHAR(ch) ((signed char)(ch))
#define COERCE_SIGNED_CHAR(ch) ((signed char)(ch))
 
 
/* Get a 1 byte signed integer.  */
/* Get a 1 byte signed integer.  */
#define NEXTBYTE(p)  \
#define NEXTBYTE(p)  \
  (p += 1, FETCH_DATA (info, p), \
  (p += 1, FETCH_DATA (info, p), \
  COERCE_SIGNED_CHAR(p[-1]))
  COERCE_SIGNED_CHAR(p[-1]))
 
 
/* Get a 2 byte signed integer.  */
/* Get a 2 byte signed integer.  */
#define COERCE16(x) ((int) (((x) ^ 0x8000) - 0x8000))
#define COERCE16(x) ((int) (((x) ^ 0x8000) - 0x8000))
#define NEXTWORD(p)  \
#define NEXTWORD(p)  \
  (p += 2, FETCH_DATA (info, p), \
  (p += 2, FETCH_DATA (info, p), \
   COERCE16 ((p[-1] << 8) + p[-2]))
   COERCE16 ((p[-1] << 8) + p[-2]))
 
 
/* Get a 4 byte signed integer.  */
/* Get a 4 byte signed integer.  */
#define COERCE32(x) ((int) (((x) ^ 0x80000000) - 0x80000000))
#define COERCE32(x) ((int) (((x) ^ 0x80000000) - 0x80000000))
#define NEXTLONG(p)  \
#define NEXTLONG(p)  \
  (p += 4, FETCH_DATA (info, p), \
  (p += 4, FETCH_DATA (info, p), \
   (COERCE32 ((((((p[-1] << 8) + p[-2]) << 8) + p[-3]) << 8) + p[-4])))
   (COERCE32 ((((((p[-1] << 8) + p[-2]) << 8) + p[-3]) << 8) + p[-4])))
 
 
/* Maximum length of an instruction.  */
/* Maximum length of an instruction.  */
#define MAXLEN 25
#define MAXLEN 25
 
 
struct private
struct private
{
{
  /* Points to first byte not fetched.  */
  /* Points to first byte not fetched.  */
  bfd_byte * max_fetched;
  bfd_byte * max_fetched;
  bfd_byte   the_buffer[MAXLEN];
  bfd_byte   the_buffer[MAXLEN];
  bfd_vma    insn_start;
  bfd_vma    insn_start;
  jmp_buf    bailout;
  jmp_buf    bailout;
};
};
 
 
/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
   to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
   to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
   on error.  */
   on error.  */
#define FETCH_DATA(info, addr) \
#define FETCH_DATA(info, addr) \
  ((addr) <= ((struct private *)(info->private_data))->max_fetched \
  ((addr) <= ((struct private *)(info->private_data))->max_fetched \
   ? 1 : fetch_data ((info), (addr)))
   ? 1 : fetch_data ((info), (addr)))
 
 
static int
static int
fetch_data (struct disassemble_info *info, bfd_byte *addr)
fetch_data (struct disassemble_info *info, bfd_byte *addr)
{
{
  int status;
  int status;
  struct private *priv = (struct private *) info->private_data;
  struct private *priv = (struct private *) info->private_data;
  bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
  bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
 
 
  status = (*info->read_memory_func) (start,
  status = (*info->read_memory_func) (start,
                                      priv->max_fetched,
                                      priv->max_fetched,
                                      addr - priv->max_fetched,
                                      addr - priv->max_fetched,
                                      info);
                                      info);
  if (status != 0)
  if (status != 0)
    {
    {
      (*info->memory_error_func) (status, start, info);
      (*info->memory_error_func) (status, start, info);
      longjmp (priv->bailout, 1);
      longjmp (priv->bailout, 1);
    }
    }
  else
  else
    priv->max_fetched = addr;
    priv->max_fetched = addr;
 
 
  return 1;
  return 1;
}
}
 
 
/* Entry mask handling.  */
/* Entry mask handling.  */
static unsigned int  entry_addr_occupied_slots = 0;
static unsigned int  entry_addr_occupied_slots = 0;
static unsigned int  entry_addr_total_slots = 0;
static unsigned int  entry_addr_total_slots = 0;
static bfd_vma *     entry_addr = NULL;
static bfd_vma *     entry_addr = NULL;
 
 
/* Parse the VAX specific disassembler options.  These contain function
/* Parse the VAX specific disassembler options.  These contain function
   entry addresses, which can be useful to disassemble ROM images, since
   entry addresses, which can be useful to disassemble ROM images, since
   there's no symbol table.  Returns TRUE upon success, FALSE otherwise.  */
   there's no symbol table.  Returns TRUE upon success, FALSE otherwise.  */
 
 
static bfd_boolean
static bfd_boolean
parse_disassembler_options (char * options)
parse_disassembler_options (char * options)
{
{
  const char * entry_switch = "entry:";
  const char * entry_switch = "entry:";
 
 
  while ((options = strstr (options, entry_switch)))
  while ((options = strstr (options, entry_switch)))
    {
    {
      options += strlen (entry_switch);
      options += strlen (entry_switch);
 
 
      /* The greater-than part of the test below is paranoia.  */
      /* The greater-than part of the test below is paranoia.  */
      if (entry_addr_occupied_slots >= entry_addr_total_slots)
      if (entry_addr_occupied_slots >= entry_addr_total_slots)
        {
        {
          /* A guesstimate of the number of entries we will have to create.  */
          /* A guesstimate of the number of entries we will have to create.  */
          entry_addr_total_slots +=
          entry_addr_total_slots +=
            strlen (options) / (strlen (entry_switch) + 5);
            strlen (options) / (strlen (entry_switch) + 5);
 
 
          entry_addr = realloc (entry_addr, sizeof (bfd_vma)
          entry_addr = realloc (entry_addr, sizeof (bfd_vma)
                                * entry_addr_total_slots);
                                * entry_addr_total_slots);
        }
        }
 
 
      if (entry_addr == NULL)
      if (entry_addr == NULL)
        return FALSE;
        return FALSE;
 
 
      entry_addr[entry_addr_occupied_slots] = bfd_scan_vma (options, NULL, 0);
      entry_addr[entry_addr_occupied_slots] = bfd_scan_vma (options, NULL, 0);
      entry_addr_occupied_slots ++;
      entry_addr_occupied_slots ++;
    }
    }
 
 
  return TRUE;
  return TRUE;
}
}
 
 
#if 0 /* FIXME:  Ideally the disassembler should have target specific
#if 0 /* FIXME:  Ideally the disassembler should have target specific
         initialisation and termination function pointers.  Then
         initialisation and termination function pointers.  Then
         parse_disassembler_options could be the init function and
         parse_disassembler_options could be the init function and
         free_entry_array (below) could be the termination routine.
         free_entry_array (below) could be the termination routine.
         Until then there is no way for the disassembler to tell us
         Until then there is no way for the disassembler to tell us
         that it has finished and that we no longer need the entry
         that it has finished and that we no longer need the entry
         array, so this routine is suppressed for now.  It does mean
         array, so this routine is suppressed for now.  It does mean
         that we leak memory, but only to the extent that we do not
         that we leak memory, but only to the extent that we do not
         free it just before the disassembler is about to terminate
         free it just before the disassembler is about to terminate
         anyway.  */
         anyway.  */
 
 
/* Free memory allocated to our entry array.  */
/* Free memory allocated to our entry array.  */
 
 
static void
static void
free_entry_array (void)
free_entry_array (void)
{
{
  if (entry_addr)
  if (entry_addr)
    {
    {
      free (entry_addr);
      free (entry_addr);
      entry_addr = NULL;
      entry_addr = NULL;
      entry_addr_occupied_slots = entry_addr_total_slots = 0;
      entry_addr_occupied_slots = entry_addr_total_slots = 0;
    }
    }
}
}
#endif
#endif
/* Check if the given address is a known function entry point.  This is
/* Check if the given address is a known function entry point.  This is
   the case if there is a symbol of the function type at this address.
   the case if there is a symbol of the function type at this address.
   We also check for synthetic symbols as these are used for PLT entries
   We also check for synthetic symbols as these are used for PLT entries
   (weak undefined symbols may not have the function type set).  Finally
   (weak undefined symbols may not have the function type set).  Finally
   the address may have been forced to be treated as an entry point.  The
   the address may have been forced to be treated as an entry point.  The
   latter helps in disassembling ROM images, because there's no symbol
   latter helps in disassembling ROM images, because there's no symbol
   table at all.  Forced entry points can be given by supplying several
   table at all.  Forced entry points can be given by supplying several
   -M options to objdump: -M entry:0xffbb7730.  */
   -M options to objdump: -M entry:0xffbb7730.  */
 
 
static bfd_boolean
static bfd_boolean
is_function_entry (struct disassemble_info *info, bfd_vma addr)
is_function_entry (struct disassemble_info *info, bfd_vma addr)
{
{
  unsigned int i;
  unsigned int i;
 
 
  /* Check if there's a function or PLT symbol at our address.  */
  /* Check if there's a function or PLT symbol at our address.  */
  if (info->symbols
  if (info->symbols
      && info->symbols[0]
      && info->symbols[0]
      && (info->symbols[0]->flags & (BSF_FUNCTION | BSF_SYNTHETIC))
      && (info->symbols[0]->flags & (BSF_FUNCTION | BSF_SYNTHETIC))
      && addr == bfd_asymbol_value (info->symbols[0]))
      && addr == bfd_asymbol_value (info->symbols[0]))
    return TRUE;
    return TRUE;
 
 
  /* Check for forced function entry address.  */
  /* Check for forced function entry address.  */
  for (i = entry_addr_occupied_slots; i--;)
  for (i = entry_addr_occupied_slots; i--;)
    if (entry_addr[i] == addr)
    if (entry_addr[i] == addr)
      return TRUE;
      return TRUE;
 
 
  return FALSE;
  return FALSE;
}
}
 
 
/* Check if the given address is the last longword of a PLT entry.
/* Check if the given address is the last longword of a PLT entry.
   This longword is data and depending on the value it may interfere
   This longword is data and depending on the value it may interfere
   with disassembly of further PLT entries.  We make use of the fact
   with disassembly of further PLT entries.  We make use of the fact
   PLT symbols are marked BSF_SYNTHETIC.  */
   PLT symbols are marked BSF_SYNTHETIC.  */
static bfd_boolean
static bfd_boolean
is_plt_tail (struct disassemble_info *info, bfd_vma addr)
is_plt_tail (struct disassemble_info *info, bfd_vma addr)
{
{
  if (info->symbols
  if (info->symbols
      && info->symbols[0]
      && info->symbols[0]
      && (info->symbols[0]->flags & BSF_SYNTHETIC)
      && (info->symbols[0]->flags & BSF_SYNTHETIC)
      && addr == bfd_asymbol_value (info->symbols[0]) + 8)
      && addr == bfd_asymbol_value (info->symbols[0]) + 8)
    return TRUE;
    return TRUE;
 
 
  return FALSE;
  return FALSE;
}
}
 
 
static int
static int
print_insn_mode (const char *d,
print_insn_mode (const char *d,
                 int size,
                 int size,
                 unsigned char *p0,
                 unsigned char *p0,
                 bfd_vma addr,  /* PC for this arg to be relative to.  */
                 bfd_vma addr,  /* PC for this arg to be relative to.  */
                 disassemble_info *info)
                 disassemble_info *info)
{
{
  unsigned char *p = p0;
  unsigned char *p = p0;
  unsigned char mode, reg;
  unsigned char mode, reg;
 
 
  /* Fetch and interpret mode byte.  */
  /* Fetch and interpret mode byte.  */
  mode = (unsigned char) NEXTBYTE (p);
  mode = (unsigned char) NEXTBYTE (p);
  reg = mode & 0xF;
  reg = mode & 0xF;
  switch (mode & 0xF0)
  switch (mode & 0xF0)
    {
    {
    case 0x00:
    case 0x00:
    case 0x10:
    case 0x10:
    case 0x20:
    case 0x20:
    case 0x30: /* Literal mode                  $number.  */
    case 0x30: /* Literal mode                  $number.  */
      if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
      if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
        (*info->fprintf_func) (info->stream, "$0x%x [%c-float]", mode, d[1]);
        (*info->fprintf_func) (info->stream, "$0x%x [%c-float]", mode, d[1]);
      else
      else
        (*info->fprintf_func) (info->stream, "$0x%x", mode);
        (*info->fprintf_func) (info->stream, "$0x%x", mode);
      break;
      break;
    case 0x40: /* Index:                        base-addr[Rn] */
    case 0x40: /* Index:                        base-addr[Rn] */
      p += print_insn_mode (d, size, p0 + 1, addr + 1, info);
      p += print_insn_mode (d, size, p0 + 1, addr + 1, info);
      (*info->fprintf_func) (info->stream, "[%s]", reg_names[reg]);
      (*info->fprintf_func) (info->stream, "[%s]", reg_names[reg]);
      break;
      break;
    case 0x50: /* Register:                     Rn */
    case 0x50: /* Register:                     Rn */
      (*info->fprintf_func) (info->stream, "%s", reg_names[reg]);
      (*info->fprintf_func) (info->stream, "%s", reg_names[reg]);
      break;
      break;
    case 0x60: /* Register deferred:            (Rn) */
    case 0x60: /* Register deferred:            (Rn) */
      (*info->fprintf_func) (info->stream, "(%s)", reg_names[reg]);
      (*info->fprintf_func) (info->stream, "(%s)", reg_names[reg]);
      break;
      break;
    case 0x70: /* Autodecrement:                -(Rn) */
    case 0x70: /* Autodecrement:                -(Rn) */
      (*info->fprintf_func) (info->stream, "-(%s)", reg_names[reg]);
      (*info->fprintf_func) (info->stream, "-(%s)", reg_names[reg]);
      break;
      break;
    case 0x80: /* Autoincrement:                (Rn)+ */
    case 0x80: /* Autoincrement:                (Rn)+ */
      if (reg == 0xF)
      if (reg == 0xF)
        {       /* Immediate?  */
        {       /* Immediate?  */
          int i;
          int i;
 
 
          FETCH_DATA (info, p + size);
          FETCH_DATA (info, p + size);
          (*info->fprintf_func) (info->stream, "$0x");
          (*info->fprintf_func) (info->stream, "$0x");
          if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
          if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
            {
            {
              int float_word;
              int float_word;
 
 
              float_word = p[0] | (p[1] << 8);
              float_word = p[0] | (p[1] << 8);
              if ((d[1] == 'd' || d[1] == 'f')
              if ((d[1] == 'd' || d[1] == 'f')
                  && (float_word & 0xff80) == 0x8000)
                  && (float_word & 0xff80) == 0x8000)
                {
                {
                  (*info->fprintf_func) (info->stream, "[invalid %c-float]",
                  (*info->fprintf_func) (info->stream, "[invalid %c-float]",
                                         d[1]);
                                         d[1]);
                }
                }
              else
              else
                {
                {
                  for (i = 0; i < size; i++)
                  for (i = 0; i < size; i++)
                    (*info->fprintf_func) (info->stream, "%02x",
                    (*info->fprintf_func) (info->stream, "%02x",
                                           p[size - i - 1]);
                                           p[size - i - 1]);
                  (*info->fprintf_func) (info->stream, " [%c-float]", d[1]);
                  (*info->fprintf_func) (info->stream, " [%c-float]", d[1]);
                }
                }
            }
            }
          else
          else
            {
            {
              for (i = 0; i < size; i++)
              for (i = 0; i < size; i++)
                (*info->fprintf_func) (info->stream, "%02x", p[size - i - 1]);
                (*info->fprintf_func) (info->stream, "%02x", p[size - i - 1]);
            }
            }
          p += size;
          p += size;
        }
        }
      else
      else
        (*info->fprintf_func) (info->stream, "(%s)+", reg_names[reg]);
        (*info->fprintf_func) (info->stream, "(%s)+", reg_names[reg]);
      break;
      break;
    case 0x90: /* Autoincrement deferred:       @(Rn)+ */
    case 0x90: /* Autoincrement deferred:       @(Rn)+ */
      if (reg == 0xF)
      if (reg == 0xF)
        (*info->fprintf_func) (info->stream, "*0x%x", NEXTLONG (p));
        (*info->fprintf_func) (info->stream, "*0x%x", NEXTLONG (p));
      else
      else
        (*info->fprintf_func) (info->stream, "@(%s)+", reg_names[reg]);
        (*info->fprintf_func) (info->stream, "@(%s)+", reg_names[reg]);
      break;
      break;
    case 0xB0: /* Displacement byte deferred:   *displ(Rn).  */
    case 0xB0: /* Displacement byte deferred:   *displ(Rn).  */
      (*info->fprintf_func) (info->stream, "*");
      (*info->fprintf_func) (info->stream, "*");
    case 0xA0: /* Displacement byte:            displ(Rn).  */
    case 0xA0: /* Displacement byte:            displ(Rn).  */
      if (reg == 0xF)
      if (reg == 0xF)
        (*info->print_address_func) (addr + 2 + NEXTBYTE (p), info);
        (*info->print_address_func) (addr + 2 + NEXTBYTE (p), info);
      else
      else
        (*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTBYTE (p),
        (*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTBYTE (p),
                               reg_names[reg]);
                               reg_names[reg]);
      break;
      break;
    case 0xD0: /* Displacement word deferred:   *displ(Rn).  */
    case 0xD0: /* Displacement word deferred:   *displ(Rn).  */
      (*info->fprintf_func) (info->stream, "*");
      (*info->fprintf_func) (info->stream, "*");
    case 0xC0: /* Displacement word:            displ(Rn).  */
    case 0xC0: /* Displacement word:            displ(Rn).  */
      if (reg == 0xF)
      if (reg == 0xF)
        (*info->print_address_func) (addr + 3 + NEXTWORD (p), info);
        (*info->print_address_func) (addr + 3 + NEXTWORD (p), info);
      else
      else
        (*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTWORD (p),
        (*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTWORD (p),
                               reg_names[reg]);
                               reg_names[reg]);
      break;
      break;
    case 0xF0: /* Displacement long deferred:   *displ(Rn).  */
    case 0xF0: /* Displacement long deferred:   *displ(Rn).  */
      (*info->fprintf_func) (info->stream, "*");
      (*info->fprintf_func) (info->stream, "*");
    case 0xE0: /* Displacement long:            displ(Rn).  */
    case 0xE0: /* Displacement long:            displ(Rn).  */
      if (reg == 0xF)
      if (reg == 0xF)
        (*info->print_address_func) (addr + 5 + NEXTLONG (p), info);
        (*info->print_address_func) (addr + 5 + NEXTLONG (p), info);
      else
      else
        (*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTLONG (p),
        (*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTLONG (p),
                               reg_names[reg]);
                               reg_names[reg]);
      break;
      break;
    }
    }
 
 
  return p - p0;
  return p - p0;
}
}
 
 
/* Returns number of bytes "eaten" by the operand, or return -1 if an
/* Returns number of bytes "eaten" by the operand, or return -1 if an
   invalid operand was found, or -2 if an opcode tabel error was
   invalid operand was found, or -2 if an opcode tabel error was
   found. */
   found. */
 
 
static int
static int
print_insn_arg (const char *d,
print_insn_arg (const char *d,
                unsigned char *p0,
                unsigned char *p0,
                bfd_vma addr,   /* PC for this arg to be relative to.  */
                bfd_vma addr,   /* PC for this arg to be relative to.  */
                disassemble_info *info)
                disassemble_info *info)
{
{
  int arg_len;
  int arg_len;
 
 
  /* Check validity of addressing length.  */
  /* Check validity of addressing length.  */
  switch (d[1])
  switch (d[1])
    {
    {
    case 'b' : arg_len = 1;     break;
    case 'b' : arg_len = 1;     break;
    case 'd' : arg_len = 8;     break;
    case 'd' : arg_len = 8;     break;
    case 'f' : arg_len = 4;     break;
    case 'f' : arg_len = 4;     break;
    case 'g' : arg_len = 8;     break;
    case 'g' : arg_len = 8;     break;
    case 'h' : arg_len = 16;    break;
    case 'h' : arg_len = 16;    break;
    case 'l' : arg_len = 4;     break;
    case 'l' : arg_len = 4;     break;
    case 'o' : arg_len = 16;    break;
    case 'o' : arg_len = 16;    break;
    case 'w' : arg_len = 2;     break;
    case 'w' : arg_len = 2;     break;
    case 'q' : arg_len = 8;     break;
    case 'q' : arg_len = 8;     break;
    default  : abort ();
    default  : abort ();
    }
    }
 
 
  /* Branches have no mode byte.  */
  /* Branches have no mode byte.  */
  if (d[0] == 'b')
  if (d[0] == 'b')
    {
    {
      unsigned char *p = p0;
      unsigned char *p = p0;
 
 
      if (arg_len == 1)
      if (arg_len == 1)
        (*info->print_address_func) (addr + 1 + NEXTBYTE (p), info);
        (*info->print_address_func) (addr + 1 + NEXTBYTE (p), info);
      else
      else
        (*info->print_address_func) (addr + 2 + NEXTWORD (p), info);
        (*info->print_address_func) (addr + 2 + NEXTWORD (p), info);
 
 
      return p - p0;
      return p - p0;
    }
    }
 
 
  return print_insn_mode (d, arg_len, p0, addr, info);
  return print_insn_mode (d, arg_len, p0, addr, info);
}
}
 
 
/* Print the vax instruction at address MEMADDR in debugged memory,
/* Print the vax instruction at address MEMADDR in debugged memory,
   on INFO->STREAM.  Returns length of the instruction, in bytes.  */
   on INFO->STREAM.  Returns length of the instruction, in bytes.  */
 
 
int
int
print_insn_vax (bfd_vma memaddr, disassemble_info *info)
print_insn_vax (bfd_vma memaddr, disassemble_info *info)
{
{
  static bfd_boolean parsed_disassembler_options = FALSE;
  static bfd_boolean parsed_disassembler_options = FALSE;
  const struct vot *votp;
  const struct vot *votp;
  const char *argp;
  const char *argp;
  unsigned char *arg;
  unsigned char *arg;
  struct private priv;
  struct private priv;
  bfd_byte *buffer = priv.the_buffer;
  bfd_byte *buffer = priv.the_buffer;
 
 
  info->private_data = & priv;
  info->private_data = & priv;
  priv.max_fetched = priv.the_buffer;
  priv.max_fetched = priv.the_buffer;
  priv.insn_start = memaddr;
  priv.insn_start = memaddr;
 
 
  if (! parsed_disassembler_options
  if (! parsed_disassembler_options
      && info->disassembler_options != NULL)
      && info->disassembler_options != NULL)
    {
    {
      parse_disassembler_options (info->disassembler_options);
      parse_disassembler_options (info->disassembler_options);
 
 
      /* To avoid repeated parsing of these options.  */
      /* To avoid repeated parsing of these options.  */
      parsed_disassembler_options = TRUE;
      parsed_disassembler_options = TRUE;
    }
    }
 
 
  if (setjmp (priv.bailout) != 0)
  if (setjmp (priv.bailout) != 0)
    /* Error return.  */
    /* Error return.  */
    return -1;
    return -1;
 
 
  argp = NULL;
  argp = NULL;
  /* Check if the info buffer has more than one byte left since
  /* Check if the info buffer has more than one byte left since
     the last opcode might be a single byte with no argument data.  */
     the last opcode might be a single byte with no argument data.  */
  if (info->buffer_length - (memaddr - info->buffer_vma) > 1)
  if (info->buffer_length - (memaddr - info->buffer_vma) > 1)
    {
    {
      FETCH_DATA (info, buffer + 2);
      FETCH_DATA (info, buffer + 2);
    }
    }
  else
  else
    {
    {
      FETCH_DATA (info, buffer + 1);
      FETCH_DATA (info, buffer + 1);
      buffer[1] = 0;
      buffer[1] = 0;
    }
    }
 
 
  /* Decode function entry mask.  */
  /* Decode function entry mask.  */
  if (is_function_entry (info, memaddr))
  if (is_function_entry (info, memaddr))
    {
    {
      int i = 0;
      int i = 0;
      int register_mask = buffer[1] << 8 | buffer[0];
      int register_mask = buffer[1] << 8 | buffer[0];
 
 
      (*info->fprintf_func) (info->stream, ".word 0x%04x # Entry mask: <",
      (*info->fprintf_func) (info->stream, ".word 0x%04x # Entry mask: <",
                             register_mask);
                             register_mask);
 
 
      for (i = 15; i >= 0; i--)
      for (i = 15; i >= 0; i--)
        if (register_mask & (1 << i))
        if (register_mask & (1 << i))
          (*info->fprintf_func) (info->stream, " %s", entry_mask_bit[i]);
          (*info->fprintf_func) (info->stream, " %s", entry_mask_bit[i]);
 
 
      (*info->fprintf_func) (info->stream, " >");
      (*info->fprintf_func) (info->stream, " >");
 
 
      return 2;
      return 2;
    }
    }
 
 
  /* Decode PLT entry offset longword.  */
  /* Decode PLT entry offset longword.  */
  if (is_plt_tail (info, memaddr))
  if (is_plt_tail (info, memaddr))
    {
    {
      int offset;
      int offset;
 
 
      FETCH_DATA (info, buffer + 4);
      FETCH_DATA (info, buffer + 4);
      offset = buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];
      offset = buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];
      (*info->fprintf_func) (info->stream, ".long 0x%08x", offset);
      (*info->fprintf_func) (info->stream, ".long 0x%08x", offset);
 
 
      return 4;
      return 4;
    }
    }
 
 
  for (votp = &votstrs[0]; votp->name[0]; votp++)
  for (votp = &votstrs[0]; votp->name[0]; votp++)
    {
    {
      vax_opcodeT opcode = votp->detail.code;
      vax_opcodeT opcode = votp->detail.code;
 
 
      /* 2 byte codes match 2 buffer pos. */
      /* 2 byte codes match 2 buffer pos. */
      if ((bfd_byte) opcode == buffer[0]
      if ((bfd_byte) opcode == buffer[0]
          && (opcode >> 8 == 0 || opcode >> 8 == buffer[1]))
          && (opcode >> 8 == 0 || opcode >> 8 == buffer[1]))
        {
        {
          argp = votp->detail.args;
          argp = votp->detail.args;
          break;
          break;
        }
        }
    }
    }
  if (argp == NULL)
  if (argp == NULL)
    {
    {
      /* Handle undefined instructions. */
      /* Handle undefined instructions. */
      (*info->fprintf_func) (info->stream, ".word 0x%x",
      (*info->fprintf_func) (info->stream, ".word 0x%x",
                             (buffer[0] << 8) + buffer[1]);
                             (buffer[0] << 8) + buffer[1]);
      return 2;
      return 2;
    }
    }
 
 
  /* Point at first byte of argument data, and at descriptor for first
  /* Point at first byte of argument data, and at descriptor for first
     argument.  */
     argument.  */
  arg = buffer + ((votp->detail.code >> 8) ? 2 : 1);
  arg = buffer + ((votp->detail.code >> 8) ? 2 : 1);
 
 
  /* Make sure we have it in mem */
  /* Make sure we have it in mem */
  FETCH_DATA (info, arg);
  FETCH_DATA (info, arg);
 
 
  (*info->fprintf_func) (info->stream, "%s", votp->name);
  (*info->fprintf_func) (info->stream, "%s", votp->name);
  if (*argp)
  if (*argp)
    (*info->fprintf_func) (info->stream, " ");
    (*info->fprintf_func) (info->stream, " ");
 
 
  while (*argp)
  while (*argp)
    {
    {
      arg += print_insn_arg (argp, arg, memaddr + arg - buffer, info);
      arg += print_insn_arg (argp, arg, memaddr + arg - buffer, info);
      argp += 2;
      argp += 2;
      if (*argp)
      if (*argp)
        (*info->fprintf_func) (info->stream, ",");
        (*info->fprintf_func) (info->stream, ",");
    }
    }
 
 
  return arg - buffer;
  return arg - buffer;
}
}
 
 
 
 

powered by: WebSVN 2.1.0

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