gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / rs6000-tdep.c
index fc12619a7b06ecec9da7e01845672681c0291402..ead3500c26300c78c9d509833eb1dad7973bbe47 100644 (file)
@@ -1,8 +1,6 @@
 /* Target-dependent code for GDB, the GNU debugger.
 
-   Copyright (C) 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
-   Free Software Foundation, Inc.
+   Copyright (C) 1986-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -22,6 +20,7 @@
 #include "defs.h"
 #include "frame.h"
 #include "inferior.h"
+#include "infrun.h"
 #include "symtab.h"
 #include "target.h"
 #include "gdbcore.h"
@@ -30,7 +29,7 @@
 #include "arch-utils.h"
 #include "regcache.h"
 #include "regset.h"
-#include "doublest.h"
+#include "target-float.h"
 #include "value.h"
 #include "parser-defs.h"
 #include "osabi.h"
 #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"
+#include "auxv.h"
 
-#include "libbfd.h"            /* for bfd_default_set_arch_mach */
 #include "coff/internal.h"     /* for libcoff.h */
 #include "libcoff.h"           /* for xcoff_data */
 #include "coff/xcoff.h"
 
 #include "elf-bfd.h"
 #include "elf/ppc.h"
+#include "elf/ppc64.h"
 
 #include "solib-svr4.h"
 #include "ppc-tdep.h"
+#include "ppc-ravenscar-thread.h"
 
-#include "gdb_assert.h"
 #include "dis-asm.h"
 
 #include "trad-frame.h"
 #include "frame-unwind.h"
 #include "frame-base.h"
 
-#include "rs6000-tdep.h"
+#include "ax.h"
+#include "ax-gdb.h"
+#include <algorithm>
 
 #include "features/rs6000/powerpc-32.c"
+#include "features/rs6000/powerpc-altivec32.c"
+#include "features/rs6000/powerpc-vsx32.c"
 #include "features/rs6000/powerpc-403.c"
 #include "features/rs6000/powerpc-403gc.c"
+#include "features/rs6000/powerpc-405.c"
 #include "features/rs6000/powerpc-505.c"
 #include "features/rs6000/powerpc-601.c"
 #include "features/rs6000/powerpc-602.c"
 #include "features/rs6000/powerpc-603.c"
 #include "features/rs6000/powerpc-604.c"
 #include "features/rs6000/powerpc-64.c"
+#include "features/rs6000/powerpc-altivec64.c"
+#include "features/rs6000/powerpc-vsx64.c"
 #include "features/rs6000/powerpc-7400.c"
 #include "features/rs6000/powerpc-750.c"
 #include "features/rs6000/powerpc-860.c"
     && (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_vsr0_regnum + ppc_num_vsrs)
+
+/* Determine if regnum is a POWER7 Extended FP register.  */
+#define IS_EFP_PSEUDOREG(tdep, regnum) ((tdep)->ppc_efpr0_regnum >= 0 \
+    && (regnum) >= (tdep)->ppc_efpr0_regnum \
+    && (regnum) < (tdep)->ppc_efpr0_regnum + ppc_num_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;
+
 /* The list of available "set powerpc ..." and "show powerpc ..."
    commands.  */
 static struct cmd_list_element *setpowerpccmdlist = NULL;
@@ -96,7 +140,7 @@ static struct cmd_list_element *showpowerpccmdlist = NULL;
 static enum auto_boolean powerpc_soft_float_global = AUTO_BOOLEAN_AUTO;
 
 /* The vector ABI to use.  Keep this in sync with powerpc_vector_abi.  */
-static const char *powerpc_vector_strings[] =
+static const char *const powerpc_vector_strings[] =
 {
   "auto",
   "generic",
@@ -109,18 +153,7 @@ static const char *powerpc_vector_strings[] =
 static enum powerpc_vector_abi powerpc_vector_abi_global = POWERPC_VEC_AUTO;
 static const char *powerpc_vector_abi_string = "auto";
 
-/* If the kernel has to deliver a signal, it pushes a sigcontext
-   structure on the stack and then calls the signal handler, passing
-   the address of the sigcontext in an argument register. Usually
-   the signal handler doesn't save this register, so we have to
-   access the sigcontext structure via an offset from the signal handler
-   frame.
-   The following constants were determined by experimentation on AIX 3.2.  */
-#define SIG_FRAME_PC_OFFSET 96
-#define SIG_FRAME_LR_OFFSET 108
-#define SIG_FRAME_FP_OFFSET 284
-
-/* To be used by skip_prologue. */
+/* To be used by skip_prologue.  */
 
 struct rs6000_framedata
   {
@@ -128,47 +161,36 @@ struct rs6000_framedata
                                   by which we decrement sp to allocate
                                   the frame */
     int saved_gpr;             /* smallest # of saved gpr */
+    unsigned int gpr_mask;     /* Each bit is an individual saved GPR.  */
     int saved_fpr;             /* smallest # of saved fpr */
     int saved_vr;               /* smallest # of saved vr */
     int saved_ev;               /* smallest # of saved ev */
     int alloca_reg;            /* alloca register number (frame ptr) */
-    char frameless;            /* true if frameless functions. */
-    char nosavedpc;            /* true if pc not saved. */
+    char frameless;            /* true if frameless functions.  */
+    char nosavedpc;            /* true if pc not saved.  */
+    char used_bl;              /* true if link register clobbered */
     int gpr_offset;            /* offset of saved gprs from prev sp */
     int fpr_offset;            /* offset of saved fprs from prev sp */
     int vr_offset;              /* offset of saved vrs from prev sp */
     int ev_offset;              /* offset of saved evs from prev sp */
     int lr_offset;             /* offset of saved lr */
+    int lr_register;           /* register of saved lr, if trustworthy */
     int cr_offset;             /* offset of saved cr */
     int vrsave_offset;          /* offset of saved vrsave register */
   };
 
-/* Description of a single register. */
-
-struct reg
-  {
-    char *name;                        /* name of register */
-    unsigned char sz32;                /* size on 32-bit arch, 0 if nonexistent */
-    unsigned char sz64;                /* size on 64-bit arch, 0 if nonexistent */
-    unsigned char fpr;         /* whether register is floating-point */
-    unsigned char pseudo;       /* whether register is pseudo */
-    int spr_num;                /* PowerPC SPR number, or -1 if not an SPR.
-                                   This is an ISA SPR number, not a GDB
-                                   register number.  */
-  };
-
-/* Hook for determining the TOC address when calling functions in the
-   inferior under AIX. The initialization code in rs6000-nat.c sets
-   this hook to point to find_toc_address.  */
-
-CORE_ADDR (*rs6000_find_toc_address_hook) (CORE_ADDR) = NULL;
-
-/* Static function prototypes */
 
-static CORE_ADDR branch_dest (struct frame_info *frame, int opcode,
-                             int instr, CORE_ADDR pc, CORE_ADDR safety);
-static CORE_ADDR skip_prologue (struct gdbarch *, CORE_ADDR, CORE_ADDR,
-                                struct rs6000_framedata *);
+/* Is REGNO a VSX register? Return 1 if so, 0 otherwise.  */
+int
+vsx_register_p (struct gdbarch *gdbarch, int regno)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  if (tdep->ppc_vsr0_regnum < 0)
+    return 0;
+  else
+    return (regno >= tdep->ppc_vsr0_upper_regnum && regno
+           <= tdep->ppc_vsr0_upper_regnum + 31);
+}
 
 /* Is REGNO an AltiVec register?  Return 1 if so, 0 otherwise.  */
 int
@@ -325,7 +347,7 @@ init_sim_regno_table (struct gdbarch *arch)
     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.  */
 
-#ifdef WITH_SIM
+#ifdef WITH_PPC_SIM
   /* Now handle all special-purpose registers.  Verify that they
      haven't mistakenly been assigned numbers by any of the above
      code.  */
@@ -358,9 +380,7 @@ rs6000_register_sim_regno (struct gdbarch *gdbarch, int reg)
   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)
@@ -376,7 +396,7 @@ rs6000_register_sim_regno (struct gdbarch *gdbarch, int reg)
 /* REGS + OFFSET contains register REGNUM in a field REGSIZE wide.
    Write the register to REGCACHE.  */
 
-static void
+void
 ppc_supply_reg (struct regcache *regcache, int regnum, 
                const gdb_byte *regs, size_t offset, int regsize)
 {
@@ -384,20 +404,20 @@ ppc_supply_reg (struct regcache *regcache, int regnum,
     {
       if (regsize > 4)
        {
-         struct gdbarch *gdbarch = get_regcache_arch (regcache);
+         struct gdbarch *gdbarch = regcache->arch ();
          int gdb_regsize = register_size (gdbarch, regnum);
          if (gdb_regsize < regsize
              && gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
            offset += regsize - gdb_regsize;
        }
-      regcache_raw_supply (regcache, regnum, regs + offset);
+      regcache->raw_supply (regnum, regs + offset);
     }
 }
 
 /* Read register REGNUM from REGCACHE and store to REGS + OFFSET
    in a field REGSIZE wide.  Zero pad as necessary.  */
 
-static void
+void
 ppc_collect_reg (const struct regcache *regcache, int regnum,
                 gdb_byte *regs, size_t offset, int regsize)
 {
@@ -405,7 +425,7 @@ ppc_collect_reg (const struct regcache *regcache, int regnum,
     {
       if (regsize > 4)
        {
-         struct gdbarch *gdbarch = get_regcache_arch (regcache);
+         struct gdbarch *gdbarch = regcache->arch ();
          int gdb_regsize = register_size (gdbarch, regnum);
          if (gdb_regsize < regsize)
            {
@@ -419,7 +439,7 @@ 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);
     }
 }
     
@@ -476,24 +496,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.  */
@@ -502,9 +504,10 @@ void
 ppc_supply_gregset (const struct regset *regset, struct regcache *regcache,
                    int regnum, const void *gregs, size_t len)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  const struct ppc_reg_offsets *offsets = regset->descr;
+  const struct ppc_reg_offsets *offsets
+    = (const struct ppc_reg_offsets *) regset->regmap;
   size_t offset;
   int regsize;
 
@@ -516,27 +519,31 @@ ppc_supply_gregset (const struct regset *regset, struct regcache *regcache,
       for (i = tdep->ppc_gp0_regnum, offset = offsets->r0_offset;
           i < tdep->ppc_gp0_regnum + ppc_num_gprs;
           i++, offset += gpr_size)
-       ppc_supply_reg (regcache, i, gregs, offset, gpr_size);
+       ppc_supply_reg (regcache, i, (const gdb_byte *) gregs, offset,
+                       gpr_size);
 
       ppc_supply_reg (regcache, gdbarch_pc_regnum (gdbarch),
-                     gregs, offsets->pc_offset, gpr_size);
+                     (const gdb_byte *) gregs, offsets->pc_offset, gpr_size);
       ppc_supply_reg (regcache, tdep->ppc_ps_regnum,
-                     gregs, offsets->ps_offset, gpr_size);
+                     (const gdb_byte *) gregs, offsets->ps_offset, gpr_size);
       ppc_supply_reg (regcache, tdep->ppc_lr_regnum,
-                     gregs, offsets->lr_offset, gpr_size);
+                     (const gdb_byte *) gregs, offsets->lr_offset, gpr_size);
       ppc_supply_reg (regcache, tdep->ppc_ctr_regnum,
-                     gregs, offsets->ctr_offset, gpr_size);
+                     (const gdb_byte *) gregs, offsets->ctr_offset, gpr_size);
       ppc_supply_reg (regcache, tdep->ppc_cr_regnum,
-                     gregs, offsets->cr_offset, offsets->xr_size);
+                     (const gdb_byte *) gregs, offsets->cr_offset,
+                     offsets->xr_size);
       ppc_supply_reg (regcache, tdep->ppc_xer_regnum,
-                     gregs, offsets->xer_offset, offsets->xr_size);
+                     (const gdb_byte *) gregs, offsets->xer_offset,
+                     offsets->xr_size);
       ppc_supply_reg (regcache, tdep->ppc_mq_regnum,
-                     gregs, offsets->mq_offset, offsets->xr_size);
+                     (const gdb_byte *) gregs, offsets->mq_offset,
+                     offsets->xr_size);
       return;
     }
 
   offset = ppc_greg_offset (gdbarch, tdep, offsets, regnum, &regsize);
-  ppc_supply_reg (regcache, regnum, gregs, offset, regsize);
+  ppc_supply_reg (regcache, regnum, (const gdb_byte *) gregs, offset, regsize);
 }
 
 /* Supply register REGNUM in the floating-point register set REGSET
@@ -547,7 +554,7 @@ void
 ppc_supply_fpregset (const struct regset *regset, struct regcache *regcache,
                     int regnum, const void *fpregs, size_t len)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   struct gdbarch_tdep *tdep;
   const struct ppc_reg_offsets *offsets;
   size_t offset;
@@ -556,7 +563,7 @@ ppc_supply_fpregset (const struct regset *regset, struct regcache *regcache,
     return;
 
   tdep = gdbarch_tdep (gdbarch);
-  offsets = regset->descr;
+  offsets = (const struct ppc_reg_offsets *) regset->regmap;
   if (regnum == -1)
     {
       int i;
@@ -564,62 +571,19 @@ ppc_supply_fpregset (const struct regset *regset, struct regcache *regcache,
       for (i = tdep->ppc_fp0_regnum, offset = offsets->f0_offset;
           i < tdep->ppc_fp0_regnum + ppc_num_fprs;
           i++, offset += 8)
-       ppc_supply_reg (regcache, i, fpregs, offset, 8);
+       ppc_supply_reg (regcache, i, (const gdb_byte *) fpregs, offset, 8);
 
       ppc_supply_reg (regcache, tdep->ppc_fpscr_regnum,
-                     fpregs, offsets->fpscr_offset, offsets->fpscr_size);
+                     (const gdb_byte *) fpregs, offsets->fpscr_offset,
+                     offsets->fpscr_size);
       return;
     }
 
   offset = ppc_fpreg_offset (tdep, offsets, regnum);
-  ppc_supply_reg (regcache, regnum, fpregs, offset,
+  ppc_supply_reg (regcache, regnum, (const gdb_byte *) fpregs, offset,
                  regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 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 = get_regcache_arch (regcache);
-  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 = regset->descr;
-  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, vrregs, offset, 16);
-
-      ppc_supply_reg (regcache, (tdep->ppc_vrsave_regnum - 1),
-                     vrregs, offsets->vscr_offset, 4);
-
-      ppc_supply_reg (regcache, tdep->ppc_vrsave_regnum,
-                     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, vrregs, offset, 16);
-  else
-    ppc_supply_reg (regcache, regnum,
-                   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
@@ -630,9 +594,10 @@ ppc_collect_gregset (const struct regset *regset,
                     const struct regcache *regcache,
                     int regnum, void *gregs, size_t len)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  const struct ppc_reg_offsets *offsets = regset->descr;
+  const struct ppc_reg_offsets *offsets
+    = (const struct ppc_reg_offsets *) regset->regmap;
   size_t offset;
   int regsize;
 
@@ -644,27 +609,30 @@ ppc_collect_gregset (const struct regset *regset,
       for (i = tdep->ppc_gp0_regnum, offset = offsets->r0_offset;
           i < tdep->ppc_gp0_regnum + ppc_num_gprs;
           i++, offset += gpr_size)
-       ppc_collect_reg (regcache, i, gregs, offset, gpr_size);
+       ppc_collect_reg (regcache, i, (gdb_byte *) gregs, offset, gpr_size);
 
       ppc_collect_reg (regcache, gdbarch_pc_regnum (gdbarch),
-                      gregs, offsets->pc_offset, gpr_size);
+                      (gdb_byte *) gregs, offsets->pc_offset, gpr_size);
       ppc_collect_reg (regcache, tdep->ppc_ps_regnum,
-                      gregs, offsets->ps_offset, gpr_size);
+                      (gdb_byte *) gregs, offsets->ps_offset, gpr_size);
       ppc_collect_reg (regcache, tdep->ppc_lr_regnum,
-                      gregs, offsets->lr_offset, gpr_size);
+                      (gdb_byte *) gregs, offsets->lr_offset, gpr_size);
       ppc_collect_reg (regcache, tdep->ppc_ctr_regnum,
-                      gregs, offsets->ctr_offset, gpr_size);
+                      (gdb_byte *) gregs, offsets->ctr_offset, gpr_size);
       ppc_collect_reg (regcache, tdep->ppc_cr_regnum,
-                      gregs, offsets->cr_offset, offsets->xr_size);
+                      (gdb_byte *) gregs, offsets->cr_offset,
+                      offsets->xr_size);
       ppc_collect_reg (regcache, tdep->ppc_xer_regnum,
-                      gregs, offsets->xer_offset, offsets->xr_size);
+                      (gdb_byte *) gregs, offsets->xer_offset,
+                      offsets->xr_size);
       ppc_collect_reg (regcache, tdep->ppc_mq_regnum,
-                      gregs, offsets->mq_offset, offsets->xr_size);
+                      (gdb_byte *) gregs, offsets->mq_offset,
+                      offsets->xr_size);
       return;
     }
 
   offset = ppc_greg_offset (gdbarch, tdep, offsets, regnum, &regsize);
-  ppc_collect_reg (regcache, regnum, gregs, offset, regsize);
+  ppc_collect_reg (regcache, regnum, (gdb_byte *) gregs, offset, regsize);
 }
 
 /* Collect register REGNUM in the floating-point register set
@@ -677,7 +645,7 @@ ppc_collect_fpregset (const struct regset *regset,
                      const struct regcache *regcache,
                      int regnum, void *fpregs, size_t len)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   struct gdbarch_tdep *tdep;
   const struct ppc_reg_offsets *offsets;
   size_t offset;
@@ -686,7 +654,7 @@ ppc_collect_fpregset (const struct regset *regset,
     return;
 
   tdep = gdbarch_tdep (gdbarch);
-  offsets = regset->descr;
+  offsets = (const struct ppc_reg_offsets *) regset->regmap;
   if (regnum == -1)
     {
       int i;
@@ -694,103 +662,19 @@ ppc_collect_fpregset (const struct regset *regset,
       for (i = tdep->ppc_fp0_regnum, offset = offsets->f0_offset;
           i < tdep->ppc_fp0_regnum + ppc_num_fprs;
           i++, offset += 8)
-       ppc_collect_reg (regcache, i, fpregs, offset, 8);
+       ppc_collect_reg (regcache, i, (gdb_byte *) fpregs, offset, 8);
 
       ppc_collect_reg (regcache, tdep->ppc_fpscr_regnum,
-                      fpregs, offsets->fpscr_offset, offsets->fpscr_size);
+                      (gdb_byte *) fpregs, offsets->fpscr_offset,
+                      offsets->fpscr_size);
       return;
     }
 
   offset = ppc_fpreg_offset (tdep, offsets, regnum);
-  ppc_collect_reg (regcache, regnum, fpregs, offset,
+  ppc_collect_reg (regcache, regnum, (gdb_byte *) fpregs, offset,
                   regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 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 = get_regcache_arch (regcache);
-  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 = regset->descr;
-  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, vrregs, offset, 16);
-
-      ppc_collect_reg (regcache, (tdep->ppc_vrsave_regnum - 1),
-                      vrregs, offsets->vscr_offset, 4);
-
-      ppc_collect_reg (regcache, tdep->ppc_vrsave_regnum,
-                      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, vrregs, offset, 16);
-  else
-    ppc_collect_reg (regcache, regnum,
-                   vrregs, offset, 4);
-}
-\f
-
-/* Read a LEN-byte address from debugged memory address MEMADDR. */
-
-static CORE_ADDR
-read_memory_addr (CORE_ADDR memaddr, int len)
-{
-  return read_memory_unsigned_integer (memaddr, len);
-}
-
-static CORE_ADDR
-rs6000_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
-{
-  struct rs6000_framedata frame;
-  CORE_ADDR limit_pc, func_addr;
-
-  /* See if we can determine the end of the prologue via the symbol table.
-     If so, then return either PC, or the PC after the prologue, whichever
-     is greater.  */
-  if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
-    {
-      CORE_ADDR post_prologue_pc = skip_prologue_using_sal (func_addr);
-      if (post_prologue_pc != 0)
-       return max (pc, post_prologue_pc);
-    }
-
-  /* Can't determine prologue from the symbol table, need to examine
-     instructions.  */
-
-  /* Find an upper limit on the function prologue using the debug
-     information.  If the debug information could not be used to provide
-     that bound, then use an arbitrary large number as the upper bound.  */
-  limit_pc = skip_prologue_using_sal (pc);
-  if (limit_pc == 0)
-    limit_pc = pc + 100;          /* Magic.  */
-
-  pc = skip_prologue (gdbarch, pc, limit_pc, &frame);
-  return pc;
-}
-
 static int
 insn_changes_sp_or_jumps (unsigned long insn)
 {
@@ -844,12 +728,14 @@ insn_changes_sp_or_jumps (unsigned long insn)
            limit for the size of an epilogue.  */
 
 static int
-rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+rs6000_in_function_epilogue_frame_p (struct frame_info *curfrm,
+                                    struct gdbarch *gdbarch, CORE_ADDR pc)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   bfd_byte insn_buf[PPC_INSN_SIZE];
   CORE_ADDR scan_pc, func_start, func_end, epilogue_start, epilogue_end;
   unsigned long insn;
-  struct frame_info *curfrm;
 
   /* Find the search limits based on function boundaries and hard limit.  */
 
@@ -862,17 +748,26 @@ rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
   epilogue_end = pc + PPC_MAX_EPILOGUE_INSTRUCTIONS * PPC_INSN_SIZE;
   if (epilogue_end > func_end) epilogue_end = func_end;
 
-  curfrm = get_current_frame ();
-
   /* Scan forward until next 'blr'.  */
 
   for (scan_pc = pc; scan_pc < epilogue_end; scan_pc += PPC_INSN_SIZE)
     {
       if (!safe_frame_unwind_memory (curfrm, scan_pc, insn_buf, PPC_INSN_SIZE))
         return 0;
-      insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE);
+      insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE, byte_order);
       if (insn == 0x4e800020)
         break;
+      /* Assume a bctr is a tail call unless it points strictly within
+        this function.  */
+      if (insn == 0x4e800420)
+       {
+         CORE_ADDR ctr = get_frame_register_unsigned (curfrm,
+                                                      tdep->ppc_ctr_regnum);
+         if (ctr > func_start && ctr < func_end)
+           return 0;
+         else
+           break;
+       }
       if (insn_changes_sp_or_jumps (insn))
         return 0;
     }
@@ -885,7 +780,7 @@ rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
     {
       if (!safe_frame_unwind_memory (curfrm, scan_pc, insn_buf, PPC_INSN_SIZE))
         return 0;
-      insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE);
+      insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE, byte_order);
       if (insn_changes_sp_or_jumps (insn))
         return 1;
     }
@@ -893,6 +788,15 @@ rs6000_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
   return 0;
 }
 
+/* Implement the stack_frame_destroyed_p gdbarch method.  */
+
+static int
+rs6000_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  return rs6000_in_function_epilogue_frame_p (get_current_frame (),
+                                             gdbarch, pc);
+}
+
 /* Get the ith function argument for the current function.  */
 static CORE_ADDR
 rs6000_fetch_pointer_argument (struct frame_info *frame, int argi, 
@@ -901,226 +805,282 @@ rs6000_fetch_pointer_argument (struct frame_info *frame, int argi,
   return get_frame_register_unsigned (frame, 3 + argi);
 }
 
-/* Calculate the destination of a branch/jump.  Return -1 if not a branch.  */
+/* Sequence of bytes for breakpoint instruction.  */
 
-static CORE_ADDR
-branch_dest (struct frame_info *frame, int opcode, int instr,
-            CORE_ADDR pc, CORE_ADDR safety)
-{
-  struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (frame));
-  CORE_ADDR dest;
-  int immediate;
-  int absolute;
-  int ext_op;
+constexpr gdb_byte big_breakpoint[] = { 0x7d, 0x82, 0x10, 0x08 };
+constexpr gdb_byte little_breakpoint[] = { 0x08, 0x10, 0x82, 0x7d };
 
-  absolute = (int) ((instr >> 1) & 1);
+typedef BP_MANIPULATION_ENDIAN (little_breakpoint, big_breakpoint)
+  rs6000_breakpoint;
 
-  switch (opcode)
-    {
-    case 18:
-      immediate = ((instr & ~3) << 6) >> 6;    /* br unconditional */
-      if (absolute)
-       dest = immediate;
-      else
-       dest = pc + immediate;
-      break;
+/* Instruction masks for displaced stepping.  */
+#define BRANCH_MASK 0xfc000000
+#define BP_MASK 0xFC0007FE
+#define B_INSN 0x48000000
+#define BC_INSN 0x40000000
+#define BXL_INSN 0x4c000000
+#define BP_INSN 0x7C000008
 
-    case 16:
-      immediate = ((instr & ~3) << 16) >> 16;  /* br conditional */
-      if (absolute)
-       dest = immediate;
-      else
-       dest = pc + immediate;
-      break;
+/* Instruction masks used during single-stepping of atomic
+   sequences.  */
+#define LOAD_AND_RESERVE_MASK 0xfc0007fe
+#define LWARX_INSTRUCTION 0x7c000028
+#define LDARX_INSTRUCTION 0x7c0000A8
+#define LBARX_INSTRUCTION 0x7c000068
+#define LHARX_INSTRUCTION 0x7c0000e8
+#define LQARX_INSTRUCTION 0x7c000228
+#define STORE_CONDITIONAL_MASK 0xfc0007ff
+#define STWCX_INSTRUCTION 0x7c00012d
+#define STDCX_INSTRUCTION 0x7c0001ad
+#define STBCX_INSTRUCTION 0x7c00056d
+#define STHCX_INSTRUCTION 0x7c0005ad
+#define STQCX_INSTRUCTION 0x7c00016d
+
+/* 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 \
+                                        || (insn & LOAD_AND_RESERVE_MASK) == LDARX_INSTRUCTION \
+                                        || (insn & LOAD_AND_RESERVE_MASK) == LBARX_INSTRUCTION \
+                                        || (insn & LOAD_AND_RESERVE_MASK) == LHARX_INSTRUCTION \
+                                        || (insn & LOAD_AND_RESERVE_MASK) == LQARX_INSTRUCTION)
+/* Check if insn is one of the Store Conditional instructions used for atomic
+   sequences.  */
+#define IS_STORE_CONDITIONAL_INSN(insn)        ((insn & STORE_CONDITIONAL_MASK) == STWCX_INSTRUCTION \
+                                        || (insn & STORE_CONDITIONAL_MASK) == STDCX_INSTRUCTION \
+                                        || (insn & STORE_CONDITIONAL_MASK) == STBCX_INSTRUCTION \
+                                        || (insn & STORE_CONDITIONAL_MASK) == STHCX_INSTRUCTION \
+                                        || (insn & STORE_CONDITIONAL_MASK) == STQCX_INSTRUCTION)
+
+typedef buf_displaced_step_copy_insn_closure ppc_displaced_step_copy_insn_closure;
+
+/* We can't displaced step atomic sequences.  */
+
+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_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;
 
-    case 19:
-      ext_op = (instr >> 1) & 0x3ff;
+  read_memory (from, buf, len);
 
-      if (ext_op == 16)                /* br conditional register */
-       {
-          dest = get_frame_register_unsigned (frame, tdep->ppc_lr_regnum) & ~3;
+  insn = extract_signed_integer (buf, PPC_INSN_SIZE, byte_order);
 
-         /* If we are about to return from a signal handler, dest is
-            something like 0x3c90.  The current frame is a signal handler
-            caller frame, upon completion of the sigreturn system call
-            execution will return to the saved PC in the frame.  */
-         if (dest < tdep->text_segment_base)
-           dest = read_memory_addr (get_frame_base (frame) + SIG_FRAME_PC_OFFSET,
-                                    tdep->wordsize);
+  /* 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",
+                             paddress (gdbarch, from));
        }
 
-      else if (ext_op == 528)  /* br cond to count reg */
-       {
-          dest = get_frame_register_unsigned (frame, tdep->ppc_ctr_regnum) & ~3;
+      return NULL;
+    }
 
-         /* If we are about to execute a system call, dest is something
-            like 0x22fc or 0x3b00.  Upon completion the system call
-            will return to the address in the link register.  */
-         if (dest < tdep->text_segment_base)
-            dest = get_frame_register_unsigned (frame, tdep->ppc_lr_regnum) & ~3;
-       }
-      else
-       return -1;
-      break;
+  write_memory (to, buf, len);
 
-    default:
-      return -1;
+  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);
     }
-  return (dest < tdep->text_segment_base) ? safety : dest;
+
+  /* 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_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_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;
+  /* Offset for non PC-relative instructions.  */
+  LONGEST offset = PPC_INSN_SIZE;
 
-/* Sequence of bytes for breakpoint instruction.  */
+  opcode = insn & BRANCH_MASK;
 
-const static unsigned char *
-rs6000_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
-                          int *bp_size)
-{
-  static unsigned char big_breakpoint[] = { 0x7d, 0x82, 0x10, 0x08 };
-  static unsigned char little_breakpoint[] = { 0x08, 0x10, 0x82, 0x7d };
-  *bp_size = 4;
-  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
-    return big_breakpoint;
-  else
-    return little_breakpoint;
-}
+  if (debug_displaced)
+    fprintf_unfiltered (gdb_stdlog,
+                       "displaced: (ppc) fixup (%s, %s)\n",
+                       paddress (gdbarch, from), paddress (gdbarch, to));
 
 
-/* Instruction masks used during single-stepping of atomic sequences.  */
-#define LWARX_MASK 0xfc0007fe
-#define LWARX_INSTRUCTION 0x7c000028
-#define LDARX_INSTRUCTION 0x7c0000A8
-#define STWCX_MASK 0xfc0007ff
-#define STWCX_INSTRUCTION 0x7c00012d
-#define STDCX_INSTRUCTION 0x7c0001ad
-#define BC_MASK 0xfc000000
-#define BC_INSTRUCTION 0x40000000
+  /* Handle PC-relative branch instructions.  */
+  if (opcode == B_INSN || opcode == BC_INSN || opcode == BXL_INSN)
+    {
+      ULONGEST current_pc;
 
-/* Checks for an atomic sequence of instructions beginning with a LWARX/LDARX
-   instruction and ending with a STWCX/STDCX instruction.  If such a sequence
-   is found, attempt to step through it.  A breakpoint is placed at the end of 
-   the sequence.  */
+      /* Read the current PC value after the instruction has been executed
+        in a displaced location.  Calculate the offset to be applied to the
+        original PC value before the displaced stepping.  */
+      regcache_cooked_read_unsigned (regs, gdbarch_pc_regnum (gdbarch),
+                                     &current_pc);
+      offset = current_pc - to;
 
-static int 
-deal_with_atomic_sequence (struct frame_info *frame)
+      if (opcode != BXL_INSN)
+       {
+         /* Check for AA bit indicating whether this is an absolute
+            addressing or PC-relative (1: absolute, 0: relative).  */
+         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));
+
+             regcache_cooked_write_unsigned (regs,
+                                             gdbarch_pc_regnum (gdbarch),
+                                             from + offset);
+           }
+       }
+      else
+       {
+         /* If we're here, it means we have a branch to LR or CTR.  If the
+            branch was taken, the offset is probably greater than 4 (the next
+            instruction), so it's safe to assume that an offset of 4 means we
+            did not take the branch.  */
+         if (offset == PPC_INSN_SIZE)
+           regcache_cooked_write_unsigned (regs, gdbarch_pc_regnum (gdbarch),
+                                           from + PPC_INSN_SIZE);
+       }
+
+      /* Check for LK bit indicating whether we should set the link
+        register to point to the next instruction
+        (1: Set, 0: Don't set).  */
+      if (insn & 0x1)
+       {
+         /* Link register needs to be set to the next instruction's PC.  */
+         regcache_cooked_write_unsigned (regs,
+                                         gdbarch_tdep (gdbarch)->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));
+
+       }
+    }
+  /* Check for breakpoints in the inferior.  If we've found one, place the PC
+     right at the breakpoint instruction.  */
+  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);
+}
+
+/* Always use hardware single-stepping to execute the
+   displaced instruction.  */
+static int
+ppc_displaced_step_hw_singlestep (struct gdbarch *gdbarch,
+                                 struct displaced_step_copy_insn_closure *closure)
 {
-  CORE_ADDR pc = get_frame_pc (frame);
-  CORE_ADDR breaks[2] = {-1, -1};
+  return 1;
+}
+
+/* Checks for an atomic sequence of instructions beginning with a
+   Load And Reserve instruction and ending with a Store Conditional
+   instruction.  If such a sequence is found, attempt to step through it.
+   A breakpoint is placed at the end of the sequence.  */
+std::vector<CORE_ADDR>
+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] = {CORE_ADDR_MAX, CORE_ADDR_MAX};
   CORE_ADDR loc = pc;
