]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/rs6000-tdep.c
Add new infrun.h header.
[thirdparty/binutils-gdb.git] / gdb / rs6000-tdep.c
index 9832b5bb3fdfb9a55c407b6c1cd7136ad142bd25..c4ce51c5430217a923d8f13c23cd5908ad192df7 100644 (file)
@@ -1,8 +1,6 @@
 /* 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, 2009,
-   2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 1986-2014 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -22,6 +20,7 @@
 #include "defs.h"
 #include "frame.h"
 #include "inferior.h"
+#include "infrun.h"
 #include "symtab.h"
 #include "target.h"
 #include "gdbcore.h"
 
 #include "elf-bfd.h"
 #include "elf/ppc.h"
+#include "elf/ppc64.h"
 
 #include "solib-svr4.h"
 #include "ppc-tdep.h"
+#include "ppc-ravenscar-thread.h"
 
 #include "gdb_assert.h"
 #include "dis-asm.h"
 /* Determine if regnum is a POWER7 Extended FP register.  */
 #define IS_EFP_PSEUDOREG(tdep, regnum) ((tdep)->ppc_efpr0_regnum >= 0 \
     && (regnum) >= (tdep)->ppc_efpr0_regnum \
-    && (regnum) < (tdep)->ppc_efpr0_regnum + ppc_num_fprs)
+    && (regnum) < (tdep)->ppc_efpr0_regnum + ppc_num_efprs)
 
 /* The list of available "set powerpc ..." and "show powerpc ..."
    commands.  */
@@ -109,7 +110,7 @@ static struct cmd_list_element *showpowerpccmdlist = NULL;
 static enum auto_boolean powerpc_soft_float_global = AUTO_BOOLEAN_AUTO;
 
 /* The vector ABI to use.  Keep this in sync with powerpc_vector_abi.  */
