x86: Adjust linker tests for --disable-separate-code
[binutils-gdb.git] / gdb / rs6000-tdep.c
index 5d0ff1d8b1b7e2c9235e38697851a951c39f346a..ce98dc2f88438eb76df8ec2d95986754b1716c12 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for GDB, the GNU debugger.
 
-   Copyright (C) 1986-2017 Free Software Foundation, Inc.
+   Copyright (C) 1986-2021 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -37,7 +37,7 @@
 #include "sim-regno.h"
 #include "gdb/sim-ppc.h"
 #include "reggroups.h"
-#include "dwarf2-frame.h"
+#include "dwarf2/frame.h"
 #include "target-descriptions.h"
 #include "user-regs.h"
 #include "record-full.h"
     && (regnum) >= (tdep)->ppc_dl0_regnum \
     && (regnum) < (tdep)->ppc_dl0_regnum + 16)
 
+/* Determine if regnum is a "vX" alias for the raw "vrX" vector
+   registers.  */
+#define IS_V_ALIAS_PSEUDOREG(tdep, regnum) (\
+    (tdep)->ppc_v0_alias_regnum >= 0 \
+    && (regnum) >= (tdep)->ppc_v0_alias_regnum \
+    && (regnum) < (tdep)->ppc_v0_alias_regnum + ppc_num_vrs)
+
 /* Determine if regnum is a POWER7 VSX register.  */
 #define IS_VSX_PSEUDOREG(tdep, regnum) ((tdep)->ppc_vsr0_regnum >= 0 \
     && (regnum) >= (tdep)->ppc_vsr0_regnum \
     && (regnum) >= (tdep)->ppc_efpr0_regnum \
     && (regnum) < (tdep)->ppc_efpr0_regnum + ppc_num_efprs)
 
+/* Determine if regnum is a checkpointed decimal float
+   pseudo-register.  */
+#define IS_CDFP_PSEUDOREG(tdep, regnum) ((tdep)->ppc_cdl0_regnum >= 0 \
+    && (regnum) >= (tdep)->ppc_cdl0_regnum \
+    && (regnum) < (tdep)->ppc_cdl0_regnum + 16)
+
+/* Determine if regnum is a Checkpointed POWER7 VSX register.  */
+#define IS_CVSX_PSEUDOREG(tdep, regnum) ((tdep)->ppc_cvsr0_regnum >= 0 \
+    && (regnum) >= (tdep)->ppc_cvsr0_regnum \
+    && (regnum) < (tdep)->ppc_cvsr0_regnum + ppc_num_vsrs)
+
+/* Determine if regnum is a Checkpointed POWER7 Extended FP register.  */
+#define IS_CEFP_PSEUDOREG(tdep, regnum) ((tdep)->ppc_cefpr0_regnum >= 0 \
+    && (regnum) >= (tdep)->ppc_cefpr0_regnum \
+    && (regnum) < (tdep)->ppc_cefpr0_regnum + ppc_num_efprs)
+
 /* Holds the current set of options to be passed to the disassembler.  */
 static char *powerpc_disassembler_options;
 
@@ -130,6 +153,23 @@ static const char *const powerpc_vector_strings[] =
 static enum powerpc_vector_abi powerpc_vector_abi_global = POWERPC_VEC_AUTO;
 static const char *powerpc_vector_abi_string = "auto";
 
+/* PowerPC-related per-inferior data.  */
+
+static inferior_key<ppc_inferior_data> ppc_inferior_data_key;
+
+/* Get the per-inferior PowerPC data for INF.  */
+
+ppc_inferior_data *
+get_ppc_per_inferior (inferior *inf)
+{
+  ppc_inferior_data *per_inf = ppc_inferior_data_key.get (inf);
+
+  if (per_inf == nullptr)
+    per_inf = ppc_inferior_data_key.emplace (inf);
+
+  return per_inf;
+}
+
 /* To be used by skip_prologue.  */
 
 struct rs6000_framedata
@@ -161,7 +201,7 @@ struct rs6000_framedata
 int
 vsx_register_p (struct gdbarch *gdbarch, int regno)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
   if (tdep->ppc_vsr0_regnum < 0)
     return 0;
   else
@@ -173,7 +213,7 @@ vsx_register_p (struct gdbarch *gdbarch, int regno)
 int
 altivec_register_p (struct gdbarch *gdbarch, int regno)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
   if (tdep->ppc_vr0_regnum < 0 || tdep->ppc_vrsave_regnum < 0)
     return 0;
   else
@@ -185,7 +225,7 @@ altivec_register_p (struct gdbarch *gdbarch, int regno)
 int
 spe_register_p (struct gdbarch *gdbarch, int regno)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
   
   /* Is it a reference to EV0 -- EV31, and do we have those?  */
   if (IS_SPE_PSEUDOREG (tdep, regno))
@@ -217,20 +257,10 @@ spe_register_p (struct gdbarch *gdbarch, int regno)
 int
 ppc_floating_point_unit_p (struct gdbarch *gdbarch)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
 
   return (tdep->ppc_fp0_regnum >= 0
-          && tdep->ppc_fpscr_regnum >= 0);
-}
-
-/* Return non-zero if the architecture described by GDBARCH has
-   VSX registers (vsr0 --- vsr63).  */
-static int
-ppc_vsx_support_p (struct gdbarch *gdbarch)
-{
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-
-  return tdep->ppc_vsr0_regnum >= 0;
+         && tdep->ppc_fpscr_regnum >= 0);
 }
 
 /* Return non-zero if the architecture described by GDBARCH has
@@ -238,10 +268,10 @@ ppc_vsx_support_p (struct gdbarch *gdbarch)
 int
 ppc_altivec_support_p (struct gdbarch *gdbarch)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
 
   return (tdep->ppc_vr0_regnum >= 0
-          && tdep->ppc_vrsave_regnum >= 0);
+         && tdep->ppc_vrsave_regnum >= 0);
 }
 
 /* Check that TABLE[GDB_REGNO] is not already initialized, and then
@@ -267,7 +297,7 @@ set_sim_regno (int *table, int gdb_regno, int sim_regno)
 static void
 init_sim_regno_table (struct gdbarch *arch)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (arch);
   int total_regs = gdbarch_num_regs (arch);
   int *sim_regno = GDBARCH_OBSTACK_CALLOC (arch, total_regs, int);
   int i;
@@ -289,8 +319,8 @@ init_sim_regno_table (struct gdbarch *arch)
   if (tdep->ppc_fp0_regnum >= 0)
     for (i = 0; i < ppc_num_fprs; i++)
       set_sim_regno (sim_regno,
-                     tdep->ppc_fp0_regnum + i,
-                     sim_ppc_f0_regnum + i);
+                    tdep->ppc_fp0_regnum + i,
+                    sim_ppc_f0_regnum + i);
   if (tdep->ppc_fpscr_regnum >= 0)
     set_sim_regno (sim_regno, tdep->ppc_fpscr_regnum, sim_ppc_fpscr_regnum);
 
@@ -312,15 +342,15 @@ init_sim_regno_table (struct gdbarch *arch)
   if (tdep->ppc_vr0_regnum >= 0)
     {
       for (i = 0; i < ppc_num_vrs; i++)
-        set_sim_regno (sim_regno,
-                       tdep->ppc_vr0_regnum + i,
-                       sim_ppc_vr0_regnum + i);
+       set_sim_regno (sim_regno,
+                      tdep->ppc_vr0_regnum + i,
+                      sim_ppc_vr0_regnum + i);
 
       /* FIXME: jimb/2004-07-15: when we have tdep->ppc_vscr_regnum,
-         we can treat this more like the other cases.  */
+        we can treat this more like the other cases.  */
       set_sim_regno (sim_regno,
-                     tdep->ppc_vr0_regnum + ppc_num_vrs,
-                     sim_ppc_vscr_regnum);
+                    tdep->ppc_vr0_regnum + ppc_num_vrs,
+                    sim_ppc_vscr_regnum);
     }
   /* vsave is a special-purpose register, so the code below handles it.  */
 
@@ -328,8 +358,8 @@ init_sim_regno_table (struct gdbarch *arch)
   if (tdep->ppc_ev0_upper_regnum >= 0)
     for (i = 0; i < ppc_num_gprs; i++)
       set_sim_regno (sim_regno,
-                     tdep->ppc_ev0_upper_regnum + i,
-                     sim_ppc_rh0_regnum + i);
+                    tdep->ppc_ev0_upper_regnum + i,
+                    sim_ppc_rh0_regnum + i);
   if (tdep->ppc_acc_regnum >= 0)
     set_sim_regno (sim_regno, tdep->ppc_acc_regnum, sim_ppc_acc_regnum);
   /* spefscr is a special-purpose register, so the code below handles it.  */
@@ -361,15 +391,13 @@ init_sim_regno_table (struct gdbarch *arch)
 static int
 rs6000_register_sim_regno (struct gdbarch *gdbarch, int reg)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
   int sim_regno;
 
   if (tdep->sim_regno == NULL)
     init_sim_regno_table (gdbarch);
 
-  gdb_assert (0 <= reg 
-             && reg <= gdbarch_num_regs (gdbarch)
-                       + gdbarch_num_pseudo_regs (gdbarch));
+  gdb_assert (0 <= reg && reg <= gdbarch_num_cooked_regs (gdbarch));
   sim_regno = tdep->sim_regno[reg];
 
   if (sim_regno >= 0)
@@ -399,7 +427,7 @@ ppc_supply_reg (struct regcache *regcache, int regnum,
              && gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
            offset += regsize - gdb_regsize;
        }
-      regcache_raw_supply (regcache, regnum, regs + offset);
+      regcache->raw_supply (regnum, regs + offset);
     }
 }
 
@@ -428,13 +456,13 @@ ppc_collect_reg (const struct regcache *regcache, int regnum,
                        regsize - gdb_regsize);
            }
        }
-      regcache_raw_collect (regcache, regnum, regs + offset);
+      regcache->raw_collect (regnum, regs + offset);
     }
 }
     
 static int
 ppc_greg_offset (struct gdbarch *gdbarch,
-                struct gdbarch_tdep *tdep,
+                ppc_gdbarch_tdep *tdep,
                 const struct ppc_reg_offsets *offsets,
                 int regnum,
                 int *regsize)
@@ -471,7 +499,7 @@ ppc_greg_offset (struct gdbarch *gdbarch,
 }
 
 static int
-ppc_fpreg_offset (struct gdbarch_tdep *tdep,
+ppc_fpreg_offset (ppc_gdbarch_tdep *tdep,
                  const struct ppc_reg_offsets *offsets,
                  int regnum)
 {
@@ -485,24 +513,6 @@ ppc_fpreg_offset (struct gdbarch_tdep *tdep,
   return -1;
 }
 
-static int
-ppc_vrreg_offset (struct gdbarch_tdep *tdep,
-                 const struct ppc_reg_offsets *offsets,
-                 int regnum)
-{
-  if (regnum >= tdep->ppc_vr0_regnum
-      && regnum < tdep->ppc_vr0_regnum + ppc_num_vrs)
-    return offsets->vr0_offset + (regnum - tdep->ppc_vr0_regnum) * 16;
-
-  if (regnum == tdep->ppc_vrsave_regnum - 1)
-    return offsets->vscr_offset;
-
-  if (regnum == tdep->ppc_vrsave_regnum)
-    return offsets->vrsave_offset;
-
-  return -1;
-}
-
 /* Supply register REGNUM in the general-purpose register set REGSET
    from the buffer specified by GREGS and LEN to register cache
    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
@@ -512,7 +522,7 @@ ppc_supply_gregset (const struct regset *regset, struct regcache *regcache,
                    int regnum, const void *gregs, size_t len)
 {
   struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
   const struct ppc_reg_offsets *offsets
     = (const struct ppc_reg_offsets *) regset->regmap;
   size_t offset;
@@ -562,14 +572,13 @@ ppc_supply_fpregset (const struct regset *regset, struct regcache *regcache,
                     int regnum, const void *fpregs, size_t len)
 {
   struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep;
   const struct ppc_reg_offsets *offsets;
   size_t offset;
 
   if (!ppc_floating_point_unit_p (gdbarch))
     return;
 
-  tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
   offsets = (const struct ppc_reg_offsets *) regset->regmap;
   if (regnum == -1)
     {
@@ -591,81 +600,6 @@ ppc_supply_fpregset (const struct regset *regset, struct regcache *regcache,
                  regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8);
 }
 
-/* Supply register REGNUM in the VSX register set REGSET
-   from the buffer specified by VSXREGS and LEN to register cache
-   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
-
-void
-ppc_supply_vsxregset (const struct regset *regset, struct regcache *regcache,
-                    int regnum, const void *vsxregs, size_t len)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep;
-
-  if (!ppc_vsx_support_p (gdbarch))
-    return;
-
-  tdep = gdbarch_tdep (gdbarch);
-
-  if (regnum == -1)
-    {
-      int i;
-
-      for (i = tdep->ppc_vsr0_upper_regnum;
-          i < tdep->ppc_vsr0_upper_regnum + 32;
-          i++)
-       ppc_supply_reg (regcache, i, (const gdb_byte *) vsxregs, 0, 8);
-
-      return;
-    }
-  else
-    ppc_supply_reg (regcache, regnum, (const gdb_byte *) vsxregs, 0, 8);
-}
-
-/* Supply register REGNUM in the Altivec register set REGSET
-   from the buffer specified by VRREGS and LEN to register cache
-   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
-
-void
-ppc_supply_vrregset (const struct regset *regset, struct regcache *regcache,
-                    int regnum, const void *vrregs, size_t len)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep;
-  const struct ppc_reg_offsets *offsets;
-  size_t offset;
-
-  if (!ppc_altivec_support_p (gdbarch))
-    return;
-
-  tdep = gdbarch_tdep (gdbarch);
-  offsets = (const struct ppc_reg_offsets *) regset->regmap;
-  if (regnum == -1)
-    {
-      int i;
-
-      for (i = tdep->ppc_vr0_regnum, offset = offsets->vr0_offset;
-          i < tdep->ppc_vr0_regnum + ppc_num_vrs;
-          i++, offset += 16)
-        ppc_supply_reg (regcache, i, (const gdb_byte *) vrregs, offset, 16);
-
-      ppc_supply_reg (regcache, (tdep->ppc_vrsave_regnum - 1),
-                     (const gdb_byte *) vrregs, offsets->vscr_offset, 4);
-
-      ppc_supply_reg (regcache, tdep->ppc_vrsave_regnum,
-                     (const gdb_byte *) vrregs, offsets->vrsave_offset, 4);
-      return;
-    }
-
-  offset = ppc_vrreg_offset (tdep, offsets, regnum);
-  if (regnum != tdep->ppc_vrsave_regnum
-      && regnum != tdep->ppc_vrsave_regnum - 1)
-    ppc_supply_reg (regcache, regnum, (const gdb_byte *) vrregs, offset, 16);
-  else
-    ppc_supply_reg (regcache, regnum,
-                   (const gdb_byte *) vrregs, offset, 4);
-}
-
 /* Collect register REGNUM in the general-purpose register set
    REGSET from register cache REGCACHE into the buffer specified by
    GREGS and LEN.  If REGNUM is -1, do this for all registers in
@@ -677,7 +611,7 @@ ppc_collect_gregset (const struct regset *regset,
                     int regnum, void *gregs, size_t len)
 {
   struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
   const struct ppc_reg_offsets *offsets
     = (const struct ppc_reg_offsets *) regset->regmap;
   size_t offset;
@@ -728,14 +662,13 @@ ppc_collect_fpregset (const struct regset *regset,
                      int regnum, void *fpregs, size_t len)
 {
   struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep;
   const struct ppc_reg_offsets *offsets;
   size_t offset;
 
   if (!ppc_floating_point_unit_p (gdbarch))
     return;
 
-  tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
   offsets = (const struct ppc_reg_offsets *) regset->regmap;
   if (regnum == -1)
     {
@@ -757,87 +690,6 @@ ppc_collect_fpregset (const struct regset *regset,
                   regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8);
 }
 
-/* Collect register REGNUM in the VSX register set
-   REGSET from register cache REGCACHE into the buffer specified by
-   VSXREGS and LEN.  If REGNUM is -1, do this for all registers in
-   REGSET.  */
-
-void
-ppc_collect_vsxregset (const struct regset *regset,
-                     const struct regcache *regcache,
-                     int regnum, void *vsxregs, size_t len)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep;
-
-  if (!ppc_vsx_support_p (gdbarch))
-    return;
-
-  tdep = gdbarch_tdep (gdbarch);
-
-  if (regnum == -1)
-    {
-      int i;
-
-      for (i = tdep->ppc_vsr0_upper_regnum;
-          i < tdep->ppc_vsr0_upper_regnum + 32;
-          i++)
-       ppc_collect_reg (regcache, i, (gdb_byte *) vsxregs, 0, 8);
-
-      return;
-    }
-  else
-    ppc_collect_reg (regcache, regnum, (gdb_byte *) vsxregs, 0, 8);
-}
-
-
-/* Collect register REGNUM in the Altivec register set
-   REGSET from register cache REGCACHE into the buffer specified by
-   VRREGS and LEN.  If REGNUM is -1, do this for all registers in
-   REGSET.  */
-
-void
-ppc_collect_vrregset (const struct regset *regset,
-                     const struct regcache *regcache,
-                     int regnum, void *vrregs, size_t len)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep;
-  const struct ppc_reg_offsets *offsets;
-  size_t offset;
-
-  if (!ppc_altivec_support_p (gdbarch))
-    return;
-
-  tdep = gdbarch_tdep (gdbarch);
-  offsets = (const struct ppc_reg_offsets *) regset->regmap;
-  if (regnum == -1)
-    {
-      int i;
-
-      for (i = tdep->ppc_vr0_regnum, offset = offsets->vr0_offset;
-          i < tdep->ppc_vr0_regnum + ppc_num_vrs;
-          i++, offset += 16)
-       ppc_collect_reg (regcache, i, (gdb_byte *) vrregs, offset, 16);
-
-      ppc_collect_reg (regcache, (tdep->ppc_vrsave_regnum - 1),
-                      (gdb_byte *) vrregs, offsets->vscr_offset, 4);
-
-      ppc_collect_reg (regcache, tdep->ppc_vrsave_regnum,
-                      (gdb_byte *) vrregs, offsets->vrsave_offset, 4);
-      return;
-    }
-
-  offset = ppc_vrreg_offset (tdep, offsets, regnum);
-  if (regnum != tdep->ppc_vrsave_regnum
-      && regnum != tdep->ppc_vrsave_regnum - 1)
-    ppc_collect_reg (regcache, regnum, (gdb_byte *) vrregs, offset, 16);
-  else
-    ppc_collect_reg (regcache, regnum,
-                   (gdb_byte *) vrregs, offset, 4);
-}
-\f
-
 static int
 insn_changes_sp_or_jumps (unsigned long insn)
 {
@@ -849,8 +701,8 @@ insn_changes_sp_or_jumps (unsigned long insn)
   /* 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.  */
+          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 */
@@ -878,23 +730,23 @@ insn_changes_sp_or_jumps (unsigned long insn)
 
    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.
+         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.
+         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.  */
+       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_frame_p (struct frame_info *curfrm,
                                     struct gdbarch *gdbarch, CORE_ADDR pc)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_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;
@@ -915,11 +767,12 @@ rs6000_in_function_epilogue_frame_p (struct frame_info *curfrm,
 
   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;
+      if (!safe_frame_unwind_memory (curfrm, scan_pc,
+                                    {insn_buf, PPC_INSN_SIZE}))
+       return 0;
       insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE, byte_order);
       if (insn == 0x4e800020)
-        break;
+       break;
       /* Assume a bctr is a tail call unless it points strictly within
         this function.  */
       if (insn == 0x4e800420)
@@ -932,7 +785,7 @@ rs6000_in_function_epilogue_frame_p (struct frame_info *curfrm,
            break;
        }
       if (insn_changes_sp_or_jumps (insn))
-        return 0;
+       return 0;
     }
 
   /* Scan backward until adjustment to stack pointer (R1).  */