-  CORE_ADDR branch_bp; /* Breakpoint at branch instruction's destination.  */
   CORE_ADDR closing_insn; /* Instruction that closes the atomic sequence.  */
-  int insn = read_memory_integer (loc, PPC_INSN_SIZE);
+  int insn = read_memory_integer (loc, PPC_INSN_SIZE, byte_order);
   int insn_count;
   int index;
   int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed).  */  
   const int atomic_sequence_length = 16; /* Instruction sequence length.  */
-  int opcode; /* Branch instruction's OPcode.  */
   int bc_insn_count = 0; /* Conditional branch instruction count.  */
 
-  /* Assume all atomic sequences start with a lwarx/ldarx instruction.  */
-  if ((insn & LWARX_MASK) != LWARX_INSTRUCTION
-      && (insn & LWARX_MASK) != LDARX_INSTRUCTION)
-    return 0;
+  /* Assume all atomic sequences start with a Load And Reserve instruction.  */
+  if (!IS_LOAD_AND_RESERVE_INSN (insn))
+    return {};
 
   /* Assume that no atomic sequence is longer than "atomic_sequence_length" 
      instructions.  */
   for (insn_count = 0; insn_count < atomic_sequence_length; ++insn_count)
     {
       loc += PPC_INSN_SIZE;
-      insn = read_memory_integer (loc, PPC_INSN_SIZE);
+      insn = read_memory_integer (loc, PPC_INSN_SIZE, byte_order);
 
       /* Assume that there is at most one conditional branch in the atomic
          sequence.  If a conditional branch is found, put a breakpoint in 
          its destination address.  */
-      if ((insn & BC_MASK) == BC_INSTRUCTION)
+      if ((insn & BRANCH_MASK) == BC_INSN)
         {
+          int immediate = ((insn & 0xfffc) ^ 0x8000) - 0x8000;
+          int absolute = insn & 2;
+
           if (bc_insn_count >= 1)
-            return 0; /* More than one conditional branch found, fallback 
-                         to the standard single-step code.  */
-          
-          opcode = insn >> 26;
-          branch_bp = branch_dest (frame, opcode, insn, pc, breaks[0]);
-          
-          if (branch_bp != -1)
-            {
-              breaks[1] = branch_bp;
-              bc_insn_count++;
-              last_breakpoint++;
-            }
+            return {}; /* More than one conditional branch found, fallback
+                          to the standard single-step code.  */
+         if (absolute)
+           breaks[1] = immediate;
+         else
+           breaks[1] = loc + immediate;
+
+         bc_insn_count++;
+         last_breakpoint++;
         }
 
-      if ((insn & STWCX_MASK) == STWCX_INSTRUCTION
-          || (insn & STWCX_MASK) == STDCX_INSTRUCTION)
+      if (IS_STORE_CONDITIONAL_INSN (insn))
         break;
     }
 
-  /* Assume that the atomic sequence ends with a stwcx/stdcx instruction.  */
-  if ((insn & STWCX_MASK) != STWCX_INSTRUCTION
-      && (insn & STWCX_MASK) != STDCX_INSTRUCTION)
-    return 0;
+  /* Assume that the atomic sequence ends with a Store Conditional
+     instruction.  */
+  if (!IS_STORE_CONDITIONAL_INSN (insn))
+    return {};
 
   closing_insn = loc;
   loc += PPC_INSN_SIZE;
-  insn = read_memory_integer (loc, PPC_INSN_SIZE);
 
   /* Insert a breakpoint right after the end of the atomic sequence.  */
   breaks[0] = loc;
 
   /* Check for duplicated breakpoints.  Check also for a breakpoint
-     placed (branch instruction's destination) at the stwcx/stdcx 
-     instruction, this resets the reservation and take us back to the 
-     lwarx/ldarx instruction at the beginning of the atomic sequence.  */
-  if (last_breakpoint && ((breaks[1] == breaks[0]) 
-      || (breaks[1] == closing_insn)))
+     placed (branch instruction's destination) anywhere in sequence.  */
+  if (last_breakpoint
+      && (breaks[1] == breaks[0]
+         || (breaks[1] >= pc && breaks[1] <= closing_insn)))
     last_breakpoint = 0;
 
-  /* Effectively inserts the breakpoints.  */
-  for (index = 0; index <= last_breakpoint; index++)
-    insert_single_step_breakpoint (breaks[index]);
-
-  return 1;
-}
-
-/* AIX does not support PT_STEP.  Simulate it.  */
-
-int
-rs6000_software_single_step (struct frame_info *frame)
-{
-  CORE_ADDR dummy;
-  int breakp_sz;
-  const gdb_byte *breakp
-    = rs6000_breakpoint_from_pc (get_frame_arch (frame), &dummy, &breakp_sz);
-  int ii, insn;
-  CORE_ADDR loc;
-  CORE_ADDR breaks[2];
-  int opcode;
-
-  loc = get_frame_pc (frame);
-
-  insn = read_memory_integer (loc, 4);
-
-  if (deal_with_atomic_sequence (frame))
-    return 1;
-  
-  breaks[0] = loc + breakp_sz;
-  opcode = insn >> 26;
-  breaks[1] = branch_dest (frame, opcode, insn, loc, breaks[0]);
+  std::vector<CORE_ADDR> next_pcs;
 
-  /* Don't put two breakpoints on the same address. */
-  if (breaks[1] == breaks[0])
-    breaks[1] = -1;
-
-  for (ii = 0; ii < 2; ++ii)
-    {
-      /* ignore invalid breakpoint. */
-      if (breaks[ii] == -1)
-       continue;
-      insert_single_step_breakpoint (breaks[ii]);
-    }
+  for (index = 0; index <= last_breakpoint; index++)
+    next_pcs.push_back (breaks[index]);
 
-  errno = 0;                   /* FIXME, don't ignore errors! */
-  /* What errors?  {read,write}_memory call error().  */
-  return 1;
+  return next_pcs;
 }
 
 
@@ -1214,7 +1174,7 @@ store_param_on_stack_p (unsigned long op, int framep, int *r0_contains_arg)
    they can use to access PIC data using PC-relative offsets.  */
 
 static int
-bl_to_blrl_insn_p (CORE_ADDR pc, int insn)
+bl_to_blrl_insn_p (CORE_ADDR pc, int insn, enum bfd_endian byte_order)
 {
   CORE_ADDR dest;
   int immediate;
@@ -1228,77 +1188,310 @@ bl_to_blrl_insn_p (CORE_ADDR pc, int insn)
   else
     dest = pc + immediate;
 
-  dest_insn = read_memory_integer (dest, 4);
+  dest_insn = read_memory_integer (dest, 4, byte_order);
   if ((dest_insn & 0xfc00ffff) == 0x4c000021) /* blrl */
     return 1;
 
   return 0;
 }
 
-/* return pc value after skipping a function prologue and also return
-   information about a function frame.
+/* Return true if OP is a stw or std instruction with
+   register operands RS and RA and any immediate offset.
 
-   in struct rs6000_framedata fdata:
-   - frameless is TRUE, if function does not have a frame.
-   - nosavedpc is TRUE, if function does not save %pc value in its frame.
-   - offset is the initial size of this stack frame --- the amount by
-   which we decrement the sp to allocate the frame.
-   - saved_gpr is the number of the first saved gpr.
-   - saved_fpr is the number of the first saved fpr.
-   - saved_vr is the number of the first saved vr.
-   - saved_ev is the number of the first saved ev.
-   - alloca_reg is the number of the register used for alloca() handling.
-   Otherwise -1.
-   - gpr_offset is the offset of the first saved gpr from the previous frame.
-   - fpr_offset is the offset of the first saved fpr from the previous frame.
-   - vr_offset is the offset of the first saved vr from the previous frame.
-   - ev_offset is the offset of the first saved ev from the previous frame.
-   - lr_offset is the offset of the saved lr
-   - cr_offset is the offset of the saved cr
-   - vrsave_offset is the offset of the saved vrsave register
- */
+   If WITH_UPDATE is true, also return true if OP is
+   a stwu or stdu instruction with the same operands.
 
-static CORE_ADDR
-skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
-              struct rs6000_framedata *fdata)
+   Return false otherwise.
+   */
+static bool
+store_insn_p (unsigned long op, unsigned long rs,
+             unsigned long ra, bool with_update)
 {
-  CORE_ADDR orig_pc = pc;
-  CORE_ADDR last_prologue_pc = pc;
-  CORE_ADDR li_found_pc = 0;
-  gdb_byte buf[4];
-  unsigned long op;
-  long offset = 0;
-  long vr_saved_offset = 0;
-  int lr_reg = -1;
-  int cr_reg = -1;
-  int vr_reg = -1;
-  int ev_reg = -1;
-  long ev_offset = 0;
-  int vrsave_reg = -1;
-  int reg;
-  int framep = 0;
-  int minimal_toc_loaded = 0;
-  int prev_insn_was_prologue_insn = 1;
-  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);
+  rs = rs << 21;
+  ra = ra << 16;
 
-  memset (fdata, 0, sizeof (struct rs6000_framedata));
-  fdata->saved_gpr = -1;
-  fdata->saved_fpr = -1;
-  fdata->saved_vr = -1;
-  fdata->saved_ev = -1;
-  fdata->alloca_reg = -1;
-  fdata->frameless = 1;
-  fdata->nosavedpc = 1;
+  if (/* std RS, SIMM(RA) */
+      ((op & 0xffff0003) == (rs | ra | 0xf8000000)) ||
+      /* stw RS, SIMM(RA) */
+      ((op & 0xffff0000) == (rs | ra | 0x90000000)))
+    return true;
 
-  for (;; pc += 4)
+  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.
+   The former is anded with the opcode in question; if the result of
+   this masking operation is equal to BL_INSTRUCTION, then the opcode in
+   question is a ``bl'' instruction.
+   
+   BL_DISPLACEMENT_MASK is anded with the opcode in order to extract
+   the branch displacement.  */
+
+#define BL_MASK 0xfc000001
+#define BL_INSTRUCTION 0x48000001
+#define BL_DISPLACEMENT_MASK 0x03fffffc
+
+static unsigned long
+rs6000_fetch_instruction (struct gdbarch *gdbarch, const CORE_ADDR pc)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  gdb_byte buf[4];
+  unsigned long op;
+
+  /* Fetch the instruction and convert it to an integer.  */
+  if (target_read_memory (pc, buf, 4))
+    return 0;
+  op = extract_unsigned_integer (buf, 4, byte_order);
+
+  return op;
+}
+
+/* GCC generates several well-known sequences of instructions at the begining
+   of each function prologue when compiling with -fstack-check.  If one of
+   such sequences starts at START_PC, then return the address of the
+   instruction immediately past this sequence.  Otherwise, return START_PC.  */
+   
+static CORE_ADDR
+rs6000_skip_stack_check (struct gdbarch *gdbarch, const CORE_ADDR start_pc)
+{
+  CORE_ADDR pc = start_pc;
+  unsigned long op = rs6000_fetch_instruction (gdbarch, pc);
+
+  /* First possible sequence: A small number of probes.
+         stw 0, -<some immediate>(1)
+         [repeat this instruction any (small) number of times].  */
+  
+  if ((op & 0xffff0000) == 0x90010000)
+    {
+      while ((op & 0xffff0000) == 0x90010000)
+        {
+          pc = pc + 4;
+          op = rs6000_fetch_instruction (gdbarch, pc);
+        }
+      return pc;
+    }
+
+  /* Second sequence: A probing loop.
+         addi 12,1,-<some immediate>
+         lis 0,-<some immediate>
+         [possibly ori 0,0,<some immediate>]
+         add 0,12,0
+         cmpw 0,12,0
+         beq 0,<disp>
+         addi 12,12,-<some immediate>
+         stw 0,0(12)
+         b <disp>
+         [possibly one last probe: stw 0,<some immediate>(12)].  */
+
+  while (1)
+    {
+      /* addi 12,1,-<some immediate> */
+      if ((op & 0xffff0000) != 0x39810000)
+        break;
+
+      /* lis 0,-<some immediate> */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      if ((op & 0xffff0000) != 0x3c000000)
+        break;
+
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      /* [possibly ori 0,0,<some immediate>] */
+      if ((op & 0xffff0000) == 0x60000000)
+        {
+          pc = pc + 4;
+          op = rs6000_fetch_instruction (gdbarch, pc);
+        }
+      /* add 0,12,0 */
+      if (op != 0x7c0c0214)
+        break;
+
+      /* cmpw 0,12,0 */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      if (op != 0x7c0c0000)
+        break;
+
+      /* beq 0,<disp> */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      if ((op & 0xff9f0001) != 0x41820000)
+        break;
+
+      /* addi 12,12,-<some immediate> */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      if ((op & 0xffff0000) != 0x398c0000)
+        break;
+
+      /* stw 0,0(12) */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      if (op != 0x900c0000)
+        break;
+
+      /* b <disp> */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      if ((op & 0xfc000001) != 0x48000000)
+        break;
+
+      /* [possibly one last probe: stw 0,<some immediate>(12)].  */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      if ((op & 0xffff0000) == 0x900c0000)
+        {
+          pc = pc + 4;
+          op = rs6000_fetch_instruction (gdbarch, pc);
+        }
+
+      /* We found a valid stack-check sequence, return the new PC.  */
+      return pc;
+    }
+
+  /* Third sequence: No probe; instead, a 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
+
+     or, with a small variant in the case of a bigger stack frame:
+        addis 0,1,<some immediate>
+        addic 0,0,-<some immediate>
+        lis 12,__gnat_stack_limit@ha
+        lwz 12,__gnat_stack_limit@l(12)
+        twllt 0,12
+  */
+  while (1)
+    {
+      /* addi 0,1,-<some immediate> */
+      if ((op & 0xffff0000) != 0x38010000)
+        {
+          /* small stack frame variant not recognized; try the
+             big stack frame variant: */
+
+          /* addis 0,1,<some immediate> */
+          if ((op & 0xffff0000) != 0x3c010000)
+            break;
+
+          /* addic 0,0,-<some immediate> */
+          pc = pc + 4;
+          op = rs6000_fetch_instruction (gdbarch, pc);
+          if ((op & 0xffff0000) != 0x30000000)
+            break;
+        }
+
+      /* lis 12,<some immediate> */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      if ((op & 0xffff0000) != 0x3d800000)
+        break;
+      
+      /* lwz 12,<some immediate>(12) */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      if ((op & 0xffff0000) != 0x818c0000)
+        break;
+
+      /* twllt 0,12 */
+      pc = pc + 4;
+      op = rs6000_fetch_instruction (gdbarch, pc);
+      if ((op & 0xfffffffe) != 0x7c406008)
+        break;
+
+      /* We found a valid stack-check sequence, return the new PC.  */
+      return pc;
+    }
+
+  /* No stack check code in our prologue, return the start_pc.  */
+  return start_pc;
+}
+
+/* return pc value after skipping a function prologue and also return
+   information about a function frame.
+
+   in struct rs6000_framedata fdata:
+   - frameless is TRUE, if function does not have a frame.
+   - nosavedpc is TRUE, if function does not save %pc value in its frame.
+   - offset is the initial size of this stack frame --- the amount by
+   which we decrement the sp to allocate the frame.
+   - saved_gpr is the number of the first saved gpr.
+   - saved_fpr is the number of the first saved fpr.
+   - saved_vr is the number of the first saved vr.
+   - saved_ev is the number of the first saved ev.
+   - alloca_reg is the number of the register used for alloca() handling.
+   Otherwise -1.
+   - gpr_offset is the offset of the first saved gpr from the previous frame.
+   - fpr_offset is the offset of the first saved fpr from the previous frame.
+   - vr_offset is the offset of the first saved vr from the previous frame.
+   - ev_offset is the offset of the first saved ev from the previous frame.
+   - lr_offset is the offset of the saved lr
+   - cr_offset is the offset of the saved cr
+   - vrsave_offset is the offset of the saved vrsave register.  */
+
+static CORE_ADDR
+skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
+              struct rs6000_framedata *fdata)
+{
+  CORE_ADDR orig_pc = pc;
+  CORE_ADDR last_prologue_pc = pc;
+  CORE_ADDR li_found_pc = 0;
+  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;
+  int vr_reg = -1;
+  int ev_reg = -1;
+  long ev_offset = 0;
+  int vrsave_reg = -1;
+  int reg;
+  int framep = 0;
+  int minimal_toc_loaded = 0;
+  int prev_insn_was_prologue_insn = 1;
+  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);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
+  memset (fdata, 0, sizeof (struct rs6000_framedata));
+  fdata->saved_gpr = -1;
+  fdata->saved_fpr = -1;
+  fdata->saved_vr = -1;
+  fdata->saved_ev = -1;
+  fdata->alloca_reg = -1;
+  fdata->frameless = 1;
+  fdata->nosavedpc = 1;
+  fdata->lr_register = -1;
+
+  pc = rs6000_skip_stack_check (gdbarch, pc);
+  if (pc >= lim_pc)
+    pc = lim_pc;
+
+  for (;; pc += 4)
     {
       /* Sometimes it isn't clear if an instruction is a prologue
          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. */
+        Otherwise, we'll assume that it really is a prologue instruction.  */
       if (prev_insn_was_prologue_insn)
        last_prologue_pc = pc;
 
@@ -1311,7 +1504,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
       /* Fetch the instruction and convert it to an integer.  */
       if (target_read_memory (pc, buf, 4))
        break;
-      op = extract_unsigned_integer (buf, 4);
+      op = extract_unsigned_integer (buf, 4, byte_order);
 
       if ((op & 0xfc1fffff) == 0x7c0802a6)
        {                       /* mflr Rx */
@@ -1333,14 +1526,14 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
             remember just the first one, but skip over additional
             ones.  */
          if (lr_reg == -1)
-           lr_reg = (op & 0x03e00000);
+           lr_reg = (op & 0x03e00000) >> 21;
           if (lr_reg == 0)
             r0_contains_arg = 0;
          continue;
        }
       else if ((op & 0xfc1fffff) == 0x7c000026)
        {                       /* mfcr Rx */
-         cr_reg = (op & 0x03e00000);
+         cr_reg = (op & 0x03e00000) >> 21;
           if (cr_reg == 0)
             r0_contains_arg = 0;
          continue;
@@ -1364,6 +1557,10 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
        {
 
          reg = GET_SRC_REG (op);
+         if ((op & 0xfc1f0000) == 0xbc010000)
+           fdata->gpr_mask |= ~((1U << reg) - 1);
+         else
+           fdata->gpr_mask |= 1U << reg;
          if (fdata->saved_gpr == -1 || fdata->saved_gpr > reg)
            {
              fdata->saved_gpr = reg;
@@ -1374,19 +1571,30 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
          continue;
 
        }
-      else if ((op & 0xffff0000) == 0x60000000)
+      else if ((op & 0xffff0000) == 0x3c4c0000
+              || (op & 0xffff0000) == 0x3c400000
+              || (op & 0xffff0000) == 0x38420000)
+       {
+         /* .  0:      addis 2,12,.TOC.-0b@ha
+            .          addi 2,2,.TOC.-0b@l
+            or
+            .          lis 2,.TOC.@ha
+            .          addi 2,2,.TOC.@l
+            used by ELFv2 global entry points to set up r2.  */
+         continue;
+       }
+      else if (op == 0x60000000)
         {
          /* nop */
          /* Allow nops in the prologue, but do not consider them to
             be part of the prologue unless followed by other prologue
-            instructions. */
+            instructions.  */
          prev_insn_was_prologue_insn = 0;
          continue;
 
        }
       else if ((op & 0xffff0000) == 0x3c000000)
-       {                       /* addis 0,0,NUM, used
-                                  for >= 32k frames */
+       {                       /* addis 0,0,NUM, used for >= 32k frames */
          fdata->offset = (op & 0x0000ffff) << 16;
          fdata->frameless = 0;
           r0_contains_arg = 0;
@@ -1394,8 +1602,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
 
        }
       else if ((op & 0xffff0000) == 0x60000000)
-       {                       /* ori 0,0,NUM, 2nd ha
-                                  lf of >= 32k frames */
+       {                       /* ori 0,0,NUM, 2nd half of >= 32k frames */
          fdata->offset |= (op & 0x0000ffff);
          fdata->frameless = 0;
           r0_contains_arg = 0;
@@ -1403,14 +1610,17 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
 
        }
       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.  */
@@ -1425,13 +1635,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.  */
@@ -1455,6 +1660,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
       else if (op == 0x48000005)
        {                       /* bl .+4 used in 
                                   -mrelocatable */
+         fdata->used_bl = 1;
          continue;
 
        }
@@ -1472,14 +1678,17 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
        }
       else if ((op & 0xfc000001) == 0x48000001)
        {                       /* bl foo, 
-                                  to save fprs??? */
+                                  to save fprs???  */
 
          fdata->frameless = 0;
 
          /* If the return address has already been saved, we can skip
             calls to blrl (for PIC).  */
-          if (lr_reg != -1 && bl_to_blrl_insn_p (pc, op))
-           continue;
+          if (lr_reg != -1 && bl_to_blrl_insn_p (pc, op, byte_order))
+           {
+             fdata->used_bl = 1;
+             continue;
+           }
 
          /* Don't skip over the subroutine call if it is not within
             the first three instructions of the prologue and either
@@ -1491,22 +1700,24 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
              struct symtab_and_line prologue_sal = find_pc_line (orig_pc, 0);
              struct symtab_and_line this_sal = find_pc_line (pc, 0);
 
-             if ((prologue_sal.line == 0) || (prologue_sal.line != this_sal.line))
+             if ((prologue_sal.line == 0)
+                 || (prologue_sal.line != this_sal.line))
                break;
            }
 
-         op = read_memory_integer (pc + 4, 4);
+         op = read_memory_integer (pc + 4, 4, byte_order);
 
          /* At this point, make sure this is not a trampoline
             function (a function that simply calls another functions,
             and nothing else).  If the next is not a nop, this branch
-            was part of the function prologue. */
+            was part of the function prologue.  */
 
          if (op == 0x4def7b82 || op == 0)      /* crorc 15, 15, 15 */
-           break;              /* don't skip over 
-                                  this branch */
-         continue;
+           break;              /* Don't skip over 
+                                  this branch.  */
 
+         fdata->used_bl = 1;
+         continue;
        }
       /* update stack pointer */
       else if ((op & 0xfc1f0000) == 0x94010000)
@@ -1516,9 +1727,9 @@ 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 */
-         /* no way to figure out what r1 is going to be */
+      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;
          continue;
@@ -1530,13 +1741,6 @@ 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 */
-         fdata->frameless = 0;
-         offset = fdata->offset;
-         continue;
-       }
       else if ((op & 0xffff0000) == 0x38210000)
        {                       /* addi r1,r1,SIMM */
          fdata->frameless = 0;
@@ -1546,8 +1750,8 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
        }
       /* 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,... */
-              (op >> 22) == 0x3af)             /* ld r31,... or ld r30,... */
+      else if (((op >> 22) == 0x20f    ||      /* l r31,... or l r30,...  */
+              (op >> 22) == 0x3af)             /* ld r31,... or ld r30,...  */
               && !framep
               && !minimal_toc_loaded)
        {
@@ -1560,7 +1764,8 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
       else if ((op & 0xfc0007fe) == 0x7c000378 &&      /* mr(.)  Rx,Ry */
                (((op >> 21) & 31) >= 3) &&              /* R3 >= Ry >= R10 */
                (((op >> 21) & 31) <= 10) &&
-               ((long) ((op >> 16) & 31) >= fdata->saved_gpr)) /* Rx: local var reg */
+               ((long) ((op >> 16) & 31)
+               >= fdata->saved_gpr)) /* Rx: local var reg */
        {
          continue;
 
@@ -1573,12 +1778,23 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
 
          /* Set up frame pointer */
        }
+      else if (op == 0x603d0000)       /* oril r29, r1, 0x0 */
+       {
+         fdata->frameless = 0;
+         framep = 1;
+         fdata->alloca_reg = (tdep->ppc_gp0_regnum + 29);
+         alloca_reg_offset = offset;
+         continue;
+
+         /* Another way to set up the frame pointer.  */
+       }
       else if (op == 0x603f0000        /* oril r31, r1, 0x0 */
               || op == 0x7c3f0b78)
        {                       /* mr r31, r1 */
          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.  */
@@ -1589,6 +1805,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.  */
@@ -1642,7 +1859,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_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
+             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;
        }
@@ -1770,9 +1987,16 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
          /* Not a recognized prologue instruction.
             Handle optimizer code motions into the prologue by continuing
             the search if we have no valid frame yet or if the return
-            address is not yet saved in the frame.  */
-         if (fdata->frameless == 0 && fdata->nosavedpc == 0)
-           break;
+            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->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 */
@@ -1796,7 +2020,7 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
 
 #if 0
 /* I have problems with skipping over __main() that I need to address
- * sometime. Previously, I used to use misc_function_vector which
+ * sometime.  Previously, I used to use misc_function_vector which
  * didn't work as well as I wanted to be.  -MGO */
 
   /* If the first thing after skipping a prolog is a branch to a function,
@@ -1807,8 +2031,8 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
 
 
   if ((op & 0xfc000001) == 0x48000001)
-    {                          /* bl foo, an initializer function? */
-      op = read_memory_integer (pc + 4, 4);
+    {                          /* bl foo, an initializer function?  */
+      op = read_memory_integer (pc + 4, 4, byte_order);
 
       if (op == 0x4def7b82)
        {                       /* cror 0xf, 0xf, 0xf (nop) */
@@ -1824,446 +2048,147 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
     }
 #endif /* 0 */
 
+  if (pc == lim_pc && lr_reg >= 0)
+    fdata->lr_register = lr_reg;
+
   fdata->offset = -fdata->offset;
   return last_prologue_pc;
 }
 
-
-/*************************************************************************
-  Support for creating pushing a dummy frame into the stack, and popping
-  frames, etc. 
-*************************************************************************/
-
-
-/* All the ABI's require 16 byte alignment.  */
-static CORE_ADDR
-rs6000_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
-{
-  return (addr & -16);
-}
-
-/* Pass the arguments in either registers, or in the stack. In RS/6000,
-   the first eight words of the argument list (that might be less than
-   eight parameters if some parameters occupy more than one word) are
-   passed in r3..r10 registers.  float and double parameters are
-   passed in fpr's, in addition to that.  Rest of the parameters if any
-   are passed in user stack.  There might be cases in which half of the
-   parameter is copied into registers, the other half is pushed into
-   stack.
-
-   Stack must be aligned on 64-bit boundaries when synthesizing
-   function calls.
-
-   If the function is returning a structure, then the return address is passed
-   in r3, then the first 7 words of the parameters can be passed in registers,
-   starting from r4.  */
-
 static CORE_ADDR
-rs6000_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
-                       struct regcache *regcache, CORE_ADDR bp_addr,
-                       int nargs, struct value **args, CORE_ADDR sp,
-                       int struct_return, CORE_ADDR struct_addr)
+rs6000_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int ii;
-  int len = 0;
-  int argno;                   /* current argument number */
-  int argbytes;                        /* current argument byte */
-  gdb_byte tmp_buffer[50];
-  int f_argno = 0;             /* current floating point argno */
-  int wordsize = gdbarch_tdep (gdbarch)->wordsize;
-  CORE_ADDR func_addr = find_function_addr (function, NULL);
-
-  struct value *arg = 0;
-  struct type *type;
-
-  ULONGEST saved_sp;
-
-  /* The calling convention this function implements assumes the
-     processor has floating-point registers.  We shouldn't be using it
-     on PPC variants that lack them.  */
-  gdb_assert (ppc_floating_point_unit_p (gdbarch));
-
-  /* The first eight words of ther arguments are passed in registers.
-     Copy them appropriately.  */
-  ii = 0;
+  struct rs6000_framedata frame;
+  CORE_ADDR limit_pc, func_addr, func_end_addr = 0;
 
-  /* If the function is returning a `struct', then the first word
-     (which will be passed in r3) is used for struct return address.
-     In that case we should advance one word and start from r4
-     register to copy parameters.  */
-  if (struct_return)
+  /* See if we can determine the end of the prologue via the symbol table.
+     If so, then return either PC, or the PC after the prologue, whichever
+     is greater.  */
+  if (find_pc_partial_function (pc, NULL, &func_addr, &func_end_addr))
     {
-      regcache_raw_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
-                                  struct_addr);
-      ii++;
+      CORE_ADDR post_prologue_pc
+       = skip_prologue_using_sal (gdbarch, func_addr);
+      if (post_prologue_pc != 0)
+       return std::max (pc, post_prologue_pc);
     }
 
