* Makefile.in (eelf32ppc.c): Depend upon elf32.em, not generic.em.
[deliverable/binutils-gdb.git] / gdb / alpha-tdep.c
index 0901d60f23315eb4726e53e92d27a3ba2bfd0043..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"
@@ -27,6 +27,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #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.  */
 
@@ -44,11 +45,15 @@ 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, struct frame_info *));
+static alpha_extra_func_info_t find_proc_desc PARAMS ((CORE_ADDR,
+                                                      struct frame_info *));
 
+#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));
@@ -144,6 +149,40 @@ alpha_find_saved_regs (frame)
     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
+  if (frame->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++)
+       {
+         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
@@ -159,7 +198,7 @@ alpha_find_saved_regs (frame)
 
   returnreg = PROC_PC_REG (proc_desc);
 
-  /* Note that RA is always saved first, regardless of it's actual
+  /* Note that RA is always saved first, regardless of its actual
      register number.  */
   if (mask & (1 << returnreg))
     {
@@ -197,30 +236,11 @@ read_next_frame_reg(fi, regno)
      struct frame_info *fi;
      int regno;
 {
-  /* 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.  */
-#ifndef SIGFRAME_PC_OFF
-#define SIGFRAME_PC_OFF                (2 * 8)
-#define SIGFRAME_REGSAVE_OFF   (4 * 8)
-#endif
   for (; fi; fi = fi->next)
     {
-      if (fi->signal_handler_caller)
-       {
-         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)
+      /* 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
        {
@@ -240,8 +260,7 @@ alpha_frame_saved_pc(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);
@@ -253,8 +272,18 @@ CORE_ADDR
 alpha_saved_pc_after_call (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);
 }
@@ -382,7 +411,6 @@ after_prologue (pc, proc_desc)
      CORE_ADDR pc;
      alpha_extra_func_info_t proc_desc;
 {
-  struct block *b;
   struct symtab_and_line sal;
   CORE_ADDR func_addr, func_end;
 
@@ -486,6 +514,11 @@ 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 AND
@@ -502,9 +535,13 @@ find_proc_desc (pc, next_frame)
                alpha_extra_func_info_t found_heuristic =
                  heuristic_proc_desc (PROC_LOW_ADDR (proc_desc),
                                       pc, next_frame);
-               PROC_LOCALOFF (found_heuristic) = PROC_LOCALOFF (proc_desc);
                if (found_heuristic)
-                 proc_desc = found_heuristic;
+                 {
+                   PROC_LOCALOFF (found_heuristic) =
+                     PROC_LOCALOFF (proc_desc);
+                   PROC_PC_REG (found_heuristic) = PROC_PC_REG (proc_desc);
+                   proc_desc = found_heuristic;
+                 }
              }
          }
     }
@@ -586,13 +623,16 @@ init_extra_frame_info (frame)
     frame->next ? cached_proc_desc : find_proc_desc(frame->pc, frame->next);
 
   frame->saved_regs = NULL;
-  frame->proc_desc =
-    proc_desc == &temp_proc_desc ? 0 : proc_desc;
+  frame->localoff = 0;
+  frame->pc_reg = RA_REGNUM;
+  frame->proc_desc = proc_desc == &temp_proc_desc ? 0 : proc_desc;
   if (proc_desc)
     {
-      /* Get the locals offset from the procedure descriptor, it is valid
-        even if we are in the middle of the prologue.  */
+      /* 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 */
 
@@ -677,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_ptr 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;
@@ -971,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?  */
 
@@ -982,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
@@ -1059,11 +1112,12 @@ alpha_extract_return_value (valtype, regbuf, valbuf)
     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', 
@@ -1074,28 +1128,20 @@ 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
@@ -1126,7 +1172,7 @@ alpha_call_dummy_address ()
   if (entry != 0)
     return entry;
 
-  sym = lookup_minimal_symbol ("_Prelude", symfile_objfile);
+  sym = lookup_minimal_symbol ("_Prelude", NULL, symfile_objfile);
 
   if (!sym || MSYMBOL_TYPE (sym) != mst_text)
     return 0;
@@ -1139,6 +1185,8 @@ _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.037854 seconds and 4 git commands to generate.