@@ -941,11 +794,12 @@ rs6000_in_function_epilogue_frame_p (struct frame_info *curfrm,
        scan_pc >= epilogue_start;
        scan_pc -= PPC_INSN_SIZE)
     {
-      if (!safe_frame_unwind_memory (curfrm, scan_pc, insn_buf, PPC_INSN_SIZE))
-        return 0;
+      if (!safe_frame_unwind_memory (curfrm, scan_pc,
+                                    {insn_buf, PPC_INSN_SIZE}))
+       return 0;
       insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE, byte_order);
       if (insn_changes_sp_or_jumps (insn))
-        return 1;
+       return 1;
     }
 
   return 0;
@@ -970,14 +824,14 @@ rs6000_fetch_pointer_argument (struct frame_info *frame, int argi,
 
 /* Sequence of bytes for breakpoint instruction.  */
 
-constexpr gdb_byte big_breakpoint[] = { 0x7d, 0x82, 0x10, 0x08 };
-constexpr gdb_byte little_breakpoint[] = { 0x08, 0x10, 0x82, 0x7d };
+constexpr gdb_byte big_breakpoint[] = { 0x7f, 0xe0, 0x00, 0x08 };
+constexpr gdb_byte little_breakpoint[] = { 0x08, 0x00, 0xe0, 0x7f };
 
 typedef BP_MANIPULATION_ENDIAN (little_breakpoint, big_breakpoint)
   rs6000_breakpoint;
 
 /* Instruction masks for displaced stepping.  */
-#define BRANCH_MASK 0xfc000000
+#define OP_MASK 0xfc000000
 #define BP_MASK 0xFC0007FE
 #define B_INSN 0x48000000
 #define BC_INSN 0x40000000
@@ -999,6 +853,17 @@ typedef BP_MANIPULATION_ENDIAN (little_breakpoint, big_breakpoint)
 #define STHCX_INSTRUCTION 0x7c0005ad
 #define STQCX_INSTRUCTION 0x7c00016d
 
+/* Instruction masks for single-stepping of addpcis/lnia.  */
+#define ADDPCIS_INSN            0x4c000004
+#define ADDPCIS_INSN_MASK       0xfc00003e
+#define ADDPCIS_TARGET_REGISTER 0x03F00000
+#define ADDPCIS_INSN_REGSHIFT   21
+
+#define PNOP_MASK 0xfff3ffff
+#define PNOP_INSN 0x07000000
+#define R_MASK 0x00100000
+#define R_ZERO 0x00000000
+
 /* Check if insn is one of the Load And Reserve instructions used for atomic
    sequences.  */
 #define IS_LOAD_AND_RESERVE_INSN(insn) ((insn & LOAD_AND_RESERVE_MASK) == LWARX_INSTRUCTION \
@@ -1014,79 +879,124 @@ typedef BP_MANIPULATION_ENDIAN (little_breakpoint, big_breakpoint)
                                         || (insn & STORE_CONDITIONAL_MASK) == STHCX_INSTRUCTION \
                                         || (insn & STORE_CONDITIONAL_MASK) == STQCX_INSTRUCTION)
 
-typedef buf_displaced_step_closure ppc_displaced_step_closure;
+typedef buf_displaced_step_copy_insn_closure
+  ppc_displaced_step_copy_insn_closure;
 
 /* We can't displaced step atomic sequences.  */
 
-static struct displaced_step_closure *
+static displaced_step_copy_insn_closure_up
 ppc_displaced_step_copy_insn (struct gdbarch *gdbarch,
                              CORE_ADDR from, CORE_ADDR to,
                              struct regcache *regs)
 {
   size_t len = gdbarch_max_insn_length (gdbarch);
-  std::unique_ptr<ppc_displaced_step_closure> closure
-    (new ppc_displaced_step_closure (len));
+  std::unique_ptr<ppc_displaced_step_copy_insn_closure> closure
+    (new ppc_displaced_step_copy_insn_closure (len));
   gdb_byte *buf = closure->buf.data ();
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   int insn;
 
-  read_memory (from, buf, len);
+  len = target_read (current_inferior()->top_target(), TARGET_OBJECT_MEMORY, NULL,
+                    buf, from, len);
+  if ((ssize_t) len < PPC_INSN_SIZE)
+    memory_error (TARGET_XFER_E_IO, from);
 
   insn = extract_signed_integer (buf, PPC_INSN_SIZE, byte_order);
 
+  /* Check for PNOP and for prefixed instructions with R=0.  Those
+     instructions are safe to displace.  Prefixed instructions with R=1
+     will read/write data to/from locations relative to the current PC.
+     We would not be able to fixup after an instruction has written data
+    into a displaced location, so decline to displace those instructions.  */
+  if ((insn & OP_MASK) == 1 << 26)
+    {
+      if (((insn & PNOP_MASK) != PNOP_INSN)
+         && ((insn & R_MASK) != R_ZERO))
+       {
+         displaced_debug_printf ("Not displacing prefixed instruction %08x at %s",
+                                 insn, paddress (gdbarch, from));
+         return NULL;
+       }
+    }
+  else
+    /* Non-prefixed instructions..  */
+    {
+      /* Set the instruction length to 4 to match the actual instruction
+        length.  */
+      len = 4;
+    }
+
   /* Assume all atomic sequences start with a Load and Reserve instruction.  */
   if (IS_LOAD_AND_RESERVE_INSN (insn))
     {
-      if (debug_displaced)
-       {
-         fprintf_unfiltered (gdb_stdlog,
-                             "displaced: can't displaced step "
-                             "atomic sequence at %s\n",
+      displaced_debug_printf ("can't displaced step atomic sequence at %s",
                              paddress (gdbarch, from));
-       }
 
       return NULL;
     }
 
   write_memory (to, buf, len);
 
-  if (debug_displaced)
-    {
-      fprintf_unfiltered (gdb_stdlog, "displaced: copy %s->%s: ",
-                          paddress (gdbarch, from), paddress (gdbarch, to));
-      displaced_step_dump_bytes (gdb_stdlog, buf, len);
-    }
+  displaced_debug_printf ("copy %s->%s: %s",
+                         paddress (gdbarch, from), paddress (gdbarch, to),
+                         displaced_step_dump_bytes (buf, len).c_str ());
 
-  return closure.release ();
+  /* This is a work around for a problem with g++ 4.8.  */
+  return displaced_step_copy_insn_closure_up (closure.release ());
 }
 
 /* Fix up the state of registers and memory after having single-stepped
    a displaced instruction.  */
 static void
 ppc_displaced_step_fixup (struct gdbarch *gdbarch,
-                         struct displaced_step_closure *closure_,
+                         struct displaced_step_copy_insn_closure *closure_,
                          CORE_ADDR from, CORE_ADDR to,
                          struct regcache *regs)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   /* Our closure is a copy of the instruction.  */
-  ppc_displaced_step_closure *closure = (ppc_displaced_step_closure *) closure_;
+  ppc_displaced_step_copy_insn_closure *closure
+    = (ppc_displaced_step_copy_insn_closure *) closure_;
   ULONGEST insn  = extract_unsigned_integer (closure->buf.data (),
                                             PPC_INSN_SIZE, byte_order);
-  ULONGEST opcode = 0;
+  ULONGEST opcode;
   /* Offset for non PC-relative instructions.  */
-  LONGEST offset = PPC_INSN_SIZE;
+  LONGEST offset;
 
-  opcode = insn & BRANCH_MASK;
+  opcode = insn & OP_MASK;
 
-  if (debug_displaced)
-    fprintf_unfiltered (gdb_stdlog,
-                       "displaced: (ppc) fixup (%s, %s)\n",
-                       paddress (gdbarch, from), paddress (gdbarch, to));
+  /* Set offset to 8 if this is an 8-byte (prefixed) instruction.  */
+  if ((opcode) == 1 << 26)
+    offset = 2 * PPC_INSN_SIZE;
+  else
+    offset = PPC_INSN_SIZE;
 
+  displaced_debug_printf ("(ppc) fixup (%s, %s)",
+                         paddress (gdbarch, from), paddress (gdbarch, to));
 
+  /* Handle the addpcis/lnia instruction.  */
+  if ((insn & ADDPCIS_INSN_MASK) == ADDPCIS_INSN)
+    {
+      LONGEST displaced_offset;
+      ULONGEST current_val;
+      /* Measure the displacement.  */
+      displaced_offset = from - to;
+      /* Identify the target register that was updated by the instruction.  */
+      int regnum = (insn & ADDPCIS_TARGET_REGISTER) >> ADDPCIS_INSN_REGSHIFT;
+      /* Read and update the target value.  */
+      regcache_cooked_read_unsigned (regs, regnum , &current_val);
+      displaced_debug_printf ("addpcis target regnum %d was %s now %s",
+                             regnum, paddress (gdbarch, current_val),
+                             paddress (gdbarch, current_val
+                                       + displaced_offset));
+      regcache_cooked_write_unsigned (regs, regnum,
+                                       current_val + displaced_offset);
+      /* point the PC back at the non-displaced instruction.  */
+      regcache_cooked_write_unsigned (regs, gdbarch_pc_regnum (gdbarch),
+                                   from + offset);
+    }
   /* Handle PC-relative branch instructions.  */
-  if (opcode == B_INSN || opcode == BC_INSN || opcode == BXL_INSN)
+  else if (opcode == B_INSN || opcode == BC_INSN || opcode == BXL_INSN)
     {
       ULONGEST current_pc;
 
@@ -1104,13 +1014,11 @@ ppc_displaced_step_fixup (struct gdbarch *gdbarch,
          if (!(insn & 0x2))
            {
              /* PC-relative addressing is being used in the branch.  */
-             if (debug_displaced)
-               fprintf_unfiltered
-                 (gdb_stdlog,
-                  "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));
+             displaced_debug_printf ("(ppc) branch instruction: %s",
+                                     paddress (gdbarch, insn));
+             displaced_debug_printf ("(ppc) adjusted PC from %s to %s",
+                                     paddress (gdbarch, current_pc),
+                                     paddress (gdbarch, from + offset));
 
              regcache_cooked_write_unsigned (regs,
                                              gdbarch_pc_regnum (gdbarch),
@@ -1134,13 +1042,12 @@ ppc_displaced_step_fixup (struct gdbarch *gdbarch,
       if (insn & 0x1)
        {
          /* Link register needs to be set to the next instruction's PC.  */
+         ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
          regcache_cooked_write_unsigned (regs,
-                                         gdbarch_tdep (gdbarch)->ppc_lr_regnum,
+                                         tdep->ppc_lr_regnum,
                                          from + PPC_INSN_SIZE);
-         if (debug_displaced)
-               fprintf_unfiltered (gdb_stdlog,
-                                   "displaced: (ppc) adjusted LR to %s\n",
-                                   paddress (gdbarch, from + PPC_INSN_SIZE));
+         displaced_debug_printf ("(ppc) adjusted LR to %s",
+                                 paddress (gdbarch, from + PPC_INSN_SIZE));
 
        }
     }
@@ -1149,18 +1056,67 @@ ppc_displaced_step_fixup (struct gdbarch *gdbarch,
   else if ((insn & BP_MASK) == BP_INSN)
     regcache_cooked_write_unsigned (regs, gdbarch_pc_regnum (gdbarch), from);
   else
-  /* Handle any other instructions that do not fit in the categories above.  */
-    regcache_cooked_write_unsigned (regs, gdbarch_pc_regnum (gdbarch),
-                                   from + offset);
+    {
+      /* Handle any other instructions that do not fit in the categories
+         above.  */
+      regcache_cooked_write_unsigned (regs, gdbarch_pc_regnum (gdbarch),
+                                     from + offset);
+    }
+}
+
+/* Implementation of gdbarch_displaced_step_prepare.  */
+
+static displaced_step_prepare_status
+ppc_displaced_step_prepare  (gdbarch *arch, thread_info *thread,
+                            CORE_ADDR &displaced_pc)
+{
+  ppc_inferior_data *per_inferior = get_ppc_per_inferior (thread->inf);
+
+  if (!per_inferior->disp_step_buf.has_value ())
+    {
+      /* Figure out where the displaced step buffer is.  */
+      CORE_ADDR disp_step_buf_addr
+       = displaced_step_at_entry_point (thread->inf->gdbarch);
+
+      per_inferior->disp_step_buf.emplace (disp_step_buf_addr);
+    }
+
+  return per_inferior->disp_step_buf->prepare (thread, displaced_pc);
+}
+
+/* Implementation of gdbarch_displaced_step_finish.  */
+
+static displaced_step_finish_status
+ppc_displaced_step_finish (gdbarch *arch, thread_info *thread,
+                          gdb_signal sig)
+{
+  ppc_inferior_data *per_inferior = get_ppc_per_inferior (thread->inf);
+
+  gdb_assert (per_inferior->disp_step_buf.has_value ());
+
+  return per_inferior->disp_step_buf->finish (arch, thread, sig);
+}
+
+/* Implementation of gdbarch_displaced_step_restore_all_in_ptid.  */
+
+static void
+ppc_displaced_step_restore_all_in_ptid (inferior *parent_inf, ptid_t ptid)
+{
+  ppc_inferior_data *per_inferior = ppc_inferior_data_key.get (parent_inf);
+
+  if (per_inferior == nullptr
+      || !per_inferior->disp_step_buf.has_value ())
+    return;
+
+  per_inferior->disp_step_buf->restore_in_ptid (ptid);
 }
 
 /* Always use hardware single-stepping to execute the
    displaced instruction.  */
-static int
-ppc_displaced_step_hw_singlestep (struct gdbarch *gdbarch,
-                                 struct displaced_step_closure *closure)
+static bool
+ppc_displaced_step_hw_singlestep (struct gdbarch *gdbarch)
 {
-  return 1;
+  return true;
 }
 
 /* Checks for an atomic sequence of instructions beginning with a
@@ -1173,7 +1129,7 @@ ppc_deal_with_atomic_sequence (struct regcache *regcache)
   struct gdbarch *gdbarch = regcache->arch ();
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   CORE_ADDR pc = regcache_read_pc (regcache);
-  CORE_ADDR breaks[2] = {-1, -1};
+  CORE_ADDR breaks[2] = {CORE_ADDR_MAX, CORE_ADDR_MAX};
   CORE_ADDR loc = pc;
   CORE_ADDR closing_insn; /* Instruction that closes the atomic sequence.  */
   int insn = read_memory_integer (loc, PPC_INSN_SIZE, byte_order);
@@ -1191,20 +1147,23 @@ ppc_deal_with_atomic_sequence (struct regcache *regcache)
      instructions.  */
   for (insn_count = 0; insn_count < atomic_sequence_length; ++insn_count)
     {
-      loc += PPC_INSN_SIZE;
+      if ((insn & OP_MASK) == 1 << 26)
+       loc += 2 * PPC_INSN_SIZE;
+      else
+       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 
-         its destination address.  */
-      if ((insn & BRANCH_MASK) == BC_INSN)
-        {
-          int immediate = ((insn & 0xfffc) ^ 0x8000) - 0x8000;
-          int absolute = insn & 2;
-
-          if (bc_insn_count >= 1)
-            return {}; /* More than one conditional branch found, fallback
-                          to the standard single-step code.  */
+        sequence.  If a conditional branch is found, put a breakpoint in 
+        its destination address.  */
+      if ((insn & OP_MASK) == BC_INSN)
+       {
+         int immediate = ((insn & 0xfffc) ^ 0x8000) - 0x8000;
+         int absolute = insn & 2;
+
+         if (bc_insn_count >= 1)
+           return {}; /* More than one conditional branch found, fallback
+                         to the standard single-step code.  */
  
          if (absolute)
            breaks[1] = immediate;
@@ -1213,10 +1172,10 @@ ppc_deal_with_atomic_sequence (struct regcache *regcache)
 
          bc_insn_count++;
          last_breakpoint++;
-        }
+       }
 
       if (IS_STORE_CONDITIONAL_INSN (insn))
-        break;
+       break;
     }
 
   /* Assume that the atomic sequence ends with a Store Conditional
@@ -1274,12 +1233,12 @@ store_param_on_stack_p (unsigned long op, int framep, int *r0_contains_arg)
       const int ry_regno = GET_SRC_REG (op);
 
       if (rx_regno == 0 && ry_regno >= 3 && ry_regno <= 10)
-        {
-          *r0_contains_arg = 1;
-          return 1;
-        }
+       {
+         *r0_contains_arg = 1;
+         return 1;
+       }
       else
-        return 0;
+       return 0;
     }
 
   /* Save a General Purpose Register on stack.  */
@@ -1292,7 +1251,7 @@ store_param_on_stack_p (unsigned long op, int framep, int *r0_contains_arg)
 
       return (rx_regno >= 3 && rx_regno <= 10);
     }
-           
+          
   /* Save a General Purpose Register on stack via the Frame Pointer.  */
 
   if (framep &&
@@ -1301,11 +1260,11 @@ store_param_on_stack_p (unsigned long op, int framep, int *r0_contains_arg)
        (op & 0xfc1f0000) == 0xd81f0000))      /* stfd Rx,NUM(r31) */
     {
       /* Rx: Usually, only r3 - r10 are used for parameter passing.
-         However, the compiler sometimes uses r0 to hold an argument.  */
+        However, the compiler sometimes uses r0 to hold an argument.  */
       const int rx_regno = GET_SRC_REG (op);
 
       return ((rx_regno >= 3 && rx_regno <= 10)
-              || (rx_regno == 0 && *r0_contains_arg));
+             || (rx_regno == 0 && *r0_contains_arg));
     }
 
   if ((op & 0xfc1f0000) == 0xfc010000)         /* frsp, fp?,NUM(r1) */
@@ -1357,6 +1316,39 @@ bl_to_blrl_insn_p (CORE_ADDR pc, int insn, enum bfd_endian byte_order)
   return 0;
 }
 
+/* Return true if OP is a stw or std instruction with
+   register operands RS and RA and any immediate offset.
+
+   If WITH_UPDATE is true, also return true if OP is
+   a stwu or stdu instruction with the same operands.
+
+   Return false otherwise.
+   */
+static bool
+store_insn_p (unsigned long op, unsigned long rs,
+             unsigned long ra, bool with_update)
+{
+  rs = rs << 21;
+  ra = ra << 16;
+
+  if (/* std RS, SIMM(RA) */
+      ((op & 0xffff0003) == (rs | ra | 0xf8000000)) ||
+      /* stw RS, SIMM(RA) */
+      ((op & 0xffff0000) == (rs | ra | 0x90000000)))
+    return true;
+
+  if (with_update)
+    {
+      if (/* stdu RS, SIMM(RA) */
+         ((op & 0xffff0003) == (rs | ra | 0xf8000001)) ||
+         /* stwu RS, SIMM(RA) */
+         ((op & 0xffff0000) == (rs | ra | 0x94000000)))
+       return true;
+    }
+
+  return false;
+}
+
 /* Masks for decoding a branch-and-link (bl) instruction.
 
    BL_MASK and BL_INSTRUCTION are used in combination with each other.
@@ -1364,7 +1356,7 @@ bl_to_blrl_insn_p (CORE_ADDR pc, int insn, enum bfd_endian byte_order)
    this masking operation is equal to BL_INSTRUCTION, then the opcode in
    question is a ``bl'' instruction.
    
-   BL_DISPLACMENT_MASK is anded with the opcode in order to extract
+   BL_DISPLACEMENT_MASK is anded with the opcode in order to extract
    the branch displacement.  */
 
 #define BL_MASK 0xfc000001
@@ -1398,150 +1390,150 @@ rs6000_skip_stack_check (struct gdbarch *gdbarch, const CORE_ADDR 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].  */
+        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);
-        }
+       {
+         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)].  */
+        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;
+       break;
 
       /* lis 0,-<some immediate> */
       pc = pc + 4;
       op = rs6000_fetch_instruction (gdbarch, pc);
       if ((op & 0xffff0000) != 0x3c000000)