-/* 
-   effectively indirect call... gcc does...
-
-   return_val example( float, int);
-
-   eabi: 
-   float in fp0, int in r3
-   offset of stack on overflow 8/16
-   for varargs, must go by type.
-   power open:
-   float in r3&r4, int in r5
-   offset of stack on overflow different 
-   both: 
-   return in r3 or f0.  If no float, must study how gcc emulates floats;
-   pay attention to arg promotion.  
-   User may have to cast\args to handle promotion correctly 
-   since gdb won't know if prototype supplied or not.
- */
-
-  for (argno = 0, argbytes = 0; argno < nargs && ii < 8; ++ii)
-    {
-      int reg_size = register_size (gdbarch, ii + 3);
+  /* Can't determine prologue from the symbol table, need to examine
+     instructions.  */
 
-      arg = args[argno];
-      type = check_typedef (value_type (arg));
-      len = TYPE_LENGTH (type);
+  /* Find an upper limit on the function prologue using the debug
+     information.  If the debug information could not be used to provide
+     that bound, then use an arbitrary large number as the upper bound.  */
+  limit_pc = skip_prologue_using_sal (gdbarch, pc);
+  if (limit_pc == 0)
+    limit_pc = pc + 100;          /* Magic.  */
 
-      if (TYPE_CODE (type) == TYPE_CODE_FLT)
-       {
+  /* Do not allow limit_pc to be past the function end, if we know
+     where that end is...  */
+  if (func_end_addr && limit_pc > func_end_addr)
+    limit_pc = func_end_addr;
 
-         /* Floating point arguments are passed in fpr's, as well as gpr's.
-            There are 13 fpr's reserved for passing parameters. At this point
-            there is no way we would run out of them.  */
+  pc = skip_prologue (gdbarch, pc, limit_pc, &frame);
+  return pc;
+}
 
-         gdb_assert (len <= 8);
+/* When compiling for EABI, some versions of GCC emit a call to __eabi
+   in the prologue of main().
 
-         regcache_cooked_write (regcache,
-                                tdep->ppc_fp0_regnum + 1 + f_argno,
-                                value_contents (arg));
-         ++f_argno;
-       }
+   The function below examines the code pointed at by PC and checks to
+   see if it corresponds to a call to __eabi.  If so, it returns the
+   address of the instruction following that call.  Otherwise, it simply
+   returns PC.  */
 
-      if (len > reg_size)
-       {
+static CORE_ADDR
+rs6000_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  gdb_byte buf[4];
+  unsigned long op;
 
-         /* Argument takes more than one register.  */
-         while (argbytes < len)
-           {
-             gdb_byte word[MAX_REGISTER_SIZE];
-             memset (word, 0, reg_size);
-             memcpy (word,
-                     ((char *) value_contents (arg)) + argbytes,
-                     (len - argbytes) > reg_size
-                       ? reg_size : len - argbytes);
-             regcache_cooked_write (regcache,
-                                   tdep->ppc_gp0_regnum + 3 + ii,
-                                   word);
-             ++ii, argbytes += reg_size;
-
-             if (ii >= 8)
-               goto ran_out_of_registers_for_arguments;
-           }
-         argbytes = 0;
-         --ii;
-       }
-      else
-       {
-         /* Argument can fit in one register.  No problem.  */
-         int adj = gdbarch_byte_order (gdbarch)
-                   == BFD_ENDIAN_BIG ? reg_size - len : 0;
-         gdb_byte word[MAX_REGISTER_SIZE];
+  if (target_read_memory (pc, buf, 4))
+    return pc;
+  op = extract_unsigned_integer (buf, 4, byte_order);
 
-         memset (word, 0, reg_size);
-         memcpy (word, value_contents (arg), len);
-         regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3 +ii, word);
-       }
-      ++argno;
+  if ((op & BL_MASK) == BL_INSTRUCTION)
+    {
+      CORE_ADDR displ = op & BL_DISPLACEMENT_MASK;
+      CORE_ADDR call_dest = pc + 4 + displ;
+      struct bound_minimal_symbol s = lookup_minimal_symbol_by_pc (call_dest);
+
+      /* We check for ___eabi (three leading underscores) in addition
+         to __eabi in case the GCC option "-fleading-underscore" was
+        used to compile the program.  */
+      if (s.minsym != NULL
+          && s.minsym->linkage_name () != NULL
+         && (strcmp (s.minsym->linkage_name (), "__eabi") == 0
+             || strcmp (s.minsym->linkage_name (), "___eabi") == 0))
+       pc += 4;
     }
+  return pc;
+}
 
-ran_out_of_registers_for_arguments:
+/* All the ABI's require 16 byte alignment.  */
+static CORE_ADDR
+rs6000_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+  return (addr & -16);
+}
 
-  regcache_cooked_read_unsigned (regcache,
-                                gdbarch_sp_regnum (gdbarch),
-                                &saved_sp);
+/* Return whether handle_inferior_event() should proceed through code
+   starting at PC in function NAME when stepping.
 
-  /* Location for 8 parameters are always reserved.  */
-  sp -= wordsize * 8;
+   The AIX -bbigtoc linker option generates functions @FIX0, @FIX1, etc. to
+   handle memory references that are too distant to fit in instructions
+   generated by the compiler.  For example, if 'foo' in the following
+   instruction:
 
-  /* Another six words for back chain, TOC register, link register, etc.  */
-  sp -= wordsize * 6;
+     lwz r9,foo(r2)
 
-  /* Stack pointer must be quadword aligned.  */
-  sp &= -16;
+   is greater than 32767, the linker might replace the lwz with a branch to
+   somewhere in @FIX1 that does the load in 2 instructions and then branches
+   back to where execution should continue.
 
-  /* If there are more arguments, allocate space for them in 
-     the stack, then push them starting from the ninth one.  */
+   GDB should silently step over @FIX code, just like AIX dbx does.
+   Unfortunately, the linker uses the "b" instruction for the
+   branches, meaning that the link register doesn't get set.
+   Therefore, GDB's usual step_over_function () mechanism won't work.
 
-  if ((argno < nargs) || argbytes)
-    {
-      int space = 0, jj;
+   Instead, use the gdbarch_skip_trampoline_code and
+   gdbarch_skip_trampoline_code hooks in handle_inferior_event() to skip past
+   @FIX code.  */
 
-      if (argbytes)
-       {
-         space += ((len - argbytes + 3) & -4);
-         jj = argno + 1;
-       }
-      else
-       jj = argno;
+static int
+rs6000_in_solib_return_trampoline (struct gdbarch *gdbarch,
+                                  CORE_ADDR pc, const char *name)
+{
+  return name && startswith (name, "@FIX");
+}
 
-      for (; jj < nargs; ++jj)
-       {
-         struct value *val = args[jj];
-         space += ((TYPE_LENGTH (value_type (val))) + 3) & -4;
-       }
+/* Skip code that the user doesn't want to see when stepping:
 
-      /* Add location required for the rest of the parameters.  */
-      space = (space + 15) & -16;
-      sp -= space;
+   1. Indirect function calls use a piece of trampoline code to do context
+   switching, i.e. to set the new TOC table.  Skip such code if we are on
+   its first instruction (as when we have single-stepped to here).
 
-      /* This is another instance we need to be concerned about
-         securing our stack space. If we write anything underneath %sp
-         (r1), we might conflict with the kernel who thinks he is free
-         to use this area.  So, update %sp first before doing anything
-         else.  */
+   2. Skip shared library trampoline code (which is different from
+   indirect function call trampolines).
 
-      regcache_raw_write_signed (regcache,
-                                gdbarch_sp_regnum (gdbarch), sp);
+   3. Skip bigtoc fixup code.
 
-      /* If the last argument copied into the registers didn't fit there 
-         completely, push the rest of it into stack.  */
+   Result is desired PC to step until, or NULL if we are not in
+   code that should be skipped.  */
 
-      if (argbytes)
-       {
-         write_memory (sp + 24 + (ii * 4),
-                       value_contents (arg) + argbytes,
-                       len - argbytes);
-         ++argno;
-         ii += ((len - argbytes + 3) & -4) / 4;
-       }
-
-      /* Push the rest of the arguments into stack.  */
-      for (; argno < nargs; ++argno)
-       {
-
-         arg = args[argno];
-         type = check_typedef (value_type (arg));
-         len = TYPE_LENGTH (type);
-
-
-         /* Float types should be passed in fpr's, as well as in the
-             stack.  */
-         if (TYPE_CODE (type) == TYPE_CODE_FLT && f_argno < 13)
-           {
-
-             gdb_assert (len <= 8);
-
-             regcache_cooked_write (regcache,
-                                    tdep->ppc_fp0_regnum + 1 + f_argno,
-                                    value_contents (arg));
-             ++f_argno;
-           }
-
-         write_memory (sp + 24 + (ii * 4), value_contents (arg), len);
-         ii += ((len + 3) & -4) / 4;
-       }
-    }
-
-  /* Set the stack pointer.  According to the ABI, the SP is meant to
-     be set _before_ the corresponding stack space is used.  On AIX,
-     this even applies when the target has been completely stopped!
-     Not doing this can lead to conflicts with the kernel which thinks
-     that it still has control over this not-yet-allocated stack
-     region.  */
-  regcache_raw_write_signed (regcache, gdbarch_sp_regnum (gdbarch), sp);
-
-  /* Set back chain properly.  */
-  store_unsigned_integer (tmp_buffer, wordsize, saved_sp);
-  write_memory (sp, tmp_buffer, wordsize);
-
-  /* Point the inferior function call's return address at the dummy's
-     breakpoint.  */
-  regcache_raw_write_signed (regcache, tdep->ppc_lr_regnum, bp_addr);
-
-  /* Set the TOC register, get the value from the objfile reader
-     which, in turn, gets it from the VMAP table.  */
-  if (rs6000_find_toc_address_hook != NULL)
-    {
-      CORE_ADDR tocvalue = (*rs6000_find_toc_address_hook) (func_addr);
-      regcache_raw_write_signed (regcache, tdep->ppc_toc_regnum, tocvalue);
-    }
-
-  target_store_registers (regcache, -1);
-  return sp;
-}
-
-static enum return_value_convention
-rs6000_return_value (struct gdbarch *gdbarch, struct type *valtype,
-                    struct regcache *regcache, gdb_byte *readbuf,
-                    const gdb_byte *writebuf)
-{
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  gdb_byte buf[8];
-
-  /* The calling convention this function implements assumes the
-     processor has floating-point registers.  We shouldn't be using it
-     on PowerPC variants that lack them.  */
-  gdb_assert (ppc_floating_point_unit_p (gdbarch));
-
-  /* AltiVec extension: Functions that declare a vector data type as a
-     return value place that return value in VR2.  */
-  if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY && TYPE_VECTOR (valtype)
-      && TYPE_LENGTH (valtype) == 16)
-    {
-      if (readbuf)
-       regcache_cooked_read (regcache, tdep->ppc_vr0_regnum + 2, readbuf);
-      if (writebuf)
-       regcache_cooked_write (regcache, tdep->ppc_vr0_regnum + 2, writebuf);
-
-      return RETURN_VALUE_REGISTER_CONVENTION;
-    }
-
-  /* If the called subprogram returns an aggregate, there exists an
-     implicit first argument, whose value is the address of a caller-
-     allocated buffer into which the callee is assumed to store its
-     return value. All explicit parameters are appropriately
-     relabeled.  */
-  if (TYPE_CODE (valtype) == TYPE_CODE_STRUCT
-      || TYPE_CODE (valtype) == TYPE_CODE_UNION
-      || TYPE_CODE (valtype) == TYPE_CODE_ARRAY)
-    return RETURN_VALUE_STRUCT_CONVENTION;
-
-  /* Scalar floating-point values are returned in FPR1 for float or
-     double, and in FPR1:FPR2 for quadword precision.  Fortran
-     complex*8 and complex*16 are returned in FPR1:FPR2, and
-     complex*32 is returned in FPR1:FPR4.  */
-  if (TYPE_CODE (valtype) == TYPE_CODE_FLT
-      && (TYPE_LENGTH (valtype) == 4 || TYPE_LENGTH (valtype) == 8))
-    {
-      struct type *regtype = register_type (gdbarch, tdep->ppc_fp0_regnum);
-      gdb_byte regval[8];
-
-      /* FIXME: kettenis/2007-01-01: Add support for quadword
-        precision and complex.  */
-
-      if (readbuf)
-       {
-         regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, regval);
-         convert_typed_floating (regval, regtype, readbuf, valtype);
-       }
-      if (writebuf)
-       {
-         convert_typed_floating (writebuf, valtype, regval, regtype);
-         regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, regval);
-       }
-
-      return RETURN_VALUE_REGISTER_CONVENTION;
-  }
-
-  /* Values of the types int, long, short, pointer, and char (length
-     is less than or equal to four bytes), as well as bit values of
-     lengths less than or equal to 32 bits, must be returned right
-     justified in GPR3 with signed values sign extended and unsigned
-     values zero extended, as necessary.  */
-  if (TYPE_LENGTH (valtype) <= tdep->wordsize)
-    {
-      if (readbuf)
-       {
-         ULONGEST regval;
-
-         /* For reading we don't have to worry about sign extension.  */
-         regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
-                                        &regval);
-         store_unsigned_integer (readbuf, TYPE_LENGTH (valtype), regval);
-       }
-      if (writebuf)
-       {
-         /* For writing, use unpack_long since that should handle any
-            required sign extension.  */
-         regcache_cooked_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
-                                         unpack_long (valtype, writebuf));
-       }
-
-      return RETURN_VALUE_REGISTER_CONVENTION;
-    }
-
-  /* Eight-byte non-floating-point scalar values must be returned in
-     GPR3:GPR4.  */
-
-  if (TYPE_LENGTH (valtype) == 8)
-    {
-      gdb_assert (TYPE_CODE (valtype) != TYPE_CODE_FLT);
-      gdb_assert (tdep->wordsize == 4);
-
-      if (readbuf)
-       {
-         gdb_byte regval[8];
-
-         regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3, regval);
-         regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
-                               regval + 4);
-         memcpy (readbuf, regval, 8);
-       }
-      if (writebuf)
-       {
-         regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3, writebuf);
-         regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
-                                writebuf + 4);
-       }
-
-      return RETURN_VALUE_REGISTER_CONVENTION;
-    }
-
-  return RETURN_VALUE_STRUCT_CONVENTION;
-}
-
-/* Return whether handle_inferior_event() should proceed through code
-   starting at PC in function NAME when stepping.
-
-   The AIX -bbigtoc linker option generates functions @FIX0, @FIX1, etc. to
-   handle memory references that are too distant to fit in instructions
-   generated by the compiler.  For example, if 'foo' in the following
-   instruction:
-
-     lwz r9,foo(r2)
-
-   is greater than 32767, the linker might replace the lwz with a branch to
-   somewhere in @FIX1 that does the load in 2 instructions and then branches
-   back to where execution should continue.
-
-   GDB should silently step over @FIX code, just like AIX dbx does.
-   Unfortunately, the linker uses the "b" instruction for the
-   branches, meaning that the link register doesn't get set.
-   Therefore, GDB's usual step_over_function () mechanism won't work.
-
-   Instead, use the gdbarch_skip_trampoline_code and
-   gdbarch_skip_trampoline_code hooks in handle_inferior_event() to skip past
-   @FIX code.  */
-
-int
-rs6000_in_solib_return_trampoline (CORE_ADDR pc, char *name)
-{
-  return name && !strncmp (name, "@FIX", 4);
-}
-
-/* Skip code that the user doesn't want to see when stepping:
-
-   1. Indirect function calls use a piece of trampoline code to do context
-   switching, i.e. to set the new TOC table.  Skip such code if we are on
-   its first instruction (as when we have single-stepped to here).
-
-   2. Skip shared library trampoline code (which is different from
-   indirect function call trampolines).
-
-   3. Skip bigtoc fixup code.
-
-   Result is desired PC to step until, or NULL if we are not in
-   code that should be skipped.  */
-
-CORE_ADDR
-rs6000_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
-{
-  unsigned int ii, op;
-  int rel;
-  CORE_ADDR solib_target_pc;
-  struct minimal_symbol *msymbol;
+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);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  unsigned int ii, op;
+  int rel;
+  CORE_ADDR solib_target_pc;
+  struct bound_minimal_symbol msymbol;
 
   static unsigned trampoline_code[] =
   {
@@ -2279,12 +2204,12 @@ rs6000_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
 
   /* Check for bigtoc fixup code.  */
   msymbol = lookup_minimal_symbol_by_pc (pc);
-  if (msymbol 
-      && rs6000_in_solib_return_trampoline (pc, 
-                                           DEPRECATED_SYMBOL_NAME (msymbol)))
+  if (msymbol.minsym
+      && rs6000_in_solib_return_trampoline (gdbarch, pc,
+                                           msymbol.minsym->linkage_name ()))
     {
       /* Double-check that the third instruction from PC is relative "b".  */
-      op = read_memory_integer (pc + 8, 4);
+      op = read_memory_integer (pc + 8, 4, byte_order);
       if ((op & 0xfc000003) == 0x48000000)
        {
          /* Extract bits 6-29 as a signed 24-bit relative word address and
@@ -2301,13 +2226,13 @@ rs6000_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
 
   for (ii = 0; trampoline_code[ii]; ++ii)
     {
-      op = read_memory_integer (pc + (ii * 4), 4);
+      op = read_memory_integer (pc + (ii * 4), 4, byte_order);
       if (op != trampoline_code[ii])
        return 0;
     }
-  ii = get_frame_register_unsigned (frame, 11);        /* r11 holds destination addr   */
-  pc = read_memory_addr (ii,
-                        gdbarch_tdep (get_frame_arch (frame))->wordsize); /* (r11) value */
+  ii = get_frame_register_unsigned (frame, 11);        /* r11 holds destination
+                                                  addr.  */
+  pc = read_memory_unsigned_integer (ii, tdep->wordsize, byte_order);
   return pc;
 }
 
@@ -2320,6 +2245,8 @@ rs6000_builtin_type_vec64 (struct gdbarch *gdbarch)
 
   if (!tdep->ppc_builtin_type_vec64)
     {
+      const struct builtin_type *bt = builtin_type (gdbarch);
+
       /* The type we're building is this: */
 #if 0
       union __gdb_builtin_type_vec64
@@ -2334,32 +2261,71 @@ rs6000_builtin_type_vec64 (struct gdbarch *gdbarch)
 
       struct type *t;
 
-      t = init_composite_type ("__ppc_builtin_type_vec64", TYPE_CODE_UNION);
-      append_composite_type_field (t, "uint64", builtin_type_int64);
+      t = arch_composite_type (gdbarch,
+                              "__ppc_builtin_type_vec64", TYPE_CODE_UNION);
+      append_composite_type_field (t, "uint64", bt->builtin_int64);
       append_composite_type_field (t, "v2_float",
-                                  init_vector_type (builtin_type_float, 2));
+                                  init_vector_type (bt->builtin_float, 2));
       append_composite_type_field (t, "v2_int32",
-                                  init_vector_type (builtin_type_int32, 2));
+                                  init_vector_type (bt->builtin_int32, 2));
       append_composite_type_field (t, "v4_int16",
-                                  init_vector_type (builtin_type_int16, 4));
+                                  init_vector_type (bt->builtin_int16, 4));
       append_composite_type_field (t, "v8_int8",
-                                  init_vector_type (builtin_type_int8, 8));
+                                  init_vector_type (bt->builtin_int8, 8));
 
-      TYPE_FLAGS (t) |= TYPE_FLAG_VECTOR;
-      TYPE_NAME (t) = "ppc_builtin_type_vec64";
+      TYPE_VECTOR (t) = 1;
+      t->set_name ("ppc_builtin_type_vec64");
       tdep->ppc_builtin_type_vec64 = t;
     }
 
   return tdep->ppc_builtin_type_vec64;
 }
 
-/* Return the size of register REG when words are WORDSIZE bytes long.  If REG
-   isn't available with that word size, return 0.  */
+/* Vector 128 type.  */
 
-static int
-regsize (const struct reg *reg, int wordsize)
+static struct type *
+rs6000_builtin_type_vec128 (struct gdbarch *gdbarch)
 {
-  return wordsize == 8 ? reg->sz64 : reg->sz32;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (!tdep->ppc_builtin_type_vec128)
+    {
+      const struct builtin_type *bt = builtin_type (gdbarch);
+
+      /* The type we're building is this
+
+        type = union __ppc_builtin_type_vec128 {
+            uint128_t uint128;
+            double v2_double[2];
+            float v4_float[4];
+            int32_t v4_int32[4];
+            int16_t v8_int16[8];
+            int8_t v16_int8[16];
+        }
+      */
+
+      struct type *t;
+
+      t = arch_composite_type (gdbarch,
+                              "__ppc_builtin_type_vec128", TYPE_CODE_UNION);
+      append_composite_type_field (t, "uint128", bt->builtin_uint128);
+      append_composite_type_field (t, "v2_double",
+                                  init_vector_type (bt->builtin_double, 2));
+      append_composite_type_field (t, "v4_float",
+                                  init_vector_type (bt->builtin_float, 4));
+      append_composite_type_field (t, "v4_int32",
+                                  init_vector_type (bt->builtin_int32, 4));
+      append_composite_type_field (t, "v8_int16",
+                                  init_vector_type (bt->builtin_int16, 8));
+      append_composite_type_field (t, "v16_int8",
+                                  init_vector_type (bt->builtin_int8, 16));
+
+      TYPE_VECTOR (t) = 1;
+      t->set_name ("ppc_builtin_type_vec128");
+      tdep->ppc_builtin_type_vec128 = t;
+    }
+
+  return tdep->ppc_builtin_type_vec128;
 }
 
 /* Return the name of register number REGNO, or the empty string if it
@@ -2378,6 +2344,17 @@ rs6000_register_name (struct gdbarch *gdbarch, int regno)
       && regno < tdep->ppc_ev0_upper_regnum + ppc_num_gprs)
     return "";
 
+  /* Hide the upper halves of the vs0~vs31 registers.  */
+  if (tdep->ppc_vsr0_regnum >= 0
+      && tdep->ppc_vsr0_upper_regnum <= 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))
     {
@@ -2402,6 +2379,90 @@ 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))
+    {
+      static const char *const vsx_regnames[] = {
+       "vs0", "vs1", "vs2", "vs3", "vs4", "vs5", "vs6", "vs7",
+       "vs8", "vs9", "vs10", "vs11", "vs12", "vs13", "vs14",
+       "vs15", "vs16", "vs17", "vs18", "vs19", "vs20", "vs21",
+       "vs22", "vs23", "vs24", "vs25", "vs26", "vs27", "vs28",
+       "vs29", "vs30", "vs31", "vs32", "vs33", "vs34", "vs35",
+       "vs36", "vs37", "vs38", "vs39", "vs40", "vs41", "vs42",
+       "vs43", "vs44", "vs45", "vs46", "vs47", "vs48", "vs49",
+       "vs50", "vs51", "vs52", "vs53", "vs54", "vs55", "vs56",
+       "vs57", "vs58", "vs59", "vs60", "vs61", "vs62", "vs63"
+      };
+      return vsx_regnames[regno - tdep->ppc_vsr0_regnum];
+    }
+
+  /* Check if the this is a Extended FP pseudo-register.  */
+  if (IS_EFP_PSEUDOREG (tdep, regno))
+    {
+      static const char *const efpr_regnames[] = {
+       "f32", "f33", "f34", "f35", "f36", "f37", "f38",
+       "f39", "f40", "f41", "f42", "f43", "f44", "f45",
+       "f46", "f47", "f48", "f49", "f50", "f51",
+       "f52", "f53", "f54", "f55", "f56", "f57",
+       "f58", "f59", "f60", "f61", "f62", "f63"
+      };
+      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);
 }
 
@@ -2413,35 +2474,49 @@ 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));
-
   /* These are the e500 pseudo-registers.  */
   if (IS_SPE_PSEUDOREG (tdep, regnum))
     return rs6000_builtin_type_vec64 (gdbarch);
-  else
-    /* Could only be the ppc decimal128 pseudo-registers.  */
+  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_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 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));
-
-  /* These are the e500 pseudo-registers.  */
-  if (IS_SPE_PSEUDOREG (tdep, regnum))
-    return group == all_reggroup || group == vector_reggroup;
+  if (IS_V_ALIAS_PSEUDOREG (tdep, regnum))
+    return 0;
   else
-    /* Could only be the ppc decimal128 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
@@ -2456,22 +2531,32 @@ rs6000_convert_register_p (struct gdbarch *gdbarch, int regnum,
   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_LENGTH (type) != TYPE_LENGTH (builtin_type_double));
+         && type->code () == TYPE_CODE_FLT
+         && TYPE_LENGTH (type)
+            != TYPE_LENGTH (builtin_type (gdbarch)->builtin_double));
 }
 
-static void
+static int
 rs6000_register_to_value (struct frame_info *frame,
                           int regnum,
                           struct type *type,
-                          gdb_byte *to)
+                          gdb_byte *to,
+                         int *optimizedp, int *unavailablep)
 {
-  gdb_byte from[MAX_REGISTER_SIZE];
+  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))
+    return 0;
 
-  get_frame_register (frame, regnum, from);
-  convert_typed_floating (from, builtin_type_double, to, type);
+  target_float_convert (from, builtin_type (gdbarch)->builtin_double,
+                       to, type);
+  *optimizedp = *unavailablep = 0;
+  return 1;
 }
 
 static void
@@ -2480,14 +2565,21 @@ rs6000_value_to_register (struct frame_info *frame,
                           struct type *type,
                           const gdb_byte *from)
 {
-  gdb_byte to[MAX_REGISTER_SIZE];
+  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);
 
-  convert_typed_floating (from, type, to, builtin_type_double);
+  target_float_convert (from, type,
+                       to, builtin_type (gdbarch)->builtin_double);
   put_frame_register (frame, regnum, to);
 }
 
+ /* The type of a function that moves the value of REG between CACHE
+    or BUF --- in either direction.  */
+typedef enum register_status (*move_ev_register_func) (struct regcache *,
+                                                      int, void *);
+
 /* Move SPE vector register values between a 64-bit buffer and the two
    32-bit raw register halves in a regcache.  This function handles
    both splitting a 64-bit value into two 32-bit halves, and joining
@@ -2511,16 +2603,16 @@ rs6000_value_to_register (struct frame_info *frame,
    MOVE, since this function can't tell at compile-time which of
    REGCACHE or BUFFER is acting as the source of the data.  If C had
    co-variant type qualifiers, ...  */
-static void
-e500_move_ev_register (void (*move) (struct regcache *regcache,
-                                     int regnum, gdb_byte *buf),
-                       struct regcache *regcache, int ev_reg,
-                       gdb_byte *buffer)
+
+static enum register_status
+e500_move_ev_register (move_ev_register_func move,
+                      struct regcache *regcache, int ev_reg, void *buffer)
 {
-  struct gdbarch *arch = get_regcache_arch (regcache);
+  struct gdbarch *arch = regcache->arch ();
   struct gdbarch_tdep *tdep = gdbarch_tdep (arch); 
   int reg_index;
-  gdb_byte *byte_buffer = buffer;
+  gdb_byte *byte_buffer = (gdb_byte *) buffer;
+  enum register_status status;
 
   gdb_assert (IS_SPE_PSEUDOREG (tdep, ev_reg));
 
@@ -2528,149 +2620,570 @@ e500_move_ev_register (void (*move) (struct regcache *regcache,
 
   if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG)
     {
-      move (regcache, tdep->ppc_ev0_upper_regnum + reg_index, byte_buffer);
-      move (regcache, tdep->ppc_gp0_regnum + reg_index, byte_buffer + 4);
+      status = move (regcache, tdep->ppc_ev0_upper_regnum + reg_index,
+                    byte_buffer);
+      if (status == REG_VALID)
+       status = move (regcache, tdep->ppc_gp0_regnum + reg_index,
+                      byte_buffer + 4);
     }
   else
     {
-      move (regcache, tdep->ppc_gp0_regnum + reg_index, byte_buffer);
-      move (regcache, tdep->ppc_ev0_upper_regnum + reg_index, byte_buffer + 4);
+      status = move (regcache, tdep->ppc_gp0_regnum + reg_index, byte_buffer);
+      if (status == REG_VALID)
+       status = move (regcache, tdep->ppc_ev0_upper_regnum + reg_index,
+                      byte_buffer + 4);
     }
+
+  return status;
 }
 
-static void
-e500_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
-                          int reg_nr, gdb_byte *buffer)
+static enum register_status
+do_regcache_raw_write (struct regcache *regcache, int regnum, void *buffer)
 {
-  e500_move_ev_register (regcache_raw_read, regcache, reg_nr, buffer);
+  regcache->raw_write (regnum, (const gdb_byte *) buffer);
+
+  return REG_VALID;
+}
+
+static enum register_status
+e500_pseudo_register_read (struct gdbarch *gdbarch, readable_regcache *regcache,
+                          int ev_reg, gdb_byte *buffer)
+{
+  struct gdbarch *arch = regcache->arch ();
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
+  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
 e500_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
                            int reg_nr, const gdb_byte *buffer)
 {
-  e500_move_ev_register ((void (*) (struct regcache *, int, gdb_byte *))
-                        regcache_raw_write,
-                        regcache, reg_nr, (gdb_byte *) buffer);
+  e500_move_ev_register (do_regcache_raw_write, regcache,
+                        reg_nr, (void *) buffer);
 }
 
-/* Read method for PPC pseudo-registers. Currently this is handling the
-   16 decimal128 registers that map into 16 pairs of FP registers.  */
-static void
-ppc_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+/* Read method for DFP pseudo-registers.  */
+static enum register_status
+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;
+  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.  */
-      regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-                        2 * reg_index, buffer);
-      regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-                        2 * reg_index + 1, buffer + 8);
+      status = regcache->raw_read (fp0 + 2 * reg_index, buffer);
+      if (status == REG_VALID)
+       status = regcache->raw_read (fp0 + 2 * reg_index + 1,
+                                    buffer + 8);
     }
   else
     {
-      regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-                        2 * reg_index + 1, buffer + 8);
-      regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-                        2 * reg_index, buffer);
+      status = regcache->raw_read (fp0 + 2 * reg_index + 1, buffer);
+      if (status == REG_VALID)
+       status = regcache->raw_read (fp0 + 2 * reg_index, buffer + 8);
     }
+
+  return status;
 }
 
-/* Write method for PPC pseudo-registers. Currently this is handling the
-   16 decimal128 registers that map into 16 pairs of FP registers.  */
+/* Write method for DFP pseudo-registers.  */
 static void
-ppc_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+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;
+  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 + 8);
-      regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
-                         2 * reg_index, buffer);
+      regcache->raw_write (fp0 + 2 * reg_index + 1, buffer);
+      regcache->raw_write (fp0 + 2 * reg_index, buffer + 8);
     }
 }
 
-static void
-rs6000_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
-                            int reg_nr, gdb_byte *buffer)
-{
-  struct gdbarch *regcache_arch = get_regcache_arch (regcache);
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 
+/* Read method for the vX aliases for the raw vrX registers.  */
 
-  gdb_assert (regcache_arch == gdbarch);
+static enum register_status
+v_alias_pseudo_register_read (struct gdbarch *gdbarch,
+                             readable_regcache *regcache, int reg_nr,
+                             gdb_byte *buffer)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  gdb_assert (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr));
 
-  if (IS_SPE_PSEUDOREG (tdep, reg_nr))
-    e500_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
-  else if (IS_DFP_PSEUDOREG (tdep, reg_nr))
-    ppc_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
-  else
-    internal_error (__FILE__, __LINE__,
-                   _("rs6000_pseudo_register_read: "
-                   "called on unexpected register '%s' (%d)"),
-                   gdbarch_register_name (gdbarch, reg_nr), 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
-rs6000_pseudo_register_write (struct gdbarch *gdbarch,
-                             struct regcache *regcache,
-                             int reg_nr, const gdb_byte *buffer)
+v_alias_pseudo_register_write (struct gdbarch *gdbarch,
+                              struct regcache *regcache,
+                              int reg_nr, const gdb_byte *buffer)
 {
-  struct gdbarch *regcache_arch = get_regcache_arch (regcache);
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 
-
-  gdb_assert (regcache_arch == gdbarch);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  gdb_assert (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr));
 
-  if (IS_SPE_PSEUDOREG (tdep, reg_nr))
-    e500_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
-  else if (IS_DFP_PSEUDOREG (tdep, reg_nr))
-    ppc_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);
+  regcache->raw_write (tdep->ppc_vr0_regnum
+                      + (reg_nr - tdep->ppc_v0_alias_regnum), buffer);
 }
 
