* Makefile.in (eelf32ppc.c): Depend upon elf32.em, not generic.em.
[deliverable/binutils-gdb.git] / gdb / alpha-tdep.c
index 81061d35ae677cc9c79a0e33cfd0c45359e03d8f..f3ba0eb3e83616417a06c4f11ec0dd866d4b9488 100644 (file)
@@ -1,5 +1,5 @@
 /* Target-dependent code for the ALPHA architecture, for GDB, the GNU Debugger.
-   Copyright 1993, 1994 Free Software Foundation, Inc.
+   Copyright 1993, 1994, 1995 Free Software Foundation, Inc.
 
 This file is part of GDB.
 
@@ -15,7 +15,7 @@ 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, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
 #include "frame.h"
@@ -25,31 +25,41 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "gdbcmd.h"
 #include "gdbcore.h"
 #include "dis-asm.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdb_string.h"
 
 /* FIXME: Some of this code should perhaps be merged with mips-tdep.c.  */
 
-#define VM_MIN_ADDRESS (CORE_ADDR)0x120000000
+/* FIXME: Put this declaration in frame.h.  */
+extern struct obstack frame_cache_obstack;
 \f
 
 /* Forward declarations.  */
 
-static CORE_ADDR
-read_next_frame_reg PARAMS ((FRAME, int));
+static CORE_ADDR read_next_frame_reg PARAMS ((struct frame_info *, int));
 
-static CORE_ADDR
-heuristic_proc_start PARAMS ((CORE_ADDR));
+static CORE_ADDR heuristic_proc_start PARAMS ((CORE_ADDR));
 
-static alpha_extra_func_info_t
-heuristic_proc_desc PARAMS ((CORE_ADDR, CORE_ADDR, FRAME));
+static alpha_extra_func_info_t heuristic_proc_desc PARAMS ((CORE_ADDR,
+                                                           CORE_ADDR,
+                                                           struct frame_info *));
 
-static alpha_extra_func_info_t
-find_proc_desc PARAMS ((CORE_ADDR, FRAME));
+static alpha_extra_func_info_t find_proc_desc PARAMS ((CORE_ADDR,
+                                                      struct frame_info *));
 
-static int
-alpha_in_lenient_prologue PARAMS ((CORE_ADDR, CORE_ADDR));
+#if 0
+static int alpha_in_lenient_prologue PARAMS ((CORE_ADDR, CORE_ADDR));
+#endif
 
-static void
-reinit_frame_cache_sfunc PARAMS ((char *, int, struct cmd_list_element *));
+static void reinit_frame_cache_sfunc PARAMS ((char *, int,
+                                             struct cmd_list_element *));
+
+static CORE_ADDR after_prologue PARAMS ((CORE_ADDR pc,
+                                        alpha_extra_func_info_t proc_desc));
+
+static int in_prologue PARAMS ((CORE_ADDR pc,
+                               alpha_extra_func_info_t proc_desc));
 
 /* 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
@@ -122,53 +132,135 @@ struct linked_proc_info
 } *linked_proc_desc_table = NULL;
 
 \f
-#define READ_FRAME_REG(fi, regno) read_next_frame_reg((fi)->next, regno)
+/* Guaranteed to set fci->saved_regs to some values (it never leaves it
+   NULL).  */
 
