[PowerPC] Fix access to VSCR in linux targets
authorPedro Franco de Carvalho <pedromfc@linux.vnet.ibm.com>
Tue, 22 May 2018 14:09:05 +0000 (11:09 -0300)
committerPedro Franco de Carvalho <pedromfc@linux.vnet.ibm.com>
Tue, 22 May 2018 14:52:03 +0000 (11:52 -0300)
The 4-byte VSCR register is found inside a 16-byte field in the regset
returned by ptrace and in core files. The position of VSCR depends on
the endianess of the target, which was previously assumed to be
big-endian for the purpose of getting VSCR. This patch removes this
assumption to fix access to VSCR in little-endian mode.

gdb/ChangeLog:
2018-05-22  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

* ppc-tdep.h (struct ppc_reg_offsets): Remove vector register
offset fields.
* ppc-fbsd-tdep.c (ppc32_fbsd_reg_offsets): Remove initializers
for vector register offset fields.
(ppc64_fbsd_reg_offsets): Likewise.
* ppc-nbsd-tdep.c (_initialize_ppcnbsd_tdep): Remove assignment
to vector register offset fields.
* ppc-obsd-tdep.c (_initialize_ppcnbsd_tdep): Remove assignment
to vector register offset fields.
* ppc-obsd-nat.c (_initialize_ppcobsd_nat): Remove assignment to
vector register offset fields.
* rs6000-aix-tdep.c (rs6000_aix32_reg_offsets): Remove
initializers for vector register offset fields.
(rs6000_aix64_reg_offsets): Likewise.
* rs6000-tdep.c (ppc_vrreg_offset): Remove.
(ppc_supply_vrregset): Remove.
(ppc_collect_vrregset): Remove.
* ppc-linux-tdep.c (ppc_linux_collect_vrregset): New function.
(ppc_linux_vrregset) : New function.
(ppc32_le_linux_vrregmap, ppc32_be_linux_vrregmap)
(ppc32_le_linux_vrregset, ppc32_be_linux_vrregset): New globals.
(ppc32_linux_vrregset): Remove.
(ppc_linux_iterate_over_regset_sections): Call ppc_linux_vrregset
and use result instead of ppc32_linux_vrregset.
(ppc32_linux_reg_offsets): Remove initializers for vector register
offset fields.
(ppc64_linux_reg_offsets): Likewise.
* ppc-linux-tdep.h (ppc_linux_vrregset): New declaration.
* ppc-linux-nat.c: Include regset.h.
(gdb_vrregset_t): Adjust comment to account for little-endian
mode.
(supply_vrregset, fill_vrregset): Remove.
(fetch_altivec_register, store_altivec_register): Remove.
(fetch_altivec_registers): Add regno parameter. Get regset using
ppc_linux_vrregset. Use regset to supply registers.
(store_altivec_registers): Add regno parameter. Get regset using
ppc_linux_vrregset. Use regset to collect registers.
(fetch_register): Call fetch_altivec_registers instead of
fetch_altivec_register.
(store_register): Call store_altivec_registers instead of
store_altivec_register.
(fetch_ppc_registers): Call fetch_altivec_registers with -1 for
the new regno parameter.
(store_ppc_registers): Call store_altivec_registers with -1 for
the new regno parameter.

gdb/gdbserver/ChangeLog:
2018-05-22  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

* linux-ppc-low.c (ppc_fill_vrregset): Add vscr_offset variable.
Set vscr_offset to 0 in little-endian mode and 12 in big-endian
mode. Call collect_register_by_name with vscr using
vscr_offset. Zero-pad vscr and vrsave fields in collector buffer.
(ppc_store_vrregset): Add and set vscr_offset variable as in
ppc_fill_vrregset. Call supply_register_by_name with vscr using
vscr_offset.

13 files changed:
gdb/ChangeLog
gdb/gdbserver/ChangeLog
gdb/gdbserver/linux-ppc-low.c
gdb/ppc-fbsd-tdep.c
gdb/ppc-linux-nat.c
gdb/ppc-linux-tdep.c
gdb/ppc-linux-tdep.h
gdb/ppc-nbsd-tdep.c
gdb/ppc-obsd-nat.c
gdb/ppc-obsd-tdep.c
gdb/ppc-tdep.h
gdb/rs6000-aix-tdep.c
gdb/rs6000-tdep.c