-/* Convert a DBX STABS register number to a GDB register number.  */
-static int
-rs6000_stab_reg_to_regnum (struct gdbarch *gdbarch, int num)
+/* Read method for POWER7 VSX pseudo-registers.  */
+static enum register_status
+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, vr0, fp0, vsr0_upper;
+  enum register_status status;
 
-  if (0 <= num && num <= 31)
-    return tdep->ppc_gp0_regnum + num;
-  else if (32 <= num && num <= 63)
-    /* FIXME: jimb/2004-05-05: What should we do when the debug info
-       specifies registers the architecture doesn't have?  Our
-       callers don't check the value we return.  */
-    return tdep->ppc_fp0_regnum + (num - 32);
-  else if (77 <= num && num <= 108)
-    return tdep->ppc_vr0_regnum + (num - 77);
-  else if (1200 <= num && num < 1200 + 32)
-    return tdep->ppc_ev0_regnum + (num - 1200);
+  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
-    switch (num)
+    {
+      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 (vr0 + reg_index - 32, buffer);
+  else
+    /* Read the portion that overlaps the FPR registers.  */
+    if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
       {
-      case 64: 
-        return tdep->ppc_mq_regnum;
-      case 65:
+       status = regcache->raw_read (fp0 + reg_index, buffer);
+       if (status == REG_VALID)
+         status = regcache->raw_read (vsr0_upper + reg_index,
+                                      buffer + 8);
+      }
+    else
+      {
+       status = regcache->raw_read (fp0 + reg_index, buffer + 8);
+       if (status == REG_VALID)
+         status = regcache->raw_read (vsr0_upper + reg_index, buffer);
+      }
+
+  return status;
+}
+
+/* Write method for POWER7 VSX pseudo-registers.  */
+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, 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 (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 (fp0 + reg_index, buffer);
+       regcache->raw_write (vsr0_upper + reg_index, buffer + 8);
+      }
+    else
+      {
+       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
+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, 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 (vr0 + reg_index, offset,
+                                 register_size (gdbarch, reg_nr),
+                                 buffer);
+}
+
+/* Write method for POWER7 Extended FP pseudo-registers.  */
+static void
+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, 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 (vr0 + reg_index, offset,
+                           register_size (gdbarch, reg_nr), buffer);
+}
+
+static enum register_status
+rs6000_pseudo_register_read (struct gdbarch *gdbarch,
+                            readable_regcache *regcache,
+                            int reg_nr, gdb_byte *buffer)
+{
+  struct gdbarch *regcache_arch = regcache->arch ();
+  struct gdbarch_tdep *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)
+          || IS_CDFP_PSEUDOREG (tdep, reg_nr))
+    return dfp_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+  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)
+          || 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: "
+                   "called on unexpected register '%s' (%d)"),
+                   gdbarch_register_name (gdbarch, reg_nr), reg_nr);
+}
+
+static void
+rs6000_pseudo_register_write (struct gdbarch *gdbarch,
+                             struct regcache *regcache,
+                             int reg_nr, const gdb_byte *buffer)
+{
+  struct gdbarch *regcache_arch = regcache->arch ();
+  struct gdbarch_tdep *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)
+{
+  struct gdbarch_tdep *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)
+{
+  struct gdbarch_tdep *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)
+{
+  struct gdbarch_tdep *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_tdep *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;
+    }
+
+  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);
+  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)
+          || IS_CDFP_PSEUDOREG (tdep, reg_nr))
+    {
+      dfp_ax_pseudo_register_collect (gdbarch, ax, reg_nr);
+    }
+  else if (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr))
+    {
+      v_alias_pseudo_register_collect (gdbarch, ax, reg_nr);
+    }
+  else if (IS_VSX_PSEUDOREG (tdep, reg_nr)
+          || IS_CVSX_PSEUDOREG (tdep, reg_nr))
+    {
+      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__,
+                   _("rs6000_pseudo_register_collect: "
+                   "called on unexpected register '%s' (%d)"),
+                   gdbarch_register_name (gdbarch, reg_nr), reg_nr);
+  return 0;
+}
+
+
+static void
+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);
+  value->type = register_type (gdbarch, tdep->ppc_lr_regnum);
+  value->kind = axs_lvalue_register;
+  value->u.reg = tdep->ppc_lr_regnum;
+}
+
+
+/* Convert a DBX STABS register number to a GDB register number.  */
+static int
+rs6000_stab_reg_to_regnum (struct gdbarch *gdbarch, int num)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (0 <= num && num <= 31)
+    return tdep->ppc_gp0_regnum + num;
+  else if (32 <= num && num <= 63)
+    /* FIXME: jimb/2004-05-05: What should we do when the debug info
+       specifies registers the architecture doesn't have?  Our
+       callers don't check the value we return.  */
+    return tdep->ppc_fp0_regnum + (num - 32);
+  else if (77 <= num && num <= 108)
+    return tdep->ppc_vr0_regnum + (num - 77);
+  else if (1200 <= num && num < 1200 + 32)
+    return tdep->ppc_ev0_upper_regnum + (num - 1200);
+  else
+    switch (num)
+      {
+      case 64: 
+        return tdep->ppc_mq_regnum;
+      case 65:
         return tdep->ppc_lr_regnum;
       case 66: 
         return tdep->ppc_ctr_regnum;
@@ -2706,7 +3219,7 @@ rs6000_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int num)
   else if (1124 <= num && num < 1124 + 32)
     return tdep->ppc_vr0_regnum + (num - 1124);
   else if (1200 <= num && num < 1200 + 32)
-    return tdep->ppc_ev0_regnum + (num - 1200);
+    return tdep->ppc_ev0_upper_regnum + (num - 1200);
   else
     switch (num)
       {
@@ -2797,52 +3310,18 @@ rs6000_adjust_frame_regnum (struct gdbarch *gdbarch, int num, int eh_frame_p)
       }
 }
 \f
-/* Support for CONVERT_FROM_FUNC_PTR_ADDR (ARCH, ADDR, TARG).
-
-   Usually a function pointer's representation is simply the address
-   of the function. On the RS/6000 however, a function pointer is
-   represented by a pointer to an OPD entry. This OPD entry contains
-   three words, the first word is the address of the function, the
-   second word is the TOC pointer (r2), and the third word is the
-   static chain value.  Throughout GDB it is currently assumed that a
-   function pointer contains the address of the function, which is not
-   easy to fix.  In addition, the conversion of a function address to
-   a function pointer would require allocation of an OPD entry in the
-   inferior's memory space, with all its drawbacks.  To be able to
-   call C++ virtual methods in the inferior (which are called via
-   function pointers), find_function_addr uses this function to get the
-   function address from a function pointer.  */
-
-/* Return real function address if ADDR (a function pointer) is in the data
-   space and is therefore a special function pointer.  */
-
-static CORE_ADDR
-rs6000_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
-                                  CORE_ADDR addr,
-                                  struct target_ops *targ)
-{
-  struct obj_section *s;
-
-  s = find_pc_section (addr);
-  if (s && s->the_bfd_section->flags & SEC_CODE)
-    return addr;
-
-  /* ADDR is in the data space, so it's a special function pointer. */
-  return read_memory_addr (addr, gdbarch_tdep (gdbarch)->wordsize);
-}
-\f
 
 /* Handling the various POWER/PowerPC variants.  */
 
 /* Information about a particular processor variant.  */
 
-struct variant
+struct ppc_variant
   {
     /* Name of this variant.  */
-    char *name;
+    const char *name;
 
     /* English description of the variant.  */
-    char *description;
+    const char *description;
 
     /* bfd_arch_info.arch corresponding to variant.  */
     enum bfd_architecture arch;
@@ -2854,14 +3333,16 @@ 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_32},
+   bfd_mach_ppc, &tdesc_powerpc_altivec32},
   {"power", "POWER user-level", bfd_arch_rs6000,
    bfd_mach_rs6k, &tdesc_rs6000},
   {"403", "IBM PowerPC 403", bfd_arch_powerpc,
    bfd_mach_ppc_403, &tdesc_powerpc_403},
+  {"405", "IBM PowerPC 405", bfd_arch_powerpc,
+   bfd_mach_ppc_405, &tdesc_powerpc_405},
   {"601", "Motorola PowerPC 601", bfd_arch_powerpc,
    bfd_mach_ppc_601, &tdesc_powerpc_601},
   {"602", "Motorola PowerPC 602", bfd_arch_powerpc,
@@ -2885,7 +3366,7 @@ static struct variant variants[] =
 
   /* 64-bit */
   {"powerpc64", "PowerPC 64-bit user-level", bfd_arch_powerpc,
-   bfd_mach_ppc64, &tdesc_powerpc_64},
+   bfd_mach_ppc64, &tdesc_powerpc_altivec64},
   {"620", "Motorola PowerPC 620", bfd_arch_powerpc,
    bfd_mach_ppc_620, &tdesc_powerpc_64},
   {"630", "Motorola PowerPC 630", bfd_arch_powerpc,
@@ -2905,16 +3386,16 @@ static struct variant variants[] =
   {"rs2", "IBM POWER RS2", bfd_arch_rs6000,
    bfd_mach_rs6k_rs2, &tdesc_rs6000},
 
-  {0, 0, 0, 0, 0}
+  {0, 0, (enum bfd_architecture) 0, 0, 0}
 };
 
 /* 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)
@@ -2923,74 +3404,68 @@ find_variant_by_arch (enum bfd_architecture arch, unsigned long mach)
   return NULL;
 }
 
-static int
-gdb_print_insn_powerpc (bfd_vma memaddr, disassemble_info *info)
-{
-  if (!info->disassembler_options)
-    info->disassembler_options = "any";
-
-  if (info->endian == BFD_ENDIAN_BIG)
-    return print_insn_big_powerpc (memaddr, info);
-  else
-    return print_insn_little_powerpc (memaddr, info);
-}
 \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_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_id_build (frame_unwind_register_unsigned
-                        (next_frame, gdbarch_sp_regnum (gdbarch)),
-                       frame_pc_unwind (next_frame));
-}
 
 struct rs6000_frame_cache
 {
   CORE_ADDR base;
   CORE_ADDR initial_sp;
   struct 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
+     collected.  */
+  int base_p;
+  /* Cache PC for building unavailable frame.  */
+  CORE_ADDR pc;
 };
 
 static struct rs6000_frame_cache *
-rs6000_frame_cache (struct frame_info *next_frame, void **this_cache)
+rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
 {
   struct rs6000_frame_cache *cache;
-  struct gdbarch *gdbarch = get_frame_arch (next_frame);
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   struct rs6000_framedata fdata;
   int wordsize = tdep->wordsize;
-  CORE_ADDR func, pc;
+  CORE_ADDR func = 0, pc = 0;
 
   if ((*this_cache) != NULL)
-    return (*this_cache);
+    return (struct rs6000_frame_cache *) (*this_cache);
   cache = FRAME_OBSTACK_ZALLOC (struct rs6000_frame_cache);
   (*this_cache) = cache;
-  cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
-
-  func = frame_func_unwind (next_frame, NORMAL_FRAME);
-  pc = frame_pc_unwind (next_frame);
-  skip_prologue (gdbarch, func, pc, &fdata);
+  cache->pc = 0;
+  cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
 
-  /* Figure out the parent's stack pointer.  */
-
-  /* NOTE: cagney/2002-04-14: The ->frame points to the inner-most
-     address of the current frame.  Things might be easier if the
-     ->frame pointed to the outer-most address of the frame.  In
-     the mean time, the address of the prev frame is used as the
-     base address of this frame.  */
-  cache->base = frame_unwind_register_unsigned
-               (next_frame, gdbarch_sp_regnum (gdbarch));
+  try
+    {
+      func = get_frame_func (this_frame);
+      cache->pc = func;
+      pc = get_frame_pc (this_frame);
+      skip_prologue (gdbarch, func, pc, &fdata);
+
+      /* Figure out the parent's stack pointer.  */
+
+      /* NOTE: cagney/2002-04-14: The ->frame points to the inner-most
+        address of the current frame.  Things might be easier if the
+        ->frame pointed to the outer-most address of the frame.  In
+        the mean time, the address of the prev frame is used as the
+        base address of this frame.  */
+      cache->base = get_frame_register_unsigned
+       (this_frame, gdbarch_sp_regnum (gdbarch));
+    }
+  catch (const gdb_exception_error &ex)
+    {
+      if (ex.error != NOT_AVAILABLE_ERROR)
+       throw;
+      return (struct rs6000_frame_cache *) (*this_cache);
+    }
 
   /* If the function appears to be frameless, check a couple of likely
      indicators that we have simply failed to find the frame setup.
      Two common cases of this are missing symbols (i.e.
-     frame_func_unwind returns the wrong address or 0), and assembly
+     get_frame_func returns the wrong address or 0), and assembly
      stubs which have a fast exit path but set up a frame on the slow
      path.
 
@@ -3001,8 +3476,7 @@ rs6000_frame_cache (struct frame_info *next_frame, void **this_cache)
       CORE_ADDR saved_lr;
       int make_frame = 0;
 
-      saved_lr = frame_unwind_register_unsigned (next_frame,
-                                                tdep->ppc_lr_regnum);
+      saved_lr = get_frame_register_unsigned (this_frame, tdep->ppc_lr_regnum);
       if (func == 0 && saved_lr == pc)
        make_frame = 1;
       else if (func != 0)
@@ -3020,8 +3494,14 @@ rs6000_frame_cache (struct frame_info *next_frame, void **this_cache)
     }
 
   if (!fdata.frameless)
-    /* Frameless really means stackless.  */
-    cache->base = read_memory_addr (cache->base, wordsize);
+    {
+      /* Frameless really means stackless.  */
+      ULONGEST backchain;
+
+      if (safe_read_memory_unsigned_integer (cache->base, wordsize,
+                                            byte_order, &backchain))
+        cache->base = (CORE_ADDR) backchain;
+    }
 
   trad_frame_set_value (cache->saved_regs,
                        gdbarch_sp_regnum (gdbarch), cache->base);
@@ -3047,7 +3527,8 @@ rs6000_frame_cache (struct frame_info *next_frame, void **this_cache)
     }
 
   /* if != -1, fdata.saved_gpr is the smallest number of saved_gpr.
-     All gpr's from saved_gpr to gpr31 are saved.  */
+     All gpr's from saved_gpr to gpr31 are saved (except during the
+     prologue).  */
 
   if (fdata.saved_gpr >= 0)
     {
@@ -3055,7 +3536,8 @@ rs6000_frame_cache (struct frame_info *next_frame, void **this_cache)
       CORE_ADDR gpr_addr = cache->base + fdata.gpr_offset;
       for (i = fdata.saved_gpr; i < ppc_num_gprs; i++)
        {
-         cache->saved_regs[tdep->ppc_gp0_regnum + i].addr = gpr_addr;
+         if (fdata.gpr_mask & (1U << i))
+           cache->saved_regs[tdep->ppc_gp0_regnum + i].addr = gpr_addr;
          gpr_addr += wordsize;
        }
     }
@@ -3077,31 +3559,37 @@ rs6000_frame_cache (struct frame_info *next_frame, void **this_cache)
     }
 
   /* if != -1, fdata.saved_ev is the smallest number of saved_ev.
-     All vr's from saved_ev to ev31 are saved. ????? */
+     All vr's from saved_ev to ev31 are saved. ?????  */
   if (tdep->ppc_ev0_regnum != -1)
     {
       if (fdata.saved_ev >= 0)
        {
          int i;
          CORE_ADDR ev_addr = cache->base + fdata.ev_offset;
+         CORE_ADDR off = (byte_order == BFD_ENDIAN_BIG ? 4 : 0);
+
          for (i = fdata.saved_ev; i < ppc_num_gprs; i++)
            {
              cache->saved_regs[tdep->ppc_ev0_regnum + i].addr = ev_addr;
-              cache->saved_regs[tdep->ppc_gp0_regnum + i].addr = ev_addr + 4;
+             cache->saved_regs[tdep->ppc_gp0_regnum + i].addr = ev_addr + off;
              ev_addr += register_size (gdbarch, tdep->ppc_ev0_regnum);
-            }
+           }
        }
     }
 
   /* 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].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].addr
+      = cache->base + fdata.lr_offset;
+  else if (fdata.lr_register != -1)
+    cache->saved_regs[tdep->ppc_lr_regnum].realreg = fdata.lr_register;
   /* The PC is found in the link register.  */
   cache->saved_regs[gdbarch_pc_regnum (gdbarch)] =
     cache->saved_regs[tdep->ppc_lr_regnum];
@@ -3109,87 +3597,189 @@ rs6000_frame_cache (struct frame_info *next_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].addr
+      = cache->base + fdata.vrsave_offset;
 
   if (fdata.alloca_reg < 0)
     /* If no alloca register used, then fi->frame is the value of the
        %sp for this frame, and it is good enough.  */
-    cache->initial_sp = frame_unwind_register_unsigned
-                       (next_frame, gdbarch_sp_regnum (gdbarch));
+    cache->initial_sp
+      = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch));
   else
-    cache->initial_sp = frame_unwind_register_unsigned (next_frame,
-                                                       fdata.alloca_reg);
+    cache->initial_sp
+      = get_frame_register_unsigned (this_frame, fdata.alloca_reg);
 
+  cache->base_p = 1;
   return cache;
 }
 
 static void
-rs6000_frame_this_id (struct frame_info *next_frame, void **this_cache,
+rs6000_frame_this_id (struct frame_info *this_frame, void **this_cache,
                      struct frame_id *this_id)
 {
-  struct rs6000_frame_cache *info = rs6000_frame_cache (next_frame,
+  struct rs6000_frame_cache *info = rs6000_frame_cache (this_frame,
                                                        this_cache);
-  (*this_id) = frame_id_build (info->base,
-                              frame_func_unwind (next_frame, NORMAL_FRAME));
+
+  if (!info->base_p)
+    {
+      (*this_id) = frame_id_build_unavailable_stack (info->pc);
+      return;
+    }
+
+  /* This marks the outermost frame.  */
+  if (info->base == 0)
+    return;
+
+  (*this_id) = frame_id_build (info->base, get_frame_func (this_frame));
 }
 
-static void
-rs6000_frame_prev_register (struct frame_info *next_frame,
-                                void **this_cache,
-                                int regnum, int *optimizedp,
-                                enum lval_type *lvalp, CORE_ADDR *addrp,
-                                int *realnump, gdb_byte *valuep)
+static struct value *
+rs6000_frame_prev_register (struct frame_info *this_frame,
+                           void **this_cache, int regnum)
 {
-  struct rs6000_frame_cache *info = rs6000_frame_cache (next_frame,
+  struct rs6000_frame_cache *info = rs6000_frame_cache (this_frame,
                                                        this_cache);
-  trad_frame_get_prev_register (next_frame, info->saved_regs, regnum,
-                               optimizedp, lvalp, addrp, realnump, valuep);
+  return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
 }
 
 static const struct frame_unwind rs6000_frame_unwind =
 {
   NORMAL_FRAME,
+  default_frame_unwind_stop_reason,
   rs6000_frame_this_id,
-  rs6000_frame_prev_register
+  rs6000_frame_prev_register,
+  NULL,
+  default_frame_sniffer
 };
 
-static const struct frame_unwind *
-rs6000_frame_sniffer (struct frame_info *next_frame)
+/* Allocate and initialize a frame cache for an epilogue frame.
+   SP is restored and prev-PC is stored in LR.  */
+
+static struct rs6000_frame_cache *
+rs6000_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache)
 {
-  return &rs6000_frame_unwind;
-}
+  struct rs6000_frame_cache *cache;
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-\f
+  if (*this_cache)
+    return (struct rs6000_frame_cache *) *this_cache;
 
-static CORE_ADDR
-rs6000_frame_base_address (struct frame_info *next_frame,
-                               void **this_cache)
-{
-  struct rs6000_frame_cache *info = rs6000_frame_cache (next_frame,
-                                                       this_cache);
-  return info->initial_sp;
-}
+  cache = FRAME_OBSTACK_ZALLOC (struct rs6000_frame_cache);
+  (*this_cache) = cache;
+  cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
 
-static const struct frame_base rs6000_frame_base = {
-  &rs6000_frame_unwind,
-  rs6000_frame_base_address,
-  rs6000_frame_base_address,
-  rs6000_frame_base_address
-};
+  try
+    {
+      /* At this point the stack looks as if we just entered the
+        function, and the return address is stored in LR.  */
+      CORE_ADDR sp, lr;
 
-static const struct frame_base *
-rs6000_frame_base_sniffer (struct frame_info *next_frame)
-{
-  return &rs6000_frame_base;
-}
+      sp = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch));
+      lr = get_frame_register_unsigned (this_frame, tdep->ppc_lr_regnum);
 
-/* DWARF-2 frame support.  Used to handle the detection of
-  clobbered registers during function calls.  */
+      cache->base = sp;
+      cache->initial_sp = sp;
 
-static void
-ppc_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
-                           struct dwarf2_frame_state_reg *reg,
-                           struct frame_info *next_frame)
+      trad_frame_set_value (cache->saved_regs,
+                           gdbarch_pc_regnum (gdbarch), lr);
+    }
+  catch (const gdb_exception_error &ex)
+    {
+      if (ex.error != NOT_AVAILABLE_ERROR)
+       throw;
+    }
+
+  return cache;
+}
+
+/* Implementation of frame_unwind.this_id, as defined in frame_unwind.h.
+   Return the frame ID of an epilogue frame.  */
+
+static void
+rs6000_epilogue_frame_this_id (struct frame_info *this_frame,
+                              void **this_cache, struct frame_id *this_id)
+{
+  CORE_ADDR pc;
+  struct rs6000_frame_cache *info =
+    rs6000_epilogue_frame_cache (this_frame, this_cache);
+
+  pc = get_frame_func (this_frame);
+  if (info->base == 0)
+    (*this_id) = frame_id_build_unavailable_stack (pc);
+  else
+    (*this_id) = frame_id_build (info->base, pc);
+}
+
+/* Implementation of frame_unwind.prev_register, as defined in frame_unwind.h.
+   Return the register value of REGNUM in previous frame.  */
+
+static struct value *
+rs6000_epilogue_frame_prev_register (struct frame_info *this_frame,
+                                    void **this_cache, int regnum)
+{
+  struct rs6000_frame_cache *info =
+    rs6000_epilogue_frame_cache (this_frame, this_cache);
+  return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
+}
+
+/* Implementation of frame_unwind.sniffer, as defined in frame_unwind.h.
+   Check whether this an epilogue frame.  */
+
+static int
+rs6000_epilogue_frame_sniffer (const struct frame_unwind *self,
+                              struct frame_info *this_frame,
+                              void **this_prologue_cache)
+{
+  if (frame_relative_level (this_frame) == 0)
+    return rs6000_in_function_epilogue_frame_p (this_frame,
+                                               get_frame_arch (this_frame),
+                                               get_frame_pc (this_frame));
+  else
+    return 0;
+}
+
+/* Frame unwinder for epilogue frame.  This is required for reverse step-over
+   a function without debug information.  */
+
+static const struct frame_unwind rs6000_epilogue_frame_unwind =
+{
+  NORMAL_FRAME,
+  default_frame_unwind_stop_reason,
+  rs6000_epilogue_frame_this_id, rs6000_epilogue_frame_prev_register,
+  NULL,
+  rs6000_epilogue_frame_sniffer
+};
+\f
+
+static CORE_ADDR
+rs6000_frame_base_address (struct frame_info *this_frame, void **this_cache)
+{
+  struct rs6000_frame_cache *info = rs6000_frame_cache (this_frame,
+                                                       this_cache);
+  return info->initial_sp;
+}
+
+static const struct frame_base rs6000_frame_base = {
+  &rs6000_frame_unwind,
+  rs6000_frame_base_address,
+  rs6000_frame_base_address,
+  rs6000_frame_base_address
+};
+
+static const struct frame_base *
+rs6000_frame_base_sniffer (struct frame_info *this_frame)
+{
+  return &rs6000_frame_base;
+}
+
+/* DWARF-2 frame support.  Used to handle the detection of
+  clobbered registers during function calls.  */
+
+static void
+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);
 
@@ -3216,35 +3806,2309 @@ ppc_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
          && regnum <= tdep->ppc_fp0_regnum + 31))
        reg->how = DWARF2_FRAME_REG_SAME_VALUE;
 