-static const char *powerpc_vector_strings[] =
+static const char *const powerpc_vector_strings[] =
 {
   "auto",
   "generic",
@@ -944,7 +945,7 @@ rs6000_fetch_pointer_argument (struct frame_info *frame, int argi,
 
 /* Sequence of bytes for breakpoint instruction.  */
 
-const static unsigned char *
+static const unsigned char *
 rs6000_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
                           int *bp_size)
 {
@@ -1116,8 +1117,8 @@ ppc_deal_with_atomic_sequence (struct frame_info *frame)
          its destination address.  */
       if ((insn & BRANCH_MASK) == BC_INSN)
         {
-          int immediate = ((insn & ~3) << 16) >> 16;
-          int absolute = ((insn >> 1) & 1);
+          int immediate = ((insn & 0xfffc) ^ 0x8000) - 0x8000;
+          int absolute = insn & 2;
 
           if (bc_insn_count >= 1)
             return 0; /* More than one conditional branch found, fallback 
@@ -1126,7 +1127,7 @@ ppc_deal_with_atomic_sequence (struct frame_info *frame)
          if (absolute)
            breaks[1] = immediate;
          else
-           breaks[1] = pc + immediate;
+           breaks[1] = loc + immediate;
 
          bc_insn_count++;
          last_breakpoint++;
@@ -1150,11 +1151,10 @@ ppc_deal_with_atomic_sequence (struct frame_info *frame)
   breaks[0] = loc;
 
   /* Check for duplicated breakpoints.  Check also for a breakpoint
-     placed (branch instruction's destination) at the stwcx/stdcx 
-     instruction, this resets the reservation and take us back to the 
-     lwarx/ldarx instruction at the beginning of the atomic sequence.  */
-  if (last_breakpoint && ((breaks[1] == breaks[0]) 
-      || (breaks[1] == closing_insn)))
+     placed (branch instruction's destination) anywhere in sequence.  */
+  if (last_breakpoint
+      && (breaks[1] == breaks[0]
+         || (breaks[1] >= pc && breaks[1] <= closing_insn)))
     last_breakpoint = 0;
 
   /* Effectively inserts the breakpoints.  */
@@ -1618,7 +1618,19 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
          continue;
 
        }
-      else if ((op & 0xffff0000) == 0x60000000)
+      else if ((op & 0xffff0000) == 0x3c4c0000
+              || (op & 0xffff0000) == 0x3c400000
+              || (op & 0xffff0000) == 0x38420000)
+       {
+         /* .  0:      addis 2,12,.TOC.-0b@ha
+            .          addi 2,2,.TOC.-0b@l
+            or
+            .          lis 2,.TOC.@ha
+            .          addi 2,2,.TOC.@l
+            used by ELFv2 global entry points to set up r2.  */
+         continue;
+       }
+      else if (op == 0x60000000)
         {
          /* nop */
          /* Allow nops in the prologue, but do not consider them to
@@ -1629,8 +1641,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
 
        }
       else if ((op & 0xffff0000) == 0x3c000000)
-       {                       /* addis 0,0,NUM, used
-                                  for >= 32k frames */
+       {                       /* addis 0,0,NUM, used for >= 32k frames */
          fdata->offset = (op & 0x0000ffff) << 16;
          fdata->frameless = 0;
           r0_contains_arg = 0;
@@ -1638,8 +1649,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
 
        }
       else if ((op & 0xffff0000) == 0x60000000)
-       {                       /* ori 0,0,NUM, 2nd ha
-                                  lf of >= 32k frames */
+       {                       /* ori 0,0,NUM, 2nd half of >= 32k frames */
          fdata->offset |= (op & 0x0000ffff);
          fdata->frameless = 0;
           r0_contains_arg = 0;
@@ -1824,6 +1834,15 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
 
          /* Set up frame pointer */
        }
+      else if (op == 0x603d0000)       /* oril r29, r1, 0x0 */
+       {
+         fdata->frameless = 0;
+         framep = 1;
+         fdata->alloca_reg = (tdep->ppc_gp0_regnum + 29);
+         continue;
+
+         /* Another way to set up the frame pointer.  */
+       }
       else if (op == 0x603f0000        /* oril r31, r1, 0x0 */
               || op == 0x7c3f0b78)
        {                       /* mr r31, r1 */
@@ -2145,15 +2164,15 @@ rs6000_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
     {
       CORE_ADDR displ = op & BL_DISPLACEMENT_MASK;
       CORE_ADDR call_dest = pc + 4 + displ;
-      struct minimal_symbol *s = lookup_minimal_symbol_by_pc (call_dest);
+      struct bound_minimal_symbol s = lookup_minimal_symbol_by_pc (call_dest);
 
       /* We check for ___eabi (three leading underscores) in addition
          to __eabi in case the GCC option "-fleading-underscore" was
         used to compile the program.  */
-      if (s != NULL
-          && SYMBOL_LINKAGE_NAME (s) != NULL
-         && (strcmp (SYMBOL_LINKAGE_NAME (s), "__eabi") == 0
-             || strcmp (SYMBOL_LINKAGE_NAME (s), "___eabi") == 0))
+      if (s.minsym != NULL
+          && MSYMBOL_LINKAGE_NAME (s.minsym) != NULL
+         && (strcmp (MSYMBOL_LINKAGE_NAME (s.minsym), "__eabi") == 0
+             || strcmp (MSYMBOL_LINKAGE_NAME (s.minsym), "___eabi") == 0))
        pc += 4;
     }
   return pc;
@@ -2191,7 +2210,7 @@ rs6000_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
 
 static int
 rs6000_in_solib_return_trampoline (struct gdbarch *gdbarch,
-                                  CORE_ADDR pc, char *name)
+                                  CORE_ADDR pc, const char *name)
 {
   return name && !strncmp (name, "@FIX", 4);
 }
@@ -2219,7 +2238,7 @@ rs6000_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
   unsigned int ii, op;
   int rel;
   CORE_ADDR solib_target_pc;
-  struct minimal_symbol *msymbol;
+  struct bound_minimal_symbol msymbol;
 
   static unsigned trampoline_code[] =
   {
@@ -2235,9 +2254,9 @@ 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 
+  if (msymbol.minsym
       && rs6000_in_solib_return_trampoline (gdbarch, pc,
-                                           SYMBOL_LINKAGE_NAME (msymbol)))
+                                           MSYMBOL_LINKAGE_NAME (msymbol.minsym)))
     {
       /* Double-check that the third instruction from PC is relative "b".  */
       op = read_memory_integer (pc + 8, 4, byte_order);
@@ -2504,20 +2523,27 @@ rs6000_convert_register_p (struct gdbarch *gdbarch, int regnum,
             != TYPE_LENGTH (builtin_type (gdbarch)->builtin_double));
 }
 
-static void
+static int
 rs6000_register_to_value (struct frame_info *frame,
                           int regnum,
                           struct type *type,
-                          gdb_byte *to)
+                          gdb_byte *to,
+                         int *optimizedp, int *unavailablep)
 {
   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);
+  if (!get_frame_register_bytes (frame, regnum, 0,
+                                register_size (gdbarch, regnum),
+                                from, optimizedp, unavailablep))
+    return 0;
+
   convert_typed_floating (from, builtin_type (gdbarch)->builtin_double,
                          to, type);
+  *optimizedp = *unavailablep = 0;
+  return 1;
 }
 
 static void
@@ -2536,6 +2562,11 @@ rs6000_value_to_register (struct frame_info *frame,
   put_frame_register (frame, regnum, to);
 }
 
+ /* The type of a function that moves the value of REG between CACHE
+    or BUF --- in either direction.  */
+typedef enum register_status (*move_ev_register_func) (struct regcache *,
+                                                      int, void *);
+
 /* Move SPE vector register values between a 64-bit buffer and the two
    32-bit raw register halves in a regcache.  This function handles
    both splitting a 64-bit value into two 32-bit halves, and joining
@@ -2559,16 +2590,16 @@ rs6000_value_to_register (struct frame_info *frame,
    MOVE, since this function can't tell at compile-time which of
    REGCACHE or BUFFER is acting as the source of the data.  If C had
    co-variant type qualifiers, ...  */
-static void
-e500_move_ev_register (void (*move) (struct regcache *regcache,
-                                     int regnum, gdb_byte *buf),
-                       struct regcache *regcache, int ev_reg,
-                       gdb_byte *buffer)
+
+static enum register_status
+e500_move_ev_register (move_ev_register_func move,
+                      struct regcache *regcache, int ev_reg, void *buffer)
 {
   struct gdbarch *arch = get_regcache_arch (regcache);
   struct gdbarch_tdep *tdep = gdbarch_tdep (arch); 
   int reg_index;
   gdb_byte *byte_buffer = buffer;
+  enum register_status status;
 
   gdb_assert (IS_SPE_PSEUDOREG (tdep, ev_reg));
 
@@ -2576,55 +2607,80 @@ e500_move_ev_register (void (*move) (struct regcache *regcache,
 
   if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG)
     {
-      move (regcache, tdep->ppc_ev0_upper_regnum + reg_index, byte_buffer);
-      move (regcache, tdep->ppc_gp0_regnum + reg_index, byte_buffer + 4);
+      status = move (regcache, tdep->ppc_ev0_upper_regnum + reg_index,
+                    byte_buffer);
+      if (status == REG_VALID)
+       status = move (regcache, tdep->ppc_gp0_regnum + reg_index,
+                      byte_buffer + 4);
     }
   else
     {
-      move (regcache, tdep->ppc_gp0_regnum + reg_index, byte_buffer);
-      move (regcache, tdep->ppc_ev0_upper_regnum + reg_index, byte_buffer + 4);
+      status = move (regcache, tdep->ppc_gp0_regnum + reg_index, byte_buffer);
+      if (status == REG_VALID)
+       status = move (regcache, tdep->ppc_ev0_upper_regnum + reg_index,
+                      byte_buffer + 4);
     }
+
+  return status;
 }
 
-static void
+static enum register_status
+do_regcache_raw_read (struct regcache *regcache, int regnum, void *buffer)
+{
+  return regcache_raw_read (regcache, regnum, buffer);
+}
+
+static enum register_status
+do_regcache_raw_write (struct regcache *regcache, int regnum, void *buffer)
+{
+  regcache_raw_write (regcache, regnum, buffer);
+
+  return REG_VALID;
+}
+
+static enum register_status
 e500_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
                           int reg_nr, gdb_byte *buffer)
 {
-  e500_move_ev_register (regcache_raw_read, regcache, reg_nr, buffer);
+  return e500_move_ev_register (do_regcache_raw_read, regcache, reg_nr, buffer);
 }
 
 static void
 e500_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
                            int reg_nr, const gdb_byte *buffer)
 {
-  e500_move_ev_register ((void (*) (struct regcache *, int, gdb_byte *))
-                        regcache_raw_write,
-                        regcache, reg_nr, (gdb_byte *) buffer);
+  e500_move_ev_register (do_regcache_raw_write, regcache,
+                        reg_nr, (void *) buffer);
 }
 
 /* Read method for DFP pseudo-registers.  */
-static void
+static enum register_status
 dfp_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
                           int reg_nr, gdb_byte *buffer)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   int reg_index = reg_nr - tdep->ppc_dl0_regnum;
