* gdb/defs.h: unconditionally include <fcntl.h>, and
[deliverable/binutils-gdb.git] / gdb / rs6000-tdep.c
index 54064c4dd1c53167673b6fa1902f1c1d1901091a..f78280009a1a81ed56292f0ebea00dfbcbd904b5 100644 (file)
@@ -1,8 +1,8 @@
 /* Target-dependent code for GDB, the GNU debugger.
 
    Copyright (C) 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996,
-   1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software
-   Foundation, Inc.
+   1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -60,6 +60,7 @@
 #include "frame-base.h"
 
 #include "reggroups.h"
+#include "rs6000-tdep.h"
 
 /* If the kernel has to deliver a signal, it pushes a sigcontext
    structure on the stack and then calls the signal handler, passing
@@ -100,8 +101,8 @@ struct rs6000_framedata
 struct reg
   {
     char *name;                        /* name of register */
-    unsigned char sz32;                /* size on 32-bit arch, 0 if nonexistant */
-    unsigned char sz64;                /* size on 64-bit arch, 0 if nonexistant */
+    unsigned char sz32;                /* size on 32-bit arch, 0 if nonexistent */
+    unsigned char sz64;                /* size on 64-bit arch, 0 if nonexistent */
     unsigned char fpr;         /* whether register is floating-point */
     unsigned char pseudo;       /* whether register is pseudo */
     int spr_num;                /* PowerPC SPR number, or -1 if not an SPR.
@@ -502,6 +503,108 @@ rs6000_skip_prologue (CORE_ADDR pc)
   return pc;
 }
 
+static int
+insn_changes_sp_or_jumps (unsigned long insn)
+{
+  int opcode = (insn >> 26) & 0x03f;
+  int sd = (insn >> 21) & 0x01f;
+  int a = (insn >> 16) & 0x01f;
+  int subcode = (insn >> 1) & 0x3ff;
+
+  /* Changes the stack pointer.  */
+
+  /* NOTE: There are many ways to change the value of a given register.
+           The ways below are those used when the register is R1, the SP,
+           in a funtion's epilogue.  */
+
+  if (opcode == 31 && subcode == 444 && a == 1)
+    return 1;  /* mr R1,Rn */
+  if (opcode == 14 && sd == 1)
+    return 1;  /* addi R1,Rn,simm */
+  if (opcode == 58 && sd == 1)
+    return 1;  /* ld R1,ds(Rn) */
+
+  /* Transfers control.  */
+
+  if (opcode == 18)
+    return 1;  /* b */
+  if (opcode == 16)
+    return 1;  /* bc */
+  if (opcode == 19 && subcode == 16)
+    return 1;  /* bclr */
+  if (opcode == 19 && subcode == 528)
+    return 1;  /* bcctr */
+
+  return 0;
+}
+
+/* Return true if we are in the function's epilogue, i.e. after the
+   instruction that destroyed the function's stack frame.
+
+   1) scan forward from the point of execution:
+       a) If you find an instruction that modifies the stack pointer
+          or transfers control (except a return), execution is not in
+          an epilogue, return.
+       b) Stop scanning if you find a return instruction or reach the
+          end of the function or reach the hard limit for the size of
+          an epilogue.
+   2) scan backward from the point of execution:
+        a) If you find an instruction that modifies the stack pointer,
+            execution *is* in an epilogue, return.
+        b) Stop scanning if you reach an instruction that transfers
+           control or the beginning of the function or reach the hard
+           limit for the size of an epilogue.  */
+
+static int
+rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  bfd_byte insn_buf[PPC_INSN_SIZE];
+  CORE_ADDR scan_pc, func_start, func_end, epilogue_start, epilogue_end;
+  unsigned long insn;
+  struct frame_info *curfrm;
+
+  /* Find the search limits based on function boundaries and hard limit.  */
+
+  if (!find_pc_partial_function (pc, NULL, &func_start, &func_end))
+    return 0;
+
+  epilogue_start = pc - PPC_MAX_EPILOGUE_INSTRUCTIONS * PPC_INSN_SIZE;
+  if (epilogue_start < func_start) epilogue_start = func_start;
+
+  epilogue_end = pc + PPC_MAX_EPILOGUE_INSTRUCTIONS * PPC_INSN_SIZE;
+  if (epilogue_end > func_end) epilogue_end = func_end;
+
+  curfrm = get_current_frame ();
+
+  /* Scan forward until next 'blr'.  */
+
+  for (scan_pc = pc; scan_pc < epilogue_end; scan_pc += PPC_INSN_SIZE)
+    {
+      if (!safe_frame_unwind_memory (curfrm, scan_pc, insn_buf, PPC_INSN_SIZE))
+        return 0;
+      insn = extract_signed_integer (insn_buf, PPC_INSN_SIZE);
+      if (insn == 0x4e800020)
+        break;
+      if (insn_changes_sp_or_jumps (insn))
+        return 0;
+    }
+
+  /* Scan backward until adjustment to stack pointer (R1).  */
+
+  for (scan_pc = pc - PPC_INSN_SIZE;
+       scan_pc >= epilogue_start;
+       scan_pc -= PPC_INSN_SIZE)
+    {
+      if (!safe_frame_unwind_memory (curfrm, scan_pc, insn_buf, PPC_INSN_SIZE))
+        return 0;
+      insn = extract_signed_integer (insn_buf, PPC_INSN_SIZE);
+      if (insn_changes_sp_or_jumps (insn))
+        return 1;
+    }
+
+  return 0;
+}
+
 
 /* Fill in fi->saved_regs */
 
