2002-04-17 Michael Chastain <mec@shout.net>
[deliverable/binutils-gdb.git] / gdb / alpha-tdep.c
index 664b131ab828d2f70b166455354a2f06efabb3c2..4ca6bcc3884fc66ebe29534eabafae0c11a0a436 100644 (file)
@@ -1,5 +1,6 @@
 /* Target-dependent code for the ALPHA architecture, for GDB, the GNU Debugger.
-   Copyright 1993, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+   Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "symfile.h"
 #include "objfiles.h"
 #include "gdb_string.h"
+#include "linespec.h"
+#include "regcache.h"
+#include "doublest.h"
+
+struct frame_extra_info
+  {
+    alpha_extra_func_info_t proc_desc;
+    int localoff;
+    int pc_reg;
+  };
 
 /* FIXME: Some of this code should perhaps be merged with mips-tdep.c.  */
 
 /* Prototypes for local functions. */
 
-static alpha_extra_func_info_t push_sigtramp_desc PARAMS ((CORE_ADDR low_addr));
+static void alpha_find_saved_regs (struct frame_info *);
 
-static CORE_ADDR read_next_frame_reg PARAMS ((struct frame_info *, int));
+static alpha_extra_func_info_t push_sigtramp_desc (CORE_ADDR low_addr);
 
-static CORE_ADDR heuristic_proc_start PARAMS ((CORE_ADDR));
+static CORE_ADDR read_next_frame_reg (struct frame_info *, int);
 
-static alpha_extra_func_info_t heuristic_proc_desc PARAMS ((CORE_ADDR,
-                                                           CORE_ADDR,
-                                                     struct frame_info *));
+static CORE_ADDR heuristic_proc_start (CORE_ADDR);
 
-static alpha_extra_func_info_t find_proc_desc PARAMS ((CORE_ADDR,
-                                                      struct frame_info *));
+static alpha_extra_func_info_t heuristic_proc_desc (CORE_ADDR,
+                                                   CORE_ADDR,
+                                                   struct frame_info *);
+
+static alpha_extra_func_info_t find_proc_desc (CORE_ADDR,
+                                              struct frame_info *);
 
 #if 0
-static int alpha_in_lenient_prologue PARAMS ((CORE_ADDR, CORE_ADDR));
+static int alpha_in_lenient_prologue (CORE_ADDR, CORE_ADDR);
 #endif
 
-static void reinit_frame_cache_sfunc PARAMS ((char *, int,
-                                             struct cmd_list_element *));
+static void reinit_frame_cache_sfunc (char *, int, struct cmd_list_element *);
 
-static CORE_ADDR after_prologue PARAMS ((CORE_ADDR pc,
-                                        alpha_extra_func_info_t proc_desc));
+static CORE_ADDR after_prologue (CORE_ADDR pc,
+                                alpha_extra_func_info_t proc_desc);
 
-static int alpha_in_prologue PARAMS ((CORE_ADDR pc,
-                                     alpha_extra_func_info_t proc_desc));
+static int alpha_in_prologue (CORE_ADDR pc,
+                             alpha_extra_func_info_t proc_desc);
 
-static int alpha_about_to_return PARAMS ((CORE_ADDR pc));
+static int alpha_about_to_return (CORE_ADDR pc);
 
-void _initialize_alpha_tdep PARAMS ((void));
+void _initialize_alpha_tdep (void);
 
 /* Heuristic_proc_start may hunt through the text section for a long
    time across a 2400 baud serial line.  Allows the user to limit this
@@ -141,6 +153,11 @@ struct linked_proc_info
   }
  *linked_proc_desc_table = NULL;
 \f
+int
+alpha_osf_in_sigtramp (CORE_ADDR pc, char *func_name)
+{
+  return (func_name != NULL && STREQ ("__sigtramp", func_name));
+}
 
 /* Under GNU/Linux, signal handler invocations can be identified by the
    designated code sequence that is used to return from a signal
@@ -169,11 +186,10 @@ struct linked_proc_info
 #ifndef TM_LINUXALPHA_H
 /* HACK: Provide a prototype when compiling this file for non
    linuxalpha targets. */
-long alpha_linux_sigtramp_offset PARAMS ((CORE_ADDR pc));
+long alpha_linux_sigtramp_offset (CORE_ADDR pc);
 #endif
 long