+  enum register_status status;
 
   if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
     {
       /* Read two FP registers to form a whole dl register.  */
-      regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-                        2 * reg_index, buffer);
-      regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-                        2 * reg_index + 1, buffer + 8);
+      status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+                                 2 * reg_index, buffer);
+      if (status == REG_VALID)
+       status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+                                   2 * reg_index + 1, buffer + 8);
     }
   else
     {
-      regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-                        2 * reg_index + 1, buffer + 8);
-      regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-                        2 * reg_index, buffer);
+      status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+                                 2 * reg_index + 1, buffer);
+      if (status == REG_VALID)
+       status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+                                   2 * reg_index, buffer + 8);
     }
+
+  return status;
 }
 
 /* Write method for DFP pseudo-registers.  */
@@ -2647,40 +2703,45 @@ dfp_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
   else
     {
       regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
-                         2 * reg_index + 1, buffer + 8);
+                         2 * reg_index + 1, buffer);
       regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
-                         2 * reg_index, buffer);
+                         2 * reg_index, buffer + 8);
     }
 }
 
 /* Read method for POWER7 VSX pseudo-registers.  */
-static void
+static enum register_status
 vsx_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
                           int reg_nr, gdb_byte *buffer)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   int reg_index = reg_nr - tdep->ppc_vsr0_regnum;