index d99f5c078a5bec149afcb7d23eb11d6cc827b37a..b234da8ceb18aea5b699ccbc9c58732dd0e8115e 100644 (file)
@@ -1,3 +1,51 @@
+2018-05-22  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
+
+       * ppc-tdep.h (struct ppc_reg_offsets): Remove vector register
+       offset fields.
+       * ppc-fbsd-tdep.c (ppc32_fbsd_reg_offsets): Remove initializers
+       for vector register offset fields.
+       (ppc64_fbsd_reg_offsets): Likewise.
+       * ppc-nbsd-tdep.c (_initialize_ppcnbsd_tdep): Remove assignment
+       to vector register offset fields.
+       * ppc-obsd-tdep.c (_initialize_ppcnbsd_tdep): Remove assignment
+       to vector register offset fields.
+       * ppc-obsd-nat.c (_initialize_ppcobsd_nat): Remove assignment to
+       vector register offset fields.
+       * rs6000-aix-tdep.c (rs6000_aix32_reg_offsets): Remove
+       initializers for vector register offset fields.
+       (rs6000_aix64_reg_offsets): Likewise.
+       * rs6000-tdep.c (ppc_vrreg_offset): Remove.
+       (ppc_supply_vrregset): Remove.
+       (ppc_collect_vrregset): Remove.
+       * ppc-linux-tdep.c (ppc_linux_collect_vrregset): New function.
+       (ppc_linux_vrregset) : New function.
+       (ppc32_le_linux_vrregmap, ppc32_be_linux_vrregmap)
+       (ppc32_le_linux_vrregset, ppc32_be_linux_vrregset): New globals.
+       (ppc32_linux_vrregset): Remove.
+       (ppc_linux_iterate_over_regset_sections): Call ppc_linux_vrregset
+       and use result instead of ppc32_linux_vrregset.
+       (ppc32_linux_reg_offsets): Remove initializers for vector register
+       offset fields.
+       (ppc64_linux_reg_offsets): Likewise.
+       * ppc-linux-tdep.h (ppc_linux_vrregset): New declaration.
+       * ppc-linux-nat.c: Include regset.h.
+       (gdb_vrregset_t): Adjust comment to account for little-endian
+       mode.
+       (supply_vrregset, fill_vrregset): Remove.
+       (fetch_altivec_register, store_altivec_register): Remove.
+       (fetch_altivec_registers): Add regno parameter. Get regset using
+       ppc_linux_vrregset. Use regset to supply registers.
+       (store_altivec_registers): Add regno parameter. Get regset using
+       ppc_linux_vrregset. Use regset to collect registers.
+       (fetch_register): Call fetch_altivec_registers instead of
+       fetch_altivec_register.
+       (store_register): Call store_altivec_registers instead of
+       store_altivec_register.
+       (fetch_ppc_registers): Call fetch_altivec_registers with -1 for
+       the new regno parameter.
+       (store_ppc_registers): Call store_altivec_registers with -1 for
+       the new regno parameter.
+
 2018-05-22  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
 
        * arch/ppc-linux-common.h (PPC_LINUX_SIZEOF_VRREGSET)
index 1efddc44a159a51be4bb471f2d1e18de0ff23864..13e34262ef590e5eb64c11a77fb43eaf5decc37c 100644 (file)
@@ -1,3 +1,13 @@
+2018-05-22  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
+
+       * linux-ppc-low.c (ppc_fill_vrregset): Add vscr_offset variable.
+       Set vscr_offset to 0 in little-endian mode and 12 in big-endian
+       mode. Call collect_register_by_name with vscr using
+       vscr_offset. Zero-pad vscr and vrsave fields in collector buffer.
+       (ppc_store_vrregset): Add and set vscr_offset variable as in
+       ppc_fill_vrregset. Call supply_register_by_name with vscr using
+       vscr_offset.
+
 2018-05-22  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
 
        * linux-ppc-low.c (SIZEOF_VSXREGS, SIZEOF_VRREGS): Remove.
index 367851836e4e90227e0f921d2e0bddfcc066ed14..c6e00b7eb8b4f0749255144e7a1c156d2badb552 100644 (file)
@@ -486,12 +486,22 @@ ppc_fill_vrregset (struct regcache *regcache, void *buf)
 {
   int i, base;
   char *regset = (char *) buf;
+  int vscr_offset = 0;
 
   base = find_regno (regcache->tdesc, "vr0");
   for (i = 0; i < 32; i++)
     collect_register (regcache, base + i, &regset[i * 16]);
 
-  collect_register_by_name (regcache, "vscr", &regset[32 * 16 + 12]);
+  if (__BYTE_ORDER == __BIG_ENDIAN)
+    vscr_offset = 12;
+
+  /* Zero-pad the unused bytes in the fields for vscr and vrsave in
+     case they get displayed somewhere.  */
+  memset (&regset[32 * 16], 0, 16);
+  collect_register_by_name (regcache, "vscr",
+                           &regset[32 * 16 + vscr_offset]);
+
+  memset (&regset[33 * 16], 0, 16);
   collect_register_by_name (regcache, "vrsave", &regset[33 * 16]);
 }
 