-alpha_linux_sigtramp_offset (pc)
-     CORE_ADDR pc;
+alpha_linux_sigtramp_offset (CORE_ADDR pc)
 {
   unsigned int i[3], w;
   long off;
@@ -216,9 +232,7 @@ alpha_linux_sigtramp_offset (pc)
 /* Under OSF/1, the __sigtramp routine is frameless and has a frame
    size of zero, but we are able to backtrace through it.  */
 CORE_ADDR
-alpha_osf_skip_sigtramp_frame (frame, pc)
-     struct frame_info *frame;
-     CORE_ADDR pc;
+alpha_osf_skip_sigtramp_frame (struct frame_info *frame, CORE_ADDR pc)
 {
   char *name;
   find_pc_partial_function (pc, &name, (CORE_ADDR *) NULL, (CORE_ADDR *) NULL);
@@ -234,8 +248,7 @@ alpha_osf_skip_sigtramp_frame (frame, pc)
    descriptor is added to the linked_proc_desc_table.  */
 
 static alpha_extra_func_info_t
-push_sigtramp_desc (low_addr)
-     CORE_ADDR low_addr;
+push_sigtramp_desc (CORE_ADDR low_addr)
 {
   struct linked_proc_info *link;
   alpha_extra_func_info_t proc_desc;
@@ -262,12 +275,78 @@ push_sigtramp_desc (low_addr)
 }
 \f
 
+char *
+alpha_register_name (int regno)
+{
+  static char *register_names[] =
+  {
+    "v0",   "t0",   "t1",   "t2",   "t3",   "t4",   "t5",   "t6",
+    "t7",   "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "fp",
+    "a0",   "a1",   "a2",   "a3",   "a4",   "a5",   "t8",   "t9",
+    "t10",  "t11",  "ra",   "t12",  "at",   "gp",   "sp",   "zero",
+    "f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7",
+    "f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15",
+    "f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",
+    "f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "fpcr",
+    "pc",   "vfp",
+  };
+
+  if (regno < 0)
+    return (NULL);
+  if (regno >= (sizeof(register_names) / sizeof(*register_names)))
+    return (NULL);
+  return (register_names[regno]);
+}
+
+int
+alpha_cannot_fetch_register (int regno)
+{
+  return (regno == FP_REGNUM || regno == ZERO_REGNUM);
+}
+
+int
+alpha_cannot_store_register (int regno)
+{
+  return (regno == FP_REGNUM || regno == ZERO_REGNUM);
+}
+
+int
+alpha_register_convertible (int regno)
+{
+  return (regno >= FP0_REGNUM && regno <= FP0_REGNUM + 31);
+}
+
+struct type *
+alpha_register_virtual_type (int regno)
+{
+  return ((regno >= FP0_REGNUM && regno < (FP0_REGNUM+31))
+         ? builtin_type_double : builtin_type_long);
+}
+
+int
+alpha_register_byte (int regno)
+{
+  return (regno * 8);
+}
+
+int
+alpha_register_raw_size (int regno)
+{
+  return 8;
+}
+
+int
+alpha_register_virtual_size (int regno)
+{
+  return 8;
+}
+\f
+
 /* Guaranteed to set frame->saved_regs to some values (it never leaves it
    NULL).  */
 
-void
-alpha_find_saved_regs (frame)
-     struct frame_info *frame;
+static void
+alpha_find_saved_regs (struct frame_info *frame)
 {
   int ireg;
   CORE_ADDR reg_position;
@@ -306,7 +385,7 @@ alpha_find_saved_regs (frame)
       return;
     }
 
-  proc_desc = frame->proc_desc;
+  proc_desc = frame->extra_info->proc_desc;
   if (proc_desc == NULL)
     /* I'm not sure how/whether this can happen.  Normally when we can't
        find a proc_desc, we "synthesize" one using heuristic_proc_desc
@@ -354,10 +433,23 @@ alpha_find_saved_regs (frame)
   frame->saved_regs[PC_REGNUM] = frame->saved_regs[returnreg];
 }
 
+void
+alpha_frame_init_saved_regs (struct frame_info *fi)
+{
+  if (fi->saved_regs == NULL)
+    alpha_find_saved_regs (fi);
+  fi->saved_regs[SP_REGNUM] = fi->frame;
+}
+
+void
+alpha_init_frame_pc_first (int fromleaf, struct frame_info *prev)
+{
+  prev->pc = (fromleaf ? SAVED_PC_AFTER_CALL (prev->next) :
+             prev->next ? FRAME_SAVED_PC (prev->next) : read_pc ());
+}
+
 static CORE_ADDR
-read_next_frame_reg (fi, regno)
-     struct frame_info *fi;
-     int regno;
+read_next_frame_reg (struct frame_info *fi, int regno)
 {
   for (; fi; fi = fi->next)
     {
@@ -377,13 +469,13 @@ read_next_frame_reg (fi, regno)
 }
 
 CORE_ADDR
-alpha_frame_saved_pc (frame)
-     struct frame_info *frame;
+alpha_frame_saved_pc (struct frame_info *frame)
 {
-  alpha_extra_func_info_t proc_desc = frame->proc_desc;
+  alpha_extra_func_info_t proc_desc = frame->extra_info->proc_desc;
   /* We have to get the saved pc from the sigcontext
      if it is a signal handler frame.  */
-  int pcreg = frame->signal_handler_caller ? PC_REGNUM : frame->pc_reg;
+  int pcreg = frame->signal_handler_caller ? PC_REGNUM
+                                           : frame->extra_info->pc_reg;
 
   if (proc_desc && PROC_DESC_IS_DUMMY (proc_desc))
     return read_memory_integer (frame->frame - 8, 8);
@@ -392,8 +484,7 @@ alpha_frame_saved_pc (frame)
 }
 
 CORE_ADDR
-alpha_saved_pc_after_call (frame)
-     struct frame_info *frame;
+alpha_saved_pc_after_call (struct frame_info *frame)
 {
   CORE_ADDR pc = frame->pc;
   CORE_ADDR tmp;
@@ -416,14 +507,13 @@ alpha_saved_pc_after_call (frame)
 
 
 static struct alpha_extra_func_info temp_proc_desc;
-static struct frame_saved_regs temp_saved_regs;
+static CORE_ADDR temp_saved_regs[NUM_REGS];
 
 /* Nonzero if instruction at PC is a return instruction.  "ret
    $zero,($ra),1" on alpha. */
 
 static int
-alpha_about_to_return (pc)
-     CORE_ADDR pc;
+alpha_about_to_return (CORE_ADDR pc)
 {
   return read_memory_integer (pc, 4) == 0x6bfa8001;
 }
@@ -435,8 +525,7 @@ alpha_about_to_return (pc)
    lines.  */
 
 static CORE_ADDR
-heuristic_proc_start (pc)
-     CORE_ADDR pc;
+heuristic_proc_start (CORE_ADDR pc)
 {
   CORE_ADDR start_pc = pc;
   CORE_ADDR fence = start_pc - heuristic_fence_post;
@@ -465,7 +554,7 @@ heuristic_proc_start (pc)
            else
              warning ("Hit heuristic-fence-post without finding");
 
-           warning ("enclosing function for address 0x%lx", pc);
+           warning ("enclosing function for address 0x%s", paddr_nz (pc));
            if (!blurb_printed)
              {
                printf_filtered ("\
@@ -489,9 +578,8 @@ Otherwise, you told GDB there was a function where there isn't one, or\n\
 }
 
 static alpha_extra_func_info_t
-heuristic_proc_desc (start_pc, limit_pc, next_frame)
-     CORE_ADDR start_pc, limit_pc;
-     struct frame_info *next_frame;
+heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
+                    struct frame_info *next_frame)
 {
   CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM);
   CORE_ADDR cur_pc;
@@ -503,7 +591,7 @@ heuristic_proc_desc (start_pc, limit_pc, next_frame)
   if (start_pc == 0)
     return NULL;
   memset (&temp_proc_desc, '\0', sizeof (temp_proc_desc));
-  memset (&temp_saved_regs, '\0', sizeof (struct frame_saved_regs));
+  memset (&temp_saved_regs, '\0', SIZEOF_FRAME_SAVED_REGS);
   PROC_LOW_ADDR (&temp_proc_desc) = start_pc;
 
   if (start_pc + 200 < limit_pc)
@@ -535,7 +623,7 @@ heuristic_proc_desc (start_pc, limit_pc, next_frame)
        {
          int reg = (word & 0x03e00000) >> 21;
          reg_mask |= 1 << reg;
-         temp_saved_regs.regs[reg] = sp + (short) word;
+         temp_saved_regs[reg] = sp + (short) word;
 
          /* Starting with OSF/1-3.2C, the system libraries are shipped
             without local symbols, but they still contain procedure
@@ -613,9 +701,7 @@ heuristic_proc_desc (start_pc, limit_pc, next_frame)
    find the prologue, then return 0.  */
 
 static CORE_ADDR
-after_prologue (pc, proc_desc)
-     CORE_ADDR pc;
-     alpha_extra_func_info_t proc_desc;
+after_prologue (CORE_ADDR pc, alpha_extra_func_info_t proc_desc)
 {
   struct symtab_and_line sal;
   CORE_ADDR func_addr, func_end;
@@ -653,9 +739,7 @@ after_prologue (pc, proc_desc)
    are definitively *not* in a function prologue.  */
 
 static int
-alpha_in_prologue (pc, proc_desc)
-     CORE_ADDR pc;
-     alpha_extra_func_info_t proc_desc;
+alpha_in_prologue (CORE_ADDR pc, alpha_extra_func_info_t proc_desc)
 {
   CORE_ADDR after_prologue_pc;
 
@@ -669,9 +753,7 @@ alpha_in_prologue (pc, proc_desc)
 }
 
 static alpha_extra_func_info_t
-find_proc_desc (pc, next_frame)
-     CORE_ADDR pc;
-     struct frame_info *next_frame;
+find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame)
 {
   alpha_extra_func_info_t proc_desc;
   struct block *b;
@@ -793,8 +875,7 @@ find_proc_desc (pc, next_frame)
 alpha_extra_func_info_t cached_proc_desc;
 
 CORE_ADDR
-alpha_frame_chain (frame)
-     struct frame_info *frame;
+alpha_frame_chain (struct frame_info *frame)
 {
   alpha_extra_func_info_t proc_desc;
   CORE_ADDR saved_pc = FRAME_SAVED_PC (frame);
@@ -828,24 +909,38 @@ alpha_frame_chain (frame)
 }
 
 void
-init_extra_frame_info (frame)
-     struct frame_info *frame;
+alpha_print_extra_frame_info (struct frame_info *fi)
+{
+  if (fi
+      && fi->extra_info
+      && fi->extra_info->proc_desc
+      && fi->extra_info->proc_desc->pdr.framereg < NUM_REGS)
+    printf_filtered (" frame pointer is at %s+%s\n",
+                    REGISTER_NAME (fi->extra_info->proc_desc->pdr.framereg),
+                    paddr_d (fi->extra_info->proc_desc->pdr.frameoffset));
+}
+
+void
+alpha_init_extra_frame_info (int fromleaf, struct frame_info *frame)
 {
   /* Use proc_desc calculated in frame_chain */
   alpha_extra_func_info_t proc_desc =
   frame->next ? cached_proc_desc : find_proc_desc (frame->pc, frame->next);
 
+  frame->extra_info = (struct frame_extra_info *)
+    frame_obstack_alloc (sizeof (struct frame_extra_info));
+
   frame->saved_regs = NULL;
-  frame->localoff = 0;
-  frame->pc_reg = RA_REGNUM;
-  frame->proc_desc = proc_desc == &temp_proc_desc ? 0 : proc_desc;
+  frame->extra_info->localoff = 0;
+  frame->extra_info->pc_reg = RA_REGNUM;
+  frame->extra_info->proc_desc = proc_desc == &temp_proc_desc ? 0 : proc_desc;
   if (proc_desc)
     {
       /* Get the locals offset and the saved pc register from the
          procedure descriptor, they are valid even if we are in the
          middle of the prologue.  */
-      frame->localoff = PROC_LOCALOFF (proc_desc);
-      frame->pc_reg = PROC_PC_REG (proc_desc);
+      frame->extra_info->localoff = PROC_LOCALOFF (proc_desc);
+      frame->extra_info->pc_reg = PROC_PC_REG (proc_desc);
 
       /* Fixup frame-pointer - only needed for top frame */
 
@@ -877,7 +972,8 @@ init_extra_frame_info (frame)
            {
              frame->saved_regs = (CORE_ADDR *)
                frame_obstack_alloc (SIZEOF_FRAME_SAVED_REGS);
-             memcpy (frame->saved_regs, temp_saved_regs.regs, SIZEOF_FRAME_SAVED_REGS);
+             memcpy (frame->saved_regs, temp_saved_regs,
+                     SIZEOF_FRAME_SAVED_REGS);
              frame->saved_regs[PC_REGNUM]
                = frame->saved_regs[RA_REGNUM];
            }
@@ -885,6 +981,18 @@ init_extra_frame_info (frame)
     }
 }
 
+CORE_ADDR
+alpha_frame_locals_address (struct frame_info *fi)
+{
+  return (fi->frame - fi->extra_info->localoff);
+}
+
+CORE_ADDR
+alpha_frame_args_address (struct frame_info *fi)
+{
+  return (fi->frame - (ALPHA_NUM_ARG_REGS * 8));
+}
+
 /* ALPHA stack frames are almost impenetrable.  When execution stops,
    we basically have to look at symbol information for the function
    that we stopped in, which tells us *which* register (if any) is
@@ -901,9 +1009,7 @@ init_extra_frame_info (frame)
    arguments without difficulty.  */
 
 struct frame_info *
-setup_arbitrary_frame (argc, argv)
-     int argc;
-     CORE_ADDR *argv;
+setup_arbitrary_frame (int argc, CORE_ADDR *argv)
 {
   if (argc != 2)
     error ("ALPHA frame specifications require two arguments: sp and pc");
@@ -922,12 +1028,8 @@ setup_arbitrary_frame (argc, argv)
    structure to be returned is passed as a hidden first argument.  */
 
 CORE_ADDR
-alpha_push_arguments (nargs, args, sp, struct_return, struct_addr)
-     int nargs;
-     value_ptr *args;
-     CORE_ADDR sp;
-     int struct_return;
-     CORE_ADDR struct_addr;
+alpha_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
+                     int struct_return, CORE_ADDR struct_addr)
 {
   int i;
   int accumulate_size = struct_return ? 8 : 0;
@@ -946,7 +1048,7 @@ alpha_push_arguments (nargs, args, sp, struct_return, struct_addr)
 
   for (i = 0, m_arg = alpha_args; i < nargs; i++, m_arg++)
     {
-      value_ptr arg = args[i];
+      struct value *arg = args[i];
       struct type *arg_type = check_typedef (VALUE_TYPE (arg));
       /* Cast argument to long if necessary as the compiler does it too.  */
       switch (TYPE_CODE (arg_type))
@@ -1008,7 +1110,7 @@ alpha_push_arguments (nargs, args, sp, struct_return, struct_addr)
 }
 
 void
-alpha_push_dummy_frame ()
+alpha_push_dummy_frame (void)
 {
   int ireg;
   struct linked_proc_info *link;
@@ -1124,13 +1226,13 @@ alpha_push_dummy_frame ()
 }
 
 void
-alpha_pop_frame ()
+alpha_pop_frame (void)
 {
   register int regnum;
   struct frame_info *frame = get_current_frame ();
   CORE_ADDR new_sp = frame->frame;
 
-  alpha_extra_func_info_t proc_desc = frame->proc_desc;
+  alpha_extra_func_info_t proc_desc = frame->extra_info->proc_desc;
 
   /* we need proc_desc to know how to restore the registers;
      if it is NULL, construct (a temporary) one */
@@ -1180,7 +1282,7 @@ alpha_pop_frame ()
       else
        linked_proc_desc_table = pi_ptr->next;
 
-      free (pi_ptr);
+      xfree (pi_ptr);
     }
 }
 \f
@@ -1190,13 +1292,11 @@ alpha_pop_frame ()
    LENIENT, then we must skip everything which is involved in setting
    up the frame (it's OK to skip more, just so long as we don't skip
    anything which might clobber the registers which are being saved.
-   Currently we must not skip more on the alpha, but we might the lenient
-   stuff some day.  */
+   Currently we must not skip more on the alpha, but we might need the
+   lenient stuff some day.  */
 
-CORE_ADDR
-alpha_skip_prologue (pc, lenient)
-     CORE_ADDR pc;
-     int lenient;
+static CORE_ADDR
+alpha_skip_prologue_internal (CORE_ADDR pc, int lenient)
 {
   unsigned long inst;
   int offset;
@@ -1268,16 +1368,20 @@ alpha_skip_prologue (pc, lenient)
   return pc + offset;
 }
 
+CORE_ADDR
+alpha_skip_prologue (CORE_ADDR addr)
+{
+  return (alpha_skip_prologue_internal (addr, 0));
+}
+
 #if 0
 /* Is address PC in the prologue (loosely defined) for function at
    STARTADDR?  */
 
 static int
-alpha_in_lenient_prologue (startaddr, pc)
-     CORE_ADDR startaddr;
-     CORE_ADDR pc;
+alpha_in_lenient_prologue (CORE_ADDR startaddr, CORE_ADDR pc)
 {
-  CORE_ADDR end_prologue = alpha_skip_prologue (startaddr, 1);
+  CORE_ADDR end_prologue = alpha_skip_prologue_internal (startaddr, 1);
   return pc >= startaddr && pc < end_prologue;
 }
 #endif
@@ -1289,11 +1393,8 @@ alpha_in_lenient_prologue (startaddr, pc)
    memory format is an integer with 4 bytes or less, as the representation
    of integers in floating point registers is different. */
 void
-alpha_register_convert_to_virtual (regnum, valtype, raw_buffer, virtual_buffer)
-     int regnum;
-     struct type *valtype;
-     char *raw_buffer;
-     char *virtual_buffer;
+alpha_register_convert_to_virtual (int regnum, struct type *valtype,
+                                  char *raw_buffer, char *virtual_buffer)
 {
   if (TYPE_LENGTH (valtype) >= REGISTER_RAW_SIZE (regnum))
     {
@@ -1318,11 +1419,8 @@ alpha_register_convert_to_virtual (regnum, valtype, raw_buffer, virtual_buffer)
 }
 
 void
-alpha_register_convert_to_raw (valtype, regnum, virtual_buffer, raw_buffer)
-     struct type *valtype;
-     int regnum;
-     char *virtual_buffer;
-     char *raw_buffer;
+alpha_register_convert_to_raw (struct type *valtype, int regnum,
+                              char *virtual_buffer, char *raw_buffer)
 {
   if (TYPE_LENGTH (valtype) >= REGISTER_RAW_SIZE (regnum))
     {
@@ -1353,10 +1451,8 @@ alpha_register_convert_to_raw (valtype, regnum, virtual_buffer, raw_buffer)
    extract and copy its value into `valbuf'.  */
 
 void
-alpha_extract_return_value (valtype, regbuf, valbuf)
-     struct type *valtype;
-     char regbuf[REGISTER_BYTES];
-     char *valbuf;
+alpha_extract_return_value (struct type *valtype,
+                           char regbuf[REGISTER_BYTES], char *valbuf)
 {
   if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
     alpha_register_convert_to_virtual (FP0_REGNUM, valtype,
@@ -1370,9 +1466,7 @@ alpha_extract_return_value (valtype, regbuf, valbuf)
    write its value into the appropriate register.  */
 
 void
-alpha_store_return_value (valtype, valbuf)
-     struct type *valtype;
-     char *valbuf;
+alpha_store_return_value (struct type *valtype, char *valbuf)
 {
   char raw_buffer[MAX_REGISTER_RAW_SIZE];
   int regnum = V0_REGNUM;
@@ -1394,10 +1488,7 @@ alpha_store_return_value (valtype, valbuf)
    callable as an sfunc.  */
 
 static void
-reinit_frame_cache_sfunc (args, from_tty, c)
-     char *args;
-     int from_tty;
-     struct cmd_list_element *c;
+reinit_frame_cache_sfunc (char *args, int from_tty, struct cmd_list_element *c)
 {
   reinit_frame_cache ();
 }
@@ -1408,7 +1499,7 @@ reinit_frame_cache_sfunc (args, from_tty, c)
  */
 
 CORE_ADDR
-alpha_call_dummy_address ()
+alpha_call_dummy_address (void)
 {
   CORE_ADDR entry;
   struct minimal_symbol *sym;
@@ -1427,7 +1518,154 @@ alpha_call_dummy_address ()
 }
 
 void
-_initialize_alpha_tdep ()
+alpha_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
+                      struct value **args, struct type *type, int gcc_p)
+{
+  CORE_ADDR bp_address = CALL_DUMMY_ADDRESS ();
+
+  if (bp_address == 0)
+    error ("no place to put call");
+  write_register (RA_REGNUM, bp_address);
+  write_register (T12_REGNUM, fun);
+}
+
+/* On the Alpha, the call dummy code is nevery copied to user space
+   (see alpha_fix_call_dummy() above).  The contents of this do not
+   matter.  */
+LONGEST alpha_call_dummy_words[] = { 0 };
+
+int
+alpha_use_struct_convention (int gcc_p, struct type *type)
+{
+  /* Structures are returned by ref in extra arg0.  */
+  return 1;
+}
+
+void
+alpha_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
+{
+  /* Store the address of the place in which to copy the structure the
+     subroutine will return.  Handled by alpha_push_arguments.  */
+}
+
+CORE_ADDR
+alpha_extract_struct_value_address (char *regbuf)
+{
+  return (extract_address (regbuf + REGISTER_BYTE (V0_REGNUM),
+                          REGISTER_RAW_SIZE (V0_REGNUM)));
+}
+
+/* alpha_software_single_step() is called just before we want to resume
+   the inferior, if we want to single-step it but there is no hardware
+   or kernel single-step support (NetBSD on Alpha, for example).  We find
+   the target of the coming instruction and breakpoint it.
+
+   single_step is also called just after the inferior stops.  If we had
+   set up a simulated single-step, we undo our damage.  */
+
+static CORE_ADDR
+alpha_next_pc (CORE_ADDR pc)
+{
+  unsigned int insn;
+  unsigned int op;
+  int offset;
+  LONGEST rav;
+
+  insn = read_memory_unsigned_integer (pc, sizeof (insn));
+
+  /* Opcode is top 6 bits. */
+  op = (insn >> 26) & 0x3f;
+
+  if (op == 0x1a)
+    {
+      /* Jump format: target PC is:
+        RB & ~3  */
+      return (read_register ((insn >> 16) & 0x1f) & ~3);
+    }
+
+  if ((op & 0x30) == 0x30)
+    {
+      /* Branch format: target PC is:
+        (new PC) + (4 * sext(displacement))  */
+      if (op == 0x30 ||                /* BR */
+         op == 0x34)           /* BSR */
+       {
+ branch_taken:
+          offset = (insn & 0x001fffff);
+         if (offset & 0x00100000)
+           offset  |= 0xffe00000;
+         offset *= 4;
+         return (pc + 4 + offset);
+       }
+
+      /* Need to determine if branch is taken; read RA.  */
+      rav = (LONGEST) read_register ((insn >> 21) & 0x1f);
+      switch (op)
+       {
+       case 0x38:              /* BLBC */
+         if ((rav & 1) == 0)
+           goto branch_taken;
+         break;
+       case 0x3c:              /* BLBS */
+         if (rav & 1)
+           goto branch_taken;
+         break;
+       case 0x39:              /* BEQ */
+         if (rav == 0)
+           goto branch_taken;
+         break;
+       case 0x3d:              /* BNE */
+         if (rav != 0)
+           goto branch_taken;
+         break;
+       case 0x3a:              /* BLT */
+         if (rav < 0)
+           goto branch_taken;
+         break;
+       case 0x3b:              /* BLE */
+         if (rav <= 0)
+           goto branch_taken;
+         break;
+       case 0x3f:              /* BGT */
+         if (rav > 0)
+           goto branch_taken;
+         break;
+       case 0x3e:              /* BGE */
+         if (rav >= 0)
+           goto branch_taken;
+         break;
+       }
+    }
+
+  /* Not a branch or branch not taken; target PC is:
+     pc + 4  */
+  return (pc + 4);
+}
+
+void
+alpha_software_single_step (enum target_signal sig, int insert_breakpoints_p)
+{
+  static CORE_ADDR next_pc;
+  typedef char binsn_quantum[BREAKPOINT_MAX];
+  static binsn_quantum break_mem;
+  CORE_ADDR pc;
+
+  if (insert_breakpoints_p)
+    {
+      pc = read_pc ();
+      next_pc = alpha_next_pc (pc);
+
+      target_insert_breakpoint (next_pc, break_mem);
+    }
+  else
+    {
+      target_remove_breakpoint (next_pc, break_mem);
+      write_pc (next_pc);
+    }
+}
+
+void
+_initialize_alpha_tdep (void)
 {
   struct cmd_list_element *c;
 
@@ -1448,6 +1686,6 @@ search.  The only need to set it is when debugging a stripped executable.",
                   &setlist);
   /* We need to throw away the frame cache when we set this, since it
      might change our ability to get backtraces.  */
-  c->function.sfunc = reinit_frame_cache_sfunc;
+  set_cmd_sfunc (c, reinit_frame_cache_sfunc);
   add_show_from_set (c, &showlist);
 }
This page took 0.03338 seconds and 4 git commands to generate.