@@ -911,7 +1014,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
 
             remember just the first one, but skip over additional
             ones.  */
-         if (lr_reg < 0)
+         if (lr_reg == -1)
            lr_reg = (op & 0x03e00000);
           if (lr_reg == 0)
             r0_contains_arg = 0;
@@ -1024,6 +1127,13 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
          continue;
 
        }
+      else if ((op & 0xfe80ffff) == 0x42800005 && lr_reg != -1)
+       {
+         /* bcl 20,xx,.+4 is used to get the current PC, with or without
+            prediction bits.  If the LR has already been saved, we can
+            skip it.  */
+         continue;
+       }
       else if (op == 0x48000005)
        {                       /* bl .+4 used in 
                                   -mrelocatable */
@@ -3120,7 +3230,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
        wordsize = 4;
     }
 
-  /* Find a candidate among existant architectures.  */
+  /* Find a candidate among extant architectures.  */
   for (arches = gdbarch_list_lookup_by_info (arches, &info);
        arches != NULL;
        arches = gdbarch_list_lookup_by_info (arches->next, &info))
@@ -3278,6 +3388,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
                     _("rs6000_gdbarch_init: "
                     "received unexpected BFD 'arch' value"));
 
+  set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
+
   /* Sanity check on registers.  */
   gdb_assert (strcmp (tdep->regs[tdep->ppc_gp0_regnum].name, "r0") == 0);
 
@@ -3342,6 +3454,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_deprecated_extract_struct_value_address (gdbarch, rs6000_extract_struct_value_address);
 
   set_gdbarch_skip_prologue (gdbarch, rs6000_skip_prologue);
+  set_gdbarch_in_function_epilogue_p (gdbarch, rs6000_in_function_epilogue_p);
+
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
   set_gdbarch_breakpoint_from_pc (gdbarch, rs6000_breakpoint_from_pc);
 
@@ -3405,16 +3519,6 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       frame_base_append_sniffer (gdbarch, rs6000_frame_base_sniffer);
     }
 
-  if (from_xcoff_exec)
-    {
-      /* NOTE: jimix/2003-06-09: This test should really check for
-        GDB_OSABI_AIX when that is defined and becomes
-        available. (Actually, once things are properly split apart,
-        the test goes away.) */
-       /* RS6000/AIX does not support PT_STEP.  Has to be simulated.  */
-       set_gdbarch_software_single_step (gdbarch, rs6000_software_single_step);
-    }
-
   init_sim_regno_table (gdbarch);
 
   return gdbarch;
This page took 0.025946 seconds and 4 git commands to generate.