@@ -500,12 +510,17 @@ ppc_store_vrregset (struct regcache *regcache, const void *buf)
 {
   int i, base;
   const char *regset = (const char *) buf;
+  int vscr_offset = 0;
 
   base = find_regno (regcache->tdesc, "vr0");
   for (i = 0; i < 32; i++)
     supply_register (regcache, base + i, &regset[i * 16]);
 
-  supply_register_by_name (regcache, "vscr", &regset[32 * 16 + 12]);
+  if (__BYTE_ORDER == __BIG_ENDIAN)
+    vscr_offset = 12;
+
+  supply_register_by_name (regcache, "vscr",
+                          &regset[32 * 16 + vscr_offset]);
   supply_register_by_name (regcache, "vrsave", &regset[33 * 16]);
 }
 
index 3ce4f0657e1b87c4139c2058cb0e55b07f73b203..495ccca8f18c975e78ff71fa48473e2a982808cf 100644 (file)
@@ -56,13 +56,7 @@ static const struct ppc_reg_offsets ppc32_fbsd_reg_offsets =
        /* Floating-point registers.  */
        /* .f0_offset = */     0,
        /* .fpscr_offset = */  256,
-       /* .fpscr_size = */    8,
-#ifdef NOTYET
-       /* AltiVec registers.  */
-       /* .vr0_offset = */    0,
-       /* .vscr_offset = */   512 + 12,
-       /* .vrsave_offset = */ 512
-#endif
+       /* .fpscr_size = */    8
   };
 
 /* 64-bit regset descriptions.  */
@@ -84,13 +78,7 @@ static const struct ppc_reg_offsets ppc64_fbsd_reg_offsets =
        /* Floating-point registers.  */
        /* .f0_offset = */     0,
        /* .fpscr_offset = */  256,
-       /* .fpscr_size = */    8,
-#ifdef NOYET
-       /* AltiVec registers.  */
-       /* .vr0_offset = */    0,
-       /* .vscr_offset = */   512 + 12,
-       /* .vrsave_offset = */ 528
-#endif
+       /* .fpscr_size = */    8
   };
 
 /* 32-bit general-purpose register set.  */
index a8f202dd33531da56eb3d3e27f7e2f8f27709dd6..e00831a248378603814938fd12686e79ff006a86 100644 (file)
@@ -24,6 +24,7 @@
 #include "gdbthread.h"
 #include "gdbcore.h"
 #include "regcache.h"
+#include "regset.h"
 #include "target.h"
 #include "linux-nat.h"
 #include <sys/types.h>
@@ -160,17 +161,18 @@ struct ppc_hw_breakpoint
    Even though this vrsave register is not included in the regset
    typedef, it is handled by the ptrace requests.
 
-   Note that GNU/Linux doesn't support little endian PPC hardware,
-   therefore the offset at which the real value of the VSCR register
-   is located will be always 12 bytes.
-
    The layout is like this (where x is the actual value of the vscr reg): */
 
 /* *INDENT-OFF* */
 /*
+Big-Endian:
    |.|.|.|.|.....|.|.|.|.||.|.|.|x||.|
    <------->     <-------><-------><->
      VR0           VR31     VSCR    VRSAVE
+Little-Endian:
+   |.|.|.|.|.....|.|.|.|.||X|.|.|.||.|
+   <------->     <-------><-------><->
+     VR0           VR31     VSCR    VRSAVE
 */
 /* *INDENT-ON* */
 
@@ -435,14 +437,13 @@ fetch_vsx_register (struct regcache *regcache, int tid, int regno)
    registers set mechanism, as opposed to the interface for all the
    other registers, that stores/fetches each register individually.  */
 static void
-fetch_altivec_register (struct regcache *regcache, int tid, int regno)
+fetch_altivec_registers (struct regcache *regcache, int tid,
+                        int regno)
 {
   int ret;
-  int offset = 0;
   gdb_vrregset_t regs;
   struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int vrregsize = register_size (gdbarch, tdep->ppc_vr0_regnum);
+  const struct regset *vrregset = ppc_linux_vrregset (gdbarch);
 
   ret = ptrace (PTRACE_GETVRREGS, tid, 0, &regs);
   if (ret < 0)
@@ -452,19 +453,11 @@ fetch_altivec_register (struct regcache *regcache, int tid, int regno)
           have_ptrace_getvrregs = 0;
           return;
         }
-      perror_with_name (_("Unable to fetch AltiVec register"));
+      perror_with_name (_("Unable to fetch AltiVec registers"));
     }