+  enum register_status status;
 
   /* Read the portion that overlaps the VMX registers.  */
   if (reg_index > 31)
-    regcache_raw_read (regcache, tdep->ppc_vr0_regnum +
-                       reg_index - 32, buffer);
+    status = regcache_raw_read (regcache, tdep->ppc_vr0_regnum +
+                               reg_index - 32, buffer);
   else
     /* Read the portion that overlaps the FPR registers.  */
     if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
       {
-       regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-                       reg_index, buffer);
-       regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
-                       reg_index, buffer + 8);
+       status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+                                   reg_index, buffer);
+       if (status == REG_VALID)
+         status = regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
+                                     reg_index, buffer + 8);
       }
     else
       {
-       regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-                       reg_index, buffer + 8);
-       regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
-                       reg_index, buffer);
+       status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+                                   reg_index, buffer + 8);
+       if (status == REG_VALID)
+         status = regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
+                                     reg_index, buffer);
       }
+
+  return status;
 }
 
 /* Write method for POWER7 VSX pseudo-registers.  */
@@ -2714,16 +2775,18 @@ vsx_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
 }
 
 /* Read method for POWER7 Extended FP pseudo-registers.  */
-static void
+static enum register_status
 efpr_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
                           int reg_nr, gdb_byte *buffer)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   int reg_index = reg_nr - tdep->ppc_efpr0_regnum;
