switch inferior/thread before calling target methods
[deliverable/binutils-gdb.git] / gdb / vax-tdep.c
index b378571ec566c6628efdb878466db8aeb7553bf5..a83decd6bd62c971d5745962420df02257302166 100644 (file)
-/* Print VAX instructions for GDB, the GNU debugger.
-   Copyright 1986, 1989, 1991, 1992, 1996 Free Software Foundation, Inc.
+/* Target-dependent code for the VAX.
 
-This file is part of GDB.
+   Copyright (C) 1986-2020 Free Software Foundation, Inc.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This file is part of GDB.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
-#include "symtab.h"
-#include "opcode/vax.h"
+#include "arch-utils.h"
+#include "dis-asm.h"
+#include "frame.h"
+#include "frame-base.h"
+#include "frame-unwind.h"
+#include "gdbcore.h"
+#include "gdbtypes.h"
+#include "osabi.h"
+#include "regcache.h"
+#include "regset.h"
+#include "trad-frame.h"
+#include "value.h"
+
+#include "vax-tdep.h"
+
+/* Return the name of register REGNUM.  */
+
+static const char *
+vax_register_name (struct gdbarch *gdbarch, int regnum)
+{
+  static const char *register_names[] =
+  {
+    "r0", "r1", "r2",  "r3",  "r4", "r5", "r6", "r7",
+    "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc",
+    "ps",
+  };
 
-/* Vax instructions are never longer than this.  */
-#define MAXLEN 62
+  if (regnum >= 0 && regnum < ARRAY_SIZE (register_names))
+    return register_names[regnum];
+
+  return NULL;
+}
 
-/* Number of elements in the opcode table.  */
-#define NOPCODES (sizeof votstrs / sizeof votstrs[0])
+/* Return the GDB type object for the "standard" data type of data in
+   register REGNUM.  */
 
-static unsigned char *print_insn_arg ();
+static struct type *
+vax_register_type (struct gdbarch *gdbarch, int regnum)
+{
+  return builtin_type (gdbarch)->builtin_int;
+}
 \f
-/* Print the vax instruction at address MEMADDR in debugged memory,
-   from disassembler info INFO.
-   Returns length of the instruction, in bytes.  */
+/* Core file support.  */
 
-static int
-vax_print_insn (memaddr, info)
-     CORE_ADDR memaddr;
-     disassemble_info *info;
+/* Supply register REGNUM from the buffer specified by GREGS and LEN
+   in the general-purpose register set REGSET to register cache
+   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
+
+static void
+vax_supply_gregset (const struct regset *regset, struct regcache *regcache,
+                   int regnum, const void *gregs, size_t len)
 {
-  unsigned char buffer[MAXLEN];
-  register int i;
-  register unsigned char *p;
-  register char *d;
+  const gdb_byte *regs = (const gdb_byte *) gregs;
+  int i;
 
-  int status = (*info->read_memory_func) (memaddr, buffer, MAXLEN, info);
-  if (status != 0)
+  for (i = 0; i < VAX_NUM_REGS; i++)
     {
-      (*info->memory_error_func) (status, memaddr, info);
-      return -1;
+      if (regnum == i || regnum == -1)
+       regcache->raw_supply (i, regs + i * 4);
     }
+}
+
+/* VAX register set.  */
+
+static const struct regset vax_gregset =
+{
+  NULL,
+  vax_supply_gregset
+};
+
+/* Iterate over core file register note sections.  */
+
+static void
+vax_iterate_over_regset_sections (struct gdbarch *gdbarch,
+                                 iterate_over_regset_sections_cb *cb,
+                                 void *cb_data,
+                                 const struct regcache *regcache)
+{
+  cb (".reg", VAX_NUM_REGS * 4, VAX_NUM_REGS * 4, &vax_gregset, NULL, cb_data);
+}
+\f
+/* The VAX UNIX calling convention uses R1 to pass a structure return
+   value address instead of passing it as a first (hidden) argument as
+   the VMS calling convention suggests.  */
 
