2009-08-10 Paul Pluzhnikov <ppluzhnikov@google.com>
[deliverable/binutils-gdb.git] / gdb / rs6000-tdep.c
index f1d97994ddacef8a8fcce2b3b96aadddaf6554a8..cd9611582445a51f5046757060de61c8a847abb8 100644 (file)
@@ -1,7 +1,7 @@
 /* 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, 2006, 2007, 2008
+   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -66,6 +66,7 @@
 #include "features/rs6000/powerpc-vsx32.c"
 #include "features/rs6000/powerpc-403.c"
 #include "features/rs6000/powerpc-403gc.c"
+#include "features/rs6000/powerpc-405.c"
 #include "features/rs6000/powerpc-505.c"
 #include "features/rs6000/powerpc-601.c"
 #include "features/rs6000/powerpc-602.c"
@@ -129,17 +130,20 @@ struct rs6000_framedata
                                   by which we decrement sp to allocate
                                   the frame */
     int saved_gpr;             /* smallest # of saved gpr */
+    unsigned int gpr_mask;     /* Each bit is an individual saved GPR.  */
     int saved_fpr;             /* smallest # of saved fpr */
     int saved_vr;               /* smallest # of saved vr */
     int saved_ev;               /* smallest # of saved ev */
     int alloca_reg;            /* alloca register number (frame ptr) */
     char frameless;            /* true if frameless functions. */
     char nosavedpc;            /* true if pc not saved. */
+    char used_bl;              /* true if link register clobbered */
     int gpr_offset;            /* offset of saved gprs from prev sp */
     int fpr_offset;            /* offset of saved fprs from prev sp */
     int vr_offset;              /* offset of saved vrs from prev sp */
     int ev_offset;              /* offset of saved evs from prev sp */
     int lr_offset;             /* offset of saved lr */
+    int lr_register;           /* register of saved lr, if trustworthy */
     int cr_offset;             /* offset of saved cr */
     int vrsave_offset;          /* offset of saved vrsave register */
   };
@@ -213,7 +217,7 @@ ppc_floating_point_unit_p (struct gdbarch *gdbarch)
 
 /* Return non-zero if the architecture described by GDBARCH has
    VSX registers (vsr0 --- vsr63).  */
-int
+static int
 ppc_vsx_support_p (struct gdbarch *gdbarch)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
@@ -870,6 +874,8 @@ insn_changes_sp_or_jumps (unsigned long insn)
 static int
 rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   bfd_byte insn_buf[PPC_INSN_SIZE];
   CORE_ADDR scan_pc, func_start, func_end, epilogue_start, epilogue_end;
   unsigned long insn;
@@ -894,9 +900,20 @@ rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
     {
       if (!safe_frame_unwind_memory (curfrm, scan_pc, insn_buf, PPC_INSN_SIZE))
         return 0;
-      insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE);
+      insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE, byte_order);
       if (insn == 0x4e800020)
         break;
+      /* Assume a bctr is a tail call unless it points strictly within
+        this function.  */
+      if (insn == 0x4e800420)
+       {
+         CORE_ADDR ctr = get_frame_register_unsigned (curfrm,
+                                                      tdep->ppc_ctr_regnum);
+         if (ctr > func_start && ctr < func_end)
+           return 0;
+         else
+           break;
+       }
       if (insn_changes_sp_or_jumps (insn))
         return 0;
     }
@@ -909,7 +926,7 @@ rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
     {
       if (!safe_frame_unwind_memory (curfrm, scan_pc, insn_buf, PPC_INSN_SIZE))
         return 0;
-      insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE);
+      insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE, byte_order);
       if (insn_changes_sp_or_jumps (insn))
         return 1;
     }
@@ -950,16 +967,17 @@ rs6000_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
 
 /* Fix up the state of registers and memory after having single-stepped
    a displaced instruction.  */
-void
+static void
 ppc_displaced_step_fixup (struct gdbarch *gdbarch,
-                          struct displaced_step_closure *closure,
-                          CORE_ADDR from, CORE_ADDR to,
-                          struct regcache *regs)
+                         struct displaced_step_closure *closure,
+                         CORE_ADDR from, CORE_ADDR to,
+                         struct regcache *regs)
 {
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   /* Since we use simple_displaced_step_copy_insn, our closure is a
      copy of the instruction.  */
   ULONGEST insn  = extract_unsigned_integer ((gdb_byte *) closure,
-                                             PPC_INSN_SIZE);
+                                             PPC_INSN_SIZE, byte_order);
   ULONGEST opcode = 0;
   /* Offset for non PC-relative instructions.  */
   LONGEST offset = PPC_INSN_SIZE;