-      /* Call-clobbered FP registers.  */
-      if ((regnum >= tdep->ppc_fp0_regnum
-         && regnum <= tdep->ppc_fp0_regnum + 13))
-       reg->how = DWARF2_FRAME_REG_UNDEFINED;
-    }
+      /* Call-clobbered FP registers.  */
+      if ((regnum >= tdep->ppc_fp0_regnum
+         && regnum <= tdep->ppc_fp0_regnum + 13))
+       reg->how = DWARF2_FRAME_REG_UNDEFINED;
+    }
+
+  /* Deal with ALTIVEC registers, if supported.  */
+  if (tdep->ppc_vr0_regnum > 0 && tdep->ppc_vrsave_regnum > 0)
+    {
+      /* Call-saved Altivec registers.  */
+      if ((regnum >= tdep->ppc_vr0_regnum + 20
+         && regnum <= tdep->ppc_vr0_regnum + 31)
+         || regnum == tdep->ppc_vrsave_regnum)
+       reg->how = DWARF2_FRAME_REG_SAME_VALUE;
+
+      /* Call-clobbered Altivec registers.  */
+      if ((regnum >= tdep->ppc_vr0_regnum
+         && regnum <= tdep->ppc_vr0_regnum + 19))
+       reg->how = DWARF2_FRAME_REG_UNDEFINED;
+    }
+
+  /* Handle PC register and Stack Pointer correctly.  */
+  if (regnum == gdbarch_pc_regnum (gdbarch))
+    reg->how = DWARF2_FRAME_REG_RA;
+  else if (regnum == gdbarch_sp_regnum (gdbarch))
+    reg->how = DWARF2_FRAME_REG_CFA;
+}
+
+
+/* Return true if a .gnu_attributes section exists in BFD and it
+   indicates we are using SPE extensions OR if a .PPC.EMB.apuinfo
+   section exists in BFD and it indicates that SPE extensions are in
+   use.  Check the .gnu.attributes section first, as the binary might be
+   compiled for SPE, but not actually using SPE instructions.  */
+
+static int
+bfd_uses_spe_extensions (bfd *abfd)
+{
+  asection *sect;
+  gdb_byte *contents = NULL;
+  bfd_size_type size;
+  gdb_byte *ptr;
+  int success = 0;
+
+  if (!abfd)
+    return 0;
+
+#ifdef HAVE_ELF
+  /* 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.  */
+  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
+
+  sect = bfd_get_section_by_name (abfd, ".PPC.EMB.apuinfo");
+  if (!sect)
+    return 0;
+
+  size = bfd_section_size (sect);
+  contents = (gdb_byte *) xmalloc (size);
+  if (!bfd_get_section_contents (abfd, sect, contents, 0, size))
+    {
+      xfree (contents);
+      return 0;
+    }
+
+  /* Parse the .PPC.EMB.apuinfo section.  The layout is as follows:
+
+     struct {
+       uint32 name_len;
+       uint32 data_len;
+       uint32 type;
+       char name[name_len rounded up to 4-byte alignment];
+       char data[data_len];
+     };
+
+     Technically, there's only supposed to be one such structure in a
+     given apuinfo section, but the linker is not always vigilant about
+     merging apuinfo sections from input files.  Just go ahead and parse
+     them all, exiting early when we discover the binary uses SPE
+     insns.
+
+     It's not specified in what endianness the information in this
+     section is stored.  Assume that it's the endianness of the BFD.  */
+  ptr = contents;
+  while (1)
+    {
+      unsigned int name_len;
+      unsigned int data_len;
+      unsigned int type;
+
+      /* If we can't read the first three fields, we're done.  */
+      if (size < 12)
+       break;
+
+      name_len = bfd_get_32 (abfd, ptr);
+      name_len = (name_len + 3) & ~3U; /* Round to 4 bytes.  */
+      data_len = bfd_get_32 (abfd, ptr + 4);
+      type = bfd_get_32 (abfd, ptr + 8);
+      ptr += 12;
+
+      /* The name must be "APUinfo\0".  */
+      if (name_len != 8
+         && strcmp ((const char *) ptr, "APUinfo") != 0)
+       break;
+      ptr += name_len;
+
+      /* The type must be 2.  */
+      if (type != 2)
+       break;
+
+      /* The data is stored as a series of uint32.  The upper half of
+        each uint32 indicates the particular APU used and the lower
+        half indicates the revision of that APU.  We just care about
+        the upper half.  */
+
+      /* Not 4-byte quantities.  */
+      if (data_len & 3U)
+       break;
+
+      while (data_len)
+       {
+         unsigned int apuinfo = bfd_get_32 (abfd, ptr);
+         unsigned int apu = apuinfo >> 16;
+         ptr += 4;
+         data_len -= 4;
+
+         /* The SPE APU is 0x100; the SPEFP APU is 0x101.  Accept
+            either.  */
+         if (apu == 0x100 || apu == 0x101)
+           {
+             success = 1;
+             data_len = 0;
+           }
+       }
+
+      if (success)
+       break;
+    }
+
+  xfree (contents);
+  return success;
+}
+
+/* These are macros for parsing instruction fields (I.1.6.28)  */
+
+#define PPC_FIELD(value, from, len) \
+       (((value) >> (32 - (from) - (len))) & ((1 << (len)) - 1))
+#define PPC_SEXT(v, bs) \
+       ((((CORE_ADDR) (v) & (((CORE_ADDR) 1 << (bs)) - 1)) \
+         ^ ((CORE_ADDR) 1 << ((bs) - 1))) \
+        - ((CORE_ADDR) 1 << ((bs) - 1)))
+#define PPC_OP6(insn)  PPC_FIELD (insn, 0, 6)
+#define PPC_EXTOP(insn)        PPC_FIELD (insn, 21, 10)
+#define PPC_RT(insn)   PPC_FIELD (insn, 6, 5)
+#define PPC_RS(insn)   PPC_FIELD (insn, 6, 5)
+#define PPC_RA(insn)   PPC_FIELD (insn, 11, 5)
+#define PPC_RB(insn)   PPC_FIELD (insn, 16, 5)
+#define PPC_NB(insn)   PPC_FIELD (insn, 16, 5)
+#define PPC_VRT(insn)  PPC_FIELD (insn, 6, 5)
+#define PPC_FRT(insn)  PPC_FIELD (insn, 6, 5)
+#define PPC_SPR(insn)  (PPC_FIELD (insn, 11, 5) \
+                       | (PPC_FIELD (insn, 16, 5) << 5))
+#define PPC_BO(insn)   PPC_FIELD (insn, 6, 5)
+#define PPC_T(insn)    PPC_FIELD (insn, 6, 5)
+#define PPC_D(insn)    PPC_SEXT (PPC_FIELD (insn, 16, 16), 16)
+#define PPC_DS(insn)   PPC_SEXT (PPC_FIELD (insn, 16, 14), 14)
+#define PPC_DQ(insn)   PPC_SEXT (PPC_FIELD (insn, 16, 12), 12)
+#define PPC_BIT(insn,n)        ((insn & (1 << (31 - (n)))) ? 1 : 0)
+#define PPC_OE(insn)   PPC_BIT (insn, 21)
+#define PPC_RC(insn)   PPC_BIT (insn, 31)
+#define PPC_Rc(insn)   PPC_BIT (insn, 21)
+#define PPC_LK(insn)   PPC_BIT (insn, 31)
+#define PPC_TX(insn)   PPC_BIT (insn, 31)
+#define PPC_LEV(insn)  PPC_FIELD (insn, 20, 7)
+
+#define PPC_XT(insn)   ((PPC_TX (insn) << 5) | PPC_T (insn))
+#define PPC_XER_NB(xer)        (xer & 0x7f)
+
+/* Record Vector-Scalar Registers.
+   For VSR less than 32, it's represented by an FPR and an VSR-upper register.
+   Otherwise, it's just a VR register.  Record them accordingly.  */
+
+static int
+ppc_record_vsr (struct regcache *regcache, struct gdbarch_tdep *tdep, int vsr)
+{
+  if (vsr < 0 || vsr >= 64)
+    return -1;
+
+  if (vsr >= 32)
+    {
+      if (tdep->ppc_vr0_regnum >= 0)
+       record_full_arch_list_add_reg (regcache, tdep->ppc_vr0_regnum + vsr - 32);
+    }
+  else
+    {
+      if (tdep->ppc_fp0_regnum >= 0)
+       record_full_arch_list_add_reg (regcache, tdep->ppc_fp0_regnum + vsr);
+      if (tdep->ppc_vsr0_upper_regnum >= 0)
+       record_full_arch_list_add_reg (regcache,
+                                      tdep->ppc_vsr0_upper_regnum + vsr);
+    }
+
+  return 0;
+}
+
+/* Parse and record instructions primary opcode-4 at ADDR.
+   Return 0 if successful.  */
+
+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);
+  int ext = PPC_FIELD (insn, 21, 11);
+  int vra = PPC_FIELD (insn, 11, 5);
+
+  switch (ext & 0x3f)
+    {
+    case 32:           /* Vector Multiply-High-Add Signed Halfword Saturate */
+    case 33:           /* Vector Multiply-High-Round-Add Signed Halfword Saturate */
+    case 39:           /* Vector Multiply-Sum Unsigned Halfword Saturate */
+    case 41:           /* Vector Multiply-Sum Signed Halfword Saturate */
+      record_full_arch_list_add_reg (regcache, PPC_VSCR_REGNUM);
+      /* FALL-THROUGH */
+    case 42:           /* Vector Select */
+    case 43:           /* Vector Permute */
+    case 59:           /* Vector Permute Right-indexed */
+    case 44:           /* Vector Shift Left Double by Octet Immediate */
+    case 45:           /* Vector Permute and Exclusive-OR */
+    case 60:           /* Vector Add Extended Unsigned Quadword Modulo */
+    case 61:           /* Vector Add Extended & write Carry Unsigned Quadword */
+    case 62:           /* Vector Subtract Extended Unsigned Quadword Modulo */
+    case 63:           /* Vector Subtract Extended & write Carry Unsigned Quadword */
+    case 34:           /* Vector Multiply-Low-Add Unsigned Halfword Modulo */
+    case 35:           /* Vector Multiply-Sum Unsigned Doubleword Modulo */
+    case 36:           /* Vector Multiply-Sum Unsigned Byte Modulo */
+    case 37:           /* Vector Multiply-Sum Mixed Byte Modulo */
+    case 38:           /* Vector Multiply-Sum Unsigned Halfword Modulo */
+    case 40:           /* Vector Multiply-Sum Signed Halfword Modulo */
+    case 46:           /* Vector Multiply-Add Single-Precision */
+    case 47:           /* Vector Negative Multiply-Subtract Single-Precision */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_vr0_regnum + PPC_VRT (insn));
+      return 0;
+
+    case 48:           /* Multiply-Add High Doubleword */
+    case 49:           /* Multiply-Add High Doubleword Unsigned */
+    case 51:           /* Multiply-Add Low Doubleword */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RT (insn));
+      return 0;
+    }
+
+  switch ((ext & 0x1ff))
+    {
+    case 385:
+      if (vra != 0     /* Decimal Convert To Signed Quadword */
+         && vra != 2   /* Decimal Convert From Signed Quadword */
+         && vra != 4   /* Decimal Convert To Zoned */
+         && vra != 5   /* Decimal Convert To National */
+         && vra != 6   /* Decimal Convert From Zoned */
+         && 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 */
+
+    case 193:          /* Decimal Shift */
+    case 129:          /* Decimal Unsigned Shift */
+    case 449:          /* Decimal Shift and Round */
+
+    case 257:          /* Decimal Truncate */
+    case 321:          /* Decimal Unsigned Truncate */
+
+      /* Bit-21 should be set.  */
+      if (!PPC_BIT (insn, 21))
+       break;
+
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_vr0_regnum + PPC_VRT (insn));
+      record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      return 0;
+    }
+
+  /* Bit-21 is used for RC */
+  switch (ext & 0x3ff)
+    {
+    case 6:            /* Vector Compare Equal To Unsigned Byte */
+    case 70:           /* Vector Compare Equal To Unsigned Halfword */
+    case 134:          /* Vector Compare Equal To Unsigned Word */
+    case 199:          /* Vector Compare Equal To Unsigned Doubleword */
+    case 774:          /* Vector Compare Greater Than Signed Byte */
+    case 838:          /* Vector Compare Greater Than Signed Halfword */
+    case 902:          /* Vector Compare Greater Than Signed Word */
+    case 967:          /* Vector Compare Greater Than Signed Doubleword */
+    case 518:          /* Vector Compare Greater Than Unsigned Byte */
+    case 646:          /* Vector Compare Greater Than Unsigned Word */
+    case 582:          /* Vector Compare Greater Than Unsigned Halfword */
+    case 711:          /* Vector Compare Greater Than Unsigned Doubleword */
+    case 966:          /* Vector Compare Bounds Single-Precision */
+    case 198:          /* Vector Compare Equal To Single-Precision */
+    case 454:          /* Vector Compare Greater Than or Equal To Single-Precision */
+    case 710:          /* Vector Compare Greater Than Single-Precision */
+    case 7:            /* Vector Compare Not Equal Byte */
+    case 71:           /* Vector Compare Not Equal Halfword */
+    case 135:          /* Vector Compare Not Equal Word */
+    case 263:          /* Vector Compare Not Equal or Zero Byte */
+    case 327:          /* Vector Compare Not Equal or Zero Halfword */
+    case 391:          /* Vector Compare Not Equal or Zero Word */
+      if (PPC_Rc (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_vr0_regnum + PPC_VRT (insn));
+      return 0;
+    }
+
+  if (ext  == 1538)
+    {
+      switch (vra)
+       {
+       case 0:         /* Vector Count Leading Zero Least-Significant Bits
+                          Byte */
+       case 1:         /* Vector Count Trailing Zero Least-Significant Bits
+                          Byte */
+         record_full_arch_list_add_reg (regcache,
+                                        tdep->ppc_gp0_regnum + PPC_RT (insn));
+         return 0;
+
+       case 6:         /* Vector Negate Word */
+       case 7:         /* Vector Negate Doubleword */
+       case 8:         /* Vector Parity Byte Word */
+       case 9:         /* Vector Parity Byte Doubleword */
+       case 10:        /* Vector Parity Byte Quadword */
+       case 16:        /* Vector Extend Sign Byte To Word */
+       case 17:        /* Vector Extend Sign Halfword To Word */
+       case 24:        /* Vector Extend Sign Byte To Doubleword */
+       case 25:        /* Vector Extend Sign Halfword To Doubleword */
+       case 26:        /* Vector Extend Sign Word To Doubleword */
+       case 28:        /* Vector Count Trailing Zeros Byte */
+       case 29:        /* Vector Count Trailing Zeros Halfword */
+       case 30:        /* Vector Count Trailing Zeros Word */
+       case 31:        /* Vector Count Trailing Zeros Doubleword */
+         record_full_arch_list_add_reg (regcache,
+                                        tdep->ppc_vr0_regnum + PPC_VRT (insn));
+         return 0;
+       }
+    }
+
+  switch (ext)
+    {
+    case 142:          /* Vector Pack Unsigned Halfword Unsigned Saturate */
+    case 206:          /* Vector Pack Unsigned Word Unsigned Saturate */
+    case 270:          /* Vector Pack Signed Halfword Unsigned Saturate */
+    case 334:          /* Vector Pack Signed Word Unsigned Saturate */
+    case 398:          /* Vector Pack Signed Halfword Signed Saturate */
+    case 462:          /* Vector Pack Signed Word Signed Saturate */
+    case 1230:         /* Vector Pack Unsigned Doubleword Unsigned Saturate */
+    case 1358:         /* Vector Pack Signed Doubleword Unsigned Saturate */
+    case 1486:         /* Vector Pack Signed Doubleword Signed Saturate */
+    case 512:          /* Vector Add Unsigned Byte Saturate */
+    case 576:          /* Vector Add Unsigned Halfword Saturate */
+    case 640:          /* Vector Add Unsigned Word Saturate */
+    case 768:          /* Vector Add Signed Byte Saturate */
+    case 832:          /* Vector Add Signed Halfword Saturate */
+    case 896:          /* Vector Add Signed Word Saturate */
+    case 1536:         /* Vector Subtract Unsigned Byte Saturate */
+    case 1600:         /* Vector Subtract Unsigned Halfword Saturate */
+    case 1664:         /* Vector Subtract Unsigned Word Saturate */
+    case 1792:         /* Vector Subtract Signed Byte Saturate */
+    case 1856:         /* Vector Subtract Signed Halfword Saturate */
+    case 1920:         /* Vector Subtract Signed Word Saturate */
+
+    case 1544:         /* Vector Sum across Quarter Unsigned Byte Saturate */
+    case 1800:         /* Vector Sum across Quarter Signed Byte Saturate */
+    case 1608:         /* Vector Sum across Quarter Signed Halfword Saturate */
+    case 1672:         /* Vector Sum across Half Signed Word Saturate */
+    case 1928:         /* Vector Sum across Signed Word Saturate */
+    case 970:          /* Vector Convert To Signed Fixed-Point Word Saturate */
+    case 906:          /* Vector Convert To Unsigned Fixed-Point Word Saturate */
+      record_full_arch_list_add_reg (regcache, PPC_VSCR_REGNUM);
+      /* FALL-THROUGH */
+    case 12:           /* Vector Merge High Byte */
+    case 14:           /* Vector Pack Unsigned Halfword Unsigned Modulo */
+    case 76:           /* Vector Merge High Halfword */
+    case 78:           /* Vector Pack Unsigned Word Unsigned Modulo */
+    case 140:          /* Vector Merge High Word */
+    case 268:          /* Vector Merge Low Byte */
+    case 332:          /* Vector Merge Low Halfword */
+    case 396:          /* Vector Merge Low Word */
+    case 526:          /* Vector Unpack High Signed Byte */
+    case 590:          /* Vector Unpack High Signed Halfword */
+    case 654:          /* Vector Unpack Low Signed Byte */
+    case 718:          /* Vector Unpack Low Signed Halfword */
+    case 782:          /* Vector Pack Pixel */
+    case 846:          /* Vector Unpack High Pixel */
+    case 974:          /* Vector Unpack Low Pixel */
+    case 1102:         /* Vector Pack Unsigned Doubleword Unsigned Modulo */
+    case 1614:         /* Vector Unpack High Signed Word */
+    case 1676:         /* Vector Merge Odd Word */
+    case 1742:         /* Vector Unpack Low Signed Word */
+    case 1932:         /* Vector Merge Even Word */
+    case 524:          /* Vector Splat Byte */
+    case 588:          /* Vector Splat Halfword */
+    case 652:          /* Vector Splat Word */
+    case 780:          /* Vector Splat Immediate Signed Byte */
+    case 844:          /* Vector Splat Immediate Signed Halfword */
+    case 908:          /* Vector Splat Immediate Signed Word */
+    case 452:          /* Vector Shift Left */
+    case 708:          /* Vector Shift Right */
+    case 1036:         /* Vector Shift Left by Octet */
+    case 1100:         /* Vector Shift Right by Octet */
+    case 0:            /* Vector Add Unsigned Byte Modulo */
+    case 64:           /* Vector Add Unsigned Halfword Modulo */
+    case 128:          /* Vector Add Unsigned Word Modulo */
+    case 192:          /* Vector Add Unsigned Doubleword Modulo */
+    case 256:          /* Vector Add Unsigned Quadword Modulo */
+    case 320:          /* Vector Add & write Carry Unsigned Quadword */
+    case 384:          /* Vector Add and Write Carry-Out Unsigned Word */
+    case 8:            /* Vector Multiply Odd Unsigned Byte */
+    case 72:           /* Vector Multiply Odd Unsigned Halfword */
+    case 136:          /* Vector Multiply Odd Unsigned Word */
+    case 264:          /* Vector Multiply Odd Signed Byte */
+    case 328:          /* Vector Multiply Odd Signed Halfword */
+    case 392:          /* Vector Multiply Odd Signed Word */
+    case 520:          /* Vector Multiply Even Unsigned Byte */
+    case 584:          /* Vector Multiply Even Unsigned Halfword */
+    case 648:          /* Vector Multiply Even Unsigned Word */
+    case 776:          /* Vector Multiply Even Signed Byte */
+    case 840:          /* Vector Multiply Even Signed Halfword */
+    case 904:          /* Vector Multiply Even Signed Word */
+    case 137:          /* Vector Multiply Unsigned Word Modulo */
+    case 1024:         /* Vector Subtract Unsigned Byte Modulo */
+    case 1088:         /* Vector Subtract Unsigned Halfword Modulo */
+    case 1152:         /* Vector Subtract Unsigned Word Modulo */
+    case 1216:         /* Vector Subtract Unsigned Doubleword Modulo */
+    case 1280:         /* Vector Subtract Unsigned Quadword Modulo */
+    case 1344:         /* Vector Subtract & write Carry Unsigned Quadword */
+    case 1408:         /* Vector Subtract and Write Carry-Out Unsigned Word */
+    case 1282:         /* Vector Average Signed Byte */
+    case 1346:         /* Vector Average Signed Halfword */
+    case 1410:         /* Vector Average Signed Word */
+    case 1026:         /* Vector Average Unsigned Byte */
+    case 1090:         /* Vector Average Unsigned Halfword */
+    case 1154:         /* Vector Average Unsigned Word */
+    case 258:          /* Vector Maximum Signed Byte */
+    case 322:          /* Vector Maximum Signed Halfword */
+    case 386:          /* Vector Maximum Signed Word */
+    case 450:          /* Vector Maximum Signed Doubleword */
+    case 2:            /* Vector Maximum Unsigned Byte */
+    case 66:           /* Vector Maximum Unsigned Halfword */
+    case 130:          /* Vector Maximum Unsigned Word */
+    case 194:          /* Vector Maximum Unsigned Doubleword */
+    case 770:          /* Vector Minimum Signed Byte */
+    case 834:          /* Vector Minimum Signed Halfword */
+    case 898:          /* Vector Minimum Signed Word */
+    case 962:          /* Vector Minimum Signed Doubleword */
+    case 514:          /* Vector Minimum Unsigned Byte */
+    case 578:          /* Vector Minimum Unsigned Halfword */
+    case 642:          /* Vector Minimum Unsigned Word */
+    case 706:          /* Vector Minimum Unsigned Doubleword */
+    case 1028:         /* Vector Logical AND */
+    case 1668:         /* Vector Logical Equivalent */
+    case 1092:         /* Vector Logical AND with Complement */
+    case 1412:         /* Vector Logical NAND */
+    case 1348:         /* Vector Logical OR with Complement */
+    case 1156:         /* Vector Logical OR */
+    case 1284:         /* Vector Logical NOR */
+    case 1220:         /* Vector Logical XOR */
+    case 4:            /* Vector Rotate Left Byte */
+    case 132:          /* Vector Rotate Left Word VX-form */
+    case 68:           /* Vector Rotate Left Halfword */
+    case 196:          /* Vector Rotate Left Doubleword */
+    case 260:          /* Vector Shift Left Byte */
+    case 388:          /* Vector Shift Left Word */
+    case 324:          /* Vector Shift Left Halfword */
+    case 1476:         /* Vector Shift Left Doubleword */
+    case 516:          /* Vector Shift Right Byte */
+    case 644:          /* Vector Shift Right Word */
+    case 580:          /* Vector Shift Right Halfword */
+    case 1732:         /* Vector Shift Right Doubleword */
+    case 772:          /* Vector Shift Right Algebraic Byte */
+    case 900:          /* Vector Shift Right Algebraic Word */
+    case 836:          /* Vector Shift Right Algebraic Halfword */
+    case 964:          /* Vector Shift Right Algebraic Doubleword */
+    case 10:           /* Vector Add Single-Precision */
+    case 74:           /* Vector Subtract Single-Precision */
+    case 1034:         /* Vector Maximum Single-Precision */
+    case 1098:         /* Vector Minimum Single-Precision */
+    case 842:          /* Vector Convert From Signed Fixed-Point Word */
+    case 778:          /* Vector Convert From Unsigned Fixed-Point Word */
+    case 714:          /* Vector Round to Single-Precision Integer toward -Infinity */
+    case 522:          /* Vector Round to Single-Precision Integer Nearest */
+    case 650:          /* Vector Round to Single-Precision Integer toward +Infinity */
+    case 586:          /* Vector Round to Single-Precision Integer toward Zero */
+    case 394:          /* Vector 2 Raised to the Exponent Estimate Floating-Point */
+    case 458:          /* Vector Log Base 2 Estimate Floating-Point */
+    case 266:          /* Vector Reciprocal Estimate Single-Precision */
+    case 330:          /* Vector Reciprocal Square Root Estimate Single-Precision */
+    case 1288:         /* Vector AES Cipher */
+    case 1289:         /* Vector AES Cipher Last */
+    case 1352:         /* Vector AES Inverse Cipher */
+    case 1353:         /* Vector AES Inverse Cipher Last */
+    case 1480:         /* Vector AES SubBytes */
+    case 1730:         /* Vector SHA-512 Sigma Doubleword */
+    case 1666:         /* Vector SHA-256 Sigma Word */
+    case 1032:         /* Vector Polynomial Multiply-Sum Byte */
+    case 1160:         /* Vector Polynomial Multiply-Sum Word */
+    case 1096:         /* Vector Polynomial Multiply-Sum Halfword */
+    case 1224:         /* Vector Polynomial Multiply-Sum Doubleword */
+    case 1292:         /* Vector Gather Bits by Bytes by Doubleword */
+    case 1794:         /* Vector Count Leading Zeros Byte */
+    case 1858:         /* Vector Count Leading Zeros Halfword */
+    case 1922:         /* Vector Count Leading Zeros Word */
+    case 1986:         /* Vector Count Leading Zeros Doubleword */
+    case 1795:         /* Vector Population Count Byte */
+    case 1859:         /* Vector Population Count Halfword */
+    case 1923:         /* Vector Population Count Word */
+    case 1987:         /* Vector Population Count Doubleword */
+    case 1356:         /* Vector Bit Permute Quadword */
+    case 1484:         /* Vector Bit Permute Doubleword */
+    case 513:          /* Vector Multiply-by-10 Unsigned Quadword */
+    case 1:            /* Vector Multiply-by-10 & write Carry Unsigned
+                          Quadword */
+    case 577:          /* Vector Multiply-by-10 Extended Unsigned Quadword */
+    case 65:           /* Vector Multiply-by-10 Extended & write Carry
+                          Unsigned Quadword */
+    case 1027:         /* Vector Absolute Difference Unsigned Byte */
+    case 1091:         /* Vector Absolute Difference Unsigned Halfword */
+    case 1155:         /* Vector Absolute Difference Unsigned Word */
+    case 1796:         /* Vector Shift Right Variable */
+    case 1860:         /* Vector Shift Left Variable */
+    case 133:          /* Vector Rotate Left Word then Mask Insert */
+    case 197:          /* Vector Rotate Left Doubleword then Mask Insert */
+    case 389:          /* Vector Rotate Left Word then AND with Mask */
+    case 453:          /* Vector Rotate Left Doubleword then AND with Mask */
+    case 525:          /* Vector Extract Unsigned Byte */
+    case 589:          /* Vector Extract Unsigned Halfword */
+    case 653:          /* Vector Extract Unsigned Word */
+    case 717:          /* Vector Extract Doubleword */
+    case 781:          /* Vector Insert Byte */
+    case 845:          /* Vector Insert Halfword */
+    case 909:          /* Vector Insert Word */
+    case 973:          /* Vector Insert Doubleword */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_vr0_regnum + PPC_VRT (insn));
+      return 0;
+
+    case 1549:         /* Vector Extract Unsigned Byte Left-Indexed */
+    case 1613:         /* Vector Extract Unsigned Halfword Left-Indexed */
+    case 1677:         /* Vector Extract Unsigned Word Left-Indexed */
+    case 1805:         /* Vector Extract Unsigned Byte Right-Indexed */
+    case 1869:         /* Vector Extract Unsigned Halfword Right-Indexed */
+    case 1933:         /* Vector Extract Unsigned Word Right-Indexed */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RT (insn));
+      return 0;
+
+    case 1604:         /* Move To Vector Status and Control Register */
+      record_full_arch_list_add_reg (regcache, PPC_VSCR_REGNUM);
+      return 0;
+    case 1540:         /* Move From Vector Status and Control Register */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_vr0_regnum + PPC_VRT (insn));
+      return 0;
+    case 833:          /* Decimal Copy Sign */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_vr0_regnum + PPC_VRT (insn));
+      record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      return 0;
+    }
+
+  fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
+                     "at %s, 4-%d.\n", insn, paddress (gdbarch, addr), ext);
+  return -1;
+}
+
+/* Parse and record instructions of primary opcode-19 at ADDR.
+   Return 0 if successful.  */
+
+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);
+  int ext = PPC_EXTOP (insn);
+
+  switch (ext & 0x01f)
+    {
+    case 2:            /* Add PC Immediate Shifted */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RT (insn));
+      return 0;
+    }
+
+  switch (ext)
+    {
+    case 0:            /* Move Condition Register Field */
+    case 33:           /* Condition Register NOR */
+    case 129:          /* Condition Register AND with Complement */
+    case 193:          /* Condition Register XOR */
+    case 225:          /* Condition Register NAND */
+    case 257:          /* Condition Register AND */
+    case 289:          /* Condition Register Equivalent */
+    case 417:          /* Condition Register OR with Complement */
+    case 449:          /* Condition Register OR */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      return 0;
+
+    case 16:           /* Branch Conditional */
+    case 560:          /* Branch Conditional to Branch Target Address Register */
+      if ((PPC_BO (insn) & 0x4) == 0)
+       record_full_arch_list_add_reg (regcache, tdep->ppc_ctr_regnum);
+      /* FALL-THROUGH */
+    case 528:          /* Branch Conditional to Count Register */
+      if (PPC_LK (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_lr_regnum);
+      return 0;
+
+    case 150:          /* Instruction Synchronize */
+      /* Do nothing.  */
+      return 0;
+    }
+
+  fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
+                     "at %s, 19-%d.\n", insn, paddress (gdbarch, addr), ext);
+  return -1;
+}
+
+/* Parse and record instructions of primary opcode-31 at ADDR.
+   Return 0 if successful.  */
+
+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);
+  int ext = PPC_EXTOP (insn);
+  int tmp, nr, nb, i;
+  CORE_ADDR at_dcsz, ea = 0;
+  ULONGEST rb, ra, xer;
+  int size = 0;
+
+  /* These instructions have OE bit.  */
+  switch (ext & 0x1ff)
+    {
+    /* These write RT and XER.  Update CR if RC is set.  */
+    case 8:            /* Subtract from carrying */
+    case 10:           /* Add carrying */
+    case 136:          /* Subtract from extended */
+    case 138:          /* Add extended */
+    case 200:          /* Subtract from zero extended */
+    case 202:          /* Add to zero extended */
+    case 232:          /* Subtract from minus one extended */
+    case 234:          /* Add to minus one extended */
+      /* CA is always altered, but SO/OV are only altered when OE=1.
+        In any case, XER is always altered.  */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum);
+      if (PPC_RC (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RT (insn));
+      return 0;
+
+    /* These write RT.  Update CR if RC is set and update XER if OE is set.  */
+    case 40:           /* Subtract from */
+    case 104:          /* Negate */
+    case 233:          /* Multiply low doubleword */
+    case 235:          /* Multiply low word */
+    case 266:          /* Add */
+    case 393:          /* Divide Doubleword Extended Unsigned */
+    case 395:          /* Divide Word Extended Unsigned */
+    case 425:          /* Divide Doubleword Extended */
+    case 427:          /* Divide Word Extended */
+    case 457:          /* Divide Doubleword Unsigned */
+    case 459:          /* Divide Word Unsigned */
+    case 489:          /* Divide Doubleword */
+    case 491:          /* Divide Word */
+      if (PPC_OE (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum);
+      /* FALL-THROUGH */
+    case 9:            /* Multiply High Doubleword Unsigned */
+    case 11:           /* Multiply High Word Unsigned */
+    case 73:           /* Multiply High Doubleword */
+    case 75:           /* Multiply High Word */
+      if (PPC_RC (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RT (insn));
+      return 0;
+    }
+
+  if ((ext & 0x1f) == 15)
+    {
+      /* Integer Select. bit[16:20] is used for BC.  */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RT (insn));
+      return 0;
+    }
+
+  if ((ext & 0xff) == 170)
+    {
+      /* Add Extended using alternate carry bits */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum);
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RT (insn));
+      return 0;
+    }
+
+  switch (ext)
+    {
+    case 78:           /* Determine Leftmost Zero Byte */
+      if (PPC_RC (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum);
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RT (insn));
+      return 0;
+
+    /* These only write RT.  */
+    case 19:           /* Move from condition register */
+                       /* Move From One Condition Register Field */
+    case 74:           /* Add and Generate Sixes */
+    case 74 | 0x200:   /* Add and Generate Sixes (bit-21 dont-care) */
+    case 302:          /* Move From Branch History Rolling Buffer */
+    case 339:          /* Move From Special Purpose Register */
+    case 371:          /* Move From Time Base [Phased-Out]  */
+    case 309:          /* Load Doubleword Monitored Indexed  */
+    case 128:          /* Set Boolean */
+    case 755:          /* Deliver A Random Number */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RT (insn));
+      return 0;
+
+    /* These only write to RA.  */
+    case 51:           /* Move From VSR Doubleword */
+    case 115:          /* Move From VSR Word and Zero */
+    case 122:          /* Population count bytes */
+    case 378:          /* Population count words */
+    case 506:          /* Population count doublewords */
+    case 154:          /* Parity Word */
+    case 186:          /* Parity Doubleword */
+    case 252:          /* Bit Permute Doubleword */
+    case 282:          /* Convert Declets To Binary Coded Decimal */
+    case 314:          /* Convert Binary Coded Decimal To Declets */
+    case 508:          /* Compare bytes */
+    case 307:          /* Move From VSR Lower Doubleword */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RA (insn));
+      return 0;
+
+    /* These write CR and optional RA.  */
+    case 792:          /* Shift Right Algebraic Word */
+    case 794:          /* Shift Right Algebraic Doubleword */
+    case 824:          /* Shift Right Algebraic Word Immediate */
+    case 826:          /* Shift Right Algebraic Doubleword Immediate (413) */
+    case 826 | 1:      /* Shift Right Algebraic Doubleword Immediate (413) */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum);
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RA (insn));
+      /* FALL-THROUGH */
+    case 0:            /* Compare */
+    case 32:           /* Compare logical */
+    case 144:          /* Move To Condition Register Fields */
+                       /* Move To One Condition Register Field */
+    case 192:          /* Compare Ranged Byte */
+    case 224:          /* Compare Equal Byte */
+    case 576:          /* Move XER to CR Extended */
+    case 902:          /* Paste (should always fail due to single-stepping and
+                          the memory location might not be accessible, so
+                          record only CR) */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      return 0;
+
+    /* These write to RT.  Update RA if 'update indexed.'  */
+    case 53:           /* Load Doubleword with Update Indexed */
+    case 119:          /* Load Byte and Zero with Update Indexed */
+    case 311:          /* Load Halfword and Zero with Update Indexed */
+    case 55:           /* Load Word and Zero with Update Indexed */
+    case 375:          /* Load Halfword Algebraic with Update Indexed */
+    case 373:          /* Load Word Algebraic with Update Indexed */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RA (insn));
+      /* FALL-THROUGH */
+    case 21:           /* Load Doubleword Indexed */
+    case 52:           /* Load Byte And Reserve Indexed */
+    case 116:          /* Load Halfword And Reserve Indexed */
+    case 20:           /* Load Word And Reserve Indexed */
+    case 84:           /* Load Doubleword And Reserve Indexed */
+    case 87:           /* Load Byte and Zero Indexed */
+    case 279:          /* Load Halfword and Zero Indexed */
+    case 23:           /* Load Word and Zero Indexed */
+    case 343:          /* Load Halfword Algebraic Indexed */
+    case 341:          /* Load Word Algebraic Indexed */
+    case 790:          /* Load Halfword Byte-Reverse Indexed */
+    case 534:          /* Load Word Byte-Reverse Indexed */
+    case 532:          /* Load Doubleword Byte-Reverse Indexed */
+    case 582:          /* Load Word Atomic */
+    case 614:          /* Load Doubleword Atomic */
+    case 265:          /* Modulo Unsigned Doubleword */
+    case 777:          /* Modulo Signed Doubleword */
+    case 267:          /* Modulo Unsigned Word */
+    case 779:          /* Modulo Signed Word */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RT (insn));
+      return 0;
+
+    case 597:          /* Load String Word Immediate */
+    case 533:          /* Load String Word Indexed */
+      if (ext == 597)
+       {
+       nr = PPC_NB (insn);
+       if (nr == 0)
+         nr = 32;
+       }
+      else
+       {
+         regcache_raw_read_unsigned (regcache, tdep->ppc_xer_regnum, &xer);
+         nr = PPC_XER_NB (xer);
+       }
+
+      nr = (nr + 3) >> 2;
+
+      /* If n=0, the contents of register RT are undefined.  */
+      if (nr == 0)
+       nr = 1;
+
+      for (i = 0; i < nr; i++)
+       record_full_arch_list_add_reg (regcache,
+                                      tdep->ppc_gp0_regnum
+                                      + ((PPC_RT (insn) + i) & 0x1f));
+      return 0;
+
+    case 276:          /* Load Quadword And Reserve Indexed */
+      tmp = tdep->ppc_gp0_regnum + (PPC_RT (insn) & ~1);
+      record_full_arch_list_add_reg (regcache, tmp);
+      record_full_arch_list_add_reg (regcache, tmp + 1);
+      return 0;
+
+    /* These write VRT.  */
+    case 6:            /* Load Vector for Shift Left Indexed */
+    case 38:           /* Load Vector for Shift Right Indexed */
+    case 7:            /* Load Vector Element Byte Indexed */
+    case 39:           /* Load Vector Element Halfword Indexed */
+    case 71:           /* Load Vector Element Word Indexed */
+    case 103:          /* Load Vector Indexed */
+    case 359:          /* Load Vector Indexed LRU */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_vr0_regnum + PPC_VRT (insn));
+      return 0;
+
+    /* These write FRT.  Update RA if 'update indexed.'  */
+    case 567:          /* Load Floating-Point Single with Update Indexed */
+    case 631:          /* Load Floating-Point Double with Update Indexed */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RA (insn));
+      /* FALL-THROUGH */
+    case 535:          /* Load Floating-Point Single Indexed */
+    case 599:          /* Load Floating-Point Double Indexed */
+    case 855:          /* Load Floating-Point as Integer Word Algebraic Indexed */
+    case 887:          /* Load Floating-Point as Integer Word and Zero Indexed */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_fp0_regnum + PPC_FRT (insn));
+      return 0;
+
+    case 791:          /* Load Floating-Point Double Pair Indexed */
+      tmp = tdep->ppc_fp0_regnum + (PPC_FRT (insn) & ~1);
+      record_full_arch_list_add_reg (regcache, tmp);
+      record_full_arch_list_add_reg (regcache, tmp + 1);
+      return 0;
+
+    case 179:          /* Move To VSR Doubleword */
+    case 211:          /* Move To VSR Word Algebraic */
+    case 243:          /* Move To VSR Word and Zero */
+    case 588:          /* Load VSX Scalar Doubleword Indexed */
+    case 524:          /* Load VSX Scalar Single-Precision Indexed */
+    case 76:           /* Load VSX Scalar as Integer Word Algebraic Indexed */
+    case 12:           /* Load VSX Scalar as Integer Word and Zero Indexed */
+    case 844:          /* Load VSX Vector Doubleword*2 Indexed */
+    case 332:          /* Load VSX Vector Doubleword & Splat Indexed */
+    case 780:          /* Load VSX Vector Word*4 Indexed */
+    case 268:          /* Load VSX Vector Indexed */
+    case 364:          /* Load VSX Vector Word & Splat Indexed */
+    case 812:          /* Load VSX Vector Halfword*8 Indexed */
+    case 876:          /* Load VSX Vector Byte*16 Indexed */
+    case 269:          /* Load VSX Vector with Length */
+    case 301:          /* Load VSX Vector Left-justified with Length */
+    case 781:          /* Load VSX Scalar as Integer Byte & Zero Indexed */
+    case 813:          /* Load VSX Scalar as Integer Halfword & Zero Indexed */
+    case 403:          /* Move To VSR Word & Splat */
+    case 435:          /* Move To VSR Double Doubleword */
+      ppc_record_vsr (regcache, tdep, PPC_XT (insn));
+      return 0;
+
+    /* These write RA.  Update CR if RC is set.  */
+    case 24:           /* Shift Left Word */
+    case 26:           /* Count Leading Zeros Word */
+    case 27:           /* Shift Left Doubleword */
+    case 28:           /* AND */
+    case 58:           /* Count Leading Zeros Doubleword */
+    case 60:           /* AND with Complement */
+    case 124:          /* NOR */
+    case 284:          /* Equivalent */
+    case 316:          /* XOR */
+    case 476:          /* NAND */
+    case 412:          /* OR with Complement */
+    case 444:          /* OR */
+    case 536:          /* Shift Right Word */
+    case 539:          /* Shift Right Doubleword */
+    case 922:          /* Extend Sign Halfword */
+    case 954:          /* Extend Sign Byte */
+    case 986:          /* Extend Sign Word */
+    case 538:          /* Count Trailing Zeros Word */
+    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,
+                                    tdep->ppc_gp0_regnum + PPC_RA (insn));
+      return 0;
+
+    /* Store memory.  */
+    case 181:          /* Store Doubleword with Update Indexed */
+    case 183:          /* Store Word with Update Indexed */
+    case 247:          /* Store Byte with Update Indexed */
+    case 439:          /* Store Half Word with Update Indexed */
+    case 695:          /* Store Floating-Point Single with Update Indexed */
+    case 759:          /* Store Floating-Point Double with Update Indexed */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RA (insn));
+      /* FALL-THROUGH */
+    case 135:          /* Store Vector Element Byte Indexed */
+    case 167:          /* Store Vector Element Halfword Indexed */
+    case 199:          /* Store Vector Element Word Indexed */
+    case 231:          /* Store Vector Indexed */
+    case 487:          /* Store Vector Indexed LRU */
+    case 716:          /* Store VSX Scalar Doubleword Indexed */
+    case 140:          /* Store VSX Scalar as Integer Word Indexed */
+    case 652:          /* Store VSX Scalar Single-Precision Indexed */
+    case 972:          /* Store VSX Vector Doubleword*2 Indexed */
+    case 908:          /* Store VSX Vector Word*4 Indexed */
+    case 149:          /* Store Doubleword Indexed */
+    case 151:          /* Store Word Indexed */
+    case 215:          /* Store Byte Indexed */
+    case 407:          /* Store Half Word Indexed */
+    case 694:          /* Store Byte Conditional Indexed */
+    case 726:          /* Store Halfword Conditional Indexed */
+    case 150:          /* Store Word Conditional Indexed */
+    case 214:          /* Store Doubleword Conditional Indexed */
+    case 182:          /* Store Quadword Conditional Indexed */
+    case 662:          /* Store Word Byte-Reverse Indexed */
+    case 918:          /* Store Halfword Byte-Reverse Indexed */
+    case 660:          /* Store Doubleword Byte-Reverse Indexed */
+    case 663:          /* Store Floating-Point Single Indexed */
+    case 727:          /* Store Floating-Point Double Indexed */
+    case 919:          /* Store Floating-Point Double Pair Indexed */
+    case 983:          /* Store Floating-Point as Integer Word Indexed */
+    case 396:          /* Store VSX Vector Indexed */
+    case 940:          /* Store VSX Vector Halfword*8 Indexed */
+    case 1004:         /* Store VSX Vector Byte*16 Indexed */
+    case 909:          /* Store VSX Scalar as Integer Byte Indexed */
+    case 941:          /* Store VSX Scalar as Integer Halfword Indexed */
+      if (ext == 694 || ext == 726 || ext == 150 || ext == 214 || ext == 182)
+       record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+
+      ra = 0;
+      if (PPC_RA (insn) != 0)
+       regcache_raw_read_unsigned (regcache,
+                                   tdep->ppc_gp0_regnum + PPC_RA (insn), &ra);
+      regcache_raw_read_unsigned (regcache,
+                                 tdep->ppc_gp0_regnum + PPC_RB (insn), &rb);
+      ea = ra + rb;
+
+      switch (ext)
+       {
+       case 183:       /* Store Word with Update Indexed */
+       case 199:       /* Store Vector Element Word Indexed */
+       case 140:       /* Store VSX Scalar as Integer Word Indexed */
+       case 652:       /* Store VSX Scalar Single-Precision Indexed */
+       case 151:       /* Store Word Indexed */
+       case 150:       /* Store Word Conditional Indexed */
+       case 662:       /* Store Word Byte-Reverse Indexed */
+       case 663:       /* Store Floating-Point Single Indexed */
+       case 695:       /* Store Floating-Point Single with Update Indexed */
+       case 983:       /* Store Floating-Point as Integer Word Indexed */
+         size = 4;
+         break;
+       case 247:       /* Store Byte with Update Indexed */
+       case 135:       /* Store Vector Element Byte Indexed */
+       case 215:       /* Store Byte Indexed */
+       case 694:       /* Store Byte Conditional Indexed */
+       case 909:       /* Store VSX Scalar as Integer Byte Indexed */
+         size = 1;
+         break;
+       case 439:       /* Store Halfword with Update Indexed */
+       case 167:       /* Store Vector Element Halfword Indexed */
+       case 407:       /* Store Halfword Indexed */
+       case 726:       /* Store Halfword Conditional Indexed */
+       case 918:       /* Store Halfword Byte-Reverse Indexed */
+       case 941:       /* Store VSX Scalar as Integer Halfword Indexed */
+         size = 2;
+         break;
+       case 181:       /* Store Doubleword with Update Indexed */
+       case 716:       /* Store VSX Scalar Doubleword Indexed */
+       case 149:       /* Store Doubleword Indexed */
+       case 214:       /* Store Doubleword Conditional Indexed */
+       case 660:       /* Store Doubleword Byte-Reverse Indexed */
+       case 727:       /* Store Floating-Point Double Indexed */
+       case 759:       /* Store Floating-Point Double with Update Indexed */
+         size = 8;
+         break;
+       case 972:       /* Store VSX Vector Doubleword*2 Indexed */
+       case 908:       /* Store VSX Vector Word*4 Indexed */
+       case 182:       /* Store Quadword Conditional Indexed */
+       case 231:       /* Store Vector Indexed */
+       case 487:       /* Store Vector Indexed LRU */
+       case 919:       /* Store Floating-Point Double Pair Indexed */
+       case 396:       /* Store VSX Vector Indexed */
+       case 940:       /* Store VSX Vector Halfword*8 Indexed */
+       case 1004:      /* Store VSX Vector Byte*16 Indexed */
+         size = 16;
+         break;
+       default:
+         gdb_assert (0);
+       }
+
+      /* Align address for Store Vector instructions.  */
+      switch (ext)
+       {
+       case 167:       /* Store Vector Element Halfword Indexed */
+         addr = addr & ~0x1ULL;
+         break;
+
+       case 199:       /* Store Vector Element Word Indexed */
+         addr = addr & ~0x3ULL;
+         break;
+
+       case 231:       /* Store Vector Indexed */
+       case 487:       /* Store Vector Indexed LRU */
+         addr = addr & ~0xfULL;
+         break;
+       }
+
+      record_full_arch_list_add_mem (addr, size);
+      return 0;
+
+    case 397:          /* Store VSX Vector with Length */
+    case 429:          /* Store VSX Vector Left-justified with Length */
+      ra = 0;
+      if (PPC_RA (insn) != 0)
+       regcache_raw_read_unsigned (regcache,
+                                   tdep->ppc_gp0_regnum + PPC_RA (insn), &ra);
+      ea = ra;
+      regcache_raw_read_unsigned (regcache,
+                                 tdep->ppc_gp0_regnum + PPC_RB (insn), &rb);
+      /* Store up to 16 bytes.  */
+      nb = (rb & 0xff) > 16 ? 16 : (rb & 0xff);
+      if (nb > 0)
+       record_full_arch_list_add_mem (ea, nb);
+      return 0;
+
+    case 710:          /* Store Word Atomic */
+    case 742:          /* Store Doubleword Atomic */
+      ra = 0;
+      if (PPC_RA (insn) != 0)
+       regcache_raw_read_unsigned (regcache,
+                                   tdep->ppc_gp0_regnum + PPC_RA (insn), &ra);
+      ea = ra;
+      switch (ext)
+       {
+       case 710:       /* Store Word Atomic */
+         size = 8;
+         break;
+       case 742:       /* Store Doubleword Atomic */
+         size = 16;
+         break;
+       default:
+         gdb_assert (0);
+       }
+      record_full_arch_list_add_mem (ea, size);
+      return 0;
+
+    case 725:          /* Store String Word Immediate */
+      ra = 0;
+      if (PPC_RA (insn) != 0)
+       regcache_raw_read_unsigned (regcache,
+                                   tdep->ppc_gp0_regnum + PPC_RA (insn), &ra);
+      ea += ra;
+
+      nb = PPC_NB (insn);
+      if (nb == 0)
+       nb = 32;
+
+      record_full_arch_list_add_mem (ea, nb);
+
+      return 0;
+
+    case 661:          /* Store String Word Indexed */
+      ra = 0;
+      if (PPC_RA (insn) != 0)
+       regcache_raw_read_unsigned (regcache,
+                                   tdep->ppc_gp0_regnum + PPC_RA (insn), &ra);
+      ea += ra;
+
+      regcache_raw_read_unsigned (regcache, tdep->ppc_xer_regnum, &xer);
+      nb = PPC_XER_NB (xer);
+
+      if (nb != 0)
+       {
+         regcache_raw_read_unsigned (regcache,
+                                     tdep->ppc_gp0_regnum + PPC_RB (insn),
+                                     &rb);
+         ea += rb;
+         record_full_arch_list_add_mem (ea, nb);
+       }
+
+      return 0;
+
+    case 467:          /* Move To Special Purpose Register */
+      switch (PPC_SPR (insn))
+       {
+       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;
+       case 9:                 /* CTR */
+         record_full_arch_list_add_reg (regcache, tdep->ppc_ctr_regnum);
+         return 0;
+       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;
+
+    case 147:          /* Move To Split Little Endian */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_ps_regnum);
+      return 0;
+
+    case 512:          /* Move to Condition Register from XER */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum);
+      return 0;
+
+    case 4:            /* Trap Word */
+    case 68:           /* Trap Doubleword */
+    case 430:          /* Clear BHRB */
+    case 598:          /* Synchronize */
+    case 62:           /* Wait for Interrupt */
+    case 30:           /* Wait */
+    case 22:           /* Instruction Cache Block Touch */
+    case 854:          /* Enforce In-order Execution of I/O */
+    case 246:          /* Data Cache Block Touch for Store */
+    case 54:           /* Data Cache Block Store */
+    case 86:           /* Data Cache Block Flush */
+    case 278:          /* Data Cache Block Touch */
+    case 758:          /* Data Cache Block Allocate */
+    case 982:          /* Instruction Cache Block Invalidate */
+    case 774:          /* Copy */
+    case 838:          /* CP_Abort */
+      return 0;
+
+    case 654:          /* Transaction Begin */
+    case 686:          /* Transaction End */
+    case 750:          /* Transaction Suspend or Resume */
+    case 782:          /* Transaction Abort Word Conditional */
+    case 814:          /* Transaction Abort Doubleword Conditional */
+    case 846:          /* Transaction Abort Word Conditional Immediate */
+    case 878:          /* Transaction Abort Doubleword Conditional Immediate */
+    case 910:          /* Transaction Abort */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_ps_regnum);
+      /* FALL-THROUGH */
+    case 718:          /* Transaction Check */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      return 0;
+
+    case 1014:         /* Data Cache Block set to Zero */
+      if (target_auxv_search (current_top_target (), AT_DCACHEBSIZE, &at_dcsz) <= 0
+         || at_dcsz == 0)
+       at_dcsz = 128; /* Assume 128-byte cache line size (POWER8)  */
+
+      ra = 0;
+      if (PPC_RA (insn) != 0)
+       regcache_raw_read_unsigned (regcache,
+                                   tdep->ppc_gp0_regnum + PPC_RA (insn), &ra);
+      regcache_raw_read_unsigned (regcache,
+                                 tdep->ppc_gp0_regnum + PPC_RB (insn), &rb);
+      ea = (ra + rb) & ~((ULONGEST) (at_dcsz - 1));
+      record_full_arch_list_add_mem (ea, at_dcsz);
+      return 0;
+    }
+
+UNKNOWN_OP:
+  fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
+                     "at %s, 31-%d.\n", insn, paddress (gdbarch, addr), ext);
+  return -1;
+}
+
+/* Parse and record instructions of primary opcode-59 at ADDR.
+   Return 0 if successful.  */
+
+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);
+  int ext = PPC_EXTOP (insn);
+
+  switch (ext & 0x1f)
+    {
+    case 18:           /* Floating Divide */
+    case 20:           /* Floating Subtract */
+    case 21:           /* Floating Add */
+    case 22:           /* Floating Square Root */
+    case 24:           /* Floating Reciprocal Estimate */
+    case 25:           /* Floating Multiply */
+    case 26:           /* Floating Reciprocal Square Root Estimate */
+    case 28:           /* Floating Multiply-Subtract */
+    case 29:           /* Floating Multiply-Add */
+    case 30:           /* Floating Negative Multiply-Subtract */
+    case 31:           /* Floating Negative Multiply-Add */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_fp0_regnum + PPC_FRT (insn));
+      if (PPC_RC (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+
+      return 0;
+    }
+
+  switch (ext)
+    {
+    case 2:            /* DFP Add */
+    case 3:            /* DFP Quantize */
+    case 34:           /* DFP Multiply */
+    case 35:           /* DFP Reround */
+    case 67:           /* DFP Quantize Immediate */
+    case 99:           /* DFP Round To FP Integer With Inexact */
+    case 227:          /* DFP Round To FP Integer Without Inexact */
+    case 258:          /* DFP Convert To DFP Long! */
+    case 290:          /* DFP Convert To Fixed */
+    case 514:          /* DFP Subtract */
+    case 546:          /* DFP Divide */
+    case 770:          /* DFP Round To DFP Short! */
+    case 802:          /* DFP Convert From Fixed */
+    case 834:          /* DFP Encode BCD To DPD */
+      if (PPC_RC (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_fp0_regnum + PPC_FRT (insn));
+      record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+      return 0;
+
+    case 130:          /* DFP Compare Ordered */
+    case 162:          /* DFP Test Exponent */
+    case 194:          /* DFP Test Data Class */
+    case 226:          /* DFP Test Data Group */
+    case 642:          /* DFP Compare Unordered */
+    case 674:          /* DFP Test Significance */
+    case 675:          /* DFP Test Significance Immediate */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+      return 0;
+
+    case 66:           /* DFP Shift Significand Left Immediate */
+    case 98:           /* DFP Shift Significand Right Immediate */
+    case 322:          /* DFP Decode DPD To BCD */
+    case 354:          /* DFP Extract Biased Exponent */
+    case 866:          /* DFP Insert Biased Exponent */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_fp0_regnum + PPC_FRT (insn));
+      if (PPC_RC (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      return 0;
+
+    case 846:          /* Floating Convert From Integer Doubleword Single */
+    case 974:          /* Floating Convert From Integer Doubleword Unsigned
+                          Single */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_fp0_regnum + PPC_FRT (insn));
+      if (PPC_RC (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+
+      return 0;
+    }
+
+  fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
+                     "at %s, 59-%d.\n", insn, paddress (gdbarch, addr), ext);
+  return -1;
+}
+
+/* Parse and record instructions of primary opcode-60 at ADDR.
+   Return 0 if successful.  */
+
+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);
+  int ext = PPC_EXTOP (insn);
+
+  switch (ext >> 2)
+    {
+    case 0:            /* VSX Scalar Add Single-Precision */
+    case 32:           /* VSX Scalar Add Double-Precision */
+    case 24:           /* VSX Scalar Divide Single-Precision */
+    case 56:           /* VSX Scalar Divide Double-Precision */
+    case 176:          /* VSX Scalar Copy Sign Double-Precision */
+    case 33:           /* VSX Scalar Multiply-Add Double-Precision */
+    case 41:           /* ditto */
+    case 1:            /* VSX Scalar Multiply-Add Single-Precision */
+    case 9:            /* ditto */
+    case 160:          /* VSX Scalar Maximum Double-Precision */
+    case 168:          /* VSX Scalar Minimum Double-Precision */
+    case 49:           /* VSX Scalar Multiply-Subtract Double-Precision */
+    case 57:           /* ditto */
+    case 17:           /* VSX Scalar Multiply-Subtract Single-Precision */
+    case 25:           /* ditto */
+    case 48:           /* VSX Scalar Multiply Double-Precision */
+    case 16:           /* VSX Scalar Multiply Single-Precision */
+    case 161:          /* VSX Scalar Negative Multiply-Add Double-Precision */
+    case 169:          /* ditto */
+    case 129:          /* VSX Scalar Negative Multiply-Add Single-Precision */
+    case 137:          /* ditto */
+    case 177:          /* VSX Scalar Negative Multiply-Subtract Double-Precision */
+    case 185:          /* ditto */
+    case 145:          /* VSX Scalar Negative Multiply-Subtract Single-Precision */
+    case 153:          /* ditto */
+    case 40:           /* VSX Scalar Subtract Double-Precision */
+    case 8:            /* VSX Scalar Subtract Single-Precision */
+    case 96:           /* VSX Vector Add Double-Precision */
+    case 64:           /* VSX Vector Add Single-Precision */
+    case 120:          /* VSX Vector Divide Double-Precision */
+    case 88:           /* VSX Vector Divide Single-Precision */
+    case 97:           /* VSX Vector Multiply-Add Double-Precision */
+    case 105:          /* ditto */
+    case 65:           /* VSX Vector Multiply-Add Single-Precision */
+    case 73:           /* ditto */
+    case 224:          /* VSX Vector Maximum Double-Precision */
+    case 192:          /* VSX Vector Maximum Single-Precision */
+    case 232:          /* VSX Vector Minimum Double-Precision */
+    case 200:          /* VSX Vector Minimum Single-Precision */
+    case 113:          /* VSX Vector Multiply-Subtract Double-Precision */
+    case 121:          /* ditto */
+    case 81:           /* VSX Vector Multiply-Subtract Single-Precision */
+    case 89:           /* ditto */
+    case 112:          /* VSX Vector Multiply Double-Precision */
+    case 80:           /* VSX Vector Multiply Single-Precision */
+    case 225:          /* VSX Vector Negative Multiply-Add Double-Precision */
+    case 233:          /* ditto */
+    case 193:          /* VSX Vector Negative Multiply-Add Single-Precision */
+    case 201:          /* ditto */
+    case 241:          /* VSX Vector Negative Multiply-Subtract Double-Precision */
+    case 249:          /* ditto */
+    case 209:          /* VSX Vector Negative Multiply-Subtract Single-Precision */
+    case 217:          /* ditto */
+    case 104:          /* VSX Vector Subtract Double-Precision */
+    case 72:           /* VSX Vector Subtract Single-Precision */
+    case 128:          /* VSX Scalar Maximum Type-C Double-Precision */
+    case 136:          /* VSX Scalar Minimum Type-C Double-Precision */
+    case 144:          /* VSX Scalar Maximum Type-J Double-Precision */
+    case 152:          /* VSX Scalar Minimum Type-J Double-Precision */
+    case 3:            /* VSX Scalar Compare Equal Double-Precision */
+    case 11:           /* VSX Scalar Compare Greater Than Double-Precision */
+    case 19:           /* VSX Scalar Compare Greater Than or Equal
+                          Double-Precision */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+      /* FALL-THROUGH */
+    case 240:          /* VSX Vector Copy Sign Double-Precision */
+    case 208:          /* VSX Vector Copy Sign Single-Precision */
+    case 130:          /* VSX Logical AND */
+    case 138:          /* VSX Logical AND with Complement */
+    case 186:          /* VSX Logical Equivalence */
+    case 178:          /* VSX Logical NAND */
+    case 170:          /* VSX Logical OR with Complement */
+    case 162:          /* VSX Logical NOR */
+    case 146:          /* VSX Logical OR */
+    case 154:          /* VSX Logical XOR */
+    case 18:           /* VSX Merge High Word */
+    case 50:           /* VSX Merge Low Word */
+    case 10:           /* VSX Permute Doubleword Immediate (DM=0) */
+    case 10 | 0x20:    /* VSX Permute Doubleword Immediate (DM=1) */
+    case 10 | 0x40:    /* VSX Permute Doubleword Immediate (DM=2) */
+    case 10 | 0x60:    /* VSX Permute Doubleword Immediate (DM=3) */
+    case 2:            /* VSX Shift Left Double by Word Immediate (SHW=0) */
+    case 2 | 0x20:     /* VSX Shift Left Double by Word Immediate (SHW=1) */
+    case 2 | 0x40:     /* VSX Shift Left Double by Word Immediate (SHW=2) */
+    case 2 | 0x60:     /* VSX Shift Left Double by Word Immediate (SHW=3) */
+    case 216:          /* VSX Vector Insert Exponent Single-Precision */
+    case 248:          /* VSX Vector Insert Exponent Double-Precision */
+    case 26:           /* VSX Vector Permute */
+    case 58:           /* VSX Vector Permute Right-indexed */
+    case 213:          /* VSX Vector Test Data Class Single-Precision (DC=0) */
+    case 213 | 0x8:    /* VSX Vector Test Data Class Single-Precision (DC=1) */
+    case 245:          /* VSX Vector Test Data Class Double-Precision (DC=0) */
+    case 245 | 0x8:    /* VSX Vector Test Data Class Double-Precision (DC=1) */
+      ppc_record_vsr (regcache, tdep, PPC_XT (insn));
+      return 0;
+
+    case 61:           /* VSX Scalar Test for software Divide Double-Precision */
+    case 125:          /* VSX Vector Test for software Divide Double-Precision */
+    case 93:           /* VSX Vector Test for software Divide Single-Precision */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      return 0;
+
+    case 35:           /* VSX Scalar Compare Unordered Double-Precision */
+    case 43:           /* VSX Scalar Compare Ordered Double-Precision */
+    case 59:           /* VSX Scalar Compare Exponents Double-Precision */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+      return 0;
+    }
+
+  switch ((ext >> 2) & 0x7f) /* Mask out Rc-bit.  */
+    {
+    case 99:           /* VSX Vector Compare Equal To Double-Precision */
+    case 67:           /* VSX Vector Compare Equal To Single-Precision */
+    case 115:          /* VSX Vector Compare Greater Than or
+                          Equal To Double-Precision */
+    case 83:           /* VSX Vector Compare Greater Than or
+                          Equal To Single-Precision */
+    case 107:          /* VSX Vector Compare Greater Than Double-Precision */
+    case 75:           /* VSX Vector Compare Greater Than Single-Precision */
+      if (PPC_Rc (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+      ppc_record_vsr (regcache, tdep, PPC_XT (insn));
+      return 0;
+    }
+
+  switch (ext >> 1)
+    {
+    case 265:          /* VSX Scalar round Double-Precision to
+                          Single-Precision and Convert to
+                          Single-Precision format */
+    case 344:          /* VSX Scalar truncate Double-Precision to
+                          Integer and Convert to Signed Integer
+                          Doubleword format with Saturate */
+    case 88:           /* VSX Scalar truncate Double-Precision to
+                          Integer and Convert to Signed Integer Word
+                          Format with Saturate */
+    case 328:          /* VSX Scalar truncate Double-Precision integer
+                          and Convert to Unsigned Integer Doubleword
+                          Format with Saturate */
+    case 72:           /* VSX Scalar truncate Double-Precision to
+                          Integer and Convert to Unsigned Integer Word
+                          Format with Saturate */
+    case 329:          /* VSX Scalar Convert Single-Precision to
+                          Double-Precision format */
+    case 376:          /* VSX Scalar Convert Signed Integer
+                          Doubleword to floating-point format and
+                          Round to Double-Precision format */
+    case 312:          /* VSX Scalar Convert Signed Integer
+                          Doubleword to floating-point format and
+                          round to Single-Precision */
+    case 360:          /* VSX Scalar Convert Unsigned Integer
+                          Doubleword to floating-point format and
+                          Round to Double-Precision format */
+    case 296:          /* VSX Scalar Convert Unsigned Integer
+                          Doubleword to floating-point format and
+                          Round to Single-Precision */
+    case 73:           /* VSX Scalar Round to Double-Precision Integer
+                          Using Round to Nearest Away */
+    case 107:          /* VSX Scalar Round to Double-Precision Integer
+                          Exact using Current rounding mode */
+    case 121:          /* VSX Scalar Round to Double-Precision Integer
+                          Using Round toward -Infinity */
+    case 105:          /* VSX Scalar Round to Double-Precision Integer
+                          Using Round toward +Infinity */
+    case 89:           /* VSX Scalar Round to Double-Precision Integer
+                          Using Round toward Zero */
+    case 90:           /* VSX Scalar Reciprocal Estimate Double-Precision */
+    case 26:           /* VSX Scalar Reciprocal Estimate Single-Precision */
+    case 281:          /* VSX Scalar Round to Single-Precision */
+    case 74:           /* VSX Scalar Reciprocal Square Root Estimate
+                          Double-Precision */
+    case 10:           /* VSX Scalar Reciprocal Square Root Estimate
+                          Single-Precision */
+    case 75:           /* VSX Scalar Square Root Double-Precision */
+    case 11:           /* VSX Scalar Square Root Single-Precision */
+    case 393:          /* VSX Vector round Double-Precision to
+                          Single-Precision and Convert to
+                          Single-Precision format */
+    case 472:          /* VSX Vector truncate Double-Precision to
+                          Integer and Convert to Signed Integer
+                          Doubleword format with Saturate */
+    case 216:          /* VSX Vector truncate Double-Precision to
+                          Integer and Convert to Signed Integer Word
+                          Format with Saturate */
+    case 456:          /* VSX Vector truncate Double-Precision to
+                          Integer and Convert to Unsigned Integer
+                          Doubleword format with Saturate */
+    case 200:          /* VSX Vector truncate Double-Precision to
+                          Integer and Convert to Unsigned Integer Word
+                          Format with Saturate */
+    case 457:          /* VSX Vector Convert Single-Precision to
+                          Double-Precision format */
+    case 408:          /* VSX Vector truncate Single-Precision to
+                          Integer and Convert to Signed Integer
+                          Doubleword format with Saturate */
+    case 152:          /* VSX Vector truncate Single-Precision to
+                          Integer and Convert to Signed Integer Word
+                          Format with Saturate */
+    case 392:          /* VSX Vector truncate Single-Precision to
+                          Integer and Convert to Unsigned Integer
+                          Doubleword format with Saturate */
+    case 136:          /* VSX Vector truncate Single-Precision to
+                          Integer and Convert to Unsigned Integer Word
+                          Format with Saturate */
+    case 504:          /* VSX Vector Convert and round Signed Integer
+                          Doubleword to Double-Precision format */
+    case 440:          /* VSX Vector Convert and round Signed Integer
+                          Doubleword to Single-Precision format */
+    case 248:          /* VSX Vector Convert Signed Integer Word to
+                          Double-Precision format */
+    case 184:          /* VSX Vector Convert and round Signed Integer
+                          Word to Single-Precision format */
+    case 488:          /* VSX Vector Convert and round Unsigned
+                          Integer Doubleword to Double-Precision format */
+    case 424:          /* VSX Vector Convert and round Unsigned
+                          Integer Doubleword to Single-Precision format */
+    case 232:          /* VSX Vector Convert and round Unsigned
+                          Integer Word to Double-Precision format */
+    case 168:          /* VSX Vector Convert and round Unsigned
+                          Integer Word to Single-Precision format */
+    case 201:          /* VSX Vector Round to Double-Precision
+                          Integer using round to Nearest Away */
+    case 235:          /* VSX Vector Round to Double-Precision
+                          Integer Exact using Current rounding mode */
+    case 249:          /* VSX Vector Round to Double-Precision
+                          Integer using round toward -Infinity */
+    case 233:          /* VSX Vector Round to Double-Precision
+                          Integer using round toward +Infinity */
+    case 217:          /* VSX Vector Round to Double-Precision
+                          Integer using round toward Zero */
+    case 218:          /* VSX Vector Reciprocal Estimate Double-Precision */
+    case 154:          /* VSX Vector Reciprocal Estimate Single-Precision */
+    case 137:          /* VSX Vector Round to Single-Precision Integer
+                          Using Round to Nearest Away */
+    case 171:          /* VSX Vector Round to Single-Precision Integer
+                          Exact Using Current rounding mode */
+    case 185:          /* VSX Vector Round to Single-Precision Integer
+                          Using Round toward -Infinity */
+    case 169:          /* VSX Vector Round to Single-Precision Integer
+                          Using Round toward +Infinity */
+    case 153:          /* VSX Vector Round to Single-Precision Integer
+                          Using round toward Zero */
+    case 202:          /* VSX Vector Reciprocal Square Root Estimate
+                          Double-Precision */
+    case 138:          /* VSX Vector Reciprocal Square Root Estimate
+                          Single-Precision */
+    case 203:          /* VSX Vector Square Root Double-Precision */
+    case 139:          /* VSX Vector Square Root Single-Precision */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+      /* FALL-THROUGH */
+    case 345:          /* VSX Scalar Absolute Value Double-Precision */
+    case 267:          /* VSX Scalar Convert Scalar Single-Precision to
+                          Vector Single-Precision format Non-signalling */
+    case 331:          /* VSX Scalar Convert Single-Precision to
+                          Double-Precision format Non-signalling */
+    case 361:          /* VSX Scalar Negative Absolute Value Double-Precision */
+    case 377:          /* VSX Scalar Negate Double-Precision */
+    case 473:          /* VSX Vector Absolute Value Double-Precision */
+    case 409:          /* VSX Vector Absolute Value Single-Precision */
+    case 489:          /* VSX Vector Negative Absolute Value Double-Precision */
+    case 425:          /* VSX Vector Negative Absolute Value Single-Precision */
+    case 505:          /* VSX Vector Negate Double-Precision */
+    case 441:          /* VSX Vector Negate Single-Precision */
+    case 164:          /* VSX Splat Word */
+    case 165:          /* VSX Vector Extract Unsigned Word */
+    case 181:          /* VSX Vector Insert Word */
+      ppc_record_vsr (regcache, tdep, PPC_XT (insn));
+      return 0;
+
+    case 298:          /* VSX Scalar Test Data Class Single-Precision */
+    case 362:          /* VSX Scalar Test Data Class Double-Precision */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+      /* FALL-THROUGH */
+    case 106:          /* VSX Scalar Test for software Square Root
+                          Double-Precision */
+    case 234:          /* VSX Vector Test for software Square Root
+                          Double-Precision */
+    case 170:          /* VSX Vector Test for software Square Root
+                          Single-Precision */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      return 0;
+
+    case 347:
+      switch (PPC_FIELD (insn, 11, 5))
+       {
+       case 0:         /* VSX Scalar Extract Exponent Double-Precision */
+       case 1:         /* VSX Scalar Extract Significand Double-Precision */
+          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
+                          Double-Precision format */
+       case 17:        /* VSX Scalar round & Convert Double-Precision format
+                          to Half-Precision format */
+         record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+         ppc_record_vsr (regcache, tdep, PPC_XT (insn));
+         return 0;
+       }
+      break;
+
+    case 475:
+      switch (PPC_FIELD (insn, 11, 5))
+       {
+       case 24:        /* VSX Vector Convert Half-Precision format to
+                          Single-Precision format */
+       case 25:        /* VSX Vector round and Convert Single-Precision format
+                          to Half-Precision format */
+         record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+         /* FALL-THROUGH */
+       case 0:         /* VSX Vector Extract Exponent Double-Precision */
+       case 1:         /* VSX Vector Extract Significand Double-Precision */
+       case 7:         /* VSX Vector Byte-Reverse Halfword */
+       case 8:         /* VSX Vector Extract Exponent Single-Precision */
+       case 9:         /* VSX Vector Extract Significand Single-Precision */
+       case 15:        /* VSX Vector Byte-Reverse Word */
+       case 23:        /* VSX Vector Byte-Reverse Doubleword */
+       case 31:        /* VSX Vector Byte-Reverse Quadword */
+         ppc_record_vsr (regcache, tdep, PPC_XT (insn));
+         return 0;
+       }
+      break;
+    }
+
+  switch (ext)
+    {
+    case 360:          /* VSX Vector Splat Immediate Byte */
+      if (PPC_FIELD (insn, 11, 2) == 0)
+       {
+         ppc_record_vsr (regcache, tdep, PPC_XT (insn));
+         return 0;
+       }
+      break;
+    case 918:          /* VSX Scalar Insert Exponent Double-Precision */
+      ppc_record_vsr (regcache, tdep, PPC_XT (insn));
+      return 0;
+    }
+
+  if (((ext >> 3) & 0x3) == 3) /* VSX Select */
+    {
+      ppc_record_vsr (regcache, tdep, PPC_XT (insn));
+      return 0;
+    }
+
+  fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
+                     "at %s, 60-%d.\n", insn, paddress (gdbarch, addr), ext);
+  return -1;
+}
+
+/* Parse and record instructions of primary opcode-61 at ADDR.
+   Return 0 if successful.  */
+
+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);
+  ULONGEST ea = 0;
+  int size;
+
+  switch (insn & 0x3)
+    {
+    case 0:            /* Store Floating-Point Double Pair */
+    case 2:            /* Store VSX Scalar Doubleword */
+    case 3:            /* Store VSX Scalar Single */
+      if (PPC_RA (insn) != 0)
+       regcache_raw_read_unsigned (regcache,
+                                   tdep->ppc_gp0_regnum + PPC_RA (insn),
+                                   &ea);
+      ea += PPC_DS (insn) << 2;
+      switch (insn & 0x3)
+       {
+       case 0:         /* Store Floating-Point Double Pair */
+         size = 16;
+         break;
+       case 2:         /* Store VSX Scalar Doubleword */
+         size = 8;
+         break;
+       case 3:         /* Store VSX Scalar Single */
+         size = 4;
+         break;
+       default:
+         gdb_assert (0);
+       }
+      record_full_arch_list_add_mem (ea, size);
+      return 0;
+    }
+
+  switch (insn & 0x7)
+    {
+    case 1:            /* Load VSX Vector */
+      ppc_record_vsr (regcache, tdep, PPC_XT (insn));
+      return 0;
+    case 5:            /* Store VSX Vector */
+      if (PPC_RA (insn) != 0)
+       regcache_raw_read_unsigned (regcache,
+                                   tdep->ppc_gp0_regnum + PPC_RA (insn),
+                                   &ea);
+      ea += PPC_DQ (insn) << 4;
+      record_full_arch_list_add_mem (ea, 16);
+      return 0;
+    }
+
+  fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
+                     "at %s.\n", insn, paddress (gdbarch, addr));
+  return -1;
+}
+
+/* Parse and record instructions of primary opcode-63 at ADDR.
+   Return 0 if successful.  */
+
+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);
+  int ext = PPC_EXTOP (insn);
+  int tmp;
+
+  switch (ext & 0x1f)
+    {
+    case 18:           /* Floating Divide */
+    case 20:           /* Floating Subtract */
+    case 21:           /* Floating Add */
+    case 22:           /* Floating Square Root */
+    case 24:           /* Floating Reciprocal Estimate */
+    case 25:           /* Floating Multiply */
+    case 26:           /* Floating Reciprocal Square Root Estimate */
+    case 28:           /* Floating Multiply-Subtract */
+    case 29:           /* Floating Multiply-Add */
+    case 30:           /* Floating Negative Multiply-Subtract */
+    case 31:           /* Floating Negative Multiply-Add */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_fp0_regnum + PPC_FRT (insn));
+      if (PPC_RC (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+      return 0;
+
+    case 23:           /* Floating Select */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_fp0_regnum + PPC_FRT (insn));
+      if (PPC_RC (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      return 0;
+    }
+
+  switch (ext & 0xff)
+    {
+    case 5:            /* VSX Scalar Round to Quad-Precision Integer */
+    case 37:           /* VSX Scalar Round Quad-Precision to Double-Extended
+                          Precision */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+      ppc_record_vsr (regcache, tdep, PPC_VRT (insn) + 32);
+      return 0;
+    }
+
+  switch (ext)
+    {
+    case 2:            /* DFP Add Quad */
+    case 3:            /* DFP Quantize Quad */
+    case 34:           /* DFP Multiply Quad */
+    case 35:           /* DFP Reround Quad */
+    case 67:           /* DFP Quantize Immediate Quad */
+    case 99:           /* DFP Round To FP Integer With Inexact Quad */
+    case 227:          /* DFP Round To FP Integer Without Inexact Quad */
+    case 258:          /* DFP Convert To DFP Extended Quad */
+    case 514:          /* DFP Subtract Quad */
+    case 546:          /* DFP Divide Quad */
+    case 770:          /* DFP Round To DFP Long Quad */
+    case 802:          /* DFP Convert From Fixed Quad */
+    case 834:          /* DFP Encode BCD To DPD Quad */
+      if (PPC_RC (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      tmp = tdep->ppc_fp0_regnum + (PPC_FRT (insn) & ~1);
+      record_full_arch_list_add_reg (regcache, tmp);
+      record_full_arch_list_add_reg (regcache, tmp + 1);
+      record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+      return 0;
+
+    case 130:          /* DFP Compare Ordered Quad */
+    case 162:          /* DFP Test Exponent Quad */
+    case 194:          /* DFP Test Data Class Quad */
+    case 226:          /* DFP Test Data Group Quad */
+    case 642:          /* DFP Compare Unordered Quad */
+    case 674:          /* DFP Test Significance Quad */
+    case 675:          /* DFP Test Significance Immediate Quad */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+      return 0;
+
+    case 66:           /* DFP Shift Significand Left Immediate Quad */
+    case 98:           /* DFP Shift Significand Right Immediate Quad */
+    case 322:          /* DFP Decode DPD To BCD Quad */
+    case 866:          /* DFP Insert Biased Exponent Quad */
+      tmp = tdep->ppc_fp0_regnum + (PPC_FRT (insn) & ~1);
+      record_full_arch_list_add_reg (regcache, tmp);
+      record_full_arch_list_add_reg (regcache, tmp + 1);
+      if (PPC_RC (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      return 0;
+
+    case 290:          /* DFP Convert To Fixed Quad */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_fp0_regnum + PPC_FRT (insn));
+      if (PPC_RC (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+      return 0;
+
+    case 354:          /* DFP Extract Biased Exponent Quad */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_fp0_regnum + PPC_FRT (insn));
+      if (PPC_RC (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      return 0;
+
+    case 12:           /* Floating Round to Single-Precision */
+    case 14:           /* Floating Convert To Integer Word */
+    case 15:           /* Floating Convert To Integer Word
+                          with round toward Zero */
+    case 142:          /* Floating Convert To Integer Word Unsigned */
+    case 143:          /* Floating Convert To Integer Word Unsigned
+                          with round toward Zero */
+    case 392:          /* Floating Round to Integer Nearest */
+    case 424:          /* Floating Round to Integer Toward Zero */
+    case 456:          /* Floating Round to Integer Plus */
+    case 488:          /* Floating Round to Integer Minus */
+    case 814:          /* Floating Convert To Integer Doubleword */
+    case 815:          /* Floating Convert To Integer Doubleword
+                          with round toward Zero */
+    case 846:          /* Floating Convert From Integer Doubleword */
+    case 942:          /* Floating Convert To Integer Doubleword Unsigned */
+    case 943:          /* Floating Convert To Integer Doubleword Unsigned
+                          with round toward Zero */
+    case 974:          /* Floating Convert From Integer Doubleword Unsigned */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_fp0_regnum + PPC_FRT (insn));
+      if (PPC_RC (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+      return 0;
+
+    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))
+             record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+           record_full_arch_list_add_reg (regcache,
+                                          tdep->ppc_fp0_regnum
+                                          + PPC_FRT (insn));
+           return 0;
+        }
+      break;
+
+    case 8:            /* Floating Copy Sign */
+    case 40:           /* Floating Negate */
+    case 72:           /* Floating Move Register */
+    case 136:          /* Floating Negative Absolute Value */
+    case 264:          /* Floating Absolute Value */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_fp0_regnum + PPC_FRT (insn));
+      if (PPC_RC (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      return 0;
+
+    case 838:          /* Floating Merge Odd Word */
+    case 966:          /* Floating Merge Even Word */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_fp0_regnum + PPC_FRT (insn));
+      return 0;
+
+    case 38:           /* Move To FPSCR Bit 1 */
+    case 70:           /* Move To FPSCR Bit 0 */
+    case 134:          /* Move To FPSCR Field Immediate */
+    case 711:          /* Move To FPSCR Fields */
+      if (PPC_RC (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+      return 0;
+
+    case 0:            /* Floating Compare Unordered */
+    case 32:           /* Floating Compare Ordered */
+    case 64:           /* Move to Condition Register from FPSCR */
+    case 132:          /* VSX Scalar Compare Ordered Quad-Precision */
+    case 164:          /* VSX Scalar Compare Exponents Quad-Precision */
+    case 644:          /* VSX Scalar Compare Unordered Quad-Precision */
+    case 708:          /* VSX Scalar Test Data Class Quad-Precision */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+      /* FALL-THROUGH */
+    case 128:          /* Floating Test for software Divide */
+    case 160:          /* Floating Test for software Square Root */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      return 0;
+
+    case 4:            /* VSX Scalar Add Quad-Precision */
+    case 36:           /* VSX Scalar Multiply Quad-Precision */
+    case 388:          /* VSX Scalar Multiply-Add Quad-Precision */
+    case 420:          /* VSX Scalar Multiply-Subtract Quad-Precision */
+    case 452:          /* VSX Scalar Negative Multiply-Add Quad-Precision */
+    case 484:          /* VSX Scalar Negative Multiply-Subtract
+                          Quad-Precision */
+    case 516:          /* VSX Scalar Subtract Quad-Precision */
+    case 548:          /* VSX Scalar Divide Quad-Precision */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+      /* FALL-THROUGH */
+    case 100:          /* VSX Scalar Copy Sign Quad-Precision */
+    case 868:          /* VSX Scalar Insert Exponent Quad-Precision */
+      ppc_record_vsr (regcache, tdep, PPC_VRT (insn) + 32);
+      return 0;
+
+    case 804:
+      switch (PPC_FIELD (insn, 11, 5))
+       {
+       case 27:        /* VSX Scalar Square Root Quad-Precision */
+         record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+         /* FALL-THROUGH */
+       case 0:         /* VSX Scalar Absolute Quad-Precision */
+       case 2:         /* VSX Scalar Extract Exponent Quad-Precision */
+       case 8:         /* VSX Scalar Negative Absolute Quad-Precision */
+       case 16:        /* VSX Scalar Negate Quad-Precision */
+       case 18:        /* VSX Scalar Extract Significand Quad-Precision */
+         ppc_record_vsr (regcache, tdep, PPC_VRT (insn) + 32);
+         return 0;
+       }
+      break;
+
+    case 836:
+      switch (PPC_FIELD (insn, 11, 5))
+       {
+       case 1:         /* VSX Scalar truncate & Convert Quad-Precision format
+                          to Unsigned Word format */
+       case 2:         /* VSX Scalar Convert Unsigned Doubleword format to
+                          Quad-Precision format */
+       case 9:         /* VSX Scalar truncate & Convert Quad-Precision format
+                          to Signed Word format */
+       case 10:        /* VSX Scalar Convert Signed Doubleword format to
+                          Quad-Precision format */
+       case 17:        /* VSX Scalar truncate & Convert Quad-Precision format
+                          to Unsigned Doubleword format */
+       case 20:        /* VSX Scalar round & Convert Quad-Precision format to
+                          Double-Precision format */
+       case 22:        /* VSX Scalar Convert Double-Precision format to
+                          Quad-Precision format */
+       case 25:        /* VSX Scalar truncate & Convert Quad-Precision format
+                          to Signed Doubleword format */
+         record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+         ppc_record_vsr (regcache, tdep, PPC_VRT (insn) + 32);
+         return 0;
+       }
+    }
+
+  fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
+                     "at %s, 63-%d.\n", insn, paddress (gdbarch, addr), ext);
+  return -1;
+}
+
+/* Parse the current instruction and record the values of the registers and
+   memory that will be changed in current instruction to "record_arch_list".
+   Return -1 if something wrong.  */
+
+int
+ppc_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+                     CORE_ADDR addr)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  uint32_t insn;
+  int op6, tmp, i;
+
+  insn = read_memory_unsigned_integer (addr, 4, byte_order);
+  op6 = PPC_OP6 (insn);
+
+  switch (op6)
+    {
+    case 2:            /* Trap Doubleword Immediate */
+    case 3:            /* Trap Word Immediate */
+      /* Do nothing.  */
+      break;
+
+    case 4:
+      if (ppc_process_record_op4 (gdbarch, regcache, addr, insn) != 0)
+       return -1;
+      break;
+
+    case 17:           /* System call */
+      if (PPC_LEV (insn) != 0)
+       goto UNKNOWN_OP;
+
+      if (tdep->ppc_syscall_record != NULL)
+       {
+         if (tdep->ppc_syscall_record (regcache) != 0)
+           return -1;
+       }
+      else
+       {
+         printf_unfiltered (_("no syscall record support\n"));
+         return -1;
+       }
+      break;
+
+    case 7:            /* Multiply Low Immediate */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RT (insn));
+      break;
+
+    case 8:            /* Subtract From Immediate Carrying */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum);
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RT (insn));
+      break;
+
+    case 10:           /* Compare Logical Immediate  */
+    case 11:           /* Compare Immediate */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      break;
+
+    case 13:           /* Add Immediate Carrying and Record */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      /* FALL-THROUGH */
+    case 12:           /* Add Immediate Carrying */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum);
+      /* FALL-THROUGH */
+    case 14:           /* Add Immediate */
+    case 15:           /* Add Immediate Shifted */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RT (insn));
+      break;
+
+    case 16:           /* Branch Conditional */
+      if ((PPC_BO (insn) & 0x4) == 0)
+       record_full_arch_list_add_reg (regcache, tdep->ppc_ctr_regnum);
+      /* FALL-THROUGH */
+    case 18:           /* Branch */
+      if (PPC_LK (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_lr_regnum);
+      break;
+
+    case 19:
+      if (ppc_process_record_op19 (gdbarch, regcache, addr, insn) != 0)
+       return -1;
+      break;
+
+    case 20:           /* Rotate Left Word Immediate then Mask Insert */
+    case 21:           /* Rotate Left Word Immediate then AND with Mask */
+    case 23:           /* Rotate Left Word then AND with Mask */
+    case 30:           /* Rotate Left Doubleword Immediate then Clear Left */
+                       /* Rotate Left Doubleword Immediate then Clear Right */
+                       /* Rotate Left Doubleword Immediate then Clear */
+                       /* Rotate Left Doubleword then Clear Left */
+                       /* Rotate Left Doubleword then Clear Right */
+                       /* Rotate Left Doubleword Immediate then Mask Insert */
+      if (PPC_RC (insn))
+       record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RA (insn));
+      break;
+
+    case 28:           /* AND Immediate */
+    case 29:           /* AND Immediate Shifted */
+      record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+      /* FALL-THROUGH */
+    case 24:           /* OR Immediate */
+    case 25:           /* OR Immediate Shifted */
+    case 26:           /* XOR Immediate */
+    case 27:           /* XOR Immediate Shifted */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RA (insn));
+      break;
+
+    case 31:
+      if (ppc_process_record_op31 (gdbarch, regcache, addr, insn) != 0)
+       return -1;
+      break;
+
+    case 33:           /* Load Word and Zero with Update */
+    case 35:           /* Load Byte and Zero with Update */
+    case 41:           /* Load Halfword and Zero with Update */
+    case 43:           /* Load Halfword Algebraic with Update */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RA (insn));
+      /* FALL-THROUGH */
+    case 32:           /* Load Word and Zero */
+    case 34:           /* Load Byte and Zero */
+    case 40:           /* Load Halfword and Zero */
+    case 42:           /* Load Halfword Algebraic */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RT (insn));
+      break;
+
+    case 46:           /* Load Multiple Word */
+      for (i = PPC_RT (insn); i < 32; i++)
+       record_full_arch_list_add_reg (regcache, tdep->ppc_gp0_regnum + i);
+      break;
+
+    case 56:           /* Load Quadword */
+      tmp = tdep->ppc_gp0_regnum + (PPC_RT (insn) & ~1);
+      record_full_arch_list_add_reg (regcache, tmp);
+      record_full_arch_list_add_reg (regcache, tmp + 1);
+      break;
+
+    case 49:           /* Load Floating-Point Single with Update */
+    case 51:           /* Load Floating-Point Double with Update */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RA (insn));
+      /* FALL-THROUGH */
+    case 48:           /* Load Floating-Point Single */
+    case 50:           /* Load Floating-Point Double */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_fp0_regnum + PPC_FRT (insn));
+      break;
+
+    case 47:           /* Store Multiple Word */
+       {
+         ULONGEST iaddr = 0;
+
+         if (PPC_RA (insn) != 0)
+           regcache_raw_read_unsigned (regcache,
+                                       tdep->ppc_gp0_regnum + PPC_RA (insn),
+                                       &iaddr);
+
+         iaddr += PPC_D (insn);
+         record_full_arch_list_add_mem (iaddr, 4 * (32 - PPC_RS (insn)));
+       }
+      break;
+
+    case 37:           /* Store Word with Update */
+    case 39:           /* Store Byte with Update */
+    case 45:           /* Store Halfword with Update */
+    case 53:           /* Store Floating-Point Single with Update */
+    case 55:           /* Store Floating-Point Double with Update */
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RA (insn));
+      /* FALL-THROUGH */
+    case 36:           /* Store Word */
+    case 38:           /* Store Byte */
+    case 44:           /* Store Halfword */
+    case 52:           /* Store Floating-Point Single */
+    case 54:           /* Store Floating-Point Double */
+       {
+         ULONGEST iaddr = 0;
+         int size = -1;
+
+         if (PPC_RA (insn) != 0)
+           regcache_raw_read_unsigned (regcache,
+                                       tdep->ppc_gp0_regnum + PPC_RA (insn),
+                                       &iaddr);
+         iaddr += PPC_D (insn);
+
+         if (op6 == 36 || op6 == 37 || op6 == 52 || op6 == 53)
+           size = 4;
+         else if (op6 == 54 || op6 == 55)
+           size = 8;
+         else if (op6 == 44 || op6 == 45)
+           size = 2;
+         else if (op6 == 38 || op6 == 39)
+           size = 1;
+         else
+           gdb_assert (0);
+
+         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);
+         record_full_arch_list_add_reg (regcache, tmp + 1);
+         break;
+       case 2:         /* Load VSX Scalar Doubleword */
+       case 3:         /* Load VSX Scalar Single */
+         ppc_record_vsr (regcache, tdep, PPC_VRT (insn) + 32);
+         break;
+       default:
+         goto UNKNOWN_OP;
+       }
+      break;
+
+    case 58:           /* Load Doubleword */
+                       /* Load Doubleword with Update */
+                       /* Load Word Algebraic */
+      if (PPC_FIELD (insn, 30, 2) > 2)
+       goto UNKNOWN_OP;
+
+      record_full_arch_list_add_reg (regcache,
+                                    tdep->ppc_gp0_regnum + PPC_RT (insn));
+      if (PPC_BIT (insn, 31))
+       record_full_arch_list_add_reg (regcache,
+                                      tdep->ppc_gp0_regnum + PPC_RA (insn));
+      break;
+
+    case 59:
+      if (ppc_process_record_op59 (gdbarch, regcache, addr, insn) != 0)
+       return -1;
+      break;
+
+    case 60:
+      if (ppc_process_record_op60 (gdbarch, regcache, addr, insn) != 0)
+       return -1;
+      break;
+
+    case 61:
+      if (ppc_process_record_op61 (gdbarch, regcache, addr, insn) != 0)
+       return -1;
+      break;
+
+    case 62:           /* Store Doubleword */
+                       /* Store Doubleword with Update */
+                       /* Store Quadword with Update */
+       {
+         ULONGEST iaddr = 0;
+         int size;
+         int sub2 = PPC_FIELD (insn, 30, 2);
+
+         if (sub2 > 2)
+           goto UNKNOWN_OP;
+
+         if (PPC_RA (insn) != 0)
+           regcache_raw_read_unsigned (regcache,
+                                       tdep->ppc_gp0_regnum + PPC_RA (insn),
+                                       &iaddr);
+
+         size = (sub2 == 2) ? 16 : 8;
 
-  /* Deal with ALTIVEC registers, if supported.  */
-  if (tdep->ppc_vr0_regnum > 0 && tdep->ppc_vrsave_regnum > 0)
-    {
-      /* Call-saved Altivec registers.  */
-      if ((regnum >= tdep->ppc_vr0_regnum + 20
-         && regnum <= tdep->ppc_vr0_regnum + 31)
-         || regnum == tdep->ppc_vrsave_regnum)
-       reg->how = DWARF2_FRAME_REG_SAME_VALUE;
+         iaddr += PPC_DS (insn) << 2;
+         record_full_arch_list_add_mem (iaddr, size);
 
-      /* Call-clobbered Altivec registers.  */
-      if ((regnum >= tdep->ppc_vr0_regnum
-         && regnum <= tdep->ppc_vr0_regnum + 19))
-       reg->how = DWARF2_FRAME_REG_UNDEFINED;
+         if (op6 == 62 && sub2 == 1)
+           record_full_arch_list_add_reg (regcache,
+                                          tdep->ppc_gp0_regnum +
+                                          PPC_RA (insn));
+
+         break;
+       }
+
+    case 63:
+      if (ppc_process_record_op63 (gdbarch, regcache, addr, insn) != 0)
+       return -1;
+      break;
+
+    default:
+UNKNOWN_OP:
+      fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
+                         "at %s, %d.\n", insn, paddress (gdbarch, addr), op6);
+      return -1;
     }
 