-static CORE_ADDR
-read_next_frame_reg(fi, regno)
-     FRAME fi;
-     int regno;
+void
+alpha_find_saved_regs (frame)
+     struct frame_info *frame;
 {
-  /* If it is the frame for sigtramp we have a pointer to the sigcontext
-     on the stack.
-     If the stack layout for __sigtramp changes or if sigcontext offsets
-     change we might have to update this code.  */
+  int ireg;
+  CORE_ADDR reg_position;
+  unsigned long mask;
+  alpha_extra_func_info_t proc_desc;
+  int returnreg;
+
+  frame->saved_regs = (struct frame_saved_regs *)
+    obstack_alloc (&frame_cache_obstack, sizeof(struct frame_saved_regs));
+  memset (frame->saved_regs, 0, sizeof (struct frame_saved_regs));
+
+  /* If it is the frame for __sigtramp, the saved registers are located
+     in a sigcontext structure somewhere on the stack. __sigtramp
+     passes a pointer to the sigcontext structure on the stack.
+     If the stack layout for __sigtramp changes, or if sigcontext offsets
+     change, we might have to update this code.  */
 #ifndef SIGFRAME_PC_OFF
 #define SIGFRAME_PC_OFF                (2 * 8)
 #define SIGFRAME_REGSAVE_OFF   (4 * 8)
+#define SIGFRAME_FPREGSAVE_OFF (SIGFRAME_REGSAVE_OFF + 32 * 8 + 8)
 #endif
-  for (; fi; fi = fi->next)
+  if (frame->signal_handler_caller)
     {
-      if (fi->signal_handler_caller)
+      CORE_ADDR sigcontext_pointer_addr;
+      CORE_ADDR sigcontext_addr;
+
+      if (frame->next)
+       sigcontext_pointer_addr = frame->next->frame;
+      else
+       sigcontext_pointer_addr = frame->frame;
+      sigcontext_addr = read_memory_integer(sigcontext_pointer_addr, 8);
+      for (ireg = 0; ireg < 32; ireg++)
+       {
+         reg_position = sigcontext_addr + SIGFRAME_REGSAVE_OFF + ireg * 8;
+         frame->saved_regs->regs[ireg] = reg_position;
+       }
+      for (ireg = 0; ireg < 32; ireg++)
        {
-         int offset;
-         CORE_ADDR sigcontext_addr = read_memory_integer(fi->frame, 8);
-
-         if (regno == PC_REGNUM)
-           offset = SIGFRAME_PC_OFF;
-         else if (regno < 32)
-           offset = SIGFRAME_REGSAVE_OFF + regno * 8;
-         else
-           return 0;
-         return read_memory_integer(sigcontext_addr + offset, 8);
-        }
-      else if (regno == SP_REGNUM)
+         reg_position = sigcontext_addr + SIGFRAME_FPREGSAVE_OFF + ireg * 8;
+         frame->saved_regs->regs[FP0_REGNUM + ireg] = reg_position;
+       }
+      frame->saved_regs->regs[PC_REGNUM] = sigcontext_addr + SIGFRAME_PC_OFF;
+      return;
+    }
+
+  proc_desc = frame->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
+       and set the saved_regs right away.  */
+    return;
+
+  /* Fill in the offsets for the registers which gen_mask says
+     were saved.  */
+
+  reg_position = frame->frame + PROC_REG_OFFSET (proc_desc);
+  mask = PROC_REG_MASK (proc_desc);
+
+  returnreg = PROC_PC_REG (proc_desc);
+
+  /* Note that RA is always saved first, regardless of its actual
+     register number.  */
+  if (mask & (1 << returnreg))
+    {
+      frame->saved_regs->regs[returnreg] = reg_position;
+      reg_position += 8;
+      mask &= ~(1 << returnreg); /* Clear bit for RA so we
+                                   don't save again later. */
+    }
+
+  for (ireg = 0; ireg <= 31 ; ++ireg)
+    if (mask & (1 << ireg))
+      {
+       frame->saved_regs->regs[ireg] = reg_position;
+       reg_position += 8;
+      }
+
+  /* Fill in the offsets for the registers which float_mask says
+     were saved.  */
+
+  reg_position = frame->frame + PROC_FREG_OFFSET (proc_desc);
+  mask = PROC_FREG_MASK (proc_desc);
+
+  for (ireg = 0; ireg <= 31 ; ++ireg)
+    if (mask & (1 << ireg))
+      {
+       frame->saved_regs->regs[FP0_REGNUM+ireg] = reg_position;
+       reg_position += 8;
+      }
+
+  frame->saved_regs->regs[PC_REGNUM] = frame->saved_regs->regs[returnreg];
+}
+
+static CORE_ADDR
+read_next_frame_reg(fi, regno)
+     struct frame_info *fi;
+     int regno;
+{
+  for (; fi; fi = fi->next)
+    {
+      /* We have to get the saved sp from the sigcontext
+        if it is a signal handler frame.  */
+      if (regno == SP_REGNUM && !fi->signal_handler_caller)
        return fi->frame;
-      else if (fi->saved_regs->regs[regno])
-       return read_memory_integer(fi->saved_regs->regs[regno], 8);
+      else
+       {
+         if (fi->saved_regs == NULL)
+           alpha_find_saved_regs (fi);
+         if (fi->saved_regs->regs[regno])
+           return read_memory_integer(fi->saved_regs->regs[regno], 8);
+       }
     }
   return read_register(regno);
 }
 
 CORE_ADDR
 alpha_frame_saved_pc(frame)