-        break;
+       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);
-        }
+       {
+         pc = pc + 4;
+         op = rs6000_fetch_instruction (gdbarch, pc);
+       }
       /* add 0,12,0 */
       if (op != 0x7c0c0214)
-        break;
+       break;
 
       /* cmpw 0,12,0 */
       pc = pc + 4;
       op = rs6000_fetch_instruction (gdbarch, pc);
       if (op != 0x7c0c0000)
-        break;
+       break;
 
       /* beq 0,<disp> */
       pc = pc + 4;
       op = rs6000_fetch_instruction (gdbarch, pc);
       if ((op & 0xff9f0001) != 0x41820000)
-        break;
+       break;
 
       /* addi 12,12,-<some immediate> */
       pc = pc + 4;
       op = rs6000_fetch_instruction (gdbarch, pc);
       if ((op & 0xffff0000) != 0x398c0000)
-        break;
+       break;
 
       /* stw 0,0(12) */
       pc = pc + 4;
       op = rs6000_fetch_instruction (gdbarch, pc);
       if (op != 0x900c0000)
-        break;
+       break;
 
       /* b <disp> */
       pc = pc + 4;
       op = rs6000_fetch_instruction (gdbarch, pc);
       if ((op & 0xfc000001) != 0x48000000)
-        break;
+       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);
-        }
+       {
+         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
+  /* Third sequence: No probe; instead, a comparison 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
+       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
+       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: */
+       {
+         /* small stack frame variant not recognized; try the
+            big stack frame variant: */
 
-          /* addis 0,1,<some immediate> */
-          if ((op & 0xffff0000) != 0x3c010000)
-            break;
+         /* 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;
-        }
+         /* 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;
+       break;
       
       /* lwz 12,<some immediate>(12) */
       pc = pc + 4;
       op = rs6000_fetch_instruction (gdbarch, pc);
       if ((op & 0xffff0000) != 0x818c0000)
-        break;
+       break;
 
       /* twllt 0,12 */
       pc = pc + 4;
       op = rs6000_fetch_instruction (gdbarch, pc);
       if ((op & 0xfffffffe) != 0x7c406008)
-        break;
+       break;
 
       /* We found a valid stack-check sequence, return the new PC.  */
       return pc;
@@ -1583,6 +1575,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
   gdb_byte buf[4];
   unsigned long op;
   long offset = 0;
+  long alloca_reg_offset = 0;
   long vr_saved_offset = 0;
   int lr_reg = -1;
   int cr_reg = -1;
@@ -1597,7 +1590,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
   int num_skip_non_prologue_insns = 0;
   int r0_contains_arg = 0;
   const struct bfd_arch_info *arch_info = gdbarch_bfd_arch_info (gdbarch);
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
   memset (fdata, 0, sizeof (struct rs6000_framedata));
@@ -1617,7 +1610,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
   for (;; pc += 4)
     {
       /* Sometimes it isn't clear if an instruction is a prologue
-         instruction or not.  When we encounter one of these ambiguous
+        instruction or not.  When we encounter one of these ambiguous
         cases, we'll set prev_insn_was_prologue_insn to 0 (false).
         Otherwise, we'll assume that it really is a prologue instruction.  */
       if (prev_insn_was_prologue_insn)
@@ -1655,15 +1648,15 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
             ones.  */
          if (lr_reg == -1)
            lr_reg = (op & 0x03e00000) >> 21;
-          if (lr_reg == 0)
-            r0_contains_arg = 0;
+         if (lr_reg == 0)
+           r0_contains_arg = 0;
          continue;
        }
       else if ((op & 0xfc1fffff) == 0x7c000026)
        {                       /* mfcr Rx */
-         cr_reg = (op & 0x03e00000);
-          if (cr_reg == 0)
-            r0_contains_arg = 0;
+         cr_reg = (op & 0x03e00000) >> 21;
+         if (cr_reg == 0)
+           r0_contains_arg = 0;
          continue;
 
        }
@@ -1712,7 +1705,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
          continue;
        }
       else if (op == 0x60000000)
-        {
+       {
          /* nop */
          /* Allow nops in the prologue, but do not consider them to
             be part of the prologue unless followed by other prologue
@@ -1725,7 +1718,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
        {                       /* addis 0,0,NUM, used for >= 32k frames */
          fdata->offset = (op & 0x0000ffff) << 16;
          fdata->frameless = 0;
-          r0_contains_arg = 0;
+         r0_contains_arg = 0;
          continue;
 
        }
@@ -1733,19 +1726,22 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
        {                       /* ori 0,0,NUM, 2nd half of >= 32k frames */
          fdata->offset |= (op & 0x0000ffff);
          fdata->frameless = 0;
-          r0_contains_arg = 0;
+         r0_contains_arg = 0;
          continue;
 
        }
       else if (lr_reg >= 0 &&
-              /* std Rx, NUM(r1) || stdu Rx, NUM(r1) */
-              (((op & 0xffff0000) == (lr_reg | 0xf8010000)) ||
-               /* stw Rx, NUM(r1) */
-               ((op & 0xffff0000) == (lr_reg | 0x90010000)) ||
-               /* stwu Rx, NUM(r1) */
-               ((op & 0xffff0000) == (lr_reg | 0x94010000))))
-       {       /* where Rx == lr */
-         fdata->lr_offset = offset;
+              ((store_insn_p (op, lr_reg, 1, true)) ||
+               (framep &&
+                (store_insn_p (op, lr_reg,
+                               fdata->alloca_reg - tdep->ppc_gp0_regnum,
+                               false)))))
+       {
+         if (store_insn_p (op, lr_reg, 1, true))
+           fdata->lr_offset = offset;
+         else /* LR save through frame pointer. */
+           fdata->lr_offset = alloca_reg_offset;
+
          fdata->nosavedpc = 0;
          /* Invalidate lr_reg, but don't set it to -1.
             That would mean that it had never been set.  */
@@ -1760,13 +1756,8 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
 
        }
       else if (cr_reg >= 0 &&
-              /* std Rx, NUM(r1) || stdu Rx, NUM(r1) */
-              (((op & 0xffff0000) == (cr_reg | 0xf8010000)) ||
-               /* stw Rx, NUM(r1) */
-               ((op & 0xffff0000) == (cr_reg | 0x90010000)) ||
-               /* stwu Rx, NUM(r1) */
-               ((op & 0xffff0000) == (cr_reg | 0x94010000))))
-       {       /* where Rx == cr */
+              (store_insn_p (op, cr_reg, 1, true)))
+       {
          fdata->cr_offset = offset;
          /* Invalidate cr_reg, but don't set it to -1.
             That would mean that it had never been set.  */
@@ -1814,7 +1805,7 @@ 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, byte_order))
+         if (lr_reg != -1 && bl_to_blrl_insn_p (pc, op, byte_order))
            {
              fdata->used_bl = 1;
              continue;
@@ -1857,8 +1848,8 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
          offset = fdata->offset;
          continue;
        }
-      else if ((op & 0xfc1f016a) == 0x7c01016e)
-       {                       /* stwux rX,r1,rY */
+      else if ((op & 0xfc1f07fa) == 0x7c01016a)
+       {               /* stwux rX,r1,rY  || stdux rX,r1,rY */
          /* No way to figure out what r1 is going to be.  */
          fdata->frameless = 0;
          offset = fdata->offset;
@@ -1871,20 +1862,13 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
          offset = fdata->offset;
          continue;
        }
-      else if ((op & 0xfc1f016a) == 0x7c01016a)
-       {                       /* stdux rX,r1,rY */
-         /* No way to figure out what r1 is going to be.  */
+      else if ((op & 0xffff0000) == 0x38210000)
+       {                       /* addi r1,r1,SIMM */
          fdata->frameless = 0;
+         fdata->offset += SIGNED_SHORT (op);
          offset = fdata->offset;
          continue;
        }
-      else if ((op & 0xffff0000) == 0x38210000)
-       {                       /* addi r1,r1,SIMM */
-         fdata->frameless = 0;
-         fdata->offset += SIGNED_SHORT (op);
-         offset = fdata->offset;
-         continue;
-       }
       /* Load up minimal toc pointer.  Do not treat an epilogue restore
         of r31 as a minimal TOC load.  */
       else if (((op >> 22) == 0x20f    ||      /* l r31,... or l r30,...  */
@@ -1896,12 +1880,12 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
          continue;
 
          /* move parameters from argument registers to local variable
-             registers */
-       }
+            registers */
+       }
       else if ((op & 0xfc0007fe) == 0x7c000378 &&      /* mr(.)  Rx,Ry */
-               (((op >> 21) & 31) >= 3) &&              /* R3 >= Ry >= R10 */
-               (((op >> 21) & 31) <= 10) &&
-               ((long) ((op >> 16) & 31)
+              (((op >> 21) & 31) >= 3) &&              /* R3 >= Ry >= R10 */
+              (((op >> 21) & 31) <= 10) &&
+              ((long) ((op >> 16) & 31)
                >= fdata->saved_gpr)) /* Rx: local var reg */
        {
          continue;
@@ -1910,7 +1894,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
        }
       /* Move parameters from argument registers to temporary register.  */
       else if (store_param_on_stack_p (op, framep, &r0_contains_arg))
-        {
+       {
          continue;
 
          /* Set up frame pointer */
@@ -1920,6 +1904,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
          fdata->frameless = 0;
          framep = 1;
          fdata->alloca_reg = (tdep->ppc_gp0_regnum + 29);
+         alloca_reg_offset = offset;
          continue;
 
          /* Another way to set up the frame pointer.  */
@@ -1930,6 +1915,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
          fdata->frameless = 0;
          framep = 1;
          fdata->alloca_reg = (tdep->ppc_gp0_regnum + 31);
+         alloca_reg_offset = offset;
          continue;
 
          /* Another way to set up the frame pointer.  */
@@ -1940,6 +1926,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
          framep = 1;
          fdata->alloca_reg = (tdep->ppc_gp0_regnum
                               + ((op & ~0x38010000) >> 21));
+         alloca_reg_offset = offset;
          continue;
        }
       /* AltiVec related instructions.  */
@@ -1952,28 +1939,28 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
         mtspr SPR256 Rn == 011111 nnnnn 0000001000 01110100110  */
       else if ((op & 0xfc1fffff) == 0x7c0042a6)    /* mfvrsave Rn */
        {
-          vrsave_reg = GET_SRC_REG (op);
+         vrsave_reg = GET_SRC_REG (op);
          continue;
        }
       else if ((op & 0xfc1fffff) == 0x7c0043a6)     /* mtvrsave Rn */
-        {
-          continue;
-        }
+       {
+         continue;
+       }
       /* Store the register where vrsave was saved to onto the stack:
-         rS is the register where vrsave was stored in a previous
+        rS is the register where vrsave was stored in a previous
         instruction.  */
       /* 100100 sssss 00001 dddddddd dddddddd */
       else if ((op & 0xfc1f0000) == 0x90010000)     /* stw rS, d(r1) */
-        {
-          if (vrsave_reg == GET_SRC_REG (op))
+       {
+         if (vrsave_reg == GET_SRC_REG (op))
            {
              fdata->vrsave_offset = SIGNED_SHORT (op) + offset;
              vrsave_reg = -1;
            }
-          continue;
-        }
+         continue;
+       }
       /* Compute the new value of vrsave, by modifying the register
-         where vrsave was saved to.  */
+        where vrsave was saved to.  */
       else if (((op & 0xfc000000) == 0x64000000)    /* oris Ra, Rs, UIMM */
               || ((op & 0xfc000000) == 0x60000000))/* ori Ra, Rs, UIMM */
        {
@@ -1985,22 +1972,22 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
       /* 001110 00000 00000 iiii iiii iiii iiii  */
       /* 001110 01110 00000 iiii iiii iiii iiii  */
       else if ((op & 0xffff0000) == 0x38000000         /* li r0, SIMM */
-               || (op & 0xffff0000) == 0x39c00000)     /* li r14, SIMM */
+              || (op & 0xffff0000) == 0x39c00000)     /* li r14, SIMM */
        {
-          if ((op & 0xffff0000) == 0x38000000)
-            r0_contains_arg = 0;
+         if ((op & 0xffff0000) == 0x38000000)
+           r0_contains_arg = 0;
          li_found_pc = pc;
          vr_saved_offset = SIGNED_SHORT (op);
 
-          /* This insn by itself is not part of the prologue, unless
-             if part of the pair of insns mentioned above.  So do not
-             record this insn as part of the prologue yet.  */
-          prev_insn_was_prologue_insn = 0;
+         /* This insn by itself is not part of the prologue, unless
+            if part of the pair of insns mentioned above.  So do not
+            record this insn as part of the prologue yet.  */
+         prev_insn_was_prologue_insn = 0;
        }
       /* Store vector register S at (r31+r0) aligned to 16 bytes.  */      
       /* 011111 sssss 11111 00000 00111001110 */
       else if ((op & 0xfc1fffff) == 0x7c1f01ce)   /* stvx Vs, R31, R0 */
-        {
+       {
          if (pc == (li_found_pc + 4))
            {
              vr_reg = GET_SRC_REG (op);
@@ -2021,16 +2008,16 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
 
       /* Start BookE related instructions.  */
       /* Store gen register S at (r31+uimm).
-         Any register less than r13 is volatile, so we don't care.  */
+        Any register less than r13 is volatile, so we don't care.  */
       /* 000100 sssss 11111 iiiii 01100100001 */
       else if (arch_info->mach == bfd_mach_ppc_e500
               && (op & 0xfc1f07ff) == 0x101f0321)    /* evstdd Rs,uimm(R31) */
        {
-          if ((op & 0x03e00000) >= 0x01a00000) /* Rs >= r13 */
+         if ((op & 0x03e00000) >= 0x01a00000)  /* Rs >= r13 */
            {
-              unsigned int imm;
+             unsigned int imm;
              ev_reg = GET_SRC_REG (op);
-              imm = (op >> 11) & 0x1f;
+             imm = (op >> 11) & 0x1f;
              ev_offset = imm * 8;
              /* If this is the first vector reg to be saved, or if
                 it has a lower number than others previously seen,
@@ -2041,40 +2028,40 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
                  fdata->ev_offset = ev_offset + offset;
                }
            }
-          continue;
-        }
+         continue;
+       }
       /* Store gen register rS at (r1+rB).  */
       /* 000100 sssss 00001 bbbbb 01100100000 */
       else if (arch_info->mach == bfd_mach_ppc_e500
               && (op & 0xffe007ff) == 0x13e00320)     /* evstddx RS,R1,Rb */
        {
-          if (pc == (li_found_pc + 4))
-            {
-              ev_reg = GET_SRC_REG (op);
+         if (pc == (li_found_pc + 4))
+           {
+             ev_reg = GET_SRC_REG (op);
              /* If this is the first vector reg to be saved, or if
-                 it has a lower number than others previously seen,
-                 reupdate the frame info.  */
-              /* We know the contents of rB from the previous instruction.  */
+                it has a lower number than others previously seen,
+                reupdate the frame info.  */
+             /* We know the contents of rB from the previous instruction.  */
              if (fdata->saved_ev == -1 || fdata->saved_ev > ev_reg)
                {
-                  fdata->saved_ev = ev_reg;
-                  fdata->ev_offset = vr_saved_offset + offset;
+                 fdata->saved_ev = ev_reg;
+                 fdata->ev_offset = vr_saved_offset + offset;
                }
              vr_saved_offset = -1;
              ev_reg = -1;
              li_found_pc = 0;
-            }
-          continue;
-        }
+           }
+         continue;
+       }
       /* Store gen register r31 at (rA+uimm).  */
       /* 000100 11111 aaaaa iiiii 01100100001 */
       else if (arch_info->mach == bfd_mach_ppc_e500
               && (op & 0xffe007ff) == 0x13e00321)   /* evstdd R31,Ra,UIMM */
-        {
-          /* Wwe know that the source register is 31 already, but
-             it can't hurt to compute it.  */
+       {
+         /* Wwe know that the source register is 31 already, but
+            it can't hurt to compute it.  */
          ev_reg = GET_SRC_REG (op);
-          ev_offset = ((op >> 11) & 0x1f) * 8;
+         ev_offset = ((op >> 11) & 0x1f) * 8;
          /* If this is the first vector reg to be saved, or if
             it has a lower number than others previously seen,
             reupdate the frame info.  */
@@ -2085,23 +2072,23 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
            }
 
          continue;
-       }
+       }
       /* Store gen register S at (r31+r0).
-         Store param on stack when offset from SP bigger than 4 bytes.  */
+        Store param on stack when offset from SP bigger than 4 bytes.  */
       /* 000100 sssss 11111 00000 01100100000 */
       else if (arch_info->mach == bfd_mach_ppc_e500
               && (op & 0xfc1fffff) == 0x101f0320)     /* evstddx Rs,R31,R0 */
        {
-          if (pc == (li_found_pc + 4))
-            {
-              if ((op & 0x03e00000) >= 0x01a00000)
+         if (pc == (li_found_pc + 4))
+           {
+             if ((op & 0x03e00000) >= 0x01a00000)
                {
                  ev_reg = GET_SRC_REG (op);
                  /* If this is the first vector reg to be saved, or if
                     it has a lower number than others previously seen,
                     reupdate the frame info.  */
-                  /* We know the contents of r0 from the previous
-                     instruction.  */
+                 /* We know the contents of r0 from the previous
+                    instruction.  */
                  if (fdata->saved_ev == -1 || fdata->saved_ev > ev_reg)
                    {
                      fdata->saved_ev = ev_reg;
@@ -2112,22 +2099,25 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
              vr_saved_offset = -1;
              li_found_pc = 0;
              continue;
-            }
+           }
        }
       /* End BookE related instructions.  */
 
       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.  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;
+             && fdata->saved_gpr != -1)
+           {
+             unsigned int all_mask = ~((1U << fdata->saved_gpr) - 1);
+
+             if ((fdata->gpr_mask & all_mask) == all_mask)
+               break;
+           }
 
          if (op == 0x4e800020          /* blr */
              || op == 0x4e800420)      /* bctr */
@@ -2138,6 +2128,12 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
            /* Never skip branches.  */
            break;
 
+         /* Test based on opcode and mask values of
+            powerpc_opcodes[svc..svcla] in opcodes/ppc-opc.c.  */
+         if ((op & 0xffff0000) == 0x44000000)
+           /* Never skip system calls.  */
+           break;
+
          if (num_skip_non_prologue_insns++ > max_skip_non_prologue_insns)
            /* Do not scan too many insns, scanning insns is expensive with
               remote targets.  */
@@ -2248,12 +2244,12 @@ rs6000_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
       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
+        to __eabi in case the GCC option "-fleading-underscore" was
         used to compile the program.  */
       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))
+         && s.minsym->linkage_name () != NULL
+         && (strcmp (s.minsym->linkage_name (), "__eabi") == 0
+             || strcmp (s.minsym->linkage_name (), "___eabi") == 0))
        pc += 4;
     }
   return pc;
@@ -2314,7 +2310,7 @@ static CORE_ADDR
 rs6000_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   unsigned int ii, op;
   int rel;
@@ -2337,7 +2333,7 @@ rs6000_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
   msymbol = lookup_minimal_symbol_by_pc (pc);
   if (msymbol.minsym
       && rs6000_in_solib_return_trampoline (gdbarch, pc,
-                                           MSYMBOL_LINKAGE_NAME (msymbol.minsym)))
+                                           msymbol.minsym->linkage_name ()))
     {
       /* Double-check that the third instruction from PC is relative "b".  */
       op = read_memory_integer (pc + 8, 4, byte_order);
@@ -2372,7 +2368,7 @@ rs6000_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
 static struct type *
 rs6000_builtin_type_vec64 (struct gdbarch *gdbarch)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
 
   if (!tdep->ppc_builtin_type_vec64)
     {
@@ -2404,8 +2400,8 @@ rs6000_builtin_type_vec64 (struct gdbarch *gdbarch)
       append_composite_type_field (t, "v8_int8",
                                   init_vector_type (bt->builtin_int8, 8));
 
-      TYPE_VECTOR (t) = 1;
-      TYPE_NAME (t) = "ppc_builtin_type_vec64";
+      t->set_is_vector (true);
+      t->set_name ("ppc_builtin_type_vec64");
       tdep->ppc_builtin_type_vec64 = t;
     }
 
@@ -2417,7 +2413,7 @@ rs6000_builtin_type_vec64 (struct gdbarch *gdbarch)
 static struct type *
 rs6000_builtin_type_vec128 (struct gdbarch *gdbarch)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
 
   if (!tdep->ppc_builtin_type_vec128)
     {
@@ -2426,6 +2422,7 @@ rs6000_builtin_type_vec128 (struct gdbarch *gdbarch)
       /* The type we're building is this
 
         type = union __ppc_builtin_type_vec128 {
+            float128_t float128;
             uint128_t uint128;
             double v2_double[2];
             float v4_float[4];
@@ -2435,10 +2432,15 @@ rs6000_builtin_type_vec128 (struct gdbarch *gdbarch)
         }
       */
 
+      /* PPC specific type for IEEE 128-bit float field */
+      struct type *t_float128
+       = arch_float_type (gdbarch, 128, "float128_t", floatformats_ia64_quad);
+
       struct type *t;
 
       t = arch_composite_type (gdbarch,
                               "__ppc_builtin_type_vec128", TYPE_CODE_UNION);
+      append_composite_type_field (t, "float128", t_float128);
       append_composite_type_field (t, "uint128", bt->builtin_uint128);
       append_composite_type_field (t, "v2_double",
                                   init_vector_type (bt->builtin_double, 2));
@@ -2451,8 +2453,8 @@ rs6000_builtin_type_vec128 (struct gdbarch *gdbarch)
       append_composite_type_field (t, "v16_int8",
                                   init_vector_type (bt->builtin_int8, 16));
 
-      TYPE_VECTOR (t) = 1;
-      TYPE_NAME (t) = "ppc_builtin_type_vec128";
+      t->set_is_vector (true);
+      t->set_name ("ppc_builtin_type_vec128");
       tdep->ppc_builtin_type_vec128 = t;
     }
 
@@ -2465,7 +2467,7 @@ rs6000_builtin_type_vec128 (struct gdbarch *gdbarch)
 static const char *
 rs6000_register_name (struct gdbarch *gdbarch, int regno)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
 
   /* The upper half "registers" have names in the XML description,
      but we present only the low GPRs and the full 64-bit registers
@@ -2481,6 +2483,11 @@ rs6000_register_name (struct gdbarch *gdbarch, int regno)
       && regno < tdep->ppc_vsr0_upper_regnum + ppc_num_gprs)
     return "";
 
+  /* Hide the upper halves of the cvs0~cvs31 registers.  */
+  if (PPC_CVSR0_UPPER_REGNUM <= regno
+      && regno < PPC_CVSR0_UPPER_REGNUM + ppc_num_gprs)
+    return "";
+
   /* Check if the SPE pseudo registers are available.  */
   if (IS_SPE_PSEUDOREG (tdep, regno))
     {
@@ -2505,6 +2512,18 @@ rs6000_register_name (struct gdbarch *gdbarch, int regno)
       return dfp128_regnames[regno - tdep->ppc_dl0_regnum];
     }
 
+  /* Check if this is a vX alias for a raw vrX vector register.  */
+  if (IS_V_ALIAS_PSEUDOREG (tdep, regno))
+    {
+      static const char *const vector_alias_regnames[] = {
+       "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
+       "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
+       "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
+       "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
+      };
+      return vector_alias_regnames[regno - tdep->ppc_v0_alias_regnum];
+    }
+
   /* Check if this is a VSX pseudo-register.  */
   if (IS_VSX_PSEUDOREG (tdep, regno))
     {
@@ -2535,6 +2554,48 @@ rs6000_register_name (struct gdbarch *gdbarch, int regno)
       return efpr_regnames[regno - tdep->ppc_efpr0_regnum];
     }
 
+  /* Check if this is a Checkpointed DFP pseudo-register.  */
+  if (IS_CDFP_PSEUDOREG (tdep, regno))
+    {
+      static const char *const cdfp128_regnames[] = {
+       "cdl0", "cdl1", "cdl2", "cdl3",
+       "cdl4", "cdl5", "cdl6", "cdl7",
+       "cdl8", "cdl9", "cdl10", "cdl11",
+       "cdl12", "cdl13", "cdl14", "cdl15"
+      };
+      return cdfp128_regnames[regno - tdep->ppc_cdl0_regnum];
+    }
+
+  /* Check if this is a Checkpointed VSX pseudo-register.  */
+  if (IS_CVSX_PSEUDOREG (tdep, regno))
+    {
+      static const char *const cvsx_regnames[] = {
+       "cvs0", "cvs1", "cvs2", "cvs3", "cvs4", "cvs5", "cvs6", "cvs7",
+       "cvs8", "cvs9", "cvs10", "cvs11", "cvs12", "cvs13", "cvs14",
+       "cvs15", "cvs16", "cvs17", "cvs18", "cvs19", "cvs20", "cvs21",
+       "cvs22", "cvs23", "cvs24", "cvs25", "cvs26", "cvs27", "cvs28",
+       "cvs29", "cvs30", "cvs31", "cvs32", "cvs33", "cvs34", "cvs35",
+       "cvs36", "cvs37", "cvs38", "cvs39", "cvs40", "cvs41", "cvs42",
+       "cvs43", "cvs44", "cvs45", "cvs46", "cvs47", "cvs48", "cvs49",
+       "cvs50", "cvs51", "cvs52", "cvs53", "cvs54", "cvs55", "cvs56",
+       "cvs57", "cvs58", "cvs59", "cvs60", "cvs61", "cvs62", "cvs63"
+      };
+      return cvsx_regnames[regno - tdep->ppc_cvsr0_regnum];
+    }
+
+  /* Check if the this is a Checkpointed Extended FP pseudo-register.  */
+  if (IS_CEFP_PSEUDOREG (tdep, regno))
+    {
+      static const char *const cefpr_regnames[] = {
+       "cf32", "cf33", "cf34", "cf35", "cf36", "cf37", "cf38",
+       "cf39", "cf40", "cf41", "cf42", "cf43", "cf44", "cf45",
+       "cf46", "cf47", "cf48", "cf49", "cf50", "cf51",
+       "cf52", "cf53", "cf54", "cf55", "cf56", "cf57",
+       "cf58", "cf59", "cf60", "cf61", "cf62", "cf63"
+      };
+      return cefpr_regnames[regno - tdep->ppc_cefpr0_regnum];
+    }
+
   return tdesc_register_name (gdbarch, regno);
 }
 
@@ -2544,47 +2605,51 @@ rs6000_register_name (struct gdbarch *gdbarch, int regno)
 static struct type *
 rs6000_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-
-  /* These are the only pseudo-registers we support.  */
-  gdb_assert (IS_SPE_PSEUDOREG (tdep, regnum)
-             || IS_DFP_PSEUDOREG (tdep, regnum)
-             || IS_VSX_PSEUDOREG (tdep, regnum)
-             || IS_EFP_PSEUDOREG (tdep, regnum));
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
 
   /* These are the e500 pseudo-registers.  */
   if (IS_SPE_PSEUDOREG (tdep, regnum))
     return rs6000_builtin_type_vec64 (gdbarch);
-  else if (IS_DFP_PSEUDOREG (tdep, regnum))
+  else if (IS_DFP_PSEUDOREG (tdep, regnum)
+          || IS_CDFP_PSEUDOREG (tdep, regnum))
     /* PPC decimal128 pseudo-registers.  */
     return builtin_type (gdbarch)->builtin_declong;
-  else if (IS_VSX_PSEUDOREG (tdep, regnum))
+  else if (IS_V_ALIAS_PSEUDOREG (tdep, regnum))
+    return gdbarch_register_type (gdbarch,
+                                 tdep->ppc_vr0_regnum
+                                 + (regnum
+                                    - tdep->ppc_v0_alias_regnum));
+  else if (IS_VSX_PSEUDOREG (tdep, regnum)
+          || IS_CVSX_PSEUDOREG (tdep, regnum))
     /* POWER7 VSX pseudo-registers.  */
     return rs6000_builtin_type_vec128 (gdbarch);
-  else
+  else if (IS_EFP_PSEUDOREG (tdep, regnum)
+          || IS_CEFP_PSEUDOREG (tdep, regnum))
     /* POWER7 Extended FP pseudo-registers.  */
     return builtin_type (gdbarch)->builtin_double;
+  else
+    internal_error (__FILE__, __LINE__,
+                   _("rs6000_pseudo_register_type: "
+                     "called on unexpected register '%s' (%d)"),
+                   gdbarch_register_name (gdbarch, regnum), regnum);
 }
 
-/* Is REGNUM a member of REGGROUP?  */
+/* Check if REGNUM is a member of REGGROUP.  We only need to handle
+   the vX aliases for the vector registers by always returning false
+   to avoid duplicated information in "info register vector/all",
+   since the raw vrX registers will already show in these cases.  For
+   other pseudo-registers we use the default membership function.  */
+
 static int
 rs6000_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
                                   struct reggroup *group)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-
-  /* These are the only pseudo-registers we support.  */
-  gdb_assert (IS_SPE_PSEUDOREG (tdep, regnum)
-             || IS_DFP_PSEUDOREG (tdep, regnum)
-             || IS_VSX_PSEUDOREG (tdep, regnum)
-             || IS_EFP_PSEUDOREG (tdep, regnum));
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
 
-  /* These are the e500 pseudo-registers or the POWER7 VSX registers.  */
-  if (IS_SPE_PSEUDOREG (tdep, regnum) || IS_VSX_PSEUDOREG (tdep, regnum))
-    return group == all_reggroup || group == vector_reggroup;
+  if (IS_V_ALIAS_PSEUDOREG (tdep, regnum))
+    return 0;
   else
-    /* PPC decimal128 or Extended FP pseudo-registers.  */
-    return group == all_reggroup || group == float_reggroup;
+    return default_register_reggroup_p (gdbarch, regnum, group);
 }
 
 /* The register format for RS/6000 floating point registers is always
@@ -2594,31 +2659,33 @@ static int
 rs6000_convert_register_p (struct gdbarch *gdbarch, int regnum,
                           struct type *type)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
 
   return (tdep->ppc_fp0_regnum >= 0
          && regnum >= tdep->ppc_fp0_regnum
          && regnum < tdep->ppc_fp0_regnum + ppc_num_fprs
-         && TYPE_CODE (type) == TYPE_CODE_FLT
+         && type->code () == TYPE_CODE_FLT
          && TYPE_LENGTH (type)
             != TYPE_LENGTH (builtin_type (gdbarch)->builtin_double));
 }
 
 static int
 rs6000_register_to_value (struct frame_info *frame,
-                          int regnum,
-                          struct type *type,
-                          gdb_byte *to,
+                         int regnum,
+                         struct type *type,
+                         gdb_byte *to,
                          int *optimizedp, int *unavailablep)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
   gdb_byte from[PPC_MAX_REGISTER_SIZE];
   
-  gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
+  gdb_assert (type->code () == TYPE_CODE_FLT);
 
   if (!get_frame_register_bytes (frame, regnum, 0,
-                                register_size (gdbarch, regnum),
-                                from, optimizedp, unavailablep))
+                                gdb::make_array_view (from,
+                                                      register_size (gdbarch,
+                                                                     regnum)),
+                                optimizedp, unavailablep))
     return 0;
 
   target_float_convert (from, builtin_type (gdbarch)->builtin_double,
@@ -2629,14 +2696,14 @@ rs6000_register_to_value (struct frame_info *frame,
 
 static void
 rs6000_value_to_register (struct frame_info *frame,
-                          int regnum,
-                          struct type *type,
-                          const gdb_byte *from)
+                         int regnum,
+                         struct type *type,
+                         const gdb_byte *from)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
   gdb_byte to[PPC_MAX_REGISTER_SIZE];
 
-  gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
+  gdb_assert (type->code () == TYPE_CODE_FLT);
 
   target_float_convert (from, type,
                        to, builtin_type (gdbarch)->builtin_double);
@@ -2677,7 +2744,7 @@ e500_move_ev_register (move_ev_register_func move,
                       struct regcache *regcache, int ev_reg, void *buffer)
 {
   struct gdbarch *arch = regcache->arch ();
-  struct gdbarch_tdep *tdep = gdbarch_tdep (arch); 
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (arch);
   int reg_index;
   gdb_byte *byte_buffer = (gdb_byte *) buffer;
   enum register_status status;
@@ -2705,25 +2772,45 @@ e500_move_ev_register (move_ev_register_func move,
   return status;
 }
 
-static enum register_status
-do_regcache_raw_read (struct regcache *regcache, int regnum, void *buffer)
-{
-  return regcache_raw_read (regcache, regnum, (gdb_byte *) buffer);
-}
-
 static enum register_status
 do_regcache_raw_write (struct regcache *regcache, int regnum, void *buffer)
 {
-  regcache_raw_write (regcache, regnum, (const gdb_byte *) buffer);
+  regcache->raw_write (regnum, (const gdb_byte *) 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_pseudo_register_read (struct gdbarch *gdbarch, readable_regcache *regcache,
+                          int ev_reg, gdb_byte *buffer)
 {
-  return e500_move_ev_register (do_regcache_raw_read, regcache, reg_nr, buffer);
+  struct gdbarch *arch = regcache->arch ();
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+  int reg_index;
+  enum register_status status;
+
+  gdb_assert (IS_SPE_PSEUDOREG (tdep, ev_reg));
+
+  reg_index = ev_reg - tdep->ppc_ev0_regnum;
+
+  if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG)
+    {
+      status = regcache->raw_read (tdep->ppc_ev0_upper_regnum + reg_index,
+                                  buffer);
+      if (status == REG_VALID)
+       status = regcache->raw_read (tdep->ppc_gp0_regnum + reg_index,
+                                    buffer + 4);
+    }
+  else
+    {
+      status = regcache->raw_read (tdep->ppc_gp0_regnum + reg_index, buffer);
+      if (status == REG_VALID)
+       status = regcache->raw_read (tdep->ppc_ev0_upper_regnum + reg_index,
+                                    buffer + 4);
+    }
+
+  return status;
+
 }
 
 static void
@@ -2736,29 +2823,39 @@ e500_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
 
 /* Read method for DFP pseudo-registers.  */
 static enum register_status