-  /* Handle PC register and Stack Pointer correctly.  */
-  if (regnum == gdbarch_pc_regnum (gdbarch))
-    reg->how = DWARF2_FRAME_REG_RA;
-  else if (regnum == gdbarch_sp_regnum (gdbarch))
-    reg->how = DWARF2_FRAME_REG_CFA;
+  if (record_full_arch_list_add_reg (regcache, PPC_PC_REGNUM))
+    return -1;
+  if (record_full_arch_list_add_end ())
+    return -1;
+  return 0;
 }
 
-
 /* 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.
@@ -3261,16 +6125,22 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   enum bfd_architecture arch;
   unsigned long mach;
   bfd abfd;
-  int sysv_abi;
-  asection *sect;
   enum auto_boolean soft_float_flag = powerpc_soft_float_global;
   int soft_float;
+  enum powerpc_long_double_abi long_double_abi = POWERPC_LONG_DOUBLE_AUTO;
   enum powerpc_vector_abi vector_abi = powerpc_vector_abi_global;
-  int have_fpu = 1, have_spe = 0, have_mq = 0, have_altivec = 0, have_dfp = 0;
+  enum powerpc_elf_abi elf_abi = POWERPC_ELF_AUTO;
+  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;
   int num_pseudoregs = 0;
+  int cur_reg;
 
   from_xcoff_exec = info.abfd && info.abfd->format == bfd_object &&
     bfd_get_flavour (info.abfd) == bfd_target_xcoff_flavour;
@@ -3278,8 +6148,6 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   from_elf_exec = info.abfd && info.abfd->format == bfd_object &&
     bfd_get_flavour (info.abfd) == bfd_target_elf_flavour;
 
-  sysv_abi = info.abfd && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour;
-
   /* Check word size.  If INFO is from a binary file, infer it from
      that, else choose a likely default.  */
   if (from_xcoff_exec)