@@ -968,8 +986,8 @@ ppc_displaced_step_fixup (struct gdbarch *gdbarch,
 
   if (debug_displaced)
     fprintf_unfiltered (gdb_stdlog,
-                       "displaced: (ppc) fixup (0x%s, 0x%s)\n",
-                       paddr_nz (from), paddr_nz (to));
+                       "displaced: (ppc) fixup (%s, %s)\n",
+                       paddress (gdbarch, from), paddress (gdbarch, to));
 
 
   /* Handle PC-relative branch instructions.  */
@@ -994,10 +1012,10 @@ ppc_displaced_step_fixup (struct gdbarch *gdbarch,
              if (debug_displaced)
                fprintf_unfiltered
                  (gdb_stdlog,
-                  "displaced: (ppc) branch instruction: 0x%s\n"
-                  "displaced: (ppc) adjusted PC from 0x%s to 0x%s\n",
-                  paddr_nz (insn), paddr_nz (current_pc),
-                  paddr_nz (from + offset));
+                  "displaced: (ppc) branch instruction: %s\n"
+                  "displaced: (ppc) adjusted PC from %s to %s\n",
+                  paddress (gdbarch, insn), paddress (gdbarch, current_pc),
+                  paddress (gdbarch, from + offset));
 
              regcache_cooked_write_unsigned (regs, gdbarch_pc_regnum (gdbarch),
                                              from + offset);
@@ -1025,8 +1043,8 @@ ppc_displaced_step_fixup (struct gdbarch *gdbarch,
                                          from + PPC_INSN_SIZE);
          if (debug_displaced)
                fprintf_unfiltered (gdb_stdlog,
-                                   "displaced: (ppc) adjusted LR to 0x%s\n",
-                                   paddr_nz (from + PPC_INSN_SIZE));
+                                   "displaced: (ppc) adjusted LR to %s\n",
+                                   paddress (gdbarch, from + PPC_INSN_SIZE));
 
        }
     }