-  /* VSCR is fetched as a 16 bytes quantity, but it is really 4 bytes
-     long on the hardware.  We deal only with the lower 4 bytes of the
-     vector.  VRSAVE is at the end of the array in a 4 bytes slot, so
-     there is no need to define an offset for it.  */
-  if (regno == (tdep->ppc_vrsave_regnum - 1))
-    offset = vrregsize - register_size (gdbarch, tdep->ppc_vrsave_regnum);
-  
-  regcache_raw_supply (regcache, regno,
-                      regs + (regno
-                              - tdep->ppc_vr0_regnum) * vrregsize + offset);
+
+  vrregset->supply_regset (vrregset, regcache, regno, &regs,
+                          PPC_LINUX_SIZEOF_VRREGSET);
 }
 
 /* Fetch the top 32 bits of TID's general-purpose registers and the
@@ -559,7 +552,7 @@ fetch_register (struct regcache *regcache, int tid, int regno)
          register.  */
       if (have_ptrace_getvrregs)
        {
-         fetch_altivec_register (regcache, tid, regno);
+         fetch_altivec_registers (regcache, tid, regno);
          return;
        }
      /* If we have discovered that there is no ptrace support for
@@ -646,31 +639,6 @@ supply_vsxregset (struct regcache *regcache, gdb_vsxregset_t *vsxregsetp)
     }
 }
 
-static void
-supply_vrregset (struct regcache *regcache, gdb_vrregset_t *vrregsetp)
-{
-  int i;
-  struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int num_of_vrregs = tdep->ppc_vrsave_regnum - tdep->ppc_vr0_regnum + 1;
-  int vrregsize = register_size (gdbarch, tdep->ppc_vr0_regnum);
-  int offset = vrregsize - register_size (gdbarch, tdep->ppc_vrsave_regnum);
-
-  for (i = 0; i < num_of_vrregs; i++)
-    {
-      /* The last 2 registers of this set are only 32 bit long, not
-         128.  However an offset is necessary only for VSCR because it
-         occupies a whole vector, while VRSAVE occupies a full 4 bytes
-         slot.  */
-      if (i == (num_of_vrregs - 2))
-        regcache_raw_supply (regcache, tdep->ppc_vr0_regnum + i,
-                            *vrregsetp + i * vrregsize + offset);
-      else
-        regcache_raw_supply (regcache, tdep->ppc_vr0_regnum + i,
-                            *vrregsetp + i * vrregsize);
-    }
-}
-
 static void
 fetch_vsx_registers (struct regcache *regcache, int tid)
 {
@@ -690,25 +658,6 @@ fetch_vsx_registers (struct regcache *regcache, int tid)
   supply_vsxregset (regcache, &regs);
 }
 
-static void
-fetch_altivec_registers (struct regcache *regcache, int tid)
-{
-  int ret;
-  gdb_vrregset_t regs;
-  
-  ret = ptrace (PTRACE_GETVRREGS, tid, 0, &regs);
-  if (ret < 0)
-    {
-      if (errno == EIO)
-       {
-          have_ptrace_getvrregs = 0;
-         return;
-       }
-      perror_with_name (_("Unable to fetch AltiVec registers"));
-    }
-  supply_vrregset (regcache, &regs);
-}
-
 /* This function actually issues the request to ptrace, telling
    it to get all general-purpose registers and put them into the
    specified regset.
@@ -847,7 +796,7 @@ fetch_ppc_registers (struct regcache *regcache, int tid)
     fetch_register (regcache, tid, tdep->ppc_fpscr_regnum);
   if (have_ptrace_getvrregs)
     if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
-      fetch_altivec_registers (regcache, tid);
+      fetch_altivec_registers (regcache, tid, -1);
   if (have_ptrace_getsetvsxregs)
     if (tdep->ppc_vsr0_upper_regnum != -1)
       fetch_vsx_registers (regcache, tid);
@@ -898,16 +847,14 @@ store_vsx_register (const struct regcache *regcache, int tid, int regno)
     perror_with_name (_("Unable to store VSX register"));
 }
 
-/* Store one register.  */
 static void
-store_altivec_register (const struct regcache *regcache, int tid, int regno)
+store_altivec_registers (const struct regcache *regcache, int tid,
+                        int regno)
 {
   int ret;
-  int offset = 0;
   gdb_vrregset_t regs;
   struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int vrregsize = register_size (gdbarch, tdep->ppc_vr0_regnum);
+  const struct regset *vrregset = ppc_linux_vrregset (gdbarch);
 
   ret = ptrace (PTRACE_GETVRREGS, tid, 0, &regs);
   if (ret < 0)
@@ -917,21 +864,15 @@ store_altivec_register (const struct regcache *regcache, int tid, int regno)
           have_ptrace_getvrregs = 0;
           return;
         }