-dfp_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+dfp_pseudo_register_read (struct gdbarch *gdbarch, readable_regcache *regcache,
                           int reg_nr, gdb_byte *buffer)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int reg_index = reg_nr - tdep->ppc_dl0_regnum;
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+  int reg_index, fp0;
   enum register_status status;
 
+  if (IS_DFP_PSEUDOREG (tdep, reg_nr))
+    {
+      reg_index = reg_nr - tdep->ppc_dl0_regnum;
+      fp0 = PPC_F0_REGNUM;
+    }
+  else
+    {
+      gdb_assert (IS_CDFP_PSEUDOREG (tdep, reg_nr));
+
+      reg_index = reg_nr - tdep->ppc_cdl0_regnum;
+      fp0 = PPC_CF0_REGNUM;
+    }
+
   if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
     {
       /* Read two FP registers to form a whole dl register.  */
-      status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-                                 2 * reg_index, buffer);
+      status = regcache->raw_read (fp0 + 2 * reg_index, buffer);
       if (status == REG_VALID)
-       status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-                                   2 * reg_index + 1, buffer + 8);
+       status = regcache->raw_read (fp0 + 2 * reg_index + 1,
+                                    buffer + 8);
     }
   else
     {
-      status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-                                 2 * reg_index + 1, buffer);
+      status = regcache->raw_read (fp0 + 2 * reg_index + 1, buffer);
       if (status == REG_VALID)
-       status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-                                   2 * reg_index, buffer + 8);
+       status = regcache->raw_read (fp0 + 2 * reg_index, buffer + 8);
     }
 
   return status;
@@ -2769,57 +2866,108 @@ static void
 dfp_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
                            int reg_nr, const gdb_byte *buffer)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int reg_index = reg_nr - tdep->ppc_dl0_regnum;
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+  int reg_index, fp0;
+
+  if (IS_DFP_PSEUDOREG (tdep, reg_nr))
+    {
+      reg_index = reg_nr - tdep->ppc_dl0_regnum;
+      fp0 = PPC_F0_REGNUM;
+    }
+  else
+    {
+      gdb_assert (IS_CDFP_PSEUDOREG (tdep, reg_nr));
+
+      reg_index = reg_nr - tdep->ppc_cdl0_regnum;
+      fp0 = PPC_CF0_REGNUM;
+    }
 
   if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
     {
       /* Write each half of the dl register into a separate
-      FP register.  */
-      regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
-                         2 * reg_index, buffer);
-      regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
-                         2 * reg_index + 1, buffer + 8);
+        FP register.  */
+      regcache->raw_write (fp0 + 2 * reg_index, buffer);
+      regcache->raw_write (fp0 + 2 * reg_index + 1, buffer + 8);
     }
   else
     {
-      regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
-                         2 * reg_index + 1, buffer);
-      regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
-                         2 * reg_index, buffer + 8);
+      regcache->raw_write (fp0 + 2 * reg_index + 1, buffer);
+      regcache->raw_write (fp0 + 2 * reg_index, buffer + 8);
     }
 }
 