@@ -1056,11 +1074,13 @@ ppc_displaced_step_fixup (struct gdbarch *gdbarch,
 int 
 ppc_deal_with_atomic_sequence (struct frame_info *frame)
 {
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   CORE_ADDR pc = get_frame_pc (frame);
   CORE_ADDR breaks[2] = {-1, -1};
   CORE_ADDR loc = pc;
   CORE_ADDR closing_insn; /* Instruction that closes the atomic sequence.  */
-  int insn = read_memory_integer (loc, PPC_INSN_SIZE);
+  int insn = read_memory_integer (loc, PPC_INSN_SIZE, byte_order);
   int insn_count;
   int index;
   int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed).  */  
@@ -1078,7 +1098,7 @@ ppc_deal_with_atomic_sequence (struct frame_info *frame)
   for (insn_count = 0; insn_count < atomic_sequence_length; ++insn_count)
     {
       loc += PPC_INSN_SIZE;
-      insn = read_memory_integer (loc, PPC_INSN_SIZE);
+      insn = read_memory_integer (loc, PPC_INSN_SIZE, byte_order);
 
       /* Assume that there is at most one conditional branch in the atomic
          sequence.  If a conditional branch is found, put a breakpoint in 
@@ -1113,7 +1133,7 @@ ppc_deal_with_atomic_sequence (struct frame_info *frame)
 
   closing_insn = loc;
   loc += PPC_INSN_SIZE;
-  insn = read_memory_integer (loc, PPC_INSN_SIZE);
+  insn = read_memory_integer (loc, PPC_INSN_SIZE, byte_order);
 
   /* Insert a breakpoint right after the end of the atomic sequence.  */
   breaks[0] = loc;
@@ -1128,7 +1148,7 @@ ppc_deal_with_atomic_sequence (struct frame_info *frame)
 
   /* Effectively inserts the breakpoints.  */
   for (index = 0; index <= last_breakpoint; index++)
-    insert_single_step_breakpoint (breaks[index]);
+    insert_single_step_breakpoint (gdbarch, breaks[index]);
 
   return 1;
 }
@@ -1224,7 +1244,7 @@ store_param_on_stack_p (unsigned long op, int framep, int *r0_contains_arg)
    they can use to access PIC data using PC-relative offsets.  */
 
 static int
-bl_to_blrl_insn_p (CORE_ADDR pc, int insn)
+bl_to_blrl_insn_p (CORE_ADDR pc, int insn, enum bfd_endian byte_order)
 {
   CORE_ADDR dest;
   int immediate;
@@ -1238,7 +1258,7 @@ bl_to_blrl_insn_p (CORE_ADDR pc, int insn)
   else
     dest = pc + immediate;
 
-  dest_insn = read_memory_integer (dest, 4);
+  dest_insn = read_memory_integer (dest, 4, byte_order);
   if ((dest_insn & 0xfc00ffff) == 0x4c000021) /* blrl */
     return 1;
 
@@ -1259,6 +1279,188 @@ bl_to_blrl_insn_p (CORE_ADDR pc, int insn)
 #define BL_INSTRUCTION 0x48000001
 #define BL_DISPLACEMENT_MASK 0x03fffffc
 
+static unsigned long
+rs6000_fetch_instruction (struct gdbarch *gdbarch, const CORE_ADDR pc)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  gdb_byte buf[4];
+  unsigned long op;
+
+  /* Fetch the instruction and convert it to an integer.  */
+  if (target_read_memory (pc, buf, 4))
+    return 0;
+  op = extract_unsigned_integer (buf, 4, byte_order);
+
+  return op;
+}
+
+/* GCC generates several well-known sequences of instructions at the begining
+   of each function prologue when compiling with -fstack-check.  If one of
+   such sequences starts at START_PC, then return the address of the
+   instruction immediately past this sequence.  Otherwise, return START_PC.  */
+   
+static CORE_ADDR
+rs6000_skip_stack_check (struct gdbarch *gdbarch, const CORE_ADDR start_pc)
+{
+  CORE_ADDR pc = start_pc;
+  unsigned long op = rs6000_fetch_instruction (gdbarch, pc);
+
+  /* First possible sequence: A small number of probes.
+         stw 0, -<some immediate>(1)
+         [repeat this instruction any (small) number of times]
+  */
+  
+  if ((op & 0xffff0000) == 0x90010000)
+    {
+      while ((op & 0xffff0000) == 0x90010000)
+        {
+          pc = pc + 4;
+          op = rs6000_fetch_instruction (gdbarch, pc);
+        }
+      return pc;
+    }
+
+  /* Second sequence: A probing loop.
+         addi 12,1,-<some immediate>
+         lis 0,-<some immediate>
+         [possibly ori 0,0,<some immediate>]
+         add 0,12,0
+         cmpw 0,12,0
+         beq 0,<disp>
+         addi 12,12,-<some immediate>
+         stw 0,0(12)
+         b <disp>
+         [possibly one last probe: stw 0,<some immediate>(12)]
+  */
+
+  while (1)
+    {
+      /* addi 12,1,-<some immediate> */
+      if ((op & 0xffff0000) != 0x39810000)
+        break;
+
+      /* lis 0,-<some immediate> */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      if ((op & 0xffff0000) != 0x3c000000)
+        break;
+
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      /* [possibly ori 0,0,<some immediate>] */
+      if ((op & 0xffff0000) == 0x60000000)
+        {
+          pc = pc + 4;
+          op = rs6000_fetch_instruction (gdbarch, pc);
+        }
+      /* add 0,12,0 */
+      if (op != 0x7c0c0214)
+        break;
+
+      /* cmpw 0,12,0 */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      if (op != 0x7c0c0000)
+        break;
+
+      /* beq 0,<disp> */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      if ((op & 0xff9f0001) != 0x41820000)
+        break;
+
+      /* addi 12,12,-<some immediate> */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      if ((op & 0xffff0000) != 0x398c0000)
+        break;
+
+      /* stw 0,0(12) */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      if (op != 0x900c0000)
+        break;
+
+      /* b <disp> */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      if ((op & 0xfc000001) != 0x48000000)
+        break;
+
+      /* [possibly one last probe: stw 0,<some immediate>(12)] */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      if ((op & 0xffff0000) == 0x900c0000)
+        {
+          pc = pc + 4;
+          op = rs6000_fetch_instruction (gdbarch, pc);
+        }
+
+      /* We found a valid stack-check sequence, return the new PC.  */
+      return pc;
+    }
+
+  /* Third sequence: No probe; instead, a comparizon between the stack size
+     limit (saved in a run-time global variable) and the current stack
+     pointer:
+
+        addi 0,1,-<some immediate>
+        lis 12,__gnat_stack_limit@ha
+        lwz 12,__gnat_stack_limit@l(12)
+        twllt 0,12
+
+     or, with a small variant in the case of a bigger stack frame:
+        addis 0,1,<some immediate>
+        addic 0,0,-<some immediate>
+        lis 12,__gnat_stack_limit@ha
+        lwz 12,__gnat_stack_limit@l(12)
+        twllt 0,12
+  */
+  while (1)
+    {
+      /* addi 0,1,-<some immediate> */
+      if ((op & 0xffff0000) != 0x38010000)
+        {
+          /* small stack frame variant not recognized; try the
+             big stack frame variant: */
+
+          /* addis 0,1,<some immediate> */
+          if ((op & 0xffff0000) != 0x3c010000)
+            break;
+
+          /* addic 0,0,-<some immediate> */
+          pc = pc + 4;
+          op = rs6000_fetch_instruction (gdbarch, pc);
+          if ((op & 0xffff0000) != 0x30000000)
+            break;
+        }
+
+      /* lis 12,<some immediate> */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      if ((op & 0xffff0000) != 0x3d800000)
+        break;
+      
+      /* lwz 12,<some immediate>(12) */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      if ((op & 0xffff0000) != 0x818c0000)
+        break;
+
+      /* twllt 0,12 */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      if ((op & 0xfffffffe) != 0x7c406008)
+        break;
+
+      /* We found a valid stack-check sequence, return the new PC.  */
+      return pc;
+    }
+
+  /* No stack check code in our prologue, return the start_pc.  */
+  return start_pc;
+}
+
 /* return pc value after skipping a function prologue and also return
    information about a function frame.
 
@@ -1307,6 +1509,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
   int r0_contains_arg = 0;
   const struct bfd_arch_info *arch_info = gdbarch_bfd_arch_info (gdbarch);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
   memset (fdata, 0, sizeof (struct rs6000_framedata));
   fdata->saved_gpr = -1;
@@ -1316,6 +1519,11 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
   fdata->alloca_reg = -1;
   fdata->frameless = 1;
   fdata->nosavedpc = 1;
+  fdata->lr_register = -1;
+
+  pc = rs6000_skip_stack_check (gdbarch, pc);
+  if (pc >= lim_pc)
+    pc = lim_pc;
 
   for (;; pc += 4)
     {
@@ -1335,7 +1543,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
       /* Fetch the instruction and convert it to an integer.  */
       if (target_read_memory (pc, buf, 4))
        break;
-      op = extract_unsigned_integer (buf, 4);
+      op = extract_unsigned_integer (buf, 4, byte_order);
 
       if ((op & 0xfc1fffff) == 0x7c0802a6)
        {                       /* mflr Rx */
@@ -1357,7 +1565,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
             remember just the first one, but skip over additional
             ones.  */
          if (lr_reg == -1)
-           lr_reg = (op & 0x03e00000);
+           lr_reg = (op & 0x03e00000) >> 21;
           if (lr_reg == 0)
             r0_contains_arg = 0;
          continue;
@@ -1388,6 +1596,10 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
        {
 
          reg = GET_SRC_REG (op);
+         if ((op & 0xfc1f0000) == 0xbc010000)
+           fdata->gpr_mask |= ~((1U << reg) - 1);
+         else
+           fdata->gpr_mask |= 1U << reg;
          if (fdata->saved_gpr == -1 || fdata->saved_gpr > reg)
            {
              fdata->saved_gpr = reg;
@@ -1479,6 +1691,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
       else if (op == 0x48000005)
        {                       /* bl .+4 used in 
                                   -mrelocatable */
+         fdata->used_bl = 1;
          continue;
 
        }
@@ -1502,8 +1715,11 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
 
          /* If the return address has already been saved, we can skip
             calls to blrl (for PIC).  */
-          if (lr_reg != -1 && bl_to_blrl_insn_p (pc, op))
-           continue;
+          if (lr_reg != -1 && bl_to_blrl_insn_p (pc, op, byte_order))
+           {
+             fdata->used_bl = 1;
+             continue;
+           }
 
          /* Don't skip over the subroutine call if it is not within
             the first three instructions of the prologue and either
@@ -1519,7 +1735,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
                break;
            }
 
-         op = read_memory_integer (pc + 4, 4);
+         op = read_memory_integer (pc + 4, 4, byte_order);
 
          /* At this point, make sure this is not a trampoline
             function (a function that simply calls another functions,
@@ -1529,8 +1745,9 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
          if (op == 0x4def7b82 || op == 0)      /* crorc 15, 15, 15 */
            break;              /* don't skip over 
                                   this branch */
-         continue;
 
+         fdata->used_bl = 1;
+         continue;
        }
       /* update stack pointer */
       else if ((op & 0xfc1f0000) == 0x94010000)
@@ -1791,11 +2008,15 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
 
       else
        {
+         unsigned int all_mask = ~((1U << fdata->saved_gpr) - 1);
+
          /* Not a recognized prologue instruction.
             Handle optimizer code motions into the prologue by continuing
             the search if we have no valid frame yet or if the return
-            address is not yet saved in the frame.  */
-         if (fdata->frameless == 0 && fdata->nosavedpc == 0)
+            address is not yet saved in the frame.  Also skip instructions
+            if some of the GPRs expected to be saved are not yet saved.  */
+         if (fdata->frameless == 0 && fdata->nosavedpc == 0
+             && (fdata->gpr_mask & all_mask) == all_mask)
            break;
 
          if (op == 0x4e800020          /* blr */
@@ -1832,7 +2053,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
 
   if ((op & 0xfc000001) == 0x48000001)
     {                          /* bl foo, an initializer function? */
-      op = read_memory_integer (pc + 4, 4);
+      op = read_memory_integer (pc + 4, 4, byte_order);
 
       if (op == 0x4def7b82)
        {                       /* cror 0xf, 0xf, 0xf (nop) */
@@ -1848,6 +2069,9 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
     }
 #endif /* 0 */
 
+  if (pc == lim_pc && lr_reg >= 0)
+    fdata->lr_register = lr_reg;
+
   fdata->offset = -fdata->offset;
   return last_prologue_pc;
 }
@@ -1863,7 +2087,8 @@ rs6000_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
      is greater.  */
   if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
     {
-      CORE_ADDR post_prologue_pc = skip_prologue_using_sal (func_addr);
+      CORE_ADDR post_prologue_pc
+       = skip_prologue_using_sal (gdbarch, func_addr);
       if (post_prologue_pc != 0)
        return max (pc, post_prologue_pc);
     }
@@ -1874,7 +2099,7 @@ rs6000_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
   /* Find an upper limit on the function prologue using the debug
      information.  If the debug information could not be used to provide
      that bound, then use an arbitrary large number as the upper bound.  */
-  limit_pc = skip_prologue_using_sal (pc);
+  limit_pc = skip_prologue_using_sal (gdbarch, pc);
   if (limit_pc == 0)
     limit_pc = pc + 100;          /* Magic.  */
 
@@ -1890,15 +2115,16 @@ rs6000_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
    address of the instruction following that call.  Otherwise, it simply
    returns PC.  */
 
-CORE_ADDR
+static CORE_ADDR
 rs6000_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   gdb_byte buf[4];
   unsigned long op;
 
   if (target_read_memory (pc, buf, 4))
     return pc;
-  op = extract_unsigned_integer (buf, 4);
+  op = extract_unsigned_integer (buf, 4, byte_order);
 
   if ((op & BL_MASK) == BL_INSTRUCTION)
     {
@@ -1948,8 +2174,9 @@ rs6000_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
    gdbarch_skip_trampoline_code hooks in handle_inferior_event() to skip past
    @FIX code.  */
 
-int
-rs6000_in_solib_return_trampoline (CORE_ADDR pc, char *name)
+static int
+rs6000_in_solib_return_trampoline (struct gdbarch *gdbarch,
+                                  CORE_ADDR pc, char *name)
 {
   return name && !strncmp (name, "@FIX", 4);
 }
@@ -1968,10 +2195,12 @@ rs6000_in_solib_return_trampoline (CORE_ADDR pc, char *name)
    Result is desired PC to step until, or NULL if we are not in
    code that should be skipped.  */
 
-CORE_ADDR
+static CORE_ADDR
 rs6000_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (frame));
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   unsigned int ii, op;
   int rel;
   CORE_ADDR solib_target_pc;
@@ -1992,10 +2221,11 @@ rs6000_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
   /* Check for bigtoc fixup code.  */
   msymbol = lookup_minimal_symbol_by_pc (pc);
   if (msymbol 
-      && rs6000_in_solib_return_trampoline (pc, SYMBOL_LINKAGE_NAME (msymbol)))
+      && rs6000_in_solib_return_trampoline (gdbarch, pc,
+                                           SYMBOL_LINKAGE_NAME (msymbol)))
     {
       /* Double-check that the third instruction from PC is relative "b".  */
-      op = read_memory_integer (pc + 8, 4);
+      op = read_memory_integer (pc + 8, 4, byte_order);
       if ((op & 0xfc000003) == 0x48000000)
        {
          /* Extract bits 6-29 as a signed 24-bit relative word address and
@@ -2012,12 +2242,12 @@ rs6000_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
 
   for (ii = 0; trampoline_code[ii]; ++ii)
     {
-      op = read_memory_integer (pc + (ii * 4), 4);
+      op = read_memory_integer (pc + (ii * 4), 4, byte_order);
       if (op != trampoline_code[ii])
        return 0;
     }
   ii = get_frame_register_unsigned (frame, 11);        /* r11 holds destination addr   */
-  pc = read_memory_unsigned_integer (ii, tdep->wordsize); /* (r11) value */
+  pc = read_memory_unsigned_integer (ii, tdep->wordsize, byte_order);
   return pc;
 }
 
@@ -2030,6 +2260,8 @@ rs6000_builtin_type_vec64 (struct gdbarch *gdbarch)
 
   if (!tdep->ppc_builtin_type_vec64)
     {
+      const struct builtin_type *bt = builtin_type (gdbarch);
+
       /* The type we're building is this: */
 #if 0
       union __gdb_builtin_type_vec64
@@ -2044,18 +2276,19 @@ rs6000_builtin_type_vec64 (struct gdbarch *gdbarch)
 
       struct type *t;
 
-      t = init_composite_type ("__ppc_builtin_type_vec64", TYPE_CODE_UNION);
-      append_composite_type_field (t, "uint64", builtin_type_int64);
+      t = arch_composite_type (gdbarch,
+                              "__ppc_builtin_type_vec64", TYPE_CODE_UNION);
+      append_composite_type_field (t, "uint64", bt->builtin_int64);
       append_composite_type_field (t, "v2_float",
-                                  init_vector_type (builtin_type_float, 2));
+                                  init_vector_type (bt->builtin_float, 2));
       append_composite_type_field (t, "v2_int32",
-                                  init_vector_type (builtin_type_int32, 2));
+                                  init_vector_type (bt->builtin_int32, 2));
       append_composite_type_field (t, "v4_int16",
-                                  init_vector_type (builtin_type_int16, 4));
+                                  init_vector_type (bt->builtin_int16, 4));
       append_composite_type_field (t, "v8_int8",
-                                  init_vector_type (builtin_type_int8, 8));
+                                  init_vector_type (bt->builtin_int8, 8));
 
-      TYPE_FLAGS (t) |= TYPE_FLAG_VECTOR;
+      TYPE_VECTOR (t) = 1;
       TYPE_NAME (t) = "ppc_builtin_type_vec64";
       tdep->ppc_builtin_type_vec64 = t;
     }
@@ -2072,6 +2305,8 @@ rs6000_builtin_type_vec128 (struct gdbarch *gdbarch)
 
   if (!tdep->ppc_builtin_type_vec128)
     {
+      const struct builtin_type *bt = builtin_type (gdbarch);
+
       /* The type we're building is this
 
         type = union __ppc_builtin_type_vec128 {
@@ -2085,18 +2320,19 @@ rs6000_builtin_type_vec128 (struct gdbarch *gdbarch)
 
       struct type *t;
 
-      t = init_composite_type ("__ppc_builtin_type_vec128", TYPE_CODE_UNION);
-      append_composite_type_field (t, "uint128", builtin_type_uint128);
+      t = arch_composite_type (gdbarch,
+                              "__ppc_builtin_type_vec128", TYPE_CODE_UNION);
+      append_composite_type_field (t, "uint128", bt->builtin_uint128);
       append_composite_type_field (t, "v4_float",
-                                  init_vector_type (builtin_type (gdbarch)->builtin_float, 4));
+                                  init_vector_type (bt->builtin_float, 4));
       append_composite_type_field (t, "v4_int32",
-                                  init_vector_type (builtin_type_int32, 4));
+                                  init_vector_type (bt->builtin_int32, 4));
       append_composite_type_field (t, "v8_int16",
-                                  init_vector_type (builtin_type_int16, 8));
+                                  init_vector_type (bt->builtin_int16, 8));
       append_composite_type_field (t, "v16_int8",
-                                  init_vector_type (builtin_type_int8, 16));
+                                  init_vector_type (bt->builtin_int8, 16));
 
-      TYPE_FLAGS (t) |= TYPE_FLAG_VECTOR;
+      TYPE_VECTOR (t) = 1;
       TYPE_NAME (t) = "ppc_builtin_type_vec128";
       tdep->ppc_builtin_type_vec128 = t;
     }
@@ -2245,7 +2481,8 @@ rs6000_convert_register_p (struct gdbarch *gdbarch, int regnum,
          && regnum >= tdep->ppc_fp0_regnum
          && regnum < tdep->ppc_fp0_regnum + ppc_num_fprs
          && TYPE_CODE (type) == TYPE_CODE_FLT
-         && TYPE_LENGTH (type) != TYPE_LENGTH (builtin_type_double));
+         && TYPE_LENGTH (type)
+            != TYPE_LENGTH (builtin_type (gdbarch)->builtin_double));
 }
 
 static void
@@ -2254,12 +2491,14 @@ rs6000_register_to_value (struct frame_info *frame,
                           struct type *type,
                           gdb_byte *to)
 {
+  struct gdbarch *gdbarch = get_frame_arch (frame);
   gdb_byte from[MAX_REGISTER_SIZE];
   
   gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
 
   get_frame_register (frame, regnum, from);
-  convert_typed_floating (from, builtin_type_double, to, type);
+  convert_typed_floating (from, builtin_type (gdbarch)->builtin_double,
+                         to, type);
 }
 
 static void
@@ -2268,11 +2507,13 @@ rs6000_value_to_register (struct frame_info *frame,
                           struct type *type,
                           const gdb_byte *from)
 {
+  struct gdbarch *gdbarch = get_frame_arch (frame);
   gdb_byte to[MAX_REGISTER_SIZE];
 
   gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
 
-  convert_typed_floating (from, type, to, builtin_type_double);
+  convert_typed_floating (from, type,
+                         to, builtin_type (gdbarch)->builtin_double);
   put_frame_register (frame, regnum, to);
 }
 
@@ -2708,6 +2949,8 @@ static struct variant variants[] =
    bfd_mach_rs6k, &tdesc_rs6000},
   {"403", "IBM PowerPC 403", bfd_arch_powerpc,
    bfd_mach_ppc_403, &tdesc_powerpc_403},
+  {"405", "IBM PowerPC 405", bfd_arch_powerpc,
+   bfd_mach_ppc_405, &tdesc_powerpc_405},
   {"601", "Motorola PowerPC 601", bfd_arch_powerpc,
    bfd_mach_ppc_601, &tdesc_powerpc_601},
   {"602", "Motorola PowerPC 602", bfd_arch_powerpc,
@@ -2809,6 +3052,7 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
   struct rs6000_frame_cache *cache;
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   struct rs6000_framedata fdata;
   int wordsize = tdep->wordsize;
   CORE_ADDR func, pc;
@@ -2866,7 +3110,8 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
 
   if (!fdata.frameless)
     /* Frameless really means stackless.  */
-    cache->base = read_memory_unsigned_integer (cache->base, wordsize);
+    cache->base
+      = read_memory_unsigned_integer (cache->base, wordsize, byte_order);
 
   trad_frame_set_value (cache->saved_regs,
                        gdbarch_sp_regnum (gdbarch), cache->base);
@@ -2892,7 +3137,8 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
     }
 
   /* if != -1, fdata.saved_gpr is the smallest number of saved_gpr.
-     All gpr's from saved_gpr to gpr31 are saved.  */
+     All gpr's from saved_gpr to gpr31 are saved (except during the
+     prologue).  */
 
   if (fdata.saved_gpr >= 0)
     {
@@ -2900,7 +3146,8 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
       CORE_ADDR gpr_addr = cache->base + fdata.gpr_offset;
       for (i = fdata.saved_gpr; i < ppc_num_gprs; i++)
        {
-         cache->saved_regs[tdep->ppc_gp0_regnum + i].addr = gpr_addr;
+         if (fdata.gpr_mask & (1U << i))
+           cache->saved_regs[tdep->ppc_gp0_regnum + i].addr = gpr_addr;
          gpr_addr += wordsize;
        }
     }