-      perror_with_name (_("Unable to fetch AltiVec register"));
+      perror_with_name (_("Unable to fetch AltiVec registers"));
     }
 
-  /* VSCR is fetched as a 16 bytes quantity, but it is really 4 bytes
-     long on the hardware.  */
-  if (regno == (tdep->ppc_vrsave_regnum - 1))
-    offset = vrregsize - register_size (gdbarch, tdep->ppc_vrsave_regnum);
-
-  regcache_raw_collect (regcache, regno,
-                       regs + (regno
-                               - tdep->ppc_vr0_regnum) * vrregsize + offset);
+  vrregset->collect_regset (vrregset, regcache, regno, &regs,
+                           PPC_LINUX_SIZEOF_VRREGSET);
 
   ret = ptrace (PTRACE_SETVRREGS, tid, 0, &regs);
   if (ret < 0)
-    perror_with_name (_("Unable to store AltiVec register"));
+    perror_with_name (_("Unable to store AltiVec registers"));
 }
 
 /* Assuming TID referrs to an SPE process, set the top halves of TID's
@@ -1034,7 +975,7 @@ store_register (const struct regcache *regcache, int tid, int regno)
 
   if (altivec_register_p (gdbarch, regno))
     {
-      store_altivec_register (regcache, tid, regno);
+      store_altivec_registers (regcache, tid, regno);
       return;
     }
   if (vsx_register_p (gdbarch, regno))
@@ -1110,29 +1051,6 @@ fill_vsxregset (const struct regcache *regcache, gdb_vsxregset_t *vsxregsetp)
                          *vsxregsetp + i * vsxregsize);
 }
 
-static void
-fill_vrregset (const struct regcache *regcache, gdb_vrregset_t *vrregsetp)
-{
-  int i;
-  struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int num_of_vrregs = tdep->ppc_vrsave_regnum - tdep->ppc_vr0_regnum + 1;
-  int vrregsize = register_size (gdbarch, tdep->ppc_vr0_regnum);
-  int offset = vrregsize - register_size (gdbarch, tdep->ppc_vrsave_regnum);
-
-  for (i = 0; i < num_of_vrregs; i++)
-    {
-      /* The last 2 registers of this set are only 32 bit long, not
-         128, but only VSCR is fetched as a 16 bytes quantity.  */
-      if (i == (num_of_vrregs - 2))
-        regcache_raw_collect (regcache, tdep->ppc_vr0_regnum + i,
-                             *vrregsetp + i * vrregsize + offset);
-      else
-        regcache_raw_collect (regcache, tdep->ppc_vr0_regnum + i,
-                             *vrregsetp + i * vrregsize);
-    }
-}
-
 static void
 store_vsx_registers (const struct regcache *regcache, int tid)
 {
@@ -1156,29 +1074,6 @@ store_vsx_registers (const struct regcache *regcache, int tid)
     perror_with_name (_("Couldn't write VSX registers"));
 }
 
-static void
-store_altivec_registers (const struct regcache *regcache, int tid)
-{
-  int ret;
-  gdb_vrregset_t regs;
-
-  ret = ptrace (PTRACE_GETVRREGS, tid, 0, &regs);
-  if (ret < 0)
-    {
-      if (errno == EIO)
-        {
-          have_ptrace_getvrregs = 0;
-          return;
-        }
-      perror_with_name (_("Couldn't get AltiVec registers"));
-    }
-
-  fill_vrregset (regcache, &regs);
-  
-  if (ptrace (PTRACE_SETVRREGS, tid, 0, &regs) < 0)
-    perror_with_name (_("Couldn't write AltiVec registers"));
-}
-
 /* This function actually issues the request to ptrace, telling
    it to store all general-purpose registers present in the specified
    regset.
@@ -1337,7 +1232,7 @@ store_ppc_registers (const struct regcache *regcache, int tid)
     }
   if (have_ptrace_getvrregs)
     if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
-      store_altivec_registers (regcache, tid);
+      store_altivec_registers (regcache, tid, -1);
   if (have_ptrace_getsetvsxregs)
     if (tdep->ppc_vsr0_upper_regnum != -1)
       store_vsx_registers (regcache, tid);
index 344069d752e3e241299505c3beb016ded11135c4..7362c4bbe19b8a3d16c7d1620e3e2b11fe6c21ac 100644 (file)
@@ -444,6 +444,24 @@ ppc_linux_collect_gregset (const struct regset *regset,
     }
 }
 
+static void
+ppc_linux_collect_vrregset (const struct regset *regset,
+                           const struct regcache *regcache,
+                           int regnum, void *buf, size_t len)
+{
+  gdb_byte *vrregs = (gdb_byte *) buf;
+
+  /* Zero-pad the unused bytes in the fields for vscr and vrsave
+     in case they get displayed somewhere (e.g. in core files).  */
+  if (regnum == PPC_VSCR_REGNUM || regnum == -1)
+    memset (&vrregs[32 * 16], 0, 16);
+
+  if (regnum == PPC_VRSAVE_REGNUM || regnum == -1)
+    memset (&vrregs[33 * 16], 0, 16);
+
+  regcache_collect_regset (regset, regcache, regnum, buf, len);
+}
+
 /* Regset descriptions.  */
 static const struct ppc_reg_offsets ppc32_linux_reg_offsets =
   {
@@ -462,12 +480,7 @@ static const struct ppc_reg_offsets ppc32_linux_reg_offsets =
     /* Floating-point registers.  */
     /* .f0_offset = */ 0,
     /* .fpscr_offset = */ 256,
-    /* .fpscr_size = */ 8,
-
-    /* AltiVec registers.  */
-    /* .vr0_offset = */ 0,
-    /* .vscr_offset = */ 512 + 12,
-    /* .vrsave_offset = */ 528
+    /* .fpscr_size = */ 8
   };
 
 static const struct ppc_reg_offsets ppc64_linux_reg_offsets =