@@ -3301,50 +6169,37 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   else
     {
       if (info.bfd_arch_info != NULL && info.bfd_arch_info->bits_per_word != 0)
-       wordsize = info.bfd_arch_info->bits_per_word /
-         info.bfd_arch_info->bits_per_byte;
+       wordsize = (info.bfd_arch_info->bits_per_word
+                   / info.bfd_arch_info->bits_per_byte);
       else
        wordsize = 4;
     }
 
-  if (!from_xcoff_exec)
-    {
-      arch = info.bfd_arch_info->arch;
-      mach = info.bfd_arch_info->mach;
-    }
-  else
-    {
-      arch = bfd_arch_powerpc;
-      bfd_default_set_arch_mach (&abfd, arch, 0);
-      info.bfd_arch_info = bfd_get_arch_info (&abfd);
-      mach = info.bfd_arch_info->mach;
-    }
+  /* Get the architecture and machine from the BFD.  */
+  arch = info.bfd_arch_info->arch;
+  mach = info.bfd_arch_info->mach;
 
   /* For e500 executables, the apuinfo section is of help here.  Such
      section contains the identifier and revision number of each
      Application-specific Processing Unit that is present on the
      chip.  The content of the section is determined by the assembler
      which looks at each instruction and determines which unit (and
-     which version of it) can execute it. In our case we just look for
-     the existance of the section.  */
+     which version of it) can execute it.  Grovel through the section
+     looking for relevant e500 APUs.  */
 