@@ -2947,6 +3194,8 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
      holds the LR.  */
   if (fdata.lr_offset != 0)
     cache->saved_regs[tdep->ppc_lr_regnum].addr = cache->base + fdata.lr_offset;
+  else if (fdata.lr_register != -1)
+    cache->saved_regs[tdep->ppc_lr_regnum].realreg = fdata.lr_register;
   /* The PC is found in the link register.  */
   cache->saved_regs[gdbarch_pc_regnum (gdbarch)] =
     cache->saved_regs[tdep->ppc_lr_regnum];
@@ -3111,6 +3360,16 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   int num_pseudoregs = 0;
   int cur_reg;
 
+  /* INFO may refer to a binary that is not of the PowerPC architecture,
+     e.g. when debugging a stand-alone SPE executable on a Cell/B.E. system.
+     In this case, we must not attempt to infer properties of the (PowerPC
+     side) of the target system from properties of that executable.  Trust
+     the target description instead.  */
+  if (info.abfd
+      && bfd_get_arch (info.abfd) != bfd_arch_powerpc
+      && bfd_get_arch (info.abfd) != bfd_arch_rs6000)
+    info.abfd = NULL;
+
   from_xcoff_exec = info.abfd && info.abfd->format == bfd_object &&
     bfd_get_flavour (info.abfd) == bfd_target_xcoff_flavour;
 