@@ -487,12 +500,7 @@ static const struct ppc_reg_offsets ppc64_linux_reg_offsets =
     /* Floating-point registers.  */
     /* .f0_offset = */ 0,
     /* .fpscr_offset = */ 256,
-    /* .fpscr_size = */ 8,
-
-    /* AltiVec registers.  */
-    /* .vr0_offset = */ 0,
-    /* .vscr_offset = */ 512 + 12,
-    /* .vrsave_offset = */ 528
+    /* .fpscr_size = */ 8
   };
 
 static const struct regset ppc32_linux_gregset = {
@@ -513,10 +521,36 @@ static const struct regset ppc32_linux_fpregset = {
   ppc_collect_fpregset
 };
 
-static const struct regset ppc32_linux_vrregset = {
-  &ppc32_linux_reg_offsets,
-  ppc_supply_vrregset,
-  ppc_collect_vrregset
+static const struct regcache_map_entry ppc32_le_linux_vrregmap[] =
+  {
+      { 32, PPC_VR0_REGNUM, 16 },
+      { 1, PPC_VSCR_REGNUM, 4 },
+      { 1, REGCACHE_MAP_SKIP, 12 },
+      { 1, PPC_VRSAVE_REGNUM, 4 },
+      { 1, REGCACHE_MAP_SKIP, 12 },
+      { 0 }
+  };
+
+static const struct regcache_map_entry ppc32_be_linux_vrregmap[] =
+  {
+      { 32, PPC_VR0_REGNUM, 16 },
+      { 1, REGCACHE_MAP_SKIP, 12},
+      { 1, PPC_VSCR_REGNUM, 4 },
+      { 1, PPC_VRSAVE_REGNUM, 4 },
+      { 1, REGCACHE_MAP_SKIP, 12 },
+      { 0 }
+  };
+
+static const struct regset ppc32_le_linux_vrregset = {
+  ppc32_le_linux_vrregmap,
+  regcache_supply_regset,
+  ppc_linux_collect_vrregset
+};
+
+static const struct regset ppc32_be_linux_vrregset = {
+  ppc32_be_linux_vrregmap,
+  regcache_supply_regset,
+  ppc_linux_collect_vrregset
 };
 
 static const struct regset ppc32_linux_vsxregset = {
@@ -537,6 +571,15 @@ ppc_linux_fpregset (void)
   return &ppc32_linux_fpregset;
 }
 
+const struct regset *
+ppc_linux_vrregset (struct gdbarch *gdbarch)
+{
+  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+    return &ppc32_be_linux_vrregset;
+  else
+    return &ppc32_le_linux_vrregset;
+}
+
 /* Iterate over supported core file register note sections. */
 
 static void
@@ -557,8 +600,11 @@ ppc_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
   cb (".reg2", 264, &ppc32_linux_fpregset, NULL, cb_data);
 
   if (have_altivec)
-    cb (".reg-ppc-vmx", PPC_LINUX_SIZEOF_VRREGSET, &ppc32_linux_vrregset,
-       "ppc Altivec", cb_data);
+    {
+      const struct regset *vrregset = ppc_linux_vrregset (gdbarch);
+      cb (".reg-ppc-vmx", PPC_LINUX_SIZEOF_VRREGSET, vrregset,
+         "ppc Altivec", cb_data);
+    }
 
   if (have_vsx)
     cb (".reg-ppc-vsx", PPC_LINUX_SIZEOF_VSXREGSET,
index 5e7c4be16ba5a462cb76cea3e3fc4e0a497304de..a8715bd41840bcc0b12d2bffae40d294b62db9f4 100644 (file)
@@ -28,6 +28,9 @@ struct regset;
 const struct regset *ppc_linux_gregset (int);
 const struct regset *ppc_linux_fpregset (void);
 
+/* Get the vector regset that matches the target byte order.  */
+const struct regset *ppc_linux_vrregset (struct gdbarch *gdbarch);
+
 /* Extra register number constants.  The Linux kernel stores a
    "trap" code and the original value of r3 into special "registers";
    these need to be saved and restored when performing an inferior
index 129ebc03426893cd936a370c3033974b82689159..c86aeb8a2957c2800d049bad97e438296a2f0438 100644 (file)
@@ -215,9 +215,5 @@ _initialize_ppcnbsd_tdep (void)
       ppcnbsd_reg_offsets.fpscr_offset = 256;
       ppcnbsd_reg_offsets.fpscr_size = 4;
 
-      /* AltiVec registers.  */
-      ppcnbsd_reg_offsets.vr0_offset = 0;
-      ppcnbsd_reg_offsets.vrsave_offset = 512;
-      ppcnbsd_reg_offsets.vscr_offset = 524;
     }
 }
index 781b09c7fe4a87283eee58c21a17819ed5aa00c3..4428dabd7b935edf01e82f8dcddc1d98928790e9 100644 (file)
@@ -213,11 +213,6 @@ _initialize_ppcobsd_nat (void)
   ppcobsd_fpreg_offsets.fpscr_size = 4;
 #endif
 
-  /* AltiVec registers.  */
-  ppcobsd_reg_offsets.vr0_offset = offsetof (struct vreg, vreg);
-  ppcobsd_reg_offsets.vscr_offset = offsetof (struct vreg, vscr);
-  ppcobsd_reg_offsets.vrsave_offset = offsetof (struct vreg, vrsave);
-
   /* Support debugging kernel virtual memory images.  */
   bsd_kvm_add_target (ppcobsd_supply_pcb);
 }