+/* Read method for the vX aliases for the raw vrX registers.  */
+
+static enum register_status
+v_alias_pseudo_register_read (struct gdbarch *gdbarch,
+                             readable_regcache *regcache, int reg_nr,
+                             gdb_byte *buffer)
+{
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+  gdb_assert (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr));
+
+  return regcache->raw_read (tdep->ppc_vr0_regnum
+                            + (reg_nr - tdep->ppc_v0_alias_regnum),
+                            buffer);
+}
+
+/* Write method for the vX aliases for the raw vrX registers.  */
+
+static void
+v_alias_pseudo_register_write (struct gdbarch *gdbarch,
+                              struct regcache *regcache,
+                              int reg_nr, const gdb_byte *buffer)
+{
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+  gdb_assert (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr));
+
+  regcache->raw_write (tdep->ppc_vr0_regnum
+                      + (reg_nr - tdep->ppc_v0_alias_regnum), buffer);
+}
+
 /* Read method for POWER7 VSX pseudo-registers.  */
 static enum register_status
-vsx_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+vsx_pseudo_register_read (struct gdbarch *gdbarch, readable_regcache *regcache,
                           int reg_nr, gdb_byte *buffer)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int reg_index = reg_nr - tdep->ppc_vsr0_regnum;
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+  int reg_index, vr0, fp0, vsr0_upper;
   enum register_status status;
 
+  if (IS_VSX_PSEUDOREG (tdep, reg_nr))
+    {
+      reg_index = reg_nr - tdep->ppc_vsr0_regnum;
+      vr0 = PPC_VR0_REGNUM;
+      fp0 = PPC_F0_REGNUM;
+      vsr0_upper = PPC_VSR0_UPPER_REGNUM;
+    }
+  else
+    {
+      gdb_assert (IS_CVSX_PSEUDOREG (tdep, reg_nr));
+
+      reg_index = reg_nr - tdep->ppc_cvsr0_regnum;
+      vr0 = PPC_CVR0_REGNUM;
+      fp0 = PPC_CF0_REGNUM;
+      vsr0_upper = PPC_CVSR0_UPPER_REGNUM;
+    }
+
   /* Read the portion that overlaps the VMX registers.  */
   if (reg_index > 31)
-    status = regcache_raw_read (regcache, tdep->ppc_vr0_regnum +
-                               reg_index - 32, buffer);
+    status = regcache->raw_read (vr0 + reg_index - 32, buffer);
   else
     /* Read the portion that overlaps the FPR registers.  */
     if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
       {
-       status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-                                   reg_index, buffer);
+       status = regcache->raw_read (fp0 + reg_index, buffer);
        if (status == REG_VALID)
-         status = regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
-                                     reg_index, buffer + 8);
+         status = regcache->raw_read (vsr0_upper + reg_index,
+                                      buffer + 8);
       }
     else
       {
-       status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-                                   reg_index, buffer + 8);
+       status = regcache->raw_read (fp0 + reg_index, buffer + 8);
        if (status == REG_VALID)
-         status = regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
-                                     reg_index, buffer);
+         status = regcache->raw_read (vsr0_upper + reg_index, buffer);
       }
 
   return status;
@@ -2830,79 +2978,131 @@ static void
 vsx_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
                            int reg_nr, const gdb_byte *buffer)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int reg_index = reg_nr - tdep->ppc_vsr0_regnum;
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+  int reg_index, vr0, fp0, vsr0_upper;
+
+  if (IS_VSX_PSEUDOREG (tdep, reg_nr))
+    {
+      reg_index = reg_nr - tdep->ppc_vsr0_regnum;
+      vr0 = PPC_VR0_REGNUM;
+      fp0 = PPC_F0_REGNUM;
+      vsr0_upper = PPC_VSR0_UPPER_REGNUM;
+    }
+  else
+    {
+      gdb_assert (IS_CVSX_PSEUDOREG (tdep, reg_nr));
+
+      reg_index = reg_nr - tdep->ppc_cvsr0_regnum;
+      vr0 = PPC_CVR0_REGNUM;
+      fp0 = PPC_CF0_REGNUM;
+      vsr0_upper = PPC_CVSR0_UPPER_REGNUM;
+    }
 
   /* Write the portion that overlaps the VMX registers.  */
   if (reg_index > 31)
-    regcache_raw_write (regcache, tdep->ppc_vr0_regnum +
-                       reg_index - 32, buffer);
+    regcache->raw_write (vr0 + reg_index - 32, buffer);
   else
     /* Write the portion that overlaps the FPR registers.  */
     if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
       {
-       regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
-                       reg_index, buffer);
-       regcache_raw_write (regcache, tdep->ppc_vsr0_upper_regnum +
-                       reg_index, buffer + 8);
+       regcache->raw_write (fp0 + reg_index, buffer);
+       regcache->raw_write (vsr0_upper + reg_index, buffer + 8);
       }
     else
       {
-       regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
-                       reg_index, buffer + 8);
-       regcache_raw_write (regcache, tdep->ppc_vsr0_upper_regnum +
-                       reg_index, buffer);
+       regcache->raw_write (fp0 + reg_index, buffer + 8);
+       regcache->raw_write (vsr0_upper + reg_index, buffer);
       }
 }
 
 /* Read method for POWER7 Extended FP pseudo-registers.  */
 static enum register_status
-efpr_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+efp_pseudo_register_read (struct gdbarch *gdbarch, readable_regcache *regcache,
                           int reg_nr, gdb_byte *buffer)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int reg_index = reg_nr - tdep->ppc_efpr0_regnum;
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+  int reg_index, vr0;
+
+  if (IS_EFP_PSEUDOREG (tdep, reg_nr))
+    {
+      reg_index = reg_nr - tdep->ppc_efpr0_regnum;
+      vr0 = PPC_VR0_REGNUM;
+    }
+  else
+    {
+      gdb_assert (IS_CEFP_PSEUDOREG (tdep, reg_nr));
+
+      reg_index = reg_nr - tdep->ppc_cefpr0_regnum;
+      vr0 = PPC_CVR0_REGNUM;
+    }
+
   int offset = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8;
 
   /* 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);
+  return regcache->raw_read_part (vr0 + reg_index, offset,
+                                 register_size (gdbarch, reg_nr),
+                                 buffer);
 }
 
 /* Write method for POWER7 Extended FP pseudo-registers.  */
 static void
-efpr_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+efp_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
                            int reg_nr, const gdb_byte *buffer)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int reg_index = reg_nr - tdep->ppc_efpr0_regnum;
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+  int reg_index, vr0;
   int offset = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8;
 
+  if (IS_EFP_PSEUDOREG (tdep, reg_nr))
+    {
+      reg_index = reg_nr - tdep->ppc_efpr0_regnum;
+      vr0 = PPC_VR0_REGNUM;
+    }
+  else
+    {
+      gdb_assert (IS_CEFP_PSEUDOREG (tdep, reg_nr));
+
+      reg_index = reg_nr - tdep->ppc_cefpr0_regnum;
+      vr0 = PPC_CVR0_REGNUM;
+
+      /* The call to raw_write_part fails silently if the initial read
+        of the read-update-write sequence returns an invalid status,
+        so we check this manually and throw an error if needed.  */
+      regcache->raw_update (vr0 + reg_index);
+      if (regcache->get_register_status (vr0 + reg_index) != REG_VALID)
+       error (_("Cannot write to the checkpointed EFP register, "
+                "the corresponding vector register is unavailable."));
+    }
+
   /* 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);
+  regcache->raw_write_part (vr0 + reg_index, offset,
+                           register_size (gdbarch, reg_nr), buffer);
 }
 
 static enum register_status
 rs6000_pseudo_register_read (struct gdbarch *gdbarch,
-                            struct regcache *regcache,
+                            readable_regcache *regcache,
                             int reg_nr, gdb_byte *buffer)
 {
   struct gdbarch *regcache_arch = regcache->arch ();
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
 
   gdb_assert (regcache_arch == gdbarch);
 
   if (IS_SPE_PSEUDOREG (tdep, reg_nr))
     return e500_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
-  else if (IS_DFP_PSEUDOREG (tdep, reg_nr))
+  else if (IS_DFP_PSEUDOREG (tdep, reg_nr)
+          || IS_CDFP_PSEUDOREG (tdep, reg_nr))
     return dfp_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
-  else if (IS_VSX_PSEUDOREG (tdep, reg_nr))
+  else if (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr))
+    return v_alias_pseudo_register_read (gdbarch, regcache, reg_nr,
+                                        buffer);
+  else if (IS_VSX_PSEUDOREG (tdep, reg_nr)
+          || IS_CVSX_PSEUDOREG (tdep, reg_nr))
     return vsx_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
-  else if (IS_EFP_PSEUDOREG (tdep, reg_nr))
-    return efpr_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+  else if (IS_EFP_PSEUDOREG (tdep, reg_nr)
+          || IS_CEFP_PSEUDOREG (tdep, reg_nr))
+    return efp_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
   else
     internal_error (__FILE__, __LINE__,
                    _("rs6000_pseudo_register_read: "
@@ -2911,64 +3111,169 @@ rs6000_pseudo_register_read (struct gdbarch *gdbarch,
 }
 
 static void
-rs6000_pseudo_register_write (struct gdbarch *gdbarch,
-                             struct regcache *regcache,
-                             int reg_nr, const gdb_byte *buffer)
+rs6000_pseudo_register_write (struct gdbarch *gdbarch,
+                             struct regcache *regcache,
+                             int reg_nr, const gdb_byte *buffer)
+{
+  struct gdbarch *regcache_arch = regcache->arch ();
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+
+  gdb_assert (regcache_arch == gdbarch);
+
+  if (IS_SPE_PSEUDOREG (tdep, reg_nr))
+    e500_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+  else if (IS_DFP_PSEUDOREG (tdep, reg_nr)
+          || IS_CDFP_PSEUDOREG (tdep, reg_nr))
+    dfp_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+  else if (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr))
+    v_alias_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+  else if (IS_VSX_PSEUDOREG (tdep, reg_nr)
+          || IS_CVSX_PSEUDOREG (tdep, reg_nr))
+    vsx_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+  else if (IS_EFP_PSEUDOREG (tdep, reg_nr)
+          || IS_CEFP_PSEUDOREG (tdep, reg_nr))
+    efp_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+  else
+    internal_error (__FILE__, __LINE__,
+                   _("rs6000_pseudo_register_write: "
+                   "called on unexpected register '%s' (%d)"),
+                   gdbarch_register_name (gdbarch, reg_nr), reg_nr);
+}
+
+/* Set the register mask in AX with the registers that form the DFP or
+   checkpointed DFP pseudo-register REG_NR.  */
+
+static void
+dfp_ax_pseudo_register_collect (struct gdbarch *gdbarch,
+                               struct agent_expr *ax, int reg_nr)
+{
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+  int reg_index, fp0;
+
+  if (IS_DFP_PSEUDOREG (tdep, reg_nr))
+    {
+      reg_index = reg_nr - tdep->ppc_dl0_regnum;
+      fp0 = PPC_F0_REGNUM;
+    }
+  else
+    {
+      gdb_assert (IS_CDFP_PSEUDOREG (tdep, reg_nr));
+
+      reg_index = reg_nr - tdep->ppc_cdl0_regnum;
+      fp0 = PPC_CF0_REGNUM;
+    }
+
+  ax_reg_mask (ax, fp0 + 2 * reg_index);
+  ax_reg_mask (ax, fp0 + 2 * reg_index + 1);
+}
+
+/* Set the register mask in AX with the raw vector register that
+   corresponds to its REG_NR alias.  */
+
+static void
+v_alias_pseudo_register_collect (struct gdbarch *gdbarch,
+                                struct agent_expr *ax, int reg_nr)
+{
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+  gdb_assert (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr));
+
+  ax_reg_mask (ax, tdep->ppc_vr0_regnum
+              + (reg_nr - tdep->ppc_v0_alias_regnum));
+}
+
+/* Set the register mask in AX with the registers that form the VSX or
+   checkpointed VSX pseudo-register REG_NR.  */
+
+static void
+vsx_ax_pseudo_register_collect (struct gdbarch *gdbarch,
+                               struct agent_expr *ax, int reg_nr)
+{
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+  int reg_index, vr0, fp0, vsr0_upper;
+
+  if (IS_VSX_PSEUDOREG (tdep, reg_nr))
+    {
+      reg_index = reg_nr - tdep->ppc_vsr0_regnum;
+      vr0 = PPC_VR0_REGNUM;
+      fp0 = PPC_F0_REGNUM;
+      vsr0_upper = PPC_VSR0_UPPER_REGNUM;
+    }
+  else
+    {
+      gdb_assert (IS_CVSX_PSEUDOREG (tdep, reg_nr));
+
+      reg_index = reg_nr - tdep->ppc_cvsr0_regnum;
+      vr0 = PPC_CVR0_REGNUM;
+      fp0 = PPC_CF0_REGNUM;
+      vsr0_upper = PPC_CVSR0_UPPER_REGNUM;
+    }
+
+  if (reg_index > 31)
+    {
+      ax_reg_mask (ax, vr0 + reg_index - 32);
+    }
+  else
+    {
+      ax_reg_mask (ax, fp0 + reg_index);
+      ax_reg_mask (ax, vsr0_upper + reg_index);
+    }
+}
+
+/* Set the register mask in AX with the register that corresponds to
+   the EFP or checkpointed EFP pseudo-register REG_NR.  */
+
+static void
+efp_ax_pseudo_register_collect (struct gdbarch *gdbarch,
+                               struct agent_expr *ax, int reg_nr)
 {
-  struct gdbarch *regcache_arch = regcache->arch ();
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 
-
-  gdb_assert (regcache_arch == gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+  int reg_index, vr0;
 
-  if (IS_SPE_PSEUDOREG (tdep, reg_nr))
-    e500_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
-  else if (IS_DFP_PSEUDOREG (tdep, reg_nr))
-    dfp_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
-  else if (IS_VSX_PSEUDOREG (tdep, reg_nr))
-    vsx_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
-  else if (IS_EFP_PSEUDOREG (tdep, reg_nr))
-    efpr_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+  if (IS_EFP_PSEUDOREG (tdep, reg_nr))
+    {
+      reg_index = reg_nr - tdep->ppc_efpr0_regnum;
+      vr0 = PPC_VR0_REGNUM;
+    }
   else
-    internal_error (__FILE__, __LINE__,
-                   _("rs6000_pseudo_register_write: "
-                   "called on unexpected register '%s' (%d)"),
-                   gdbarch_register_name (gdbarch, reg_nr), reg_nr);
+    {
+      gdb_assert (IS_CEFP_PSEUDOREG (tdep, reg_nr));
+
+      reg_index = reg_nr - tdep->ppc_cefpr0_regnum;
+      vr0 = PPC_CVR0_REGNUM;
+    }
+
+  ax_reg_mask (ax, vr0 + reg_index);
 }
 
 static int
 rs6000_ax_pseudo_register_collect (struct gdbarch *gdbarch,
                                   struct agent_expr *ax, int reg_nr)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
   if (IS_SPE_PSEUDOREG (tdep, reg_nr))
     {
       int reg_index = reg_nr - tdep->ppc_ev0_regnum;
       ax_reg_mask (ax, tdep->ppc_gp0_regnum + reg_index);
       ax_reg_mask (ax, tdep->ppc_ev0_upper_regnum + reg_index);
     }
-  else if (IS_DFP_PSEUDOREG (tdep, reg_nr))
+  else if (IS_DFP_PSEUDOREG (tdep, reg_nr)
+          || IS_CDFP_PSEUDOREG (tdep, reg_nr))
     {
-      int reg_index = reg_nr - tdep->ppc_dl0_regnum;
-      ax_reg_mask (ax, tdep->ppc_fp0_regnum + 2 * reg_index);
-      ax_reg_mask (ax, tdep->ppc_fp0_regnum + 2 * reg_index + 1);
+      dfp_ax_pseudo_register_collect (gdbarch, ax, reg_nr);
     }
-  else if (IS_VSX_PSEUDOREG (tdep, reg_nr))
+  else if (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr))
     {
-      int reg_index = reg_nr - tdep->ppc_vsr0_regnum;
-      if (reg_index > 31)
-        {
-          ax_reg_mask (ax, tdep->ppc_vr0_regnum + reg_index - 32);
-       }
-      else
-        {
-          ax_reg_mask (ax, tdep->ppc_fp0_regnum + reg_index);
-          ax_reg_mask (ax, tdep->ppc_vsr0_upper_regnum + reg_index);
-        }
+      v_alias_pseudo_register_collect (gdbarch, ax, reg_nr);
     }
-  else if (IS_EFP_PSEUDOREG (tdep, reg_nr))
+  else if (IS_VSX_PSEUDOREG (tdep, reg_nr)
+          || IS_CVSX_PSEUDOREG (tdep, reg_nr))
     {
-      int reg_index = reg_nr - tdep->ppc_efpr0_regnum;
-      ax_reg_mask (ax, tdep->ppc_vr0_regnum + reg_index);
+      vsx_ax_pseudo_register_collect (gdbarch, ax, reg_nr);
+    }
+  else if (IS_EFP_PSEUDOREG (tdep, reg_nr)
+          || IS_CEFP_PSEUDOREG (tdep, reg_nr))
+    {
+      efp_ax_pseudo_register_collect (gdbarch, ax, reg_nr);
     }
   else
     internal_error (__FILE__, __LINE__,
@@ -2984,7 +3289,7 @@ rs6000_gen_return_address (struct gdbarch *gdbarch,
                           struct agent_expr *ax, struct axs_value *value,
                           CORE_ADDR scope)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
   value->type = register_type (gdbarch, tdep->ppc_lr_regnum);
   value->kind = axs_lvalue_register;
   value->u.reg = tdep->ppc_lr_regnum;
@@ -2995,7 +3300,7 @@ rs6000_gen_return_address (struct gdbarch *gdbarch,
 static int
 rs6000_stab_reg_to_regnum (struct gdbarch *gdbarch, int num)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
 
   if (0 <= num && num <= 31)
     return tdep->ppc_gp0_regnum + num;
@@ -3012,23 +3317,23 @@ rs6000_stab_reg_to_regnum (struct gdbarch *gdbarch, int num)
     switch (num)
       {
       case 64: 
-        return tdep->ppc_mq_regnum;
+       return tdep->ppc_mq_regnum;
       case 65:
-        return tdep->ppc_lr_regnum;
+       return tdep->ppc_lr_regnum;
       case 66: 
-        return tdep->ppc_ctr_regnum;
+       return tdep->ppc_ctr_regnum;
       case 76: 
-        return tdep->ppc_xer_regnum;
+       return tdep->ppc_xer_regnum;
       case 109:
-        return tdep->ppc_vrsave_regnum;
+       return tdep->ppc_vrsave_regnum;
       case 110:
-        return tdep->ppc_vrsave_regnum - 1; /* vscr */
+       return tdep->ppc_vrsave_regnum - 1; /* vscr */
       case 111:
-        return tdep->ppc_acc_regnum;
+       return tdep->ppc_acc_regnum;
       case 112:
-        return tdep->ppc_spefscr_regnum;
+       return tdep->ppc_spefscr_regnum;
       default: 
-        return num;
+       return num;
       }
 }
 
@@ -3037,7 +3342,7 @@ rs6000_stab_reg_to_regnum (struct gdbarch *gdbarch, int num)
 static int
 rs6000_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int num)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
 
   if (0 <= num && num <= 31)
     return tdep->ppc_gp0_regnum + num;