+  int offset = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8;
 
-  /* Read the portion that overlaps the VMX registers.  */
-  regcache_raw_read (regcache, tdep->ppc_vr0_regnum +
-                    reg_index, buffer);
+  /* Read the portion that overlaps the VMX register.  */
+  return regcache_raw_read_part (regcache, tdep->ppc_vr0_regnum + reg_index,
+                                offset, register_size (gdbarch, reg_nr),
+                                buffer);
 }
 
 /* Write method for POWER7 Extended FP pseudo-registers.  */
@@ -2733,13 +2796,15 @@ efpr_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   int reg_index = reg_nr - tdep->ppc_efpr0_regnum;
+  int offset = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8;
 
-  /* Write the portion that overlaps the VMX registers.  */
-  regcache_raw_write (regcache, tdep->ppc_vr0_regnum +
-                     reg_index, buffer);
+  /* Write the portion that overlaps the VMX register.  */
+  regcache_raw_write_part (regcache, tdep->ppc_vr0_regnum + reg_index,
+                          offset, register_size (gdbarch, reg_nr),
+                          buffer);
 }
 
-static void
+static enum register_status
 rs6000_pseudo_register_read (struct gdbarch *gdbarch,
                             struct regcache *regcache,
                             int reg_nr, gdb_byte *buffer)