@@ -3633,6 +3892,17 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Frame handling.  */
   dwarf2_frame_set_init_reg (gdbarch, ppc_dwarf2_frame_init_reg);
 
+  /* Setup displaced stepping.  */
+  set_gdbarch_displaced_step_copy_insn (gdbarch,
+                                       simple_displaced_step_copy_insn);
+  set_gdbarch_displaced_step_fixup (gdbarch, ppc_displaced_step_fixup);
+  set_gdbarch_displaced_step_free_closure (gdbarch,
+                                          simple_displaced_step_free_closure);
+  set_gdbarch_displaced_step_location (gdbarch,
+                                      displaced_step_at_entry_point);
+
+  set_gdbarch_max_insn_length (gdbarch, PPC_INSN_SIZE);
+
   /* Hook in ABI-specific overrides, if they have been registered.  */
   info.target_desc = tdesc;
   info.tdep_info = (void *) tdesc_data;
@@ -3696,17 +3966,6 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   gdb_assert (gdbarch_num_regs (gdbarch)
              + gdbarch_num_pseudo_regs (gdbarch) == cur_reg);
 
-  /* Setup displaced stepping.  */
-  set_gdbarch_displaced_step_copy_insn (gdbarch,
-                                       simple_displaced_step_copy_insn);
-  set_gdbarch_displaced_step_fixup (gdbarch, ppc_displaced_step_fixup);
-  set_gdbarch_displaced_step_free_closure (gdbarch,
-                                          simple_displaced_step_free_closure);
-  set_gdbarch_displaced_step_location (gdbarch,
-                                      displaced_step_at_entry_point);
-
-  set_gdbarch_max_insn_length (gdbarch, PPC_INSN_SIZE);
-
   return gdbarch;
 }
 
@@ -3792,6 +4051,7 @@ _initialize_rs6000_tdep (void)
   initialize_tdesc_powerpc_vsx32 ();
   initialize_tdesc_powerpc_403 ();
   initialize_tdesc_powerpc_403gc ();
+  initialize_tdesc_powerpc_405 ();
   initialize_tdesc_powerpc_505 ();
   initialize_tdesc_powerpc_601 ();
   initialize_tdesc_powerpc_602 ();
This page took 0.034386 seconds and 4 git commands to generate.