-  for (i = 0; i < NOPCODES; i++)
-    if (votstrs[i].detail.code == buffer[0]
-       || votstrs[i].detail.code == *(unsigned short *)buffer)
-      break;
+static CORE_ADDR
+vax_store_arguments (struct regcache *regcache, int nargs,
+                    struct value **args, CORE_ADDR sp)
+{
+  struct gdbarch *gdbarch = regcache->arch ();
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  gdb_byte buf[4];
+  int count = 0;
+  int i;
 
-  /* Handle undefined instructions.  */
-  if (i == NOPCODES)
+  /* We create an argument list on the stack, and make the argument
+     pointer to it.  */
+
+  /* Push arguments in reverse order.  */
+  for (i = nargs - 1; i >= 0; i--)
     {
-      (*info->fprintf_func) (info->stream, "0%o", buffer[0]);
-      return 1;
+      int len = TYPE_LENGTH (value_enclosing_type (args[i]));
+
+      sp -= (len + 3) & ~3;
+      count += (len + 3) / 4;
+      write_memory (sp, value_contents_all (args[i]), len);
     }
 
-  (*info->fprintf_func) (info->stream, "%s", votstrs[i].name);
+  /* Push argument count.  */
+  sp -= 4;
+  store_unsigned_integer (buf, 4, byte_order, count);
+  write_memory (sp, buf, 4);
+
+  /* Update the argument pointer.  */
+  store_unsigned_integer (buf, 4, byte_order, sp);
+  regcache->cooked_write (VAX_AP_REGNUM, buf);
 
-  /* Point at first byte of argument data,
-     and at descriptor for first argument.  */
-  p = buffer + 1 + (votstrs[i].detail.code >= 0x100);
-  d = votstrs[i].detail.args;
+  return sp;
+}
 
-  if (*d)
-    (*info->fprintf_func) (info->stream, " ");
+static CORE_ADDR
+vax_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
+                    struct regcache *regcache, CORE_ADDR bp_addr, int nargs,
+                    struct value **args, CORE_ADDR sp,
+                    function_call_return_method return_method,
+                    CORE_ADDR struct_addr)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  CORE_ADDR fp = sp;
+  gdb_byte buf[4];
+
+  /* Set up the function arguments.  */
+  sp = vax_store_arguments (regcache, nargs, args, sp);
+
+  /* Store return value address.  */
+  if (return_method == return_method_struct)
+    regcache_cooked_write_unsigned (regcache, VAX_R1_REGNUM, struct_addr);
+
+  /* Store return address in the PC slot.  */
+  sp -= 4;
+  store_unsigned_integer (buf, 4, byte_order, bp_addr);
+  write_memory (sp, buf, 4);
+
+  /* Store the (fake) frame pointer in the FP slot.  */
+  sp -= 4;
+  store_unsigned_integer (buf, 4, byte_order, fp);
+  write_memory (sp, buf, 4);
+
+  /* Skip the AP slot.  */
+  sp -= 4;
+
+  /* Store register save mask and control bits.  */
+  sp -= 4;
+  store_unsigned_integer (buf, 4, byte_order, 0);
+  write_memory (sp, buf, 4);
+
+  /* Store condition handler.  */
+  sp -= 4;
+  store_unsigned_integer (buf, 4, byte_order, 0);
+  write_memory (sp, buf, 4);
+
+  /* Update the stack pointer and frame pointer.  */
+  store_unsigned_integer (buf, 4, byte_order, sp);
+  regcache->cooked_write (VAX_SP_REGNUM, buf);
+  regcache->cooked_write (VAX_FP_REGNUM, buf);
+
+  /* Return the saved (fake) frame pointer.  */
+  return fp;
+}
 