-  if (info.abfd)
+  if (bfd_uses_spe_extensions (info.abfd))
     {
-      sect = bfd_get_section_by_name (info.abfd, ".PPC.EMB.apuinfo");
-      if (sect)
-       {
-         arch = info.bfd_arch_info->arch;
-         mach = bfd_mach_ppc_e500;
-         bfd_default_set_arch_mach (&abfd, arch, mach);
-         info.bfd_arch_info = bfd_get_arch_info (&abfd);
-       }
+      arch = info.bfd_arch_info->arch;
+      mach = bfd_mach_ppc_e500;
+      bfd_default_set_arch_mach (&abfd, arch, mach);
+      info.bfd_arch_info = bfd_get_arch_info (&abfd);
     }
 
   /* Find a default target description which describes our register
      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);
@@ -3365,10 +6220,6 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
        "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
        "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
       };
-      static const char *const segment_regs[] = {
-       "sr0", "sr1", "sr2", "sr3", "sr4", "sr5", "sr6", "sr7",
-       "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15"
-      };
       const struct tdesc_feature *feature;
       int i, valid_p;
       static const char *const msr_names[] = { "msr", "ps" };
@@ -3401,128 +6252,473 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
                                                  PPC_CTR_REGNUM, ctr_names);
 
-      if (!valid_p)
+      if (!valid_p)
+       {
+         tdesc_data_cleanup (tdesc_data);
+         return NULL;
+       }
+
+      have_mq = tdesc_numbered_register (feature, tdesc_data, PPC_MQ_REGNUM,
+                                        "mq");
+
+      tdesc_wordsize = tdesc_register_bitsize (feature, "pc") / 8;
+      if (wordsize == -1)
+       wordsize = tdesc_wordsize;
+
+      feature = tdesc_find_feature (tdesc,
+                                   "org.gnu.gdb.power.fpu");
+      if (feature != NULL)
+       {
+         static const char *const fprs[] = {
+           "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+           "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+           "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+           "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
+         };
+         valid_p = 1;
+         for (i = 0; i < ppc_num_fprs; i++)
+           valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                               PPC_F0_REGNUM + i, fprs[i]);
+         valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                             PPC_FPSCR_REGNUM, "fpscr");
+
+         if (!valid_p)
+           {
+             tdesc_data_cleanup (tdesc_data);
+             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;
+
+      feature = tdesc_find_feature (tdesc,
+                                   "org.gnu.gdb.power.altivec");
+      if (feature != NULL)
+       {
+         static const char *const vector_regs[] = {
+           "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7",
+           "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
+           "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
+           "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31"
+         };
+
+         valid_p = 1;
+         for (i = 0; i < ppc_num_gprs; i++)
+           valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                               PPC_VR0_REGNUM + i,
+                                               vector_regs[i]);
+         valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                             PPC_VSCR_REGNUM, "vscr");
+         valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                             PPC_VRSAVE_REGNUM, "vrsave");
+
+         if (have_spe || !valid_p)
+           {
+             tdesc_data_cleanup (tdesc_data);
+             return NULL;
+           }
+         have_altivec = 1;
+       }
+      else
+       have_altivec = 0;
+
+      /* Check for POWER7 VSX registers support.  */
+      feature = tdesc_find_feature (tdesc,
+                                   "org.gnu.gdb.power.vsx");
+
+      if (feature != NULL)
+       {
+         static const char *const vsx_regs[] = {
+           "vs0h", "vs1h", "vs2h", "vs3h", "vs4h", "vs5h",
+           "vs6h", "vs7h", "vs8h", "vs9h", "vs10h", "vs11h",
+           "vs12h", "vs13h", "vs14h", "vs15h", "vs16h", "vs17h",
+           "vs18h", "vs19h", "vs20h", "vs21h", "vs22h", "vs23h",
+           "vs24h", "vs25h", "vs26h", "vs27h", "vs28h", "vs29h",
+           "vs30h", "vs31h"
+         };
+
+         valid_p = 1;
+
+         for (i = 0; i < ppc_num_vshrs; i++)
+           valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                               PPC_VSR0_UPPER_REGNUM + i,
+                                               vsx_regs[i]);
+
+         if (!valid_p || !have_fpu || !have_altivec)
+           {
+             tdesc_data_cleanup (tdesc_data);
+             return NULL;
+           }
+
+         have_vsx = 1;
+       }
+      else
+       have_vsx = 0;
+
+      /* On machines supporting the SPE APU, the general-purpose registers
+        are 64 bits long.  There are SIMD vector instructions to treat them
+        as pairs of floats, but the rest of the instruction set treats them
+        as 32-bit registers, and only operates on their lower halves.
+
+        In the GDB regcache, we treat their high and low halves as separate
+        registers.  The low halves we present as the general-purpose
+        registers, and then we have pseudo-registers that stitch together
+        the upper and lower halves and present them as pseudo-registers.
+
+        Thus, the target description is expected to supply the upper
+        halves separately.  */
+
+      feature = tdesc_find_feature (tdesc,
+                                   "org.gnu.gdb.power.spe");
+      if (feature != NULL)
+       {
+         static const char *const upper_spe[] = {
+           "ev0h", "ev1h", "ev2h", "ev3h",
+           "ev4h", "ev5h", "ev6h", "ev7h",
+           "ev8h", "ev9h", "ev10h", "ev11h",
+           "ev12h", "ev13h", "ev14h", "ev15h",
+           "ev16h", "ev17h", "ev18h", "ev19h",
+           "ev20h", "ev21h", "ev22h", "ev23h",
+           "ev24h", "ev25h", "ev26h", "ev27h",
+           "ev28h", "ev29h", "ev30h", "ev31h"
+         };
+
+         valid_p = 1;
+         for (i = 0; i < ppc_num_gprs; i++)
+           valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                               PPC_SPE_UPPER_GP0_REGNUM + i,
+                                               upper_spe[i]);
+         valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                             PPC_SPE_ACC_REGNUM, "acc");
+         valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                             PPC_SPE_FSCR_REGNUM, "spefscr");
+
+         if (have_mq || have_fpu || !valid_p)
+           {
+             tdesc_data_cleanup (tdesc_data);
+             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,
+                                             PPC_PPR_REGNUM, "ppr");
+
+         if (!valid_p)
+           {
+             tdesc_data_cleanup (tdesc_data);
+             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,
+                                             PPC_DSCR_REGNUM, "dscr");
+
+         if (!valid_p)
+           {
+             tdesc_data_cleanup (tdesc_data);
+             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,
+                                             PPC_TAR_REGNUM, "tar");
+
+         if (!valid_p)
+           {
+             tdesc_data_cleanup (tdesc_data);
+             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,
+                                               PPC_BESCR_REGNUM + i,
+                                               ebb_regs[i]);
+         if (!valid_p)
+           {
+             tdesc_data_cleanup (tdesc_data);
+             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,
+                                             PPC_MMCR0_REGNUM,
+                                             "mmcr0");
+         valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                             PPC_MMCR2_REGNUM,
+                                             "mmcr2");
+         valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                             PPC_SIAR_REGNUM,
+                                             "siar");
+         valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                             PPC_SDAR_REGNUM,
+                                             "sdar");
+         valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                             PPC_SIER_REGNUM,
+                                             "sier");
+
+         if (!valid_p)
+           {
+             tdesc_data_cleanup (tdesc_data);
+             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)
        {
-         tdesc_data_cleanup (tdesc_data);
-         return NULL;
-       }
+         static const char *const tm_spr_regs[] = {
+           "tfhar", "texasr", "tfiar"
+         };
 
-      have_mq = tdesc_numbered_register (feature, tdesc_data, PPC_MQ_REGNUM,
-                                        "mq");
+         valid_p = 1;
+         for (i = 0; i < ARRAY_SIZE (tm_spr_regs); i++)
+           valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                               PPC_TFHAR_REGNUM + i,
+                                               tm_spr_regs[i]);
+         if (!valid_p)
+           {
+             tdesc_data_cleanup (tdesc_data);
+             return NULL;
+           }
 
-      tdesc_wordsize = tdesc_register_size (feature, "pc") / 8;
-      if (wordsize == -1)
-       wordsize = tdesc_wordsize;
+         have_htm_spr = 1;
+       }
+      else
+       have_htm_spr = 0;
 
       feature = tdesc_find_feature (tdesc,
-                                   "org.gnu.gdb.power.fpu");
+                                   "org.gnu.gdb.power.htm.core");
       if (feature != NULL)
        {
-         static const char *const fprs[] = {
-           "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
-           "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
-           "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
-           "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
+         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 < ppc_num_fprs; i++)
-           valid_p &= tdesc_numbered_register (feature, tdesc_data,
-                                               PPC_F0_REGNUM + i, fprs[i]);
-         valid_p &= tdesc_numbered_register (feature, tdesc_data,
-                                             PPC_FPSCR_REGNUM, "fpscr");
 
+         for (i = 0; i < ARRAY_SIZE (cgprs); i++)
+           valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                               PPC_CR0_REGNUM + i,
+                                               cgprs[i]);
          if (!valid_p)
            {
              tdesc_data_cleanup (tdesc_data);
              return NULL;
            }
-         have_fpu = 1;
+
+         have_htm_core = 1;
        }
       else
-       have_fpu = 0;
-
-      /* The DFP pseudo-registers will be available when there are floating
-         point registers.  */
-      have_dfp = have_fpu;
+       have_htm_core = 0;
 
       feature = tdesc_find_feature (tdesc,
-                                   "org.gnu.gdb.power.altivec");
+                                   "org.gnu.gdb.power.htm.fpu");
       if (feature != NULL)
        {
-         static const char *const vector_regs[] = {
-           "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7",
-           "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
-           "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
-           "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31"
+         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"
          };
 
-         valid_p = 1;
-         for (i = 0; i < ppc_num_gprs; i++)
+         for (i = 0; i < ARRAY_SIZE (cfprs); i++)
            valid_p &= tdesc_numbered_register (feature, tdesc_data,
-                                               PPC_VR0_REGNUM + i,
-                                               vector_regs[i]);
-         valid_p &= tdesc_numbered_register (feature, tdesc_data,
-                                             PPC_VSCR_REGNUM, "vscr");
-         valid_p &= tdesc_numbered_register (feature, tdesc_data,
-                                             PPC_VRSAVE_REGNUM, "vrsave");
+                                               PPC_CF0_REGNUM + i,
+                                               cfprs[i]);
 
-         if (have_spe || !valid_p)
+         if (!valid_p)
            {
              tdesc_data_cleanup (tdesc_data);
              return NULL;
            }
-         have_altivec = 1;
+         have_htm_fpu = 1;
        }
       else
-       have_altivec = 0;
+       have_htm_fpu = 0;
 
-      /* On machines supporting the SPE APU, the general-purpose registers
-        are 64 bits long.  There are SIMD vector instructions to treat them
-        as pairs of floats, but the rest of the instruction set treats them
-        as 32-bit registers, and only operates on their lower halves.
+      feature = tdesc_find_feature (tdesc,
+                                   "org.gnu.gdb.power.htm.altivec");
+      if (feature != NULL)
+       {
+         valid_p = 1;
 
-        In the GDB regcache, we treat their high and low halves as separate
-        registers.  The low halves we present as the general-purpose
-        registers, and then we have pseudo-registers that stitch together
-        the upper and lower halves and present them as pseudo-registers.
+         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"
+         };
 
-        Thus, the target description is expected to supply the upper
-        halves separately.  */
+         for (i = 0; i < ARRAY_SIZE (cvmx); i++)
+           valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                               PPC_CVR0_REGNUM + i,
+                                               cvmx[i]);
+
+         if (!valid_p)
+           {
+             tdesc_data_cleanup (tdesc_data);
+             return NULL;
+           }
+         have_htm_altivec = 1;
+       }
+      else
+       have_htm_altivec = 0;
 
       feature = tdesc_find_feature (tdesc,
-                                   "org.gnu.gdb.power.spe");
+                                   "org.gnu.gdb.power.htm.vsx");
       if (feature != NULL)
        {
-         static const char *const upper_spe[] = {
-           "ev0h", "ev1h", "ev2h", "ev3h",
-           "ev4h", "ev5h", "ev6h", "ev7h",
-           "ev8h", "ev9h", "ev10h", "ev11h",
-           "ev12h", "ev13h", "ev14h", "ev15h",
-           "ev16h", "ev17h", "ev18h", "ev19h",
-           "ev20h", "ev21h", "ev22h", "ev23h",
-           "ev24h", "ev25h", "ev26h", "ev27h",
-           "ev28h", "ev29h", "ev30h", "ev31h"
+         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"
          };
 
-         valid_p = 1;
-         for (i = 0; i < ppc_num_gprs; i++)
+         for (i = 0; i < ARRAY_SIZE (cvsx); i++)
            valid_p &= tdesc_numbered_register (feature, tdesc_data,
-                                               PPC_SPE_UPPER_GP0_REGNUM + i,
-                                               upper_spe[i]);
-         valid_p &= tdesc_numbered_register (feature, tdesc_data,
-                                             PPC_SPE_ACC_REGNUM, "acc");
-         valid_p &= tdesc_numbered_register (feature, tdesc_data,
-                                             PPC_SPE_FSCR_REGNUM, "spefscr");
+                                               (PPC_CVSR0_UPPER_REGNUM
+                                                + i),
+                                               cvsx[i]);
 
-         if (have_mq || have_fpu || !valid_p)
+         if (!valid_p || !have_htm_fpu || !have_htm_altivec)
            {
              tdesc_data_cleanup (tdesc_data);
              return NULL;
            }
-         have_spe = 1;
+         have_htm_vsx = 1;
        }
       else
-       have_spe = 0;
+       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,
+                                            PPC_CPPR_REGNUM, "cppr");
+
+         if (!valid_p)
+           {
+             tdesc_data_cleanup (tdesc_data);
+             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,
+                                            PPC_CDSCR_REGNUM, "cdscr");
+
+         if (!valid_p)
+           {
+             tdesc_data_cleanup (tdesc_data);
+             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,
+                                            PPC_CTAR_REGNUM, "ctar");
+
+         if (!valid_p)
+           {
+             tdesc_data_cleanup (tdesc_data);
+             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
@@ -3543,10 +6739,25 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     }
 
 #ifdef HAVE_ELF
+  if (from_elf_exec)
+    {
+      switch (elf_elfheader (info.abfd)->e_flags & EF_PPC64_ABI)
+       {
+       case 1:
+         elf_abi = POWERPC_ELF_V1;
+         break;
+       case 2:
+         elf_abi = POWERPC_ELF_V2;
+         break;
+       default:
+         break;
+       }
+    }
+
   if (soft_float_flag == AUTO_BOOLEAN_AUTO && from_elf_exec)
     {
       switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU,
-                                       Tag_GNU_Power_ABI_FP))
+                                       Tag_GNU_Power_ABI_FP) & 3)
        {
        case 1:
          soft_float_flag = AUTO_BOOLEAN_FALSE;
@@ -3559,6 +6770,22 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
        }
     }
 
+  if (long_double_abi == POWERPC_LONG_DOUBLE_AUTO && from_elf_exec)
+    {
+      switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU,
+                                       Tag_GNU_Power_ABI_FP) >> 2)
+       {
+       case 1:
+         long_double_abi = POWERPC_LONG_DOUBLE_IBM128;
+         break;
+       case 3:
+         long_double_abi = POWERPC_LONG_DOUBLE_IEEE128;
+         break;
+       default:
+         break;
+       }
+    }
+
   if (vector_abi == POWERPC_VEC_AUTO && from_elf_exec)
     {
       switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU,
@@ -3579,6 +6806,21 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     }
 #endif
 
+  /* At this point, the only supported ELF-based 64-bit little-endian
+     operating system is GNU/Linux, and this uses the ELFv2 ABI by
+     default.  All other supported ELF-based operating systems use the
+     ELFv1 ABI by default.  Therefore, if the ABI marker is missing,
+     e.g. because we run a legacy binary, or have attached to a process
+     and have not found any associated binary file, set the default
+     according to this heuristic.  */
+  if (elf_abi == POWERPC_ELF_AUTO)
+    {
+      if (wordsize == 8 && info.byte_order == BFD_ENDIAN_LITTLE)
+        elf_abi = POWERPC_ELF_V2;
+      else
+        elf_abi = POWERPC_ELF_V1;
+    }
+
   if (soft_float_flag == AUTO_BOOLEAN_TRUE)
     soft_float = 1;
   else if (soft_float_flag == AUTO_BOOLEAN_FALSE)
@@ -3621,8 +6863,12 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
          meaningful, because 64-bit CPUs can run in 32-bit mode.  So, perform
          separate word size check.  */
       tdep = gdbarch_tdep (arches->gdbarch);
+      if (tdep && tdep->elf_abi != elf_abi)
+       continue;
       if (tdep && tdep->soft_float != soft_float)
        continue;
+      if (tdep && tdep->long_double_abi != long_double_abi)
+       continue;
       if (tdep && tdep->vector_abi != vector_abi)
        continue;
       if (tdep && tdep->wordsize == wordsize)
@@ -3641,9 +6887,11 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
        - "set arch"            trust blindly
        - GDB startup           useless but harmless */
 
-  tdep = XCALLOC (1, struct gdbarch_tdep);
+  tdep = XCNEW (struct gdbarch_tdep);
   tdep->wordsize = wordsize;
+  tdep->elf_abi = elf_abi;
   tdep->soft_float = soft_float;
+  tdep->long_double_abi = long_double_abi;
   tdep->vector_abi = vector_abi;
 
   gdbarch = gdbarch_alloc (&info, tdep);
@@ -3659,15 +6907,41 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   tdep->ppc_fp0_regnum = have_fpu ? PPC_F0_REGNUM : -1;
   tdep->ppc_fpscr_regnum = have_fpu ? PPC_FPSCR_REGNUM : -1;
+  tdep->ppc_vsr0_upper_regnum = have_vsx ? PPC_VSR0_UPPER_REGNUM : -1;
   tdep->ppc_vr0_regnum = have_altivec ? PPC_VR0_REGNUM : -1;
   tdep->ppc_vrsave_regnum = have_altivec ? PPC_VRSAVE_REGNUM : -1;
   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);
-  set_gdbarch_deprecated_fp_regnum (gdbarch, PPC_R0_REGNUM + 1);
   set_gdbarch_fp0_regnum (gdbarch, tdep->ppc_fp0_regnum);
   set_gdbarch_register_sim_regno (gdbarch, rs6000_register_sim_regno);
 
@@ -3676,34 +6950,30 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      alias.  */
   set_gdbarch_ps_regnum (gdbarch, tdep->ppc_ps_regnum);
 
-  if (sysv_abi && wordsize == 8)
+  if (wordsize == 8)
     set_gdbarch_return_value (gdbarch, ppc64_sysv_abi_return_value);
-  else if (sysv_abi && wordsize == 4)
-    set_gdbarch_return_value (gdbarch, ppc_sysv_abi_return_value);
   else
-    set_gdbarch_return_value (gdbarch, rs6000_return_value);
+    set_gdbarch_return_value (gdbarch, ppc_sysv_abi_return_value);
 
   /* Set lr_frame_offset.  */
   if (wordsize == 8)
     tdep->lr_frame_offset = 16;
-  else if (sysv_abi)
-    tdep->lr_frame_offset = 4;
   else
-    tdep->lr_frame_offset = 8;
+    tdep->lr_frame_offset = 4;
 
-  if (have_spe || have_dfp)
+  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, rs6000_pseudo_register_write);
+      set_gdbarch_pseudo_register_write (gdbarch,
+                                        rs6000_pseudo_register_write);
+      set_gdbarch_ax_pseudo_register_collect (gdbarch,
+             rs6000_ax_pseudo_register_collect);
     }
 
-  set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
+  set_gdbarch_gen_return_address (gdbarch, rs6000_gen_return_address);
 
-  /* Select instruction printer.  */
-  if (arch == bfd_arch_rs6000)
-    set_gdbarch_print_insn (gdbarch, print_insn_rs6000);
-  else
-    set_gdbarch_print_insn (gdbarch, gdb_print_insn_powerpc);
+  set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
 
   set_gdbarch_num_regs (gdbarch, PPC_NUM_REGS);
 
@@ -3711,6 +6981,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);
 
@@ -3721,22 +7001,13 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_long_long_bit (gdbarch, 8 * TARGET_CHAR_BIT);
   set_gdbarch_float_bit (gdbarch, 4 * TARGET_CHAR_BIT);
   set_gdbarch_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
-  if (sysv_abi)
-    set_gdbarch_long_double_bit (gdbarch, 16 * TARGET_CHAR_BIT);
-  else
-    set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
+  set_gdbarch_long_double_bit (gdbarch, 16 * TARGET_CHAR_BIT);
   set_gdbarch_char_signed (gdbarch, 0);
 
   set_gdbarch_frame_align (gdbarch, rs6000_frame_align);
-  if (sysv_abi && wordsize == 8)
+  if (wordsize == 8)
     /* PPC64 SYSV.  */
     set_gdbarch_frame_red_zone_size (gdbarch, 288);
-  else if (!sysv_abi && wordsize == 4)
-    /* PowerOpen / AIX 32 bit.  The saved area or red zone consists of
-       19 4 byte GPRS + 18 8 byte FPRs giving a total of 220 bytes.
-       Problem is, 220 isn't frame (16 byte) aligned.  Round it up to
-       224.  */
-    set_gdbarch_frame_red_zone_size (gdbarch, 224);
 
   set_gdbarch_convert_register_p (gdbarch, rs6000_convert_register_p);
   set_gdbarch_register_to_value (gdbarch, rs6000_register_to_value);
@@ -3745,46 +7016,32 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_stab_reg_to_regnum (gdbarch, rs6000_stab_reg_to_regnum);
   set_gdbarch_dwarf2_reg_to_regnum (gdbarch, rs6000_dwarf2_reg_to_regnum);
 
-  if (sysv_abi && wordsize == 4)
+  if (wordsize == 4)
     set_gdbarch_push_dummy_call (gdbarch, ppc_sysv_abi_push_dummy_call);
-  else if (sysv_abi && wordsize == 8)
+  else if (wordsize == 8)
     set_gdbarch_push_dummy_call (gdbarch, ppc64_sysv_abi_push_dummy_call);
-  else
-    set_gdbarch_push_dummy_call (gdbarch, rs6000_push_dummy_call);
 
   set_gdbarch_skip_prologue (gdbarch, rs6000_skip_prologue);
-  set_gdbarch_in_function_epilogue_p (gdbarch, rs6000_in_function_epilogue_p);
+  set_gdbarch_stack_frame_destroyed_p (gdbarch, rs6000_stack_frame_destroyed_p);
+  set_gdbarch_skip_main_prologue (gdbarch, rs6000_skip_main_prologue);
 
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
-  set_gdbarch_breakpoint_from_pc (gdbarch, rs6000_breakpoint_from_pc);
+
+  set_gdbarch_breakpoint_kind_from_pc (gdbarch,
+                                      rs6000_breakpoint::kind_from_pc);
+  set_gdbarch_sw_breakpoint_from_kind (gdbarch,
+                                      rs6000_breakpoint::bp_from_kind);
 
   /* The value of symbols of type N_SO and N_FUN maybe null when
-     it shouldn't be. */
+     it shouldn't be.  */
   set_gdbarch_sofun_address_maybe_missing (gdbarch, 1);
 
   /* Handles single stepping of atomic sequences.  */
-  set_gdbarch_software_single_step (gdbarch, deal_with_atomic_sequence);
+  set_gdbarch_software_single_step (gdbarch, ppc_deal_with_atomic_sequence);
   
-  /* Handle the 64-bit SVR4 minimal-symbol convention of using "FN"
-     for the descriptor and ".FN" for the entry-point -- a user
-     specifying "break FN" will unexpectedly end up with a breakpoint
-     on the descriptor and not the function.  This architecture method
-     transforms any breakpoints on descriptors into breakpoints on the
-     corresponding entry point.  */
-  if (sysv_abi && wordsize == 8)
-    set_gdbarch_adjust_breakpoint_address (gdbarch, ppc64_sysv_abi_adjust_breakpoint_address);
-
-  /* Not sure on this. FIXMEmgo */
+  /* Not sure on this.  FIXMEmgo */
   set_gdbarch_frame_args_skip (gdbarch, 8);
 
-  if (!sysv_abi)
-    {
-      /* Handle RS/6000 function pointers (which are really function
-         descriptors).  */
-      set_gdbarch_convert_from_func_ptr_addr (gdbarch,
-       rs6000_convert_from_func_ptr_addr);
-    }
-
   /* Helpers for function argument information.  */
   set_gdbarch_fetch_pointer_argument (gdbarch, rs6000_fetch_pointer_argument);
 
@@ -3794,32 +7051,42 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_skip_trampoline_code (gdbarch, rs6000_skip_trampoline_code);
 
   /* Hook in the DWARF CFI frame unwinder.  */
-  frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
+  dwarf2_append_unwinders (gdbarch);
   dwarf2_frame_set_adjust_regnum (gdbarch, rs6000_adjust_frame_regnum);
 
   /* Frame handling.  */
   dwarf2_frame_set_init_reg (gdbarch, ppc_dwarf2_frame_init_reg);
 
+  /* Setup displaced stepping.  */
+  set_gdbarch_displaced_step_copy_insn (gdbarch,
+                                       ppc_displaced_step_copy_insn);
+  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_max_insn_length (gdbarch, PPC_INSN_SIZE);
+
   /* Hook in ABI-specific overrides, if they have been registered.  */
+  info.target_desc = tdesc;
+  info.tdesc_data = tdesc_data;
   gdbarch_init_osabi (info, gdbarch);
 
   switch (info.osabi)
     {
     case GDB_OSABI_LINUX:
-    case GDB_OSABI_NETBSD_AOUT:
-    case GDB_OSABI_NETBSD_ELF:
+    case GDB_OSABI_NETBSD:
     case GDB_OSABI_UNKNOWN:
-      set_gdbarch_unwind_pc (gdbarch, rs6000_unwind_pc);
-      frame_unwind_append_sniffer (gdbarch, rs6000_frame_sniffer);
-      set_gdbarch_unwind_dummy_id (gdbarch, rs6000_unwind_dummy_id);
+      frame_unwind_append_unwinder (gdbarch, &rs6000_epilogue_frame_unwind);
+      frame_unwind_append_unwinder (gdbarch, &rs6000_frame_unwind);
       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_sniffer (gdbarch, rs6000_frame_sniffer);
-      set_gdbarch_unwind_dummy_id (gdbarch, rs6000_unwind_dummy_id);
+      frame_unwind_append_unwinder (gdbarch, &rs6000_epilogue_frame_unwind);
+      frame_unwind_append_unwinder (gdbarch, &rs6000_frame_unwind);
       frame_base_append_sniffer (gdbarch, rs6000_frame_base_sniffer);
     }
 
@@ -3832,15 +7099,64 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      halves anonymous.  */
   set_gdbarch_register_name (gdbarch, rs6000_register_name);
 
-  /* Recording the numbering of pseudo registers.  */
-  tdep->ppc_ev0_regnum = have_spe ? gdbarch_num_regs (gdbarch) : -1;
+  /* 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;
 
-  /* Set the register number for _Decimal128 pseudo-registers.  */
-  tdep->ppc_dl0_regnum = have_dfp? gdbarch_num_regs (gdbarch) : -1;
+  cur_reg = gdbarch_num_regs (gdbarch);
 
-  if (have_dfp && have_spe)
-    /* Put the _Decimal128 pseudo-registers after the SPE registers.  */
-    tdep->ppc_dl0_regnum += 32;
+  if (have_spe)
+    {
+      tdep->ppc_ev0_regnum = cur_reg;
+      cur_reg += 32;
+    }
+  if (have_dfp)
+    {
+      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;
+      cur_reg += 64;
+      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_cooked_regs (gdbarch) == cur_reg);
+
+  /* Register the ravenscar_arch_ops.  */
+  if (mach == bfd_mach_ppc_e500)
+    register_e500_ravenscar_ops (gdbarch);
+  else
+    register_ppc_ravenscar_ops (gdbarch);
+
+  set_gdbarch_disassembler_options (gdbarch, &powerpc_disassembler_options);
+  set_gdbarch_valid_disassembler_options (gdbarch,
+                                         disassembler_options_powerpc ());
 
   return gdbarch;
 }
@@ -3856,24 +7172,8 @@ rs6000_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
   /* FIXME: Dump gdbarch_tdep.  */
 }
 
-/* PowerPC-specific commands.  */
-
-static void
-set_powerpc_command (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 (char *args, int from_tty)
-{
-  cmd_show_list (showpowerpccmdlist, from_tty, "");
-}
-
 static void
-powerpc_set_soft_float (char *args, int from_tty,
+powerpc_set_soft_float (const char *args, int from_tty,
                        struct cmd_list_element *c)
 {
   struct gdbarch_info info;
@@ -3881,15 +7181,15 @@ powerpc_set_soft_float (char *args, int from_tty,
   /* Update the architecture.  */
   gdbarch_info_init (&info);
   if (!gdbarch_update_p (info))
-    internal_error (__FILE__, __LINE__, "could not update architecture");
+    internal_error (__FILE__, __LINE__, _("could not update architecture"));
 }
 
 static void
-powerpc_set_vector_abi (char *args, int from_tty,
+powerpc_set_vector_abi (const char *args, int from_tty,
                        struct cmd_list_element *c)
 {
   struct gdbarch_info info;
-  enum powerpc_vector_abi vector_abi;
+  int vector_abi;
 
   for (vector_abi = POWERPC_VEC_AUTO;
        vector_abi != POWERPC_VEC_LAST;
@@ -3897,7 +7197,7 @@ powerpc_set_vector_abi (char *args, int from_tty,
     if (strcmp (powerpc_vector_abi_string,
                powerpc_vector_strings[vector_abi]) == 0)
       {
-       powerpc_vector_abi_global = vector_abi;
+       powerpc_vector_abi_global = (enum powerpc_vector_abi) vector_abi;
        break;
       }
 
@@ -3908,29 +7208,112 @@ powerpc_set_vector_abi (char *args, int from_tty,
   /* Update the architecture.  */
   gdbarch_info_init (&info);
   if (!gdbarch_update_p (info))
-    internal_error (__FILE__, __LINE__, "could not update architecture");
+    internal_error (__FILE__, __LINE__, _("could not update architecture"));
 }
 
-/* Initialization code.  */
+/* Show the current setting of the exact watchpoints flag.  */
+
+static void
+show_powerpc_exact_watchpoints (struct ui_file *file, int from_tty,
+                               struct cmd_list_element *c,
+                               const char *value)
+{
+  fprintf_filtered (file, _("Use of exact watchpoints is %s.\n"), value);
+}
 
-extern initialize_file_ftype _initialize_rs6000_tdep; /* -Wmissing-prototypes */
+/* Read a PPC instruction from memory.  */
 
+static unsigned int
+read_insn (struct frame_info *frame, CORE_ADDR pc)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
+  return read_memory_unsigned_integer (pc, 4, byte_order);
+}
+
+/* Return non-zero if the instructions at PC match the series
+   described in PATTERN, or zero otherwise.  PATTERN is an array of
+   'struct ppc_insn_pattern' objects, terminated by an entry whose
+   mask is zero.
+
+   When the match is successful, fill INSNS[i] with what PATTERN[i]
+   matched.  If PATTERN[i] is optional, and the instruction wasn't
+   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,
+                        const struct ppc_insn_pattern *pattern,
+                        unsigned int *insns)
+{
+  int i;
+  unsigned int insn;
+
+  for (i = 0, insn = 0; pattern[i].mask; i++)
+    {
+      if (insn == 0)
+       insn = read_insn (frame, pc);
+      insns[i] = 0;
+      if ((insn & pattern[i].mask) == pattern[i].data)
+       {
+         insns[i] = insn;
+         pc += 4;
+         insn = 0;
+       }
+      else if (!pattern[i].optional)
+       return 0;
+    }
+
+  return 1;
+}
+
+/* Return the 'd' field of the d-form instruction INSN, properly
+   sign-extended.  */
+
+CORE_ADDR
+ppc_insn_d_field (unsigned int insn)
+{
+  return ((((CORE_ADDR) insn & 0xffff) ^ 0x8000) - 0x8000);
+}
+
+/* Return the 'ds' field of the ds-form instruction INSN, with the two
+   zero bits concatenated at the right, and properly
+   sign-extended.  */
+
+CORE_ADDR
+ppc_insn_ds_field (unsigned int insn)
+{
+  return ((((CORE_ADDR) insn & 0xfffc) ^ 0x8000) - 0x8000);
+}
+
+/* Initialization code.  */
+
+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);
 
   /* Initialize the standard target descriptions.  */
   initialize_tdesc_powerpc_32 ();
+  initialize_tdesc_powerpc_altivec32 ();
+  initialize_tdesc_powerpc_vsx32 ();
   initialize_tdesc_powerpc_403 ();
   initialize_tdesc_powerpc_403gc ();
+  initialize_tdesc_powerpc_405 ();
   initialize_tdesc_powerpc_505 ();
   initialize_tdesc_powerpc_601 ();
   initialize_tdesc_powerpc_602 ();
   initialize_tdesc_powerpc_603 ();
   initialize_tdesc_powerpc_604 ();
   initialize_tdesc_powerpc_64 ();
+  initialize_tdesc_powerpc_altivec64 ();
+  initialize_tdesc_powerpc_vsx64 ();
   initialize_tdesc_powerpc_7400 ();
   initialize_tdesc_powerpc_750 ();
   initialize_tdesc_powerpc_860 ();
@@ -3939,13 +7322,13 @@ _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_basic_prefix_cmd ("powerpc", no_class,
+                       _("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_show_prefix_cmd ("powerpc", no_class,
+                      _("Various PowerPC-specific commands."),
+                      &showpowerpccmdlist, "show powerpc ", 0, &showlist);
 
   /* Add a command to allow the user to force the ABI.  */
   add_setshow_auto_boolean_cmd ("soft-float", class_support,
@@ -3962,4 +7345,17 @@ _initialize_rs6000_tdep (void)
                        _("Show the vector ABI."),
                        NULL, powerpc_set_vector_abi, NULL,
                        &setpowerpccmdlist, &showpowerpccmdlist);
+
+  add_setshow_boolean_cmd ("exact-watchpoints", class_support,
+                          &target_exact_watchpoints,
+                          _("\
+Set whether to use just one debug register for watchpoints on scalars."),
+                          _("\
+Show whether to use just one debug register for watchpoints on scalars."),
+                          _("\
+If true, GDB will use only one debug register when watching a variable of\n\
+scalar type, thus assuming that the variable is accessed through the address\n\
+of its first byte."),
+                          NULL, show_powerpc_exact_watchpoints,
+                          &setpowerpccmdlist, &showpowerpccmdlist);
 }
This page took 0.105885 seconds and 4 git commands to generate.