@@ -3056,24 +3361,25 @@ rs6000_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int num)
       case 64:
        return tdep->ppc_cr_regnum;
       case 67:
-        return tdep->ppc_vrsave_regnum - 1; /* vscr */
+       return tdep->ppc_vrsave_regnum - 1; /* vscr */
       case 99:
-        return tdep->ppc_acc_regnum;
+       return tdep->ppc_acc_regnum;
       case 100:
-        return tdep->ppc_mq_regnum;
+       return tdep->ppc_mq_regnum;
       case 101:
-        return tdep->ppc_xer_regnum;
+       return tdep->ppc_xer_regnum;
       case 108:
-        return tdep->ppc_lr_regnum;
+       return tdep->ppc_lr_regnum;
       case 109:
-        return tdep->ppc_ctr_regnum;
+       return tdep->ppc_ctr_regnum;
       case 356:
-        return tdep->ppc_vrsave_regnum;
+       return tdep->ppc_vrsave_regnum;
       case 612:
-        return tdep->ppc_spefscr_regnum;
-      default:
-        return num;
+       return tdep->ppc_spefscr_regnum;
       }
+
+  /* Unknown DWARF register number.  */
+  return -1;
 }
 
 /* Translate a .eh_frame register to DWARF register, or adjust a
@@ -3145,7 +3451,7 @@ rs6000_adjust_frame_regnum (struct gdbarch *gdbarch, int num, int eh_frame_p)
 
 /* Information about a particular processor variant.  */
 
-struct variant
+struct ppc_variant
   {
     /* Name of this variant.  */
     const char *name;
@@ -3163,7 +3469,7 @@ struct variant
     struct target_desc **tdesc;
   };
 
-static struct variant variants[] =
+static struct ppc_variant variants[] =
 {
   {"powerpc", "PowerPC user-level", bfd_arch_powerpc,
    bfd_mach_ppc, &tdesc_powerpc_altivec32},
@@ -3222,10 +3528,10 @@ static struct variant variants[] =
 /* Return the variant corresponding to architecture ARCH and machine number
    MACH.  If no such variant exists, return null.  */
 
-static const struct variant *
+static const struct ppc_variant *
 find_variant_by_arch (enum bfd_architecture arch, unsigned long mach)
 {
-  const struct variant *v;
+  const struct ppc_variant *v;
 
   for (v = variants; v->name; v++)
     if (arch == v->arch && mach == v->mach)
@@ -3235,26 +3541,12 @@ find_variant_by_arch (enum bfd_architecture arch, unsigned long mach)
 }
 
 \f
-static CORE_ADDR
-rs6000_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame,
-                                        gdbarch_pc_regnum (gdbarch));
-}
-
-static struct frame_id
-rs6000_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
-{
-  return frame_id_build (get_frame_register_unsigned
-                         (this_frame, gdbarch_sp_regnum (gdbarch)),
-                        get_frame_pc (this_frame));
-}
 
 struct rs6000_frame_cache
 {
   CORE_ADDR base;
   CORE_ADDR initial_sp;
-  struct trad_frame_saved_reg *saved_regs;
+  trad_frame_saved_reg *saved_regs;
 
   /* Set BASE_P to true if this frame cache is properly initialized.
      Otherwise set to false because some registers or memory cannot
@@ -3269,7 +3561,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);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   struct rs6000_framedata fdata;
   int wordsize = tdep->wordsize;
@@ -3282,7 +3574,7 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
   cache->pc = 0;
   cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
 
-  TRY
+  try
     {
       func = get_frame_func (this_frame);
       cache->pc = func;
@@ -3299,13 +3591,12 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
       cache->base = get_frame_register_unsigned
        (this_frame, gdbarch_sp_regnum (gdbarch));
     }
-  CATCH (ex, RETURN_MASK_ERROR)
+  catch (const gdb_exception_error &ex)
     {
       if (ex.error != NOT_AVAILABLE_ERROR)
-       throw_exception (ex);
+       throw;
       return (struct rs6000_frame_cache *) (*this_cache);
     }
-  END_CATCH
 
   /* If the function appears to be frameless, check a couple of likely
      indicators that we have simply failed to find the frame setup.
@@ -3345,11 +3636,10 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
 
       if (safe_read_memory_unsigned_integer (cache->base, wordsize,
                                             byte_order, &backchain))
-        cache->base = (CORE_ADDR) backchain;
+       cache->base = (CORE_ADDR) backchain;
     }
 
-  trad_frame_set_value (cache->saved_regs,
-                       gdbarch_sp_regnum (gdbarch), cache->base);
+  cache->saved_regs[gdbarch_sp_regnum (gdbarch)].set_value (cache->base);
 
   /* if != -1, fdata.saved_fpr is the smallest number of saved_fpr.
      All fpr's from saved_fpr to fp31 are saved.  */
@@ -3360,15 +3650,15 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
       CORE_ADDR fpr_addr = cache->base + fdata.fpr_offset;
 
       /* If skip_prologue says floating-point registers were saved,
-         but the current architecture has no floating-point registers,
-         then that's strange.  But we have no indices to even record
-         the addresses under, so we just ignore it.  */
+        but the current architecture has no floating-point registers,
+        then that's strange.  But we have no indices to even record
+        the addresses under, so we just ignore it.  */
       if (ppc_floating_point_unit_p (gdbarch))
-        for (i = fdata.saved_fpr; i < ppc_num_fprs; i++)
-          {
-            cache->saved_regs[tdep->ppc_fp0_regnum + i].addr = fpr_addr;
-            fpr_addr += 8;
-          }
+       for (i = fdata.saved_fpr; i < ppc_num_fprs; i++)
+         {
+           cache->saved_regs[tdep->ppc_fp0_regnum + i].set_addr (fpr_addr);
+           fpr_addr += 8;
+         }
     }
 
   /* if != -1, fdata.saved_gpr is the smallest number of saved_gpr.
@@ -3382,7 +3672,7 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
       for (i = fdata.saved_gpr; i < ppc_num_gprs; i++)
        {
          if (fdata.gpr_mask & (1U << i))
-           cache->saved_regs[tdep->ppc_gp0_regnum + i].addr = gpr_addr;
+           cache->saved_regs[tdep->ppc_gp0_regnum + i].set_addr (gpr_addr);
          gpr_addr += wordsize;
        }
     }
@@ -3397,7 +3687,7 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
          CORE_ADDR vr_addr = cache->base + fdata.vr_offset;
          for (i = fdata.saved_vr; i < 32; i++)
            {
-             cache->saved_regs[tdep->ppc_vr0_regnum + i].addr = vr_addr;
+             cache->saved_regs[tdep->ppc_vr0_regnum + i].set_addr (vr_addr);
              vr_addr += register_size (gdbarch, tdep->ppc_vr0_regnum);
            }
        }
@@ -3415,8 +3705,9 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
 
          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 + off;
+             cache->saved_regs[tdep->ppc_ev0_regnum + i].set_addr (ev_addr);
+             cache->saved_regs[tdep->ppc_gp0_regnum + i].set_addr (ev_addr
+                                                                   + off);
              ev_addr += register_size (gdbarch, tdep->ppc_ev0_regnum);
            }
        }
@@ -3425,16 +3716,16 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
   /* If != 0, fdata.cr_offset is the offset from the frame that
      holds the CR.  */
   if (fdata.cr_offset != 0)
-    cache->saved_regs[tdep->ppc_cr_regnum].addr
-      = cache->base + fdata.cr_offset;
+    cache->saved_regs[tdep->ppc_cr_regnum].set_addr (cache->base
+                                                    + fdata.cr_offset);
 
   /* If != 0, fdata.lr_offset is the offset from the frame that
      holds the LR.  */
   if (fdata.lr_offset != 0)
-    cache->saved_regs[tdep->ppc_lr_regnum].addr
-      = cache->base + fdata.lr_offset;
+    cache->saved_regs[tdep->ppc_lr_regnum].set_addr (cache->base
+                                                    + fdata.lr_offset);
   else if (fdata.lr_register != -1)
-    cache->saved_regs[tdep->ppc_lr_regnum].realreg = fdata.lr_register;
+    cache->saved_regs[tdep->ppc_lr_regnum].set_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];
@@ -3442,8 +3733,8 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
   /* If != 0, fdata.vrsave_offset is the offset from the frame that
      holds the VRSAVE.  */
   if (fdata.vrsave_offset != 0)
-    cache->saved_regs[tdep->ppc_vrsave_regnum].addr
-      = cache->base + fdata.vrsave_offset;
+    cache->saved_regs[tdep->ppc_vrsave_regnum].set_addr (cache->base
+                                                        + fdata.vrsave_offset);
 
   if (fdata.alloca_reg < 0)
     /* If no alloca register used, then fi->frame is the value of the
@@ -3489,6 +3780,7 @@ rs6000_frame_prev_register (struct frame_info *this_frame,
 
 static const struct frame_unwind rs6000_frame_unwind =
 {
+  "rs6000 prologue",
   NORMAL_FRAME,
   default_frame_unwind_stop_reason,
   rs6000_frame_this_id,
@@ -3505,7 +3797,7 @@ rs6000_epilogue_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);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
 
   if (*this_cache)
     return (struct rs6000_frame_cache *) *this_cache;
@@ -3514,7 +3806,7 @@ rs6000_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache)
   (*this_cache) = cache;
   cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
 
-  TRY
+  try
     {
       /* At this point the stack looks as if we just entered the
         function, and the return address is stored in LR.  */
@@ -3526,15 +3818,13 @@ rs6000_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache)
       cache->base = sp;
       cache->initial_sp = sp;
 
-      trad_frame_set_value (cache->saved_regs,
-                           gdbarch_pc_regnum (gdbarch), lr);
+      cache->saved_regs[gdbarch_pc_regnum (gdbarch)].set_value (lr);
     }
-  CATCH (ex, RETURN_MASK_ERROR)
+  catch (const gdb_exception_error &ex)
     {
       if (ex.error != NOT_AVAILABLE_ERROR)
-       throw_exception (ex);
+       throw;
     }
-  END_CATCH
 
   return cache;
 }