-     FRAME frame;
+     struct frame_info *frame;
 {
   alpha_extra_func_info_t proc_desc = frame->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
-             : (proc_desc ? PROC_PC_REG(proc_desc) : RA_REGNUM);
+  int pcreg = frame->signal_handler_caller ? PC_REGNUM : frame->pc_reg;
 
   if (proc_desc && PROC_DESC_IS_DUMMY(proc_desc))
       return read_memory_integer(frame->frame - 8, 8);
@@ -178,10 +270,20 @@ alpha_frame_saved_pc(frame)
 
 CORE_ADDR
 alpha_saved_pc_after_call (frame)
-     FRAME frame;
+     struct frame_info *frame;
 {
-  alpha_extra_func_info_t proc_desc = find_proc_desc (frame->pc, frame->next);
-  int pcreg = proc_desc ? PROC_PC_REG (proc_desc) : RA_REGNUM;
+  CORE_ADDR pc = frame->pc;
+  CORE_ADDR tmp;
+  alpha_extra_func_info_t proc_desc;
+  int pcreg;
+
+  /* Skip over shared library trampoline if necessary.  */
+  tmp = SKIP_TRAMPOLINE_CODE (pc);
+  if (tmp != 0)
+    pc = tmp;
+
+  proc_desc = find_proc_desc (pc, frame->next);
+  pcreg = proc_desc ? PROC_PC_REG (proc_desc) : RA_REGNUM;
 
   return read_register (pcreg);
 }
@@ -250,9 +352,9 @@ 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;
-    FRAME next_frame;
+    struct frame_info *next_frame;
 {
-    CORE_ADDR sp = next_frame ? next_frame->frame : read_register (SP_REGNUM);
+    CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM);
     CORE_ADDR cur_pc;
     int frame_size;
     int has_frame_reg = 0;
@@ -260,9 +362,9 @@ 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));
-    PROC_LOW_ADDR(&temp_proc_desc) = start_pc;
+    memset (&temp_proc_desc, '\0', sizeof(temp_proc_desc));
+    memset (&temp_saved_regs, '\0', sizeof(struct frame_saved_regs));
+    PROC_LOW_ADDR (&temp_proc_desc) = start_pc;
 
     if (start_pc + 200 < limit_pc)
       limit_pc = start_pc + 200;
@@ -297,13 +399,70 @@ heuristic_proc_desc(start_pc, limit_pc, next_frame)
     PROC_FRAME_OFFSET(&temp_proc_desc) = frame_size;
     PROC_REG_MASK(&temp_proc_desc) = reg_mask;
     PROC_PC_REG(&temp_proc_desc) = RA_REGNUM;
+    PROC_LOCALOFF(&temp_proc_desc) = 0;        /* XXX - bogus */
     return &temp_proc_desc;
 }
 
+/* This returns the PC of the first inst after the prologue.  If we can't
+   find the prologue, then return 0.  */
+
+static CORE_ADDR
+after_prologue (pc, proc_desc)
+     CORE_ADDR pc;
+     alpha_extra_func_info_t proc_desc;
+{
+  struct symtab_and_line sal;
+  CORE_ADDR func_addr, func_end;
+
+  if (!proc_desc)
+    proc_desc = find_proc_desc (pc, NULL);
+
+  if (proc_desc)
+    {
+      /* If function is frameless, then we need to do it the hard way.  I
+        strongly suspect that frameless always means prologueless... */
+      if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
+         && PROC_FRAME_OFFSET (proc_desc) == 0)
+       return 0;
+    }
+
+  if (!find_pc_partial_function (pc, NULL, &func_addr, &func_end))
+    return 0;                  /* Unknown */
+
+  sal = find_pc_line (func_addr, 0);
+
+  if (sal.end < func_end)
+    return sal.end;
+
+  /* The line after the prologue is after the end of the function.  In this
+     case, tell the caller to find the prologue the hard way.  */
+
+  return 0;
+}
+
+/* Return non-zero if we *might* be in a function prologue.  Return zero if we
+   are definatly *not* in a function prologue.  */
+
+static int
+in_prologue (pc, proc_desc)
+     CORE_ADDR pc;
+     alpha_extra_func_info_t proc_desc;
+{
+  CORE_ADDR after_prologue_pc;
+
+  after_prologue_pc = after_prologue (pc, proc_desc);
+
+  if (after_prologue_pc == 0
+      || pc < after_prologue_pc)
+    return 1;
+  else
+    return 0;
+}
+
 static alpha_extra_func_info_t