@@ -2750,13 +2815,13 @@ rs6000_pseudo_register_read (struct gdbarch *gdbarch,
   gdb_assert (regcache_arch == gdbarch);
 
   if (IS_SPE_PSEUDOREG (tdep, reg_nr))
-    e500_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+    return e500_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
   else if (IS_DFP_PSEUDOREG (tdep, reg_nr))
-    dfp_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+    return dfp_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
   else if (IS_VSX_PSEUDOREG (tdep, reg_nr))
-    vsx_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+    return vsx_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
   else if (IS_EFP_PSEUDOREG (tdep, reg_nr))
-    efpr_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+    return efpr_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
   else
     internal_error (__FILE__, __LINE__,
                    _("rs6000_pseudo_register_read: "
@@ -2805,7 +2870,7 @@ rs6000_stab_reg_to_regnum (struct gdbarch *gdbarch, int num)
   else if (77 <= num && num <= 108)
     return tdep->ppc_vr0_regnum + (num - 77);
   else if (1200 <= num && num < 1200 + 32)
-    return tdep->ppc_ev0_regnum + (num - 1200);
+    return tdep->ppc_ev0_upper_regnum + (num - 1200);
   else
     switch (num)
       {
@@ -2847,7 +2912,7 @@ rs6000_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int num)
   else if (1124 <= num && num < 1124 + 32)
     return tdep->ppc_vr0_regnum + (num - 1124);
   else if (1200 <= num && num < 1200 + 32)
-    return tdep->ppc_ev0_regnum + (num - 1200);
+    return tdep->ppc_ev0_upper_regnum + (num - 1200);
   else
     switch (num)
       {
@@ -3035,21 +3100,6 @@ find_variant_by_arch (enum bfd_architecture arch, unsigned long mach)
 static int
 gdb_print_insn_powerpc (bfd_vma memaddr, disassemble_info *info)
 {
-  if (!info->disassembler_options)
-    {
-      /* When debugging E500 binaries and disassembling code containing
-        E500-specific (SPE) instructions, one sometimes sees AltiVec
-        instructions instead.  The opcode spaces for SPE instructions
-        and AltiVec instructions overlap, and specifiying the "any" cpu
-        looks for AltiVec instructions first.  If we know we're
-        debugging an E500 binary, however, we can specify the "e500x2"
-        cpu and get much more sane disassembly output.  */
-      if (info->mach == bfd_mach_ppc_e500)
-       info->disassembler_options = "e500x2";
-      else
-       info->disassembler_options = "any";
-    }
-
   if (info->endian == BFD_ENDIAN_BIG)
     return print_insn_big_powerpc (memaddr, info);
   else
@@ -3208,12 +3258,14 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
        {
          int i;
          CORE_ADDR ev_addr = cache->base + fdata.ev_offset;
+         CORE_ADDR off = (byte_order == BFD_ENDIAN_BIG ? 4 : 0);
+
          for (i = fdata.saved_ev; i < ppc_num_gprs; i++)
            {
              cache->saved_regs[tdep->ppc_ev0_regnum + i].addr = ev_addr;
-              cache->saved_regs[tdep->ppc_gp0_regnum + i].addr = ev_addr + 4;
+             cache->saved_regs[tdep->ppc_gp0_regnum + i].addr = ev_addr + off;
              ev_addr += register_size (gdbarch, tdep->ppc_ev0_regnum);
-            }
+           }
        }
     }
 
@@ -3277,6 +3329,7 @@ rs6000_frame_prev_register (struct frame_info *this_frame,
 static const struct frame_unwind rs6000_frame_unwind =
 {
   NORMAL_FRAME,
+  default_frame_unwind_stop_reason,
   rs6000_frame_this_id,
   rs6000_frame_prev_register,
   NULL,
@@ -3502,10 +3555,10 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   enum bfd_architecture arch;
   unsigned long mach;
   bfd abfd;
-  asection *sect;
   enum auto_boolean soft_float_flag = powerpc_soft_float_global;
   int soft_float;
   enum powerpc_vector_abi vector_abi = powerpc_vector_abi_global;
+  enum powerpc_elf_abi elf_abi = POWERPC_ELF_AUTO;
   int have_fpu = 1, have_spe = 0, have_mq = 0, have_altivec = 0, have_dfp = 0,
       have_vsx = 0;
   int tdesc_wordsize = -1;
@@ -3602,10 +3655,6 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
        "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
        "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
       };
-      static const char *const segment_regs[] = {
-       "sr0", "sr1", "sr2", "sr3", "sr4", "sr5", "sr6", "sr7",
-       "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15"
-      };
       const struct tdesc_feature *feature;
       int i, valid_p;
       static const char *const msr_names[] = { "msr", "ps" };
@@ -3812,6 +3861,21 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     }
 
 #ifdef HAVE_ELF
+  if (from_elf_exec)
+    {
+      switch (elf_elfheader (info.abfd)->e_flags & EF_PPC64_ABI)
+       {
+       case 1:
+         elf_abi = POWERPC_ELF_V1;
+         break;
+       case 2:
+         elf_abi = POWERPC_ELF_V2;
+         break;
+       default:
+         break;
+       }
+    }
+
   if (soft_float_flag == AUTO_BOOLEAN_AUTO && from_elf_exec)
     {
       switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU,
@@ -3848,6 +3912,21 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     }
 #endif
 
+  /* At this point, the only supported ELF-based 64-bit little-endian
+     operating system is GNU/Linux, and this uses the ELFv2 ABI by
+     default.  All other supported ELF-based operating systems use the
+     ELFv1 ABI by default.  Therefore, if the ABI marker is missing,
+     e.g. because we run a legacy binary, or have attached to a process
+     and have not found any associated binary file, set the default
+     according to this heuristic.  */
+  if (elf_abi == POWERPC_ELF_AUTO)
+    {
+      if (wordsize == 8 && info.byte_order == BFD_ENDIAN_LITTLE)
+        elf_abi = POWERPC_ELF_V2;
+      else
+        elf_abi = POWERPC_ELF_V1;
+    }
+
   if (soft_float_flag == AUTO_BOOLEAN_TRUE)
     soft_float = 1;
   else if (soft_float_flag == AUTO_BOOLEAN_FALSE)
@@ -3890,6 +3969,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
          meaningful, because 64-bit CPUs can run in 32-bit mode.  So, perform
          separate word size check.  */
       tdep = gdbarch_tdep (arches->gdbarch);
+      if (tdep && tdep->elf_abi != elf_abi)
+       continue;
       if (tdep && tdep->soft_float != soft_float)
        continue;
       if (tdep && tdep->vector_abi != vector_abi)
@@ -3910,8 +3991,9 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
        - "set arch"            trust blindly
        - GDB startup           useless but harmless */
 
-  tdep = XCALLOC (1, struct gdbarch_tdep);
+  tdep = XCNEW (struct gdbarch_tdep);
   tdep->wordsize = wordsize;
+  tdep->elf_abi = elf_abi;
   tdep->soft_float = soft_float;
   tdep->vector_abi = vector_abi;
 
@@ -4119,6 +4201,12 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   gdb_assert (gdbarch_num_regs (gdbarch)
              + gdbarch_num_pseudo_regs (gdbarch) == cur_reg);
 
+  /* Register the ravenscar_arch_ops.  */
+  if (mach == bfd_mach_ppc_e500)
+    register_e500_ravenscar_ops (gdbarch);
+  else
+    register_ppc_ravenscar_ops (gdbarch);
+
   return gdbarch;
 }
 
@@ -4198,6 +4286,75 @@ show_powerpc_exact_watchpoints (struct ui_file *file, int from_tty,
   fprintf_filtered (file, _("Use of exact watchpoints is %s.\n"), value);
 }
 
+/* Read a PPC instruction from memory.  */
+
+static unsigned int
+read_insn (struct frame_info *frame, CORE_ADDR pc)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
+  return read_memory_unsigned_integer (pc, 4, byte_order);
+}
+
+/* Return non-zero if the instructions at PC match the series
+   described in PATTERN, or zero otherwise.  PATTERN is an array of
+   'struct ppc_insn_pattern' objects, terminated by an entry whose
+   mask is zero.
+
+   When the match is successful, fill INSN[i] with what PATTERN[i]
+   matched.  If PATTERN[i] is optional, and the instruction wasn't
+   present, set INSN[i] to 0 (which is not a valid PPC instruction).
+   INSN should have as many elements as PATTERN.  Note that, if
+   PATTERN contains optional instructions which aren't present in
+   memory, then INSN will have holes, so INSN[i] isn't necessarily the
+   i'th instruction in memory.  */
+
+int
+ppc_insns_match_pattern (struct frame_info *frame, CORE_ADDR pc,
+                        struct ppc_insn_pattern *pattern,
+                        unsigned int *insns)
+{
+  int i;
+  unsigned int insn;
+
+  for (i = 0, insn = 0; pattern[i].mask; i++)
+    {
+      if (insn == 0)
+       insn = read_insn (frame, pc);
+      insns[i] = 0;
+      if ((insn & pattern[i].mask) == pattern[i].data)
+       {
+         insns[i] = insn;
+         pc += 4;
+         insn = 0;
+       }
+      else if (!pattern[i].optional)
+       return 0;
+    }
+
+  return 1;
+}
+
+/* Return the 'd' field of the d-form instruction INSN, properly
+   sign-extended.  */
+
+CORE_ADDR
+ppc_insn_d_field (unsigned int insn)
+{
+  return ((((CORE_ADDR) insn & 0xffff) ^ 0x8000) - 0x8000);
+}
+
+/* Return the 'ds' field of the ds-form instruction INSN, with the two
+   zero bits concatenated at the right, and properly
+   sign-extended.  */
+
+CORE_ADDR
+ppc_insn_ds_field (unsigned int insn)
+{
+  return ((((CORE_ADDR) insn & 0xfffc) ^ 0x8000) - 0x8000);
+}
+
 /* Initialization code.  */
 
 /* -Wmissing-prototypes */