@@ -3590,6 +3880,7 @@ rs6000_epilogue_frame_sniffer (const struct frame_unwind *self,
 
 static const struct frame_unwind rs6000_epilogue_frame_unwind =
 {
+  "rs6000 epilogue",
   NORMAL_FRAME,
   default_frame_unwind_stop_reason,
   rs6000_epilogue_frame_this_id, rs6000_epilogue_frame_prev_register,
@@ -3627,7 +3918,7 @@ ppc_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
                            struct dwarf2_frame_state_reg *reg,
                            struct frame_info *this_frame)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
 
   /* PPC32 and PPC64 ABI's are the same regarding volatile and
      non-volatile registers.  We will use the same code for both.  */
@@ -3695,7 +3986,6 @@ bfd_uses_spe_extensions (bfd *abfd)
   bfd_size_type size;
   gdb_byte *ptr;
   int success = 0;
-  int vector_abi;
 
   if (!abfd)
     return 0;
@@ -3704,8 +3994,8 @@ bfd_uses_spe_extensions (bfd *abfd)
   /* Using Tag_GNU_Power_ABI_Vector here is a bit of a hack, as the user
      could be using the SPE vector abi without actually using any spe
      bits whatsoever.  But it's close enough for now.  */
-  vector_abi = bfd_elf_get_obj_attr_int (abfd, OBJ_ATTR_GNU,
-                                        Tag_GNU_Power_ABI_Vector);
+  int vector_abi = bfd_elf_get_obj_attr_int (abfd, OBJ_ATTR_GNU,
+                                            Tag_GNU_Power_ABI_Vector);
   if (vector_abi == 3)
     return 1;
 #endif
@@ -3714,7 +4004,7 @@ bfd_uses_spe_extensions (bfd *abfd)
   if (!sect)
     return 0;
 
-  size = bfd_get_section_size (sect);
+  size = bfd_section_size (sect);
   contents = (gdb_byte *) xmalloc (size);
   if (!bfd_get_section_contents (abfd, sect, contents, 0, size))
     {
@@ -3840,7 +4130,7 @@ bfd_uses_spe_extensions (bfd *abfd)
    Otherwise, it's just a VR register.  Record them accordingly.  */
 
 static int
-ppc_record_vsr (struct regcache *regcache, struct gdbarch_tdep *tdep, int vsr)
+ppc_record_vsr (struct regcache *regcache, ppc_gdbarch_tdep *tdep, int vsr)
 {
   if (vsr < 0 || vsr >= 64)
     return -1;
@@ -3869,7 +4159,7 @@ static int
 ppc_process_record_op4 (struct gdbarch *gdbarch, struct regcache *regcache,
                        CORE_ADDR addr, uint32_t insn)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
   int ext = PPC_FIELD (insn, 21, 11);
   int vra = PPC_FIELD (insn, 11, 5);
 
@@ -3921,6 +4211,7 @@ ppc_process_record_op4 (struct gdbarch *gdbarch, struct regcache *regcache,
          && vra != 7   /* Decimal Convert From National */
          && vra != 31) /* Decimal Set Sign */
        break;
+      /* Fall through.  */
                        /* 5.16 Decimal Integer Arithmetic Instructions */
     case 1:            /* Decimal Add Modulo */
     case 65:           /* Decimal Subtract Modulo */
@@ -4241,7 +4532,7 @@ static int
 ppc_process_record_op19 (struct gdbarch *gdbarch, struct regcache *regcache,
                           CORE_ADDR addr, uint32_t insn)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
   int ext = PPC_EXTOP (insn);
 
   switch (ext & 0x01f)
@@ -4293,7 +4584,7 @@ static int
 ppc_process_record_op31 (struct gdbarch *gdbarch, struct regcache *regcache,
                           CORE_ADDR addr, uint32_t insn)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
   int ext = PPC_EXTOP (insn);
   int tmp, nr, nb, i;
   CORE_ADDR at_dcsz, ea = 0;
@@ -4573,6 +4864,17 @@ ppc_process_record_op31 (struct gdbarch *gdbarch, struct regcache *regcache,
     case 570:          /* Count Trailing Zeros Doubleword */
     case 890:          /* Extend-Sign Word and Shift Left Immediate (445) */
     case 890 | 1:      /* Extend-Sign Word and Shift Left Immediate (445) */
+
+      if (ext == 444 && tdep->ppc_ppr_regnum >= 0
+         && (PPC_RS (insn) == PPC_RA (insn))
+         && (PPC_RA (insn) == PPC_RB (insn))
+         && !PPC_RC (insn))
+       {
+         /* or Rx,Rx,Rx alters PRI in PPR.  */
+         record_full_arch_list_add_reg (regcache, tdep->ppc_ppr_regnum);
+         return 0;
+       }
+
       if (PPC_RC (insn))
        record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
       record_full_arch_list_add_reg (regcache,
@@ -4688,20 +4990,20 @@ ppc_process_record_op31 (struct gdbarch *gdbarch, struct regcache *regcache,
       switch (ext)
        {
        case 167:       /* Store Vector Element Halfword Indexed */
-         addr = addr & ~0x1ULL;
+         ea = ea & ~0x1ULL;
          break;
 
        case 199:       /* Store Vector Element Word Indexed */
-         addr = addr & ~0x3ULL;
+         ea = ea & ~0x3ULL;
          break;
 
        case 231:       /* Store Vector Indexed */
        case 487:       /* Store Vector Indexed LRU */
-         addr = addr & ~0xfULL;
+         ea = ea & ~0xfULL;
          break;
        }
 
-      record_full_arch_list_add_mem (addr, size);
+      record_full_arch_list_add_mem (ea, size);
       return 0;
 
     case 397:          /* Store VSX Vector with Length */
@@ -4782,6 +5084,10 @@ ppc_process_record_op31 (struct gdbarch *gdbarch, struct regcache *regcache,
        case 1:                 /* XER */
          record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum);
          return 0;
+       case 3:                 /* DSCR */
+         if (tdep->ppc_dscr_regnum >= 0)
+           record_full_arch_list_add_reg (regcache, tdep->ppc_dscr_regnum);
+         return 0;
        case 8:                 /* LR */
          record_full_arch_list_add_reg (regcache, tdep->ppc_lr_regnum);
          return 0;
@@ -4791,6 +5097,15 @@ ppc_process_record_op31 (struct gdbarch *gdbarch, struct regcache *regcache,
        case 256:               /* VRSAVE */
          record_full_arch_list_add_reg (regcache, tdep->ppc_vrsave_regnum);
          return 0;
+       case 815:               /* TAR */
+         if (tdep->ppc_tar_regnum >= 0)
+           record_full_arch_list_add_reg (regcache, tdep->ppc_tar_regnum);
+         return 0;
+       case 896:
+       case 898:               /* PPR */
+         if (tdep->ppc_ppr_regnum >= 0)
+           record_full_arch_list_add_reg (regcache, tdep->ppc_ppr_regnum);
+         return 0;
        }
 
       goto UNKNOWN_OP;
@@ -4837,7 +5152,8 @@ ppc_process_record_op31 (struct gdbarch *gdbarch, struct regcache *regcache,
       return 0;
 
     case 1014:         /* Data Cache Block set to Zero */
-      if (target_auxv_search (&current_target, AT_DCACHEBSIZE, &at_dcsz) <= 0
+      if (target_auxv_search (current_inferior ()->top_target (),
+                             AT_DCACHEBSIZE, &at_dcsz) <= 0
          || at_dcsz == 0)
        at_dcsz = 128; /* Assume 128-byte cache line size (POWER8)  */
 
@@ -4865,7 +5181,7 @@ static int
 ppc_process_record_op59 (struct gdbarch *gdbarch, struct regcache *regcache,
                           CORE_ADDR addr, uint32_t insn)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
   int ext = PPC_EXTOP (insn);
 
   switch (ext & 0x1f)
@@ -4959,7 +5275,7 @@ static int
 ppc_process_record_op60 (struct gdbarch *gdbarch, struct regcache *regcache,
                           CORE_ADDR addr, uint32_t insn)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
   int ext = PPC_EXTOP (insn);
 
   switch (ext >> 2)
@@ -5253,7 +5569,7 @@ ppc_process_record_op60 (struct gdbarch *gdbarch, struct regcache *regcache,
        {
        case 0:         /* VSX Scalar Extract Exponent Double-Precision */
        case 1:         /* VSX Scalar Extract Significand Double-Precision */
-          record_full_arch_list_add_reg (regcache,
+         record_full_arch_list_add_reg (regcache,
                                         tdep->ppc_gp0_regnum + PPC_RT (insn));
          return 0;
        case 16:        /* VSX Scalar Convert Half-Precision format to
@@ -5321,7 +5637,7 @@ static int
 ppc_process_record_op61 (struct gdbarch *gdbarch, struct regcache *regcache,
                           CORE_ADDR addr, uint32_t insn)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
   ULONGEST ea = 0;
   int size;
 
@@ -5380,7 +5696,7 @@ static int
 ppc_process_record_op63 (struct gdbarch *gdbarch, struct regcache *regcache,
                           CORE_ADDR addr, uint32_t insn)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
   int ext = PPC_EXTOP (insn);
   int tmp;
 
@@ -5510,13 +5826,14 @@ ppc_process_record_op63 (struct gdbarch *gdbarch, struct regcache *regcache,
 
     case 583:
       switch (PPC_FIELD (insn, 11, 5))
-        {
+       {
          case 1:       /* Move From FPSCR & Clear Enables */
          case 20:      /* Move From FPSCR Control & set DRN */
          case 21:      /* Move From FPSCR Control & set DRN Immediate */
          case 22:      /* Move From FPSCR Control & set RN */
          case 23:      /* Move From FPSCR Control & set RN Immediate */
            record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+           /* Fall through.  */
          case 0:       /* Move From FPSCR */
          case 24:      /* Move From FPSCR Lightweight */
            if (PPC_FIELD (insn, 11, 5) == 0 && PPC_RC (insn))
@@ -5525,7 +5842,7 @@ ppc_process_record_op63 (struct gdbarch *gdbarch, struct regcache *regcache,
                                           tdep->ppc_fp0_regnum
                                           + PPC_FRT (insn));
            return 0;
-        }
+       }
       break;
 
     case 8:            /* Floating Copy Sign */
@@ -5638,7 +5955,7 @@ int
 ppc_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
                      CORE_ADDR addr)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   uint32_t insn;
   int op6, tmp, i;
@@ -5787,15 +6104,15 @@ ppc_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
 
     case 47:           /* Store Multiple Word */
        {
-         ULONGEST addr = 0;
+         ULONGEST iaddr = 0;
 
          if (PPC_RA (insn) != 0)
            regcache_raw_read_unsigned (regcache,
                                        tdep->ppc_gp0_regnum + PPC_RA (insn),
-                                       &addr);
+                                       &iaddr);
 
-         addr += PPC_D (insn);
-         record_full_arch_list_add_mem (addr, 4 * (32 - PPC_RS (insn)));
+         iaddr += PPC_D (insn);
+         record_full_arch_list_add_mem (iaddr, 4 * (32 - PPC_RS (insn)));
        }
       break;
 
@@ -5813,14 +6130,14 @@ ppc_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
     case 52:           /* Store Floating-Point Single */
     case 54:           /* Store Floating-Point Double */
        {
-         ULONGEST addr = 0;
+         ULONGEST iaddr = 0;
          int size = -1;
 
          if (PPC_RA (insn) != 0)
            regcache_raw_read_unsigned (regcache,
                                        tdep->ppc_gp0_regnum + PPC_RA (insn),
-                                       &addr);
-         addr += PPC_D (insn);
+                                       &iaddr);
+         iaddr += PPC_D (insn);
 
          if (op6 == 36 || op6 == 37 || op6 == 52 || op6 == 53)
            size = 4;
@@ -5833,13 +6150,13 @@ ppc_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
          else
            gdb_assert (0);
 
-         record_full_arch_list_add_mem (addr, size);
+         record_full_arch_list_add_mem (iaddr, size);
        }
       break;
 
     case 57:
       switch (insn & 0x3)
-        {
+       {
        case 0:         /* Load Floating-Point Double Pair */
          tmp = tdep->ppc_fp0_regnum + (PPC_RT (insn) & ~1);
          record_full_arch_list_add_reg (regcache, tmp);
@@ -5886,7 +6203,7 @@ ppc_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
                        /* Store Doubleword with Update */
                        /* Store Quadword with Update */
        {
-         ULONGEST addr = 0;
+         ULONGEST iaddr = 0;
          int size;
          int sub2 = PPC_FIELD (insn, 30, 2);
 
@@ -5896,12 +6213,12 @@ ppc_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
          if (PPC_RA (insn) != 0)
            regcache_raw_read_unsigned (regcache,
                                        tdep->ppc_gp0_regnum + PPC_RA (insn),
-                                       &addr);
+                                       &iaddr);
 
          size = (sub2 == 2) ? 16 : 8;
 
-         addr += PPC_DS (insn) << 2;
-         record_full_arch_list_add_mem (addr, size);
+         iaddr += PPC_DS (insn) << 2;
+         record_full_arch_list_add_mem (iaddr, size);
 
          if (op6 == 62 && sub2 == 1)
            record_full_arch_list_add_reg (regcache,
@@ -5930,6 +6247,69 @@ UNKNOWN_OP:
   return 0;
 }
 
+/* Used for matching tw, twi, td and tdi instructions for POWER.  */
+
+static constexpr uint32_t TX_INSN_MASK = 0xFC0007FF;
+static constexpr uint32_t TW_INSN = 0x7C000008;
+static constexpr uint32_t TD_INSN = 0x7C000088;
+
+static constexpr uint32_t TXI_INSN_MASK = 0xFC000000;
+static constexpr uint32_t TWI_INSN = 0x0C000000;
+static constexpr uint32_t TDI_INSN = 0x08000000;
+
+static inline bool
+is_tw_insn (uint32_t insn)
+{
+  return (insn & TX_INSN_MASK) == TW_INSN;
+}
+
+static inline bool
+is_twi_insn (uint32_t insn)
+{
+  return (insn & TXI_INSN_MASK) == TWI_INSN;
+}
+
+static inline bool
+is_td_insn (uint32_t insn)
+{
+  return (insn & TX_INSN_MASK) == TD_INSN;
+}
+
+static inline bool
+is_tdi_insn (uint32_t insn)
+{
+  return (insn & TXI_INSN_MASK) == TDI_INSN;
+}
+
+/* Implementation of gdbarch_program_breakpoint_here_p for POWER.  */
+
+static bool
+rs6000_program_breakpoint_here_p (gdbarch *gdbarch, CORE_ADDR address)
+{
+  gdb_byte target_mem[PPC_INSN_SIZE];
+
+  /* Enable the automatic memory restoration from breakpoints while
+     we read the memory.  Otherwise we may find temporary breakpoints, ones
+     inserted by GDB, and flag them as permanent breakpoints.  */
+  scoped_restore restore_memory
+    = make_scoped_restore_show_memory_breakpoints (0);
+
+  if (target_read_memory (address, target_mem, PPC_INSN_SIZE) == 0)
+    {
+      uint32_t insn = (uint32_t) extract_unsigned_integer
+        (target_mem, PPC_INSN_SIZE, gdbarch_byte_order_for_code (gdbarch));
+
+      /* Check if INSN is a TW, TWI, TD or TDI instruction.  There
+         are multiple choices of such instructions with different registers
+         and / or immediate values but they all cause a break. */
+      if (is_tw_insn (insn) || is_twi_insn (insn) || is_td_insn (insn)
+          || is_tdi_insn (insn))
+        return true;
+    }
+
+  return false;
+}
+
 /* Initialize the current architecture based on INFO.  If possible, re-use an
    architecture from ARCHES, which is a list of architectures already created
    during this debugging session.
@@ -5941,7 +6321,6 @@ static struct gdbarch *
 rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
   struct gdbarch *gdbarch;
-  struct gdbarch_tdep *tdep;
   int wordsize, from_xcoff_exec, from_elf_exec;
   enum bfd_architecture arch;
   unsigned long mach;
@@ -5951,24 +6330,18 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   enum powerpc_long_double_abi long_double_abi = POWERPC_LONG_DOUBLE_AUTO;
   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 have_fpu = 0, have_spe = 0, have_mq = 0, have_altivec = 0;
+  int have_dfp = 0, have_vsx = 0, have_ppr = 0, have_dscr = 0;
+  int have_tar = 0, have_ebb = 0, have_pmu = 0, have_htm_spr = 0;
+  int have_htm_core = 0, have_htm_fpu = 0, have_htm_altivec = 0;
+  int have_htm_vsx = 0, have_htm_ppr = 0, have_htm_dscr = 0;
+  int have_htm_tar = 0;
   int tdesc_wordsize = -1;
   const struct target_desc *tdesc = info.target_desc;
-  struct tdesc_arch_data *tdesc_data = NULL;
+  tdesc_arch_data_up tdesc_data;
   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;
 
@@ -6026,7 +6399,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      layout, if we do not already have one.  */
   if (! tdesc_has_registers (tdesc))
     {
-      const struct variant *v;
+      const struct ppc_variant *v;
 
       /* Choose variant.  */
       v = find_variant_by_arch (arch, mach);
@@ -6062,33 +6435,31 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
       valid_p = 1;
       for (i = 0; i < ppc_num_gprs; i++)
-       valid_p &= tdesc_numbered_register (feature, tdesc_data, i, gprs[i]);
-      valid_p &= tdesc_numbered_register (feature, tdesc_data, PPC_PC_REGNUM,
-                                         "pc");
-      valid_p &= tdesc_numbered_register (feature, tdesc_data, PPC_LR_REGNUM,
-                                         "lr");
-      valid_p &= tdesc_numbered_register (feature, tdesc_data, PPC_XER_REGNUM,
-                                         "xer");
+       valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+                                           i, gprs[i]);
+      valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+                                         PPC_PC_REGNUM, "pc");
+      valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+                                         PPC_LR_REGNUM, "lr");
+      valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+                                         PPC_XER_REGNUM, "xer");
 
       /* Allow alternate names for these registers, to accomodate GDB's
         historic naming.  */
-      valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
+      valid_p &= tdesc_numbered_register_choices (feature, tdesc_data.get (),
                                                  PPC_MSR_REGNUM, msr_names);
-      valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
+      valid_p &= tdesc_numbered_register_choices (feature, tdesc_data.get (),
                                                  PPC_CR_REGNUM, cr_names);
-      valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
+      valid_p &= tdesc_numbered_register_choices (feature, tdesc_data.get (),
                                                  PPC_CTR_REGNUM, ctr_names);
 
       if (!valid_p)
-       {
-         tdesc_data_cleanup (tdesc_data);
-         return NULL;
-       }
+       return NULL;
 
-      have_mq = tdesc_numbered_register (feature, tdesc_data, PPC_MQ_REGNUM,
-                                        "mq");
+      have_mq = tdesc_numbered_register (feature, tdesc_data.get (),
+                                        PPC_MQ_REGNUM, "mq");
 
-      tdesc_wordsize = tdesc_register_size (feature, "pc") / 8;
+      tdesc_wordsize = tdesc_register_bitsize (feature, "pc") / 8;
       if (wordsize == -1)
        wordsize = tdesc_wordsize;
 
@@ -6104,25 +6475,24 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
          };
          valid_p = 1;
          for (i = 0; i < ppc_num_fprs; i++)
-           valid_p &= tdesc_numbered_register (feature, tdesc_data,
+           valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
                                                PPC_F0_REGNUM + i, fprs[i]);
-         valid_p &= tdesc_numbered_register (feature, tdesc_data,
+         valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
                                              PPC_FPSCR_REGNUM, "fpscr");
 
          if (!valid_p)
-           {
-             tdesc_data_cleanup (tdesc_data);
-             return NULL;
-           }
+           return NULL;
          have_fpu = 1;
+
+         /* The fpscr register was expanded in isa 2.05 to 64 bits
+            along with the addition of the decimal floating point
+            facility.  */
+         if (tdesc_register_bitsize (feature, "fpscr") > 32)
+           have_dfp = 1;
        }
       else
        have_fpu = 0;
 
-      /* The DFP pseudo-registers will be available when there are floating
-         point registers.  */
-      have_dfp = have_fpu;
-
       feature = tdesc_find_feature (tdesc,
                                    "org.gnu.gdb.power.altivec");
       if (feature != NULL)
@@ -6136,19 +6506,16 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
          valid_p = 1;
          for (i = 0; i < ppc_num_gprs; i++)
-           valid_p &= tdesc_numbered_register (feature, tdesc_data,
+           valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
                                                PPC_VR0_REGNUM + i,
                                                vector_regs[i]);
-         valid_p &= tdesc_numbered_register (feature, tdesc_data,
+         valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
                                              PPC_VSCR_REGNUM, "vscr");
-         valid_p &= tdesc_numbered_register (feature, tdesc_data,
+         valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
                                              PPC_VRSAVE_REGNUM, "vrsave");
 
          if (have_spe || !valid_p)
-           {
-             tdesc_data_cleanup (tdesc_data);
-             return NULL;
-           }
+           return NULL;
          have_altivec = 1;
        }
       else
@@ -6172,14 +6539,12 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
          valid_p = 1;
 
          for (i = 0; i < ppc_num_vshrs; i++)
-           valid_p &= tdesc_numbered_register (feature, tdesc_data,
+           valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
                                                PPC_VSR0_UPPER_REGNUM + i,
                                                vsx_regs[i]);
-         if (!valid_p)
-           {
-             tdesc_data_cleanup (tdesc_data);
-             return NULL;
-           }
+
+         if (!valid_p || !have_fpu || !have_altivec)
+           return NULL;
 
          have_vsx = 1;
        }
@@ -6216,23 +6581,291 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
          valid_p = 1;
          for (i = 0; i < ppc_num_gprs; i++)
-           valid_p &= tdesc_numbered_register (feature, tdesc_data,
+           valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
                                                PPC_SPE_UPPER_GP0_REGNUM + i,
                                                upper_spe[i]);
-         valid_p &= tdesc_numbered_register (feature, tdesc_data,
+         valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
                                              PPC_SPE_ACC_REGNUM, "acc");
-         valid_p &= tdesc_numbered_register (feature, tdesc_data,
+         valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
                                              PPC_SPE_FSCR_REGNUM, "spefscr");
 
          if (have_mq || have_fpu || !valid_p)
-           {
-             tdesc_data_cleanup (tdesc_data);
-             return NULL;
-           }
+           return NULL;
          have_spe = 1;
        }
       else
        have_spe = 0;
+
+      /* Program Priority Register.  */
+      feature = tdesc_find_feature (tdesc,
+                                   "org.gnu.gdb.power.ppr");
+      if (feature != NULL)
+       {
+         valid_p = 1;
+         valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+                                             PPC_PPR_REGNUM, "ppr");
+
+         if (!valid_p)
+           return NULL;
+         have_ppr = 1;
+       }
+      else
+       have_ppr = 0;
+
+      /* Data Stream Control Register.  */
+      feature = tdesc_find_feature (tdesc,
+                                   "org.gnu.gdb.power.dscr");
+      if (feature != NULL)
+       {
+         valid_p = 1;
+         valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+                                             PPC_DSCR_REGNUM, "dscr");
+
+         if (!valid_p)
+           return NULL;
+         have_dscr = 1;
+       }
+      else
+       have_dscr = 0;
+
+      /* Target Address Register.  */
+      feature = tdesc_find_feature (tdesc,
+                                   "org.gnu.gdb.power.tar");
+      if (feature != NULL)
+       {
+         valid_p = 1;
+         valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+                                             PPC_TAR_REGNUM, "tar");
+
+         if (!valid_p)
+           return NULL;
+         have_tar = 1;
+       }
+      else
+       have_tar = 0;
+
+      /* Event-based Branching Registers.  */
+      feature = tdesc_find_feature (tdesc,
+                                   "org.gnu.gdb.power.ebb");
+      if (feature != NULL)
+       {
+         static const char *const ebb_regs[] = {
+           "bescr", "ebbhr", "ebbrr"
+         };
+
+         valid_p = 1;
+         for (i = 0; i < ARRAY_SIZE (ebb_regs); i++)
+           valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+                                               PPC_BESCR_REGNUM + i,
+                                               ebb_regs[i]);
+         if (!valid_p)
+           return NULL;
+         have_ebb = 1;
+       }
+      else
+       have_ebb = 0;
+
+      /* Subset of the ISA 2.07 Performance Monitor Registers provided
+        by Linux.  */
+      feature = tdesc_find_feature (tdesc,
+                                   "org.gnu.gdb.power.linux.pmu");
+      if (feature != NULL)
+       {
+         valid_p = 1;
+
+         valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+                                             PPC_MMCR0_REGNUM,
+                                             "mmcr0");
+         valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+                                             PPC_MMCR2_REGNUM,
+                                             "mmcr2");
+         valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+                                             PPC_SIAR_REGNUM,
+                                             "siar");
+         valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+                                             PPC_SDAR_REGNUM,
+                                             "sdar");
+         valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+                                             PPC_SIER_REGNUM,
+                                             "sier");
+
+         if (!valid_p)
+           return NULL;
+         have_pmu = 1;
+       }
+      else
+       have_pmu = 0;
+
+      /* Hardware Transactional Memory Registers.  */
+      feature = tdesc_find_feature (tdesc,
+                                   "org.gnu.gdb.power.htm.spr");
+      if (feature != NULL)
+       {
+         static const char *const tm_spr_regs[] = {
+           "tfhar", "texasr", "tfiar"
+         };
+
+         valid_p = 1;
+         for (i = 0; i < ARRAY_SIZE (tm_spr_regs); i++)
+           valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+                                               PPC_TFHAR_REGNUM + i,
+                                               tm_spr_regs[i]);
+         if (!valid_p)
+           return NULL;
+
+         have_htm_spr = 1;
+       }
+      else
+       have_htm_spr = 0;
+
+      feature = tdesc_find_feature (tdesc,
+                                   "org.gnu.gdb.power.htm.core");
+      if (feature != NULL)
+       {
+         static const char *const cgprs[] = {
+           "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
+           "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14",
+           "cr15", "cr16", "cr17", "cr18", "cr19", "cr20", "cr21",
+           "cr22", "cr23", "cr24", "cr25", "cr26", "cr27", "cr28",
+           "cr29", "cr30", "cr31", "ccr", "cxer", "clr", "cctr"
+         };
+
+         valid_p = 1;
+
+         for (i = 0; i < ARRAY_SIZE (cgprs); i++)
+           valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+                                               PPC_CR0_REGNUM + i,
+                                               cgprs[i]);
+         if (!valid_p)
+           return NULL;
+
+         have_htm_core = 1;
+       }
+      else
+       have_htm_core = 0;
+
+      feature = tdesc_find_feature (tdesc,
+                                   "org.gnu.gdb.power.htm.fpu");
+      if (feature != NULL)
+       {
+         valid_p = 1;
+
+         static const char *const cfprs[] = {
+           "cf0", "cf1", "cf2", "cf3", "cf4", "cf5", "cf6", "cf7",
+           "cf8", "cf9", "cf10", "cf11", "cf12", "cf13", "cf14", "cf15",
+           "cf16", "cf17", "cf18", "cf19", "cf20", "cf21", "cf22",
+           "cf23", "cf24", "cf25", "cf26", "cf27", "cf28", "cf29",
+           "cf30", "cf31", "cfpscr"
+         };
+
+         for (i = 0; i < ARRAY_SIZE (cfprs); i++)
+           valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+                                               PPC_CF0_REGNUM + i,
+                                               cfprs[i]);
+
+         if (!valid_p)
+           return NULL;
+         have_htm_fpu = 1;
+       }
+      else
+       have_htm_fpu = 0;
+
+      feature = tdesc_find_feature (tdesc,
+                                   "org.gnu.gdb.power.htm.altivec");
+      if (feature != NULL)
+       {
+         valid_p = 1;
+
+         static const char *const cvmx[] = {
+           "cvr0", "cvr1", "cvr2", "cvr3", "cvr4", "cvr5", "cvr6",
+           "cvr7", "cvr8", "cvr9", "cvr10", "cvr11", "cvr12", "cvr13",
+           "cvr14", "cvr15","cvr16", "cvr17", "cvr18", "cvr19", "cvr20",
+           "cvr21", "cvr22", "cvr23", "cvr24", "cvr25", "cvr26",
+           "cvr27", "cvr28", "cvr29", "cvr30", "cvr31", "cvscr",
+           "cvrsave"
+         };
+
+         for (i = 0; i < ARRAY_SIZE (cvmx); i++)
+           valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+                                               PPC_CVR0_REGNUM + i,
+                                               cvmx[i]);
+
+         if (!valid_p)
+           return NULL;
+         have_htm_altivec = 1;
+       }
+      else
+       have_htm_altivec = 0;
+
+      feature = tdesc_find_feature (tdesc,
+                                   "org.gnu.gdb.power.htm.vsx");
+      if (feature != NULL)
+       {
+         valid_p = 1;
+
+         static const char *const cvsx[] = {
+           "cvs0h", "cvs1h", "cvs2h", "cvs3h", "cvs4h", "cvs5h",
+           "cvs6h", "cvs7h", "cvs8h", "cvs9h", "cvs10h", "cvs11h",
+           "cvs12h", "cvs13h", "cvs14h", "cvs15h", "cvs16h", "cvs17h",
+           "cvs18h", "cvs19h", "cvs20h", "cvs21h", "cvs22h", "cvs23h",
+           "cvs24h", "cvs25h", "cvs26h", "cvs27h", "cvs28h", "cvs29h",
+           "cvs30h", "cvs31h"
+         };
+
+         for (i = 0; i < ARRAY_SIZE (cvsx); i++)
+           valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+                                               (PPC_CVSR0_UPPER_REGNUM
+                                                + i),
+                                               cvsx[i]);
+
+         if (!valid_p || !have_htm_fpu || !have_htm_altivec)
+           return NULL;
+         have_htm_vsx = 1;
+       }
+      else
+       have_htm_vsx = 0;
+
+      feature = tdesc_find_feature (tdesc,
+                                   "org.gnu.gdb.power.htm.ppr");
+      if (feature != NULL)
+       {
+         valid_p = tdesc_numbered_register (feature, tdesc_data.get (),
+                                            PPC_CPPR_REGNUM, "cppr");
+
+         if (!valid_p)
+           return NULL;
+         have_htm_ppr = 1;
+       }
+      else
+       have_htm_ppr = 0;
+
+      feature = tdesc_find_feature (tdesc,
+                                   "org.gnu.gdb.power.htm.dscr");
+      if (feature != NULL)
+       {
+         valid_p = tdesc_numbered_register (feature, tdesc_data.get (),
+                                            PPC_CDSCR_REGNUM, "cdscr");
+
+         if (!valid_p)
+           return NULL;
+         have_htm_dscr = 1;
+       }
+      else
+       have_htm_dscr = 0;
+
+      feature = tdesc_find_feature (tdesc,
+                                   "org.gnu.gdb.power.htm.tar");
+      if (feature != NULL)
+       {
+         valid_p = tdesc_numbered_register (feature, tdesc_data.get (),
+                                            PPC_CTAR_REGNUM, "ctar");
+
+         if (!valid_p)
+           return NULL;
+         have_htm_tar = 1;
+       }
+      else
+       have_htm_tar = 0;
     }
 
   /* If we have a 64-bit binary on a 32-bit target, complain.  Also
@@ -6247,10 +6880,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      supplies a 64-bit description while debugging a 32-bit
      binary.  */
   if (tdesc_wordsize != -1 && tdesc_wordsize != wordsize)