index 986ab041339ea004fb19e64282e23a499742ec47..838783111a251a6ab599c9af75fe8e4556f445a5 100644 (file)
@@ -289,10 +289,6 @@ _initialize_ppcobsd_tdep (void)
       ppcobsd_reg_offsets.f0_offset = 128;
       ppcobsd_reg_offsets.fpscr_offset = -1;
 
-      /* AltiVec registers.  */
-      ppcobsd_reg_offsets.vr0_offset = 0;
-      ppcobsd_reg_offsets.vscr_offset = 512;
-      ppcobsd_reg_offsets.vrsave_offset = 520;
     }
 
   if (ppcobsd_fpreg_offsets.fpscr_offset == 0)
index 156f82d39b447543989c9042c9443979ba477aa7..c3571cbd51bdcfe4a234f4f524d4a535f6b4dc28 100644 (file)
@@ -100,11 +100,6 @@ struct ppc_reg_offsets
   int f0_offset;
   int fpscr_offset;
   int fpscr_size;
-
-  /* AltiVec registers.  */
-  int vr0_offset;
-  int vscr_offset;
-  int vrsave_offset;
 };
 
 extern void ppc_supply_reg (struct regcache *regcache, int regnum,
index e3e086c2102ccaa91551400ae5d38fa9545d45e8..ecf6191df017c361c4cca5795b46182d62fe6049 100644 (file)
@@ -70,12 +70,7 @@ static struct ppc_reg_offsets rs6000_aix32_reg_offsets =
   /* Floating-point registers.  */
   336, /* f0_offset */
   56, /* fpscr_offset */
-  4,  /* fpscr_size */
-
-  /* AltiVec registers.  */
-  -1, /* vr0_offset */
-  -1, /* vscr_offset */
-  -1 /* vrsave_offset */
+  4  /* fpscr_size */
 };
 
 static struct ppc_reg_offsets rs6000_aix64_reg_offsets =
@@ -95,12 +90,7 @@ static struct ppc_reg_offsets rs6000_aix64_reg_offsets =
   /* Floating-point registers.  */
   312, /* f0_offset */
   296, /* fpscr_offset */
-  4,  /* fpscr_size */
-
-  /* AltiVec registers.  */
-  -1, /* vr0_offset */
-  -1, /* vscr_offset */
-  -1 /* vrsave_offset */
+  4  /* fpscr_size */
 };
 
 