-  while (*d)
+static struct frame_id
+vax_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
+{
+  CORE_ADDR fp;
+
+  fp = get_frame_register_unsigned (this_frame, VAX_FP_REGNUM);
+  return frame_id_build (fp, get_frame_pc (this_frame));
+}
+\f
+
+static enum return_value_convention
+vax_return_value (struct gdbarch *gdbarch, struct value *function,
+                 struct type *type, struct regcache *regcache,
+                 gdb_byte *readbuf, const gdb_byte *writebuf)
+{
+  int len = TYPE_LENGTH (type);
+  gdb_byte buf[8];
+
+  if (TYPE_CODE (type) == TYPE_CODE_STRUCT
+      || TYPE_CODE (type) == TYPE_CODE_UNION
+      || TYPE_CODE (type) == TYPE_CODE_ARRAY)
+    {
+      /* The default on VAX is to return structures in static memory.
+         Consequently a function must return the address where we can
+         find the return value.  */
+
+      if (readbuf)
+       {
+         ULONGEST addr;
+
+         regcache_raw_read_unsigned (regcache, VAX_R0_REGNUM, &addr);
+         read_memory (addr, readbuf, len);
+       }
+
+      return RETURN_VALUE_ABI_RETURNS_ADDRESS;
+    }
+
+  if (readbuf)
     {
-      p = print_insn_arg (d, p, memaddr + (p - buffer), info);
-      d += 2;
-      if (*d)
-       (*info->fprintf_func) (info->stream, ",");
+      /* Read the contents of R0 and (if necessary) R1.  */
+      regcache->cooked_read (VAX_R0_REGNUM, buf);
+      if (len > 4)
+       regcache->cooked_read (VAX_R1_REGNUM, buf + 4);
+      memcpy (readbuf, buf, len);
     }
-  return p - buffer;
+  if (writebuf)
+    {
+      /* Read the contents to R0 and (if necessary) R1.  */
+      memcpy (buf, writebuf, len);
+      regcache->cooked_write (VAX_R0_REGNUM, buf);
+      if (len > 4)
+       regcache->cooked_write (VAX_R1_REGNUM, buf + 4);
+    }
+
+  return RETURN_VALUE_REGISTER_CONVENTION;
 }
+\f
+
+/* Use the program counter to determine the contents and size of a
+   breakpoint instruction.  Return a pointer to a string of bytes that
+   encode a breakpoint instruction, store the length of the string in
+   *LEN and optionally adjust *PC to point to the correct memory
+   location for inserting the breakpoint.  */
 
-static unsigned char *
-print_insn_arg (d, p, addr, info)
-     char *d;
-     register char *p;
-     CORE_ADDR addr;
-     disassemble_info *info;
+constexpr gdb_byte vax_break_insn[] = { 3 };
+
+typedef BP_MANIPULATION (vax_break_insn) vax_breakpoint;
+\f
+/* Advance PC across any function entry prologue instructions
+   to reach some "real" code.  */
+
+static CORE_ADDR
+vax_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
-  register int regnum = *p & 0xf;
-  float floatlitbuf;
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  gdb_byte op = read_memory_unsigned_integer (pc, 1, byte_order);
+
+  if (op == 0x11)
+    pc += 2;                   /* skip brb */
+  if (op == 0x31)
+    pc += 3;                   /* skip brw */
+  if (op == 0xC2
+      && read_memory_unsigned_integer (pc + 2, 1, byte_order) == 0x5E)
+    pc += 3;                   /* skip subl2 */
+  if (op == 0x9E
+      && read_memory_unsigned_integer (pc + 1, 1, byte_order) == 0xAE
+      && read_memory_unsigned_integer (pc + 3, 1, byte_order) == 0x5E)
+    pc += 4;                   /* skip movab */
+  if (op == 0x9E
+      && read_memory_unsigned_integer (pc + 1, 1, byte_order) == 0xCE
+      && read_memory_unsigned_integer (pc + 4, 1, byte_order) == 0x5E)
+    pc += 5;                   /* skip movab */
+  if (op == 0x9E
+      && read_memory_unsigned_integer (pc + 1, 1, byte_order) == 0xEE
+      && read_memory_unsigned_integer (pc + 6, 1, byte_order) == 0x5E)
+    pc += 7;                   /* skip movab */
+
+  return pc;
+}
+\f
 