-    {
-      tdesc_data_cleanup (tdesc_data);
-      return NULL;
-    }
+    return NULL;
 
 #ifdef HAVE_ELF
   if (from_elf_exec)
@@ -6330,9 +6960,9 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   if (elf_abi == POWERPC_ELF_AUTO)
     {
       if (wordsize == 8 && info.byte_order == BFD_ENDIAN_LITTLE)
-        elf_abi = POWERPC_ELF_V2;
+       elf_abi = POWERPC_ELF_V2;
       else
-        elf_abi = POWERPC_ELF_V1;
+       elf_abi = POWERPC_ELF_V1;
     }
 
   if (soft_float_flag == AUTO_BOOLEAN_TRUE)
@@ -6374,9 +7004,10 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
        arches = gdbarch_list_lookup_by_info (arches->next, &info))
     {
       /* Word size in the various PowerPC bfd_arch_info structs isn't
-         meaningful, because 64-bit CPUs can run in 32-bit mode.  So, perform
-         separate word size check.  */
-      tdep = gdbarch_tdep (arches->gdbarch);
+        meaningful, because 64-bit CPUs can run in 32-bit mode.  So, perform
+        separate word size check.  */
+      ppc_gdbarch_tdep *tdep
+       = (ppc_gdbarch_tdep *) gdbarch_tdep (arches->gdbarch);
       if (tdep && tdep->elf_abi != elf_abi)
        continue;
       if (tdep && tdep->soft_float != soft_float)
@@ -6386,11 +7017,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       if (tdep && tdep->vector_abi != vector_abi)
        continue;
       if (tdep && tdep->wordsize == wordsize)
-       {
-         if (tdesc_data != NULL)
-           tdesc_data_cleanup (tdesc_data);
-         return arches->gdbarch;
-       }
+       return arches->gdbarch;
     }
 
   /* None found, create a new architecture from INFO, whose bfd_arch_info
@@ -6401,7 +7028,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
        - "set arch"            trust blindly
        - GDB startup           useless but harmless */
 
-  tdep = XCNEW (struct gdbarch_tdep);
+  ppc_gdbarch_tdep *tdep = new ppc_gdbarch_tdep;
   tdep->wordsize = wordsize;
   tdep->elf_abi = elf_abi;
   tdep->soft_float = soft_float;
@@ -6427,6 +7054,32 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->ppc_ev0_upper_regnum = have_spe ? PPC_SPE_UPPER_GP0_REGNUM : -1;
   tdep->ppc_acc_regnum = have_spe ? PPC_SPE_ACC_REGNUM : -1;
   tdep->ppc_spefscr_regnum = have_spe ? PPC_SPE_FSCR_REGNUM : -1;
+  tdep->ppc_ppr_regnum = have_ppr ? PPC_PPR_REGNUM : -1;
+  tdep->ppc_dscr_regnum = have_dscr ? PPC_DSCR_REGNUM : -1;
+  tdep->ppc_tar_regnum = have_tar ? PPC_TAR_REGNUM : -1;
+  tdep->have_ebb = have_ebb;
+
+  /* If additional pmu registers are added, care must be taken when
+     setting new fields in the tdep below, to maintain compatibility
+     with features that only provide some of the registers.  Currently
+     gdb access to the pmu registers is only supported in linux, and
+     linux only provides a subset of the pmu registers defined in the
+     architecture.  */
+
+  tdep->ppc_mmcr0_regnum = have_pmu ? PPC_MMCR0_REGNUM : -1;
+  tdep->ppc_mmcr2_regnum = have_pmu ? PPC_MMCR2_REGNUM : -1;
+  tdep->ppc_siar_regnum = have_pmu ? PPC_SIAR_REGNUM : -1;
+  tdep->ppc_sdar_regnum = have_pmu ? PPC_SDAR_REGNUM : -1;
+  tdep->ppc_sier_regnum = have_pmu ? PPC_SIER_REGNUM : -1;
+
+  tdep->have_htm_spr = have_htm_spr;
+  tdep->have_htm_core = have_htm_core;
+  tdep->have_htm_fpu = have_htm_fpu;
+  tdep->have_htm_altivec = have_htm_altivec;
+  tdep->have_htm_vsx = have_htm_vsx;
+  tdep->ppc_cppr_regnum = have_htm_ppr ? PPC_CPPR_REGNUM : -1;
+  tdep->ppc_cdscr_regnum = have_htm_dscr ? PPC_CDSCR_REGNUM : -1;
+  tdep->ppc_ctar_regnum = have_htm_tar ? PPC_CTAR_REGNUM : -1;
 
   set_gdbarch_pc_regnum (gdbarch, PPC_PC_REGNUM);
   set_gdbarch_sp_regnum (gdbarch, PPC_R0_REGNUM + 1);
@@ -6449,7 +7102,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   else
     tdep->lr_frame_offset = 4;
 
-  if (have_spe || have_dfp || have_vsx)
+  if (have_spe || have_dfp || have_altivec
+      || have_vsx || have_htm_fpu || have_htm_vsx)
     {
       set_gdbarch_pseudo_register_read (gdbarch, rs6000_pseudo_register_read);
       set_gdbarch_pseudo_register_write (gdbarch,
@@ -6468,9 +7122,16 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     num_pseudoregs += 32;
   if (have_dfp)
     num_pseudoregs += 16;
+  if (have_altivec)
+    num_pseudoregs += 32;
   if (have_vsx)
     /* Include both VSX and Extended FP registers.  */
     num_pseudoregs += 96;
+  if (have_htm_fpu)
+    num_pseudoregs += 16;
+  /* Include both checkpointed VSX and EFP registers.  */
+  if (have_htm_vsx)
+    num_pseudoregs += 64 + 32;
 
   set_gdbarch_num_pseudo_regs (gdbarch, num_pseudoregs);
 
@@ -6511,6 +7172,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
                                       rs6000_breakpoint::kind_from_pc);
   set_gdbarch_sw_breakpoint_from_kind (gdbarch,
                                       rs6000_breakpoint::bp_from_kind);
+  set_gdbarch_program_breakpoint_here_p (gdbarch,
+                                         rs6000_program_breakpoint_here_p);
 
   /* The value of symbols of type N_SO and N_FUN maybe null when
      it shouldn't be.  */
@@ -6543,14 +7206,16 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_displaced_step_hw_singlestep (gdbarch,
                                            ppc_displaced_step_hw_singlestep);
   set_gdbarch_displaced_step_fixup (gdbarch, ppc_displaced_step_fixup);
-  set_gdbarch_displaced_step_location (gdbarch,
-                                      displaced_step_at_entry_point);
+  set_gdbarch_displaced_step_prepare (gdbarch, ppc_displaced_step_prepare);
+  set_gdbarch_displaced_step_finish (gdbarch, ppc_displaced_step_finish);
+  set_gdbarch_displaced_step_restore_all_in_ptid
+    (gdbarch, ppc_displaced_step_restore_all_in_ptid);
 
-  set_gdbarch_max_insn_length (gdbarch, PPC_INSN_SIZE);
+  set_gdbarch_max_insn_length (gdbarch, 2 * PPC_INSN_SIZE);
 
   /* Hook in ABI-specific overrides, if they have been registered.  */
   info.target_desc = tdesc;
-  info.tdesc_data = tdesc_data;
+  info.tdesc_data = tdesc_data.get ();
   gdbarch_init_osabi (info, gdbarch);
 
   switch (info.osabi)
@@ -6558,26 +7223,22 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     case GDB_OSABI_LINUX:
     case GDB_OSABI_NETBSD:
     case GDB_OSABI_UNKNOWN:
-      set_gdbarch_unwind_pc (gdbarch, rs6000_unwind_pc);
       frame_unwind_append_unwinder (gdbarch, &rs6000_epilogue_frame_unwind);
       frame_unwind_append_unwinder (gdbarch, &rs6000_frame_unwind);
-      set_gdbarch_dummy_id (gdbarch, rs6000_dummy_id);
       frame_base_append_sniffer (gdbarch, rs6000_frame_base_sniffer);
       break;
     default:
       set_gdbarch_believe_pcc_promotion (gdbarch, 1);
 
-      set_gdbarch_unwind_pc (gdbarch, rs6000_unwind_pc);
       frame_unwind_append_unwinder (gdbarch, &rs6000_epilogue_frame_unwind);
       frame_unwind_append_unwinder (gdbarch, &rs6000_frame_unwind);
-      set_gdbarch_dummy_id (gdbarch, rs6000_dummy_id);
       frame_base_append_sniffer (gdbarch, rs6000_frame_base_sniffer);
     }
 
   set_tdesc_pseudo_register_type (gdbarch, rs6000_pseudo_register_type);
   set_tdesc_pseudo_register_reggroup_p (gdbarch,
                                        rs6000_pseudo_register_reggroup_p);
-  tdesc_use_registers (gdbarch, tdesc, tdesc_data);
+  tdesc_use_registers (gdbarch, tdesc, std::move (tdesc_data));
 
   /* Override the normal target description method to make the SPE upper
      halves anonymous.  */
@@ -6586,8 +7247,12 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Choose register numbers for all supported pseudo-registers.  */
   tdep->ppc_ev0_regnum = -1;
   tdep->ppc_dl0_regnum = -1;
+  tdep->ppc_v0_alias_regnum = -1;
   tdep->ppc_vsr0_regnum = -1;
   tdep->ppc_efpr0_regnum = -1;
+  tdep->ppc_cdl0_regnum = -1;
+  tdep->ppc_cvsr0_regnum = -1;
+  tdep->ppc_cefpr0_regnum = -1;
 
   cur_reg = gdbarch_num_regs (gdbarch);
 
@@ -6601,6 +7266,11 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       tdep->ppc_dl0_regnum = cur_reg;
       cur_reg += 16;
     }
+  if (have_altivec)
+    {
+      tdep->ppc_v0_alias_regnum = cur_reg;
+      cur_reg += 32;
+    }
   if (have_vsx)
     {
       tdep->ppc_vsr0_regnum = cur_reg;
@@ -6608,9 +7278,20 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       tdep->ppc_efpr0_regnum = cur_reg;
       cur_reg += 32;
     }
+  if (have_htm_fpu)
+    {
+      tdep->ppc_cdl0_regnum = cur_reg;
+      cur_reg += 16;
+    }
+  if (have_htm_vsx)
+    {
+      tdep->ppc_cvsr0_regnum = cur_reg;
+      cur_reg += 64;
+      tdep->ppc_cefpr0_regnum = cur_reg;
+      cur_reg += 32;
+    }
 
-  gdb_assert (gdbarch_num_regs (gdbarch)
-             + gdbarch_num_pseudo_regs (gdbarch) == cur_reg);
+  gdb_assert (gdbarch_num_cooked_regs (gdbarch) == cur_reg);
 
   /* Register the ravenscar_arch_ops.  */
   if (mach == bfd_mach_ppc_e500)
@@ -6628,7 +7309,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 static void
 rs6000_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
 
   if (tdep == NULL)
     return;
@@ -6636,22 +7317,6 @@ rs6000_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
   /* FIXME: Dump gdbarch_tdep.  */
 }
 
-/* PowerPC-specific commands.  */
-
-static void
-set_powerpc_command (const char *args, int from_tty)
-{
-  printf_unfiltered (_("\
-\"set powerpc\" must be followed by an appropriate subcommand.\n"));
-  help_list (setpowerpccmdlist, "set powerpc ", all_commands, gdb_stdout);
-}
-
-static void
-show_powerpc_command (const char *args, int from_tty)
-{
-  cmd_show_list (showpowerpccmdlist, from_tty, "");
-}
-
 static void
 powerpc_set_soft_float (const char *args, int from_tty,
                        struct cmd_list_element *c)
@@ -6659,7 +7324,6 @@ powerpc_set_soft_float (const char *args, int from_tty,
   struct gdbarch_info info;
 
   /* Update the architecture.  */
-  gdbarch_info_init (&info);
   if (!gdbarch_update_p (info))
     internal_error (__FILE__, __LINE__, _("could not update architecture"));
 }
@@ -6668,7 +7332,6 @@ static void
 powerpc_set_vector_abi (const char *args, int from_tty,
                        struct cmd_list_element *c)
 {
-  struct gdbarch_info info;
   int vector_abi;
 
   for (vector_abi = POWERPC_VEC_AUTO;
@@ -6686,7 +7349,7 @@ powerpc_set_vector_abi (const char *args, int from_tty,
                    powerpc_vector_abi_string);
 
   /* Update the architecture.  */
-  gdbarch_info_init (&info);
+  gdbarch_info info;
   if (!gdbarch_update_p (info))
     internal_error (__FILE__, __LINE__, _("could not update architecture"));
 }
@@ -6717,17 +7380,17 @@ read_insn (struct frame_info *frame, CORE_ADDR pc)
    '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]
+   When the match is successful, fill INSNS[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.  */
+   present, set INSNS[i] to 0 (which is not a valid PPC instruction).
+   INSNS should have as many elements as PATTERN, minus the terminator.
+   Note that, if PATTERN contains optional instructions which aren't
+   present in memory, then INSNS will have holes, so INSNS[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,
+                        const struct ppc_insn_pattern *pattern,
                         unsigned int *insns)
 {
   int i;
@@ -6770,10 +7433,19 @@ ppc_insn_ds_field (unsigned int insn)
   return ((((CORE_ADDR) insn & 0xfffc) ^ 0x8000) - 0x8000);
 }
 
+CORE_ADDR
+ppc_insn_prefix_dform (unsigned int insn1, unsigned int insn2)
+{
+  /* result is 34-bits  */
+  return (CORE_ADDR) ((((insn1 & 0x3ffff) ^ 0x20000) - 0x20000) << 16)
+    | (CORE_ADDR)(insn2 & 0xffff);
+}
+
 /* Initialization code.  */
 
+void _initialize_rs6000_tdep ();
 void
-_initialize_rs6000_tdep (void)
+_initialize_rs6000_tdep ()
 {
   gdbarch_register (bfd_arch_rs6000, rs6000_gdbarch_init, rs6000_dump_tdep);
   gdbarch_register (bfd_arch_powerpc, rs6000_gdbarch_init, rs6000_dump_tdep);
@@ -6801,13 +7473,11 @@ _initialize_rs6000_tdep (void)
 
   /* Add root prefix command for all "set powerpc"/"show powerpc"
      commands.  */
-  add_prefix_cmd ("powerpc", no_class, set_powerpc_command,
-                 _("Various PowerPC-specific commands."),
-                 &setpowerpccmdlist, "set powerpc ", 0, &setlist);
-
-  add_prefix_cmd ("powerpc", no_class, show_powerpc_command,
-                 _("Various PowerPC-specific commands."),
-                 &showpowerpccmdlist, "show powerpc ", 0, &showlist);
+  add_setshow_prefix_cmd ("powerpc", no_class,
+                         _("Various PowerPC-specific commands."),
+                         _("Various PowerPC-specific commands."),
+                         &setpowerpccmdlist, &showpowerpccmdlist,
+                         &setlist, &showlist);
 
   /* Add a command to allow the user to force the ABI.  */
   add_setshow_auto_boolean_cmd ("soft-float", class_support,