index c5b49c5f465d7e88e82d9e274246ae1b23d46dda..4ef6f9e9805bcd97cf2b192d1f88e4c3610e6151 100644 (file)
@@ -485,24 +485,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.  */
@@ -622,50 +604,6 @@ ppc_supply_vsxregset (const struct regset *regset, struct regcache *regcache,
     ppc_supply_reg (regcache, regnum, (const gdb_byte *) vsxregs, 0, 8);
 }
 
-/* Supply register REGNUM in the Altivec register set REGSET
-   from the buffer specified by VRREGS and LEN to register cache
-   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
-
-void
-ppc_supply_vrregset (const struct regset *regset, struct regcache *regcache,
-                    int regnum, const void *vrregs, size_t len)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep;
-  const struct ppc_reg_offsets *offsets;
-  size_t offset;
-
-  if (!ppc_altivec_support_p (gdbarch))
-    return;
-
-  tdep = gdbarch_tdep (gdbarch);
-  offsets = (const struct ppc_reg_offsets *) regset->regmap;
-  if (regnum == -1)
-    {
-      int i;
-
-      for (i = tdep->ppc_vr0_regnum, offset = offsets->vr0_offset;
-          i < tdep->ppc_vr0_regnum + ppc_num_vrs;
-          i++, offset += 16)
-        ppc_supply_reg (regcache, i, (const gdb_byte *) vrregs, offset, 16);
-
-      ppc_supply_reg (regcache, (tdep->ppc_vrsave_regnum - 1),
-                     (const gdb_byte *) vrregs, offsets->vscr_offset, 4);
-
-      ppc_supply_reg (regcache, tdep->ppc_vrsave_regnum,
-                     (const gdb_byte *) vrregs, offsets->vrsave_offset, 4);
-      return;
-    }
-
-  offset = ppc_vrreg_offset (tdep, offsets, regnum);
-  if (regnum != tdep->ppc_vrsave_regnum
-      && regnum != tdep->ppc_vrsave_regnum - 1)
-    ppc_supply_reg (regcache, regnum, (const gdb_byte *) vrregs, offset, 16);
-  else
-    ppc_supply_reg (regcache, regnum,
-                   (const gdb_byte *) vrregs, offset, 4);
-}
-
 /* Collect register REGNUM in the general-purpose register set
    REGSET from register cache REGCACHE into the buffer specified by
    GREGS and LEN.  If REGNUM is -1, do this for all registers in
@@ -790,54 +728,6 @@ ppc_collect_vsxregset (const struct regset *regset,
     ppc_collect_reg (regcache, regnum, (gdb_byte *) vsxregs, 0, 8);
 }
 
-
-/* Collect register REGNUM in the Altivec register set
-   REGSET from register cache REGCACHE into the buffer specified by
-   VRREGS and LEN.  If REGNUM is -1, do this for all registers in
-   REGSET.  */
-
-void
-ppc_collect_vrregset (const struct regset *regset,
-                     const struct regcache *regcache,
-                     int regnum, void *vrregs, size_t len)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep;
-  const struct ppc_reg_offsets *offsets;
-  size_t offset;
-
-  if (!ppc_altivec_support_p (gdbarch))
-    return;
-
-  tdep = gdbarch_tdep (gdbarch);
-  offsets = (const struct ppc_reg_offsets *) regset->regmap;
-  if (regnum == -1)
-    {
-      int i;
-
-      for (i = tdep->ppc_vr0_regnum, offset = offsets->vr0_offset;
-          i < tdep->ppc_vr0_regnum + ppc_num_vrs;
-          i++, offset += 16)
-       ppc_collect_reg (regcache, i, (gdb_byte *) vrregs, offset, 16);
-
-      ppc_collect_reg (regcache, (tdep->ppc_vrsave_regnum - 1),
-                      (gdb_byte *) vrregs, offsets->vscr_offset, 4);
-
-      ppc_collect_reg (regcache, tdep->ppc_vrsave_regnum,
-                      (gdb_byte *) vrregs, offsets->vrsave_offset, 4);
-      return;
-    }
-
-  offset = ppc_vrreg_offset (tdep, offsets, regnum);
-  if (regnum != tdep->ppc_vrsave_regnum
-      && regnum != tdep->ppc_vrsave_regnum - 1)
-    ppc_collect_reg (regcache, regnum, (gdb_byte *) vrregs, offset, 16);
-  else
-    ppc_collect_reg (regcache, regnum,
-                   (gdb_byte *) vrregs, offset, 4);
-}
-\f
-
 static int
 insn_changes_sp_or_jumps (unsigned long insn)
 {