-  if (*d == 'b')
+/* Unwinding the stack is relatively easy since the VAX has a
+   dedicated frame pointer, and frames are set up automatically as the
+   result of a function call.  Most of the relevant information can be
+   inferred from the documentation of the Procedure Call Instructions
+   in the VAX MACRO and Instruction Set Reference Manual.  */
+
+struct vax_frame_cache
+{
+  /* Base address.  */
+  CORE_ADDR base;
+
+  /* Table of saved registers.  */
+  struct trad_frame_saved_reg *saved_regs;
+};
+
+static struct vax_frame_cache *
+vax_frame_cache (struct frame_info *this_frame, void **this_cache)
+{
+  struct vax_frame_cache *cache;
+  CORE_ADDR addr;
+  ULONGEST mask;
+  int regnum;
+
+  if (*this_cache)
+    return (struct vax_frame_cache *) *this_cache;
+
+  /* Allocate a new cache.  */
+  cache = FRAME_OBSTACK_ZALLOC (struct vax_frame_cache);
+  cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
+
+  /* The frame pointer is used as the base for the frame.  */
+  cache->base = get_frame_register_unsigned (this_frame, VAX_FP_REGNUM);
+  if (cache->base == 0)
+    return cache;
+
+  /* The register save mask and control bits determine the layout of
+     the stack frame.  */
+  mask = get_frame_memory_unsigned (this_frame, cache->base + 4, 4) >> 16;
+
+  /* These are always saved.  */
+  cache->saved_regs[VAX_PC_REGNUM].addr = cache->base + 16;
+  cache->saved_regs[VAX_FP_REGNUM].addr = cache->base + 12;
+  cache->saved_regs[VAX_AP_REGNUM].addr = cache->base + 8;
+  cache->saved_regs[VAX_PS_REGNUM].addr = cache->base + 4;
+
+  /* Scan the register save mask and record the location of the saved
+     registers.  */
+  addr = cache->base + 20;
+  for (regnum = 0; regnum < VAX_AP_REGNUM; regnum++)
     {
-      if (d[1] == 'b')
-       (*info->fprintf_func) (info->stream, "0x%x", addr + *p++ + 1);
-      else
+      if (mask & (1 << regnum))
        {
-         (*info->fprintf_func) (info->stream, "0x%x", addr + *(short *)p + 2);
-         p += 2;
+         cache->saved_regs[regnum].addr = addr;
+         addr += 4;
        }
     }
-  else
-    switch ((*p++ >> 4) & 0xf)
-      {
-      case 0:
-      case 1:
-      case 2:
-      case 3:                  /* Literal mode */
-       if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
-         {
-           *(int *)&floatlitbuf = 0x4000 + ((p[-1] & 0x3f) << 4);
-           (*info->fprintf_func) (info->stream, "$%f", floatlitbuf);
-         }
-       else
-         (*info->fprintf_func) (info->stream, "$%d", p[-1] & 0x3f);
-       break;
-
-      case 4:                  /* Indexed */
-       p = (char *) print_insn_arg (d, p, addr + 1, info);
-       (*info->fprintf_func) (info->stream, "[%s]", REGISTER_NAME (regnum));
-       break;
-
-      case 5:                  /* Register */
-       (*info->fprintf_func) (info->stream, REGISTER_NAME (regnum));
-       break;
-
-      case 7:                  /* Autodecrement */
-       (*info->fprintf_func) (info->stream, "-");
-      case 6:                  /* Register deferred */
-       (*info->fprintf_func) (info->stream, "(%s)", REGISTER_NAME (regnum));
-       break;
-
-      case 9:                  /* Autoincrement deferred */
-       (*info->fprintf_func) (info->stream, "@");
-       if (regnum == PC_REGNUM)
-         {
-           (*info->fprintf_func) (info->stream, "#");
-           info->target = *(long *)p;
-           (*info->print_address_func) (info->target, info);
-           p += 4;
-           break;
-         }
-      case 8:                  /* Autoincrement */
-       if (regnum == PC_REGNUM)
-         {
-           (*info->fprintf_func) (info->stream, "#");
-           switch (d[1])
-             {
-             case 'b':
-               (*info->fprintf_func) (info->stream, "%d", *p++);
-               break;
-
-             case 'w':
-               (*info->fprintf_func) (info->stream, "%d", *(short *)p);
-               p += 2;
-               break;
-
-             case 'l':
-               (*info->fprintf_func) (info->stream, "%d", *(long *)p);
-               p += 4;
-               break;
-
-             case 'q':
-               (*info->fprintf_func) (info->stream, "0x%x%08x",
-                                      ((long *)p)[1], ((long *)p)[0]);
-               p += 8;
-               break;
-
-             case 'o':
-               (*info->fprintf_func) (info->stream, "0x%x%08x%08x%08x",
-                                      ((long *)p)[3], ((long *)p)[2],
-                                      ((long *)p)[1], ((long *)p)[0]);
-               p += 16;
-               break;
-
-             case 'f':
-               if (INVALID_FLOAT (p, 4))
-                 (*info->fprintf_func) (info->stream,
-                                        "<<invalid float 0x%x>>",
-                                        *(int *) p);
-               else
-                 (*info->fprintf_func) (info->stream, "%f", *(float *) p);
-               p += 4;
-               break;
-
-             case 'd':
-               if (INVALID_FLOAT (p, 8))
-                 (*info->fprintf_func) (info->stream,
-                                        "<<invalid float 0x%x%08x>>",
-                                        ((long *)p)[1], ((long *)p)[0]);
-               else
-                 (*info->fprintf_func) (info->stream, "%f", *(double *) p);
-               p += 8;
-               break;
-
-             case 'g':
-               (*info->fprintf_func) (info->stream, "g-float");
-               p += 8;
-               break;
-
-             case 'h':
-               (*info->fprintf_func) (info->stream, "h-float");
-               p += 16;
-               break;
-
-             }
-         }
-       else
-         (*info->fprintf_func) (info->stream, "(%s)+", REGISTER_NAME (regnum));
-       break;
-
-      case 11:                 /* Byte displacement deferred */
-       (*info->fprintf_func) (info->stream, "@");
-      case 10:                 /* Byte displacement */
-       if (regnum == PC_REGNUM)
-         {
-           info->target = addr + *p + 2;
-           (*info->print_address_func) (info->target, info);
-         }
-       else
-         (*info->fprintf_func) (info->stream, "%d(%s)", *p, REGISTER_NAME (regnum));
-       p += 1;
-       break;
-
-      case 13:                 /* Word displacement deferred */
-       (*info->fprintf_func) (info->stream, "@");
-      case 12:                 /* Word displacement */
-       if (regnum == PC_REGNUM)
-         {
-           info->target = addr + *(short *)p + 3;
-           (*info->print_address_func) (info->target, info);
-         }
-       else
-         (*info->fprintf_func) (info->stream, "%d(%s)",
-                                *(short *)p, REGISTER_NAME (regnum));
-       p += 2;
-       break;
-
-      case 15:                 /* Long displacement deferred */
-       (*info->fprintf_func) (info->stream, "@");
-      case 14:                 /* Long displacement */
-       if (regnum == PC_REGNUM)
-         {
-           info->target = addr + *(short *)p + 5;
-           (*info->print_address_func) (info->target, info);
-         }
-       else
-         (*info->fprintf_func) (info->stream, "%d(%s)",
-                                *(long *)p, REGISTER_NAME (regnum));
-       p += 4;
-      }
-
-  return (unsigned char *) p;
+
+  /* The CALLS/CALLG flag determines whether this frame has a General
+     Argument List or a Stack Argument List.  */
+  if (mask & (1 << 13))
+    {
+      ULONGEST numarg;
+
+      /* This is a procedure with Stack Argument List.  Adjust the
+         stack address for the arguments that were pushed onto the
+         stack.  The return instruction will automatically pop the
+         arguments from the stack.  */
+      numarg = get_frame_memory_unsigned (this_frame, addr, 1);
+      addr += 4 + numarg * 4;
+    }
+
+  /* Bits 1:0 of the stack pointer were saved in the control bits.  */
+  trad_frame_set_value (cache->saved_regs, VAX_SP_REGNUM, addr + (mask >> 14));
+
+  return cache;
+}
+
+static void
+vax_frame_this_id (struct frame_info *this_frame, void **this_cache,
+                  struct frame_id *this_id)
+{
+  struct vax_frame_cache *cache = vax_frame_cache (this_frame, this_cache);
+
+  /* This marks the outermost frame.  */
+  if (cache->base == 0)
+    return;
+
+  (*this_id) = frame_id_build (cache->base, get_frame_func (this_frame));
+}
+
+static struct value *
+vax_frame_prev_register (struct frame_info *this_frame,
+                        void **this_cache, int regnum)
+{
+  struct vax_frame_cache *cache = vax_frame_cache (this_frame, this_cache);
+
+  return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
+}
+
+static const struct frame_unwind vax_frame_unwind =
+{
+  NORMAL_FRAME,
+  default_frame_unwind_stop_reason,
+  vax_frame_this_id,
+  vax_frame_prev_register,
+  NULL,
+  default_frame_sniffer
+};
+\f
+
+static CORE_ADDR
+vax_frame_base_address (struct frame_info *this_frame, void **this_cache)
+{
+  struct vax_frame_cache *cache = vax_frame_cache (this_frame, this_cache);
+
+  return cache->base;
+}
+
+static CORE_ADDR
+vax_frame_args_address (struct frame_info *this_frame, void **this_cache)
+{
+  return get_frame_register_unsigned (this_frame, VAX_AP_REGNUM);
+}
+
+static const struct frame_base vax_frame_base =
+{
+  &vax_frame_unwind,
+  vax_frame_base_address,
+  vax_frame_base_address,
+  vax_frame_args_address
+};
+
+/* Return number of arguments for FRAME.  */
+
+static int
+vax_frame_num_args (struct frame_info *frame)
+{
+  CORE_ADDR args;
+
+  /* Assume that the argument pointer for the outermost frame is
+     hosed, as is the case on NetBSD/vax ELF.  */
+  if (get_frame_base_address (frame) == 0)
+    return 0;
+
+  args = get_frame_register_unsigned (frame, VAX_AP_REGNUM);
+  return get_frame_memory_unsigned (frame, args, 1);
+}
+
+\f
+
+/* Initialize the current architecture based on INFO.  If possible, re-use an
+   architecture from ARCHES, which is a list of architectures already created
+   during this debugging session.
+
+   Called e.g. at program startup, when reading a core file, and when reading
+   a binary file.  */
+
+static struct gdbarch *
+vax_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+{
+  struct gdbarch *gdbarch;
+
+  /* If there is already a candidate, use it.  */
+  arches = gdbarch_list_lookup_by_info (arches, &info);
+  if (arches != NULL)
+    return arches->gdbarch;
+
+  gdbarch = gdbarch_alloc (&info, NULL);
+
+  set_gdbarch_float_format (gdbarch, floatformats_vax_f);
+  set_gdbarch_double_format (gdbarch, floatformats_vax_d);
+  set_gdbarch_long_double_format (gdbarch, floatformats_vax_d);
+  set_gdbarch_long_double_bit (gdbarch, 64);
+
+  /* Register info */
+  set_gdbarch_num_regs (gdbarch, VAX_NUM_REGS);
+  set_gdbarch_register_name (gdbarch, vax_register_name);
+  set_gdbarch_register_type (gdbarch, vax_register_type);
+  set_gdbarch_sp_regnum (gdbarch, VAX_SP_REGNUM);
+  set_gdbarch_pc_regnum (gdbarch, VAX_PC_REGNUM);
+  set_gdbarch_ps_regnum (gdbarch, VAX_PS_REGNUM);
+
+  set_gdbarch_iterate_over_regset_sections
+    (gdbarch, vax_iterate_over_regset_sections);
+
+  /* Frame and stack info */
+  set_gdbarch_skip_prologue (gdbarch, vax_skip_prologue);
+  set_gdbarch_frame_num_args (gdbarch, vax_frame_num_args);
+  set_gdbarch_frame_args_skip (gdbarch, 4);
+
+  /* Stack grows downward.  */
+  set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+
+  /* Return value info */
+  set_gdbarch_return_value (gdbarch, vax_return_value);
+
+  /* Call dummy code.  */
+  set_gdbarch_push_dummy_call (gdbarch, vax_push_dummy_call);
+  set_gdbarch_dummy_id (gdbarch, vax_dummy_id);
+
+  /* Breakpoint info */
+  set_gdbarch_breakpoint_kind_from_pc (gdbarch, vax_breakpoint::kind_from_pc);
+  set_gdbarch_sw_breakpoint_from_kind (gdbarch, vax_breakpoint::bp_from_kind);
+
+  /* Misc info */
+  set_gdbarch_deprecated_function_start_offset (gdbarch, 2);
+  set_gdbarch_believe_pcc_promotion (gdbarch, 1);
+
+  frame_base_set_default (gdbarch, &vax_frame_base);
+
+  /* Hook in ABI-specific overrides, if they have been registered.  */
+  gdbarch_init_osabi (info, gdbarch);
+
+  frame_unwind_append_unwinder (gdbarch, &vax_frame_unwind);
+
+  return (gdbarch);
 }
 
 void
-_initialize_vax_tdep ()
+_initialize_vax_tdep (void)
 {
-  tm_print_insn = vax_print_insn;
+  gdbarch_register (bfd_arch_vax, vax_gdbarch_init, NULL);
 }
This page took 0.037744 seconds and 4 git commands to generate.