-find_proc_desc(pc, next_frame)
+find_proc_desc (pc, next_frame)
     CORE_ADDR pc;
-    FRAME next_frame;
+    struct frame_info *next_frame;
 {
   alpha_extra_func_info_t proc_desc;
   struct block *b;
@@ -317,10 +476,11 @@ find_proc_desc(pc, next_frame)
      as it will be contained in the proc_desc we are searching for.
      So we have to find the proc_desc whose frame is closest to the current
      stack pointer.  */
+
   if (PC_IN_CALL_DUMMY (pc, 0, 0))
     {
       struct linked_proc_info *link;
-      CORE_ADDR sp = next_frame ? next_frame->frame : read_register (SP_REGNUM);
+      CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM);
       alpha_extra_func_info_t found_proc_desc = NULL;
       long min_distance = LONG_MAX;
 
@@ -338,6 +498,7 @@ find_proc_desc(pc, next_frame)
     }
 
   b = block_for_pc(pc);
+
   find_pc_partial_function (pc, NULL, &startaddr, NULL);
   if (b == NULL)
     sym = NULL;
@@ -353,47 +514,50 @@ find_proc_desc(pc, next_frame)
                             0, NULL);
     }
 
+  /* If we never found a PDR for this function in symbol reading, then
+     examine prologues to find the information.  */
+  if (sym && ((mips_extra_func_info_t) SYMBOL_VALUE (sym))->pdr.framereg == -1)
+    sym = NULL;
+
   if (sym)
     {
-       /* IF (this is the topmost frame OR a frame interrupted by a signal)
-        * AND (this proc does not have debugging information OR
+       /* IF this is the topmost frame AND
+        * (this proc does not have debugging information OR
         * the PC is in the procedure prologue)
         * THEN create a "heuristic" proc_desc (by analyzing
         * the actual code) to replace the "official" proc_desc.
         */
        proc_desc = (alpha_extra_func_info_t)SYMBOL_VALUE(sym);
-       if (next_frame == NULL || next_frame->signal_handler_caller) {
-           struct symtab_and_line val;
-           struct symbol *proc_symbol =
-               PROC_DESC_IS_DUMMY(proc_desc) ? 0 : PROC_SYMBOL(proc_desc);
-
-           if (proc_symbol) {
-               val = find_pc_line (BLOCK_START
-                                   (SYMBOL_BLOCK_VALUE(proc_symbol)),
-                                   0);
-               val.pc = val.end ? val.end : pc;
-           }
-           if (!proc_symbol || pc < val.pc) {
+       if (next_frame == NULL)
+         {
+           if (PROC_DESC_IS_DUMMY (proc_desc) || in_prologue (pc, proc_desc))
+             {
                alpha_extra_func_info_t found_heuristic =
-                   heuristic_proc_desc(PROC_LOW_ADDR(proc_desc),
-                                       pc, next_frame);
+                 heuristic_proc_desc (PROC_LOW_ADDR (proc_desc),
+                                      pc, next_frame);
                if (found_heuristic)
                  {
-                   /* The call to heuristic_proc_desc determines
-                      which registers have been saved so far and if the
-                      frame is already set up.
-                      The heuristic algorithm doesn't work well for other
-                      information in the procedure descriptor, so copy
-                      it from the found procedure descriptor.  */
-                   PROC_LOCALOFF(found_heuristic) = PROC_LOCALOFF(proc_desc);
-                   PROC_PC_REG(found_heuristic) = PROC_PC_REG(proc_desc);
+                   PROC_LOCALOFF (found_heuristic) =
+                     PROC_LOCALOFF (proc_desc);
+                   PROC_PC_REG (found_heuristic) = PROC_PC_REG (proc_desc);
                    proc_desc = found_heuristic;
                  }
-           }
-       }
+             }
+         }
     }
   else
     {
+      /* Is linked_proc_desc_table really necessary?  It only seems to be used
+        by procedure call dummys.  However, the procedures being called ought
+        to have their own proc_descs, and even if they don't,
+        heuristic_proc_desc knows how to create them! */
+
+      register struct linked_proc_info *link;
+      for (link = linked_proc_desc_table; link; link = link->next)
+         if (PROC_LOW_ADDR(&link->info) <= pc
+             && PROC_HIGH_ADDR(&link->info) > pc)
+             return &link->info;
+
       if (startaddr == 0)
        startaddr = heuristic_proc_start (pc);
 
@@ -405,9 +569,9 @@ find_proc_desc(pc, next_frame)
 
 alpha_extra_func_info_t cached_proc_desc;
 
-FRAME_ADDR
+CORE_ADDR
 alpha_frame_chain(frame)
-    FRAME frame;
+    struct frame_info *frame;
 {
     alpha_extra_func_info_t proc_desc;
     CORE_ADDR saved_pc = FRAME_SAVED_PC(frame);
@@ -424,7 +588,7 @@ alpha_frame_chain(frame)
     /* Fetch the frame pointer for a dummy frame from the procedure
        descriptor.  */
     if (PROC_DESC_IS_DUMMY(proc_desc))
-      return (FRAME_ADDR) PROC_DUMMY_FRAME(proc_desc);
+      return (CORE_ADDR) PROC_DUMMY_FRAME(proc_desc);
 
     /* If no frame pointer and frame size is zero, we must be at end
        of stack (or otherwise hosed).  If we don't check frame size,
@@ -451,107 +615,49 @@ alpha_frame_chain(frame)
 }
 
 void
-init_extra_frame_info(fci)
-     struct frame_info *fci;
+init_extra_frame_info (frame)
+     struct frame_info *frame;
 {
-  extern struct obstack frame_cache_obstack;
   /* Use proc_desc calculated in frame_chain */
   alpha_extra_func_info_t proc_desc =
-    fci->next ? cached_proc_desc : find_proc_desc(fci->pc, fci->next);
+    frame->next ? cached_proc_desc : find_proc_desc(frame->pc, frame->next);
 
-  fci->saved_regs = (struct frame_saved_regs*)
-    obstack_alloc (&frame_cache_obstack, sizeof(struct frame_saved_regs));
-  memset (fci->saved_regs, 0, sizeof (struct frame_saved_regs));
-  fci->proc_desc =
-    proc_desc == &temp_proc_desc ? 0 : proc_desc;
+  frame->saved_regs = NULL;
+  frame->localoff = 0;
+  frame->pc_reg = RA_REGNUM;
+  frame->proc_desc = proc_desc == &temp_proc_desc ? 0 : proc_desc;
   if (proc_desc)
     {
-      int ireg;
-      CORE_ADDR reg_position;
-      unsigned long mask;
-      int returnreg;
-
-      /* Get the locals offset from the procedure descriptor, it is valid
-        even if we are in the middle of the prologue.  */
-      fci->localoff = PROC_LOCALOFF(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);
 
       /* Fixup frame-pointer - only needed for top frame */
+
       /* Fetch the frame pointer for a dummy frame from the procedure
         descriptor.  */
       if (PROC_DESC_IS_DUMMY(proc_desc))
-       fci->frame = (FRAME_ADDR) PROC_DUMMY_FRAME(proc_desc);
+       frame->frame = (CORE_ADDR) PROC_DUMMY_FRAME(proc_desc);
+
       /* This may not be quite right, if proc has a real frame register.
         Get the value of the frame relative sp, procedure might have been
         interrupted by a signal at it's very start.  */
-      else if (fci->pc == PROC_LOW_ADDR(proc_desc))
-       fci->frame = READ_FRAME_REG(fci, SP_REGNUM);
+      else if (frame->pc == PROC_LOW_ADDR (proc_desc) && !PROC_DESC_IS_DUMMY (proc_desc))
+       frame->frame = read_next_frame_reg (frame->next, SP_REGNUM);
       else
-       fci->frame = READ_FRAME_REG(fci, PROC_FRAME_REG(proc_desc))
-                     + PROC_FRAME_OFFSET(proc_desc);
-
-      /* If this is the innermost frame, and we are still in the
-        prologue (loosely defined), then the registers may not have
-        been saved yet.  */
-      if (fci->next == NULL
-          && !PROC_DESC_IS_DUMMY(proc_desc)
-         && alpha_in_lenient_prologue (PROC_LOW_ADDR (proc_desc), fci->pc))
-       {
-         /* Can't just say that the registers are not saved, because they
-            might get clobbered halfway through the prologue.
-            heuristic_proc_desc already has the right code to figure out
-            exactly what has been saved, so use it.  As far as I know we
-            could be doing this (as we do on the 68k, for example)
-            regardless of whether we are in the prologue; I'm leaving in
-            the check for being in the prologue only out of conservatism
-            (I'm not sure whether heuristic_proc_desc handles all cases,
-            for example).
-
-            This stuff is ugly (and getting uglier by the minute).  Probably
-            the best way to clean it up is to ignore the proc_desc's from
-            the symbols altogher, and get all the information we need by
-            examining the prologue (provided we can make the prologue
-            examining code good enough to get all the cases...).  */
-         proc_desc =
-           heuristic_proc_desc (PROC_LOW_ADDR (proc_desc),
-                                fci->pc,
-                                fci->next);
-       }
+       frame->frame = read_next_frame_reg (frame->next, PROC_FRAME_REG (proc_desc))
+         + PROC_FRAME_OFFSET (proc_desc);
 
       if (proc_desc == &temp_proc_desc)
-       *fci->saved_regs = temp_saved_regs;
-      else
        {
-         /* Find which general-purpose registers were saved.
-            The return address register is the first saved register,
-            the other registers follow in ascending order.  */
-         reg_position = fci->frame + PROC_REG_OFFSET(proc_desc);
-         mask = PROC_REG_MASK(proc_desc) & 0xffffffffL;
-         returnreg = PROC_PC_REG(proc_desc);
-         if (mask & (1 << returnreg))
-           {
-             fci->saved_regs->regs[returnreg] = reg_position;
-             reg_position += 8;
-           }
-         for (ireg = 0; mask; ireg++, mask >>= 1)
-           if (mask & 1)
-             {
-               if (ireg == returnreg)
-                 continue;
-               fci->saved_regs->regs[ireg] = reg_position;
-               reg_position += 8;
-             }
-         /* find which floating-point registers were saved */
-         reg_position = fci->frame + PROC_FREG_OFFSET(proc_desc);
-         mask = PROC_FREG_MASK(proc_desc) & 0xffffffffL;
-         for (ireg = 0; mask; ireg++, mask >>= 1)
-           if (mask & 1)
-             {
-               fci->saved_regs->regs[FP0_REGNUM+ireg] = reg_position;
-               reg_position += 8;
-             }
+         frame->saved_regs = (struct frame_saved_regs*)
+           obstack_alloc (&frame_cache_obstack,
+                          sizeof (struct frame_saved_regs));
+         *frame->saved_regs = temp_saved_regs;
+         frame->saved_regs->regs[PC_REGNUM] = frame->saved_regs->regs[RA_REGNUM];
        }
-
-      fci->saved_regs->regs[PC_REGNUM] = fci->saved_regs->regs[PROC_PC_REG(proc_desc)];
     }
 }
 
@@ -570,10 +676,10 @@ init_extra_frame_info(fci)
    cache.  This allows the rest of info frame to extract the important
    arguments without difficulty.  */
 
-FRAME
+struct frame_info *
 setup_arbitrary_frame (argc, argv)
      int argc;
-     FRAME_ADDR *argv;
+     CORE_ADDR *argv;
 {
   if (argc != 2)
     error ("ALPHA frame specifications require two arguments: sp and pc");
@@ -593,11 +699,11 @@ setup_arbitrary_frame (argc, argv)
 
 CORE_ADDR
 alpha_push_arguments (nargs, args, sp, struct_return, struct_addr)
-  int nargs;
-  value *args;
-  CORE_ADDR sp;
-  int struct_return;
-  CORE_ADDR struct_addr;
+     int nargs;
+     value_ptr *args;
+     CORE_ADDR sp;
+     int struct_return;
+     CORE_ADDR struct_addr;
 {
   register i;
   int accumulate_size = struct_return ? 8 : 0;
@@ -611,10 +717,21 @@ alpha_push_arguments (nargs, args, sp, struct_return, struct_addr)
 
   for (i = 0, m_arg = alpha_args; i < nargs; i++, m_arg++)
     {
-      value arg = value_arg_coerce (args[i]);
+      value_ptr arg = args[i];
       /* Cast argument to long if necessary as the compiler does it too.  */
-      if (TYPE_LENGTH (VALUE_TYPE (arg)) < TYPE_LENGTH (builtin_type_long))
-        arg = value_cast (builtin_type_long, arg);
+      switch (TYPE_CODE (VALUE_TYPE (arg)))
+       {
+       case TYPE_CODE_INT:
+       case TYPE_CODE_BOOL:
+       case TYPE_CODE_CHAR:
+       case TYPE_CODE_RANGE:
+       case TYPE_CODE_ENUM:
+         if (TYPE_LENGTH (VALUE_TYPE (arg)) < TYPE_LENGTH (builtin_type_long))
+           arg = value_cast (builtin_type_long, arg);
+         break;
+       default:
+         break;
+       }
       m_arg->len = TYPE_LENGTH (VALUE_TYPE (arg));
       m_arg->offset = accumulate_size;
       accumulate_size = (accumulate_size + m_arg->len + 7) & ~7;
@@ -661,16 +778,18 @@ void
 alpha_push_dummy_frame()
 {
   int ireg;
-  struct linked_proc_info *link = (struct linked_proc_info*)
-      xmalloc(sizeof (struct linked_proc_info));
-  alpha_extra_func_info_t proc_desc = &link->info;
+  struct linked_proc_info *link;
+  alpha_extra_func_info_t proc_desc;
   CORE_ADDR sp = read_register (SP_REGNUM);
   CORE_ADDR save_address;
   char raw_buffer[MAX_REGISTER_RAW_SIZE];
   unsigned long mask;
 
+  link = (struct linked_proc_info *) xmalloc(sizeof (struct linked_proc_info));
   link->next = linked_proc_desc_table;
   linked_proc_desc_table = link;
+  proc_desc = &link->info;
 
   /*
    * The registers we must save are all those not preserved across
@@ -764,7 +883,7 @@ alpha_push_dummy_frame()
   sp += PROC_REG_OFFSET(proc_desc);
   write_register (SP_REGNUM, sp);
 
-  PROC_LOW_ADDR(proc_desc) = entry_point_address ();
+  PROC_LOW_ADDR(proc_desc) = CALL_DUMMY_ADDRESS ();
   PROC_HIGH_ADDR(proc_desc) = PROC_LOW_ADDR(proc_desc) + 4;
 
   SET_PROC_DESC_IS_DUMMY(proc_desc);
@@ -775,12 +894,14 @@ void
 alpha_pop_frame()
 {
   register int regnum;
-  FRAME frame = get_current_frame ();
+  struct frame_info *frame = get_current_frame ();
   CORE_ADDR new_sp = frame->frame;
 
   alpha_extra_func_info_t proc_desc = frame->proc_desc;
 
   write_register (PC_REGNUM, FRAME_SAVED_PC(frame));
+  if (frame->saved_regs == NULL)
+    alpha_find_saved_regs (frame);
   if (proc_desc)
     {
       for (regnum = 32; --regnum >= 0; )
@@ -795,8 +916,6 @@ alpha_pop_frame()
     }
   write_register (SP_REGNUM, new_sp);
   flush_cached_frames ();
-  /* We let init_extra_frame_info figure out the frame pointer */
-  set_current_frame (create_new_frame (0, read_pc ()));
 
   if (proc_desc && PROC_DESC_IS_DUMMY(proc_desc))
     {
@@ -838,13 +957,37 @@ alpha_skip_prologue (pc, lenient)
 {
     unsigned long inst;
     int offset;
+    CORE_ADDR post_prologue_pc;
+    char buf[4];
+
+#ifdef GDB_TARGET_HAS_SHARED_LIBS
+    /* Silently return the unaltered pc upon memory errors.
+       This could happen on OSF/1 if decode_line_1 tries to skip the
+       prologue for quickstarted shared library functions when the
+       shared library is not yet mapped in.
+       Reading target memory is slow over serial lines, so we perform
+       this check only if the target has shared libraries.  */
+    if (target_read_memory (pc, buf, 4))
+      return pc;
+#endif
+
+    /* See if we can determine the end of the prologue via the symbol table.
+       If so, then return either PC, or the PC after the prologue, whichever
+       is greater.  */
+
+    post_prologue_pc = after_prologue (pc, NULL);
+
+    if (post_prologue_pc != 0)
+      return max (pc, post_prologue_pc);
+
+    /* Can't determine prologue from the symbol table, need to examine
+       instructions.  */
 
     /* Skip the typical prologue instructions. These are the stack adjustment
        instruction and the instructions that save registers on the stack
        or in the gcc frame.  */
     for (offset = 0; offset < 100; offset += 4)
       {
-       char buf[4];
        int status;
 
        status = read_memory_nobpt (pc + offset, buf, 4);
@@ -879,6 +1022,7 @@ alpha_skip_prologue (pc, lenient)
     return pc + offset;
 }
 
+#if 0
 /* Is address PC in the prologue (loosely defined) for function at
    STARTADDR?  */
 
@@ -890,6 +1034,7 @@ alpha_in_lenient_prologue (startaddr, pc)
   CORE_ADDR end_prologue = alpha_skip_prologue (startaddr, 1);
   return pc >= startaddr && pc < end_prologue;
 }
+#endif
 
 /* The alpha needs a conversion between register and memory format if
    the register is a floating point register and
@@ -960,52 +1105,48 @@ alpha_register_convert_to_raw (valtype, regnum, virtual_buffer, raw_buffer)
 
 /* Given a return value in `regbuf' with a type `valtype', 
    extract and copy its value into `valbuf'.  */
+
 void
 alpha_extract_return_value (valtype, regbuf, valbuf)
     struct type *valtype;
     char regbuf[REGISTER_BYTES];
     char *valbuf;
 {
-  int regnum;
-  
-  regnum = TYPE_CODE (valtype) == TYPE_CODE_FLT ? FP0_REGNUM : V0_REGNUM;
-
-  memcpy (valbuf, regbuf + REGISTER_BYTE (regnum), TYPE_LENGTH (valtype));
+  if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
+    alpha_register_convert_to_virtual (FP0_REGNUM, valtype,
+                                      regbuf + REGISTER_BYTE (FP0_REGNUM),
+                                      valbuf);
+  else
+    memcpy (valbuf, regbuf + REGISTER_BYTE (V0_REGNUM), TYPE_LENGTH (valtype));
 }
 
 /* Given a return value in `regbuf' with a type `valtype', 
-   write it's value into the appropriate register.  */
+   write its value into the appropriate register.  */
+
 void
 alpha_store_return_value (valtype, valbuf)
     struct type *valtype;
     char *valbuf;
 {
-  int regnum;
   char raw_buffer[MAX_REGISTER_RAW_SIZE];
+  int regnum = V0_REGNUM;
+  int length = TYPE_LENGTH (valtype);
   
-  regnum = TYPE_CODE (valtype) == TYPE_CODE_FLT ? FP0_REGNUM : V0_REGNUM;
-  memcpy(raw_buffer, valbuf, TYPE_LENGTH (valtype));
-
-  write_register_bytes(REGISTER_BYTE (regnum), raw_buffer, TYPE_LENGTH (valtype));
-}
-
-/* Print the instruction at address MEMADDR in debugged memory,
-   on STREAM.  Returns length of the instruction, in bytes.  */
-
-int
-print_insn (memaddr, stream)
-     CORE_ADDR memaddr;
-     GDB_FILE *stream;
-{
-  disassemble_info info;
-
-  GDB_INIT_DISASSEMBLE_INFO(info, stream);
+  if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
+    {
+      regnum = FP0_REGNUM;
+      length = REGISTER_RAW_SIZE (regnum);
+      alpha_register_convert_to_raw (valtype, regnum, valbuf, raw_buffer);
+    }
+  else
+    memcpy (raw_buffer, valbuf, length);
 
-  return print_insn_alpha (memaddr, &info);
+  write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, length);
 }
 
 /* Just like reinit_frame_cache, but with the right arguments to be
    callable as an sfunc.  */
+
 static void
 reinit_frame_cache_sfunc (args, from_tty, c)
      char *args;
@@ -1015,11 +1156,37 @@ reinit_frame_cache_sfunc (args, from_tty, c)
   reinit_frame_cache ();
 }
 
+/* This is the definition of CALL_DUMMY_ADDRESS.  It's a heuristic that is used
+   to find a convenient place in the text segment to stick a breakpoint to
+   detect the completion of a target function call (ala call_function_by_hand).
+ */
+
+CORE_ADDR
+alpha_call_dummy_address ()
+{
+  CORE_ADDR entry;
+  struct minimal_symbol *sym;
+
+  entry = entry_point_address ();
+
+  if (entry != 0)
+    return entry;
+
+  sym = lookup_minimal_symbol ("_Prelude", NULL, symfile_objfile);
+
+  if (!sym || MSYMBOL_TYPE (sym) != mst_text)
+    return 0;
+  else
+    return SYMBOL_VALUE_ADDRESS (sym) + 4;
+}
+
 void
 _initialize_alpha_tdep ()
 {
   struct cmd_list_element *c;
 
+  tm_print_insn = print_insn_alpha;
+
   /* Let the user set the fence post for heuristic_proc_start.  */
 
   /* We really would like to have both "0" and "unlimited" work, but
This page took 0.033019 seconds and 4 git commands to generate.