Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH-ppc 1/5] Add basic support for new VSX register set
@ 2008-07-25 20:16 Luis Machado
       [not found] ` <1217646694.26214.3.camel@localhost.localdomain>
  0 siblings, 1 reply; 8+ messages in thread
From: Luis Machado @ 2008-07-25 20:16 UTC (permalink / raw)
  To: gdb-patches

This patch adds basic functionality for VSX registers as follows:

* Adds pseudo-registers for VSX and Extended FPR's.
* Read/Write functions for pseudo-registers.
* Read/Write functions for VSxH registers.
* New ptrace definitions for GET_VSRREGS and SET_VSRREGS and calls to
fetch/store registers, in synch with the kernel.
* Defines numbering scheme for pseudo-registers. 

---
2008-07-25  Luis Machado  <luisgpm@br.ibm.com>

	* rs6000-tdep: Include "features/rs6000/powerpc-vsx32.c".
	Include "features/rs6000/powerpc-vsx64.c".
	(ppc_supply_vsxregset): New function.
	(ppc_collect_vsxregset): New function.
	(IS_VSX_PSEUDOREG): New macro.
	(IS_EFP_PSEUDOREG): New macro.
	(vsx_register_p): New function.
	(ppc_vsx_support_p): New function.
	(rs6000_builtin_type_vec128): New function.
	(rs6000_register_name): Hide upper halves of vs0~vs31.  Return
	correct names for VSX registers and EFPR registers.
	(rs6000_pseudo_register_type): Return correct types for VSX
	and EFPR registers.
	(rs6000_pseudo_register_reggroup_p): Return correct group for
	VSX and EFPR registers.
	(ppc_pseudo_register_read): Rename to dfp_pseudo_register_read.
	(ppc_pseudo_register_write): Rename to dfp_pseudo_register_write.
	(vsx_pseudo_register_read): New function.
	(vsx_pseudo_register_write): New function.
	(efpr_pseudo_register_read): New function.
	(efpr_pseudo_register_write): New function.
	(rs6000_pseudo_register_read): Call new VSX and EFPR read functions.
	(rs6000_pseudo_register_write): Call new VSX and EFPR write functions.
	(rs6000_gdbarch_init): Declare have_vsx.
	Initialize new upper half VSX registers.
	Initialize VSX-related and EFPR-related pseudo-registers variables.
	Adjust the number of pseudo registers accordingly.
	
	* ppc-linux-nat.c: Define PTRACE_GETVSXREGS, PTRACE_SETVSXREGS
	and SIZEOF_VSRREGS.
	(gdb_vsxregset_t): New type.
	(have_ptrace_getsetvsxregs): New variable.
	(fetch_vsx_register): New function.	
	(fetch_register): Handle VSX registers.
	(fetch_vsx_registers): New function.
	(fetch_ppc_registers): Handle VSX registers.
	(store_ppc_registers): Handle VSX registers.
	(store_vsx_register): New function.	
	(store_register): Handle VSX registers.
	(store_vsx_registers): New function.
	(ppc_linux_read_description): Handle VSX-enabled inferiors.
	(gdb_vsxregset_t): New type.
	(supply_vsxregset): New function.
	(fill_vsxregset): New function.

	* ppc-tdep.h (vsx_register_p): New prototype.
	(vsx_support_p): New prototype.
	(ppc_vsr0_regnum): New variable.
	(ppc_vsr0_upper_regnum): Likewise.
	(ppc_efpr0_regnum): Likewise.
	(ppc_builtin_type_vec128): New type.
	(ppc_num_vsrs): New constant.
	(ppc_num_efprs): Likewise.
	Define POWERPC_VEC_VSX PPC_VSR0_UPPER_REGNUM and PPC_VSR31_UPPER_REGNUM.
	(ppc_supply_vsxregset): New prototype.
	(ppc_collect_vsxregset): New prototype.

	* ppc-linux-tdep.c: Include "features/rs6000/powerpc-vsx32l.c"
	Include "features/rs6000/powerpc-vsx64l.c".
	(_initialize_ppc_linux_tdep): Initialize VSX-enabled targets.

	* ppc-linux-tdep.h: Declare *tdesc_powerpc_vsx32l
	Declare tdesc_powerpc_vsx64l

Index: gdb/rs6000-tdep.c
===================================================================
--- gdb.orig/rs6000-tdep.c	2008-07-15 11:32:06.000000000 -0700
+++ gdb/rs6000-tdep.c	2008-07-25 09:47:33.000000000 -0700
@@ -63,6 +63,7 @@
 
 #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-505.c"
@@ -72,6 +73,7 @@
 #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"
@@ -88,6 +90,16 @@
     && (regnum) >= (tdep)->ppc_dl0_regnum \
     && (regnum) < (tdep)->ppc_dl0_regnum + 16)
 
+/* 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_fprs)
+
 /* The list of available "set powerpc ..." and "show powerpc ..."
    commands.  */
 static struct cmd_list_element *setpowerpccmdlist = NULL;
@@ -133,6 +145,18 @@
   };
 

+/* 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
 altivec_register_p (struct gdbarch *gdbarch, int regno)
@@ -188,6 +212,16 @@
 }
 
 /* Return non-zero if the architecture described by GDBARCH has
+   VSX registers (vsr0 --- vsr63).  */
+int
+ppc_vsx_support_p (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  return tdep->ppc_vsr0_regnum >= 0;
+}
+
+/* Return non-zero if the architecture described by GDBARCH has
    Altivec registers (vr0 --- vr31, vrsave and vscr).  */
 int
 ppc_altivec_support_p (struct gdbarch *gdbarch)
@@ -539,6 +573,38 @@
 		  regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8);
 }
 
+/* Supply register REGNUM in the VSX register set REGSET
+   from the buffer specified by VSRREGS and LEN to register cache
+   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
+
+void
+ppc_supply_vsxregset (const struct regset *regset, struct regcache *regcache,
+		     int regnum, const void *vsxregs, size_t len)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep;
+  size_t offset = 0;
+
+  if (!ppc_vsx_support_p (gdbarch))
+    return;
+
+  tdep = gdbarch_tdep (gdbarch);
+
+  if (regnum == -1)
+    {
+      int i;
+
+      for (i = tdep->ppc_vsr0_upper_regnum;
+	   i < tdep->ppc_vsr0_upper_regnum + 32;
+	   i++)
+	ppc_supply_reg (regcache, i, vsxregs, offset, 8);
+
+      return;
+    }
+  else
+    ppc_supply_reg (regcache, regnum, vsxregs, offset, 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.  */
@@ -669,6 +735,41 @@
 		   regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8);
 }
 
+/* Collect register REGNUM in the VSX register set
+   REGSET from register cache REGCACHE into the buffer specified by
+   VSRREGS and LEN.  If REGNUM is -1, do this for all registers in
+   REGSET.  */
+
+void
+ppc_collect_vsxregset (const struct regset *regset,
+		      const struct regcache *regcache,
+		      int regnum, void *vsxregs, size_t len)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep;
+  size_t offset = 0;
+
+  if (!ppc_vsx_support_p (gdbarch))
+    return;
+
+  tdep = gdbarch_tdep (gdbarch);
+
+  if (regnum == -1)
+    {
+      int i;
+
+      for (i = tdep->ppc_vsr0_upper_regnum;
+	   i < tdep->ppc_vsr0_upper_regnum + 32;
+	   i++)
+	ppc_collect_reg (regcache, i, vsxregs, offset, 8);
+
+      return;
+    }
+  else
+    ppc_collect_reg (regcache, regnum, vsxregs, offset, 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
@@ -1915,6 +2016,47 @@
   return tdep->ppc_builtin_type_vec64;
 }
 
+/* Vector 128 type.  */
+
+static struct type *
+rs6000_builtin_type_vec128 (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (!tdep->ppc_builtin_type_vec128)
+    {
+      /* The type we're building is this
+
+	 type = union __ppc_builtin_type_vec128 {
+	     uint128_t uint128;
+	     float v4_float[4];
+	     int32_t v4_int32[4];
+	     int16_t v8_int16[8];
+	     int8_t v16_int8[16];
+	 }
+      */
+
+      struct type *t;
+
+      t = init_composite_type ("__ppc_builtin_type_vec128", TYPE_CODE_UNION);
+      append_composite_type_field (t, "uint128", builtin_type_uint128);
+      append_composite_type_field (t, "v4_float",
+				   init_vector_type (builtin_type_float, 4));
+      append_composite_type_field (t, "v4_int32",
+				   init_vector_type (builtin_type_int32, 4));
+      append_composite_type_field (t, "v8_int16",
+				   init_vector_type (builtin_type_int16, 8));
+      append_composite_type_field (t, "v16_int8",
+				   init_vector_type (builtin_type_int8, 16));
+
+      TYPE_FLAGS (t) |= TYPE_FLAG_VECTOR;
+      TYPE_NAME (t) = "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
    is an anonymous register.  */
 
@@ -1931,6 +2073,12 @@
       && 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 "";
+
   /* Check if the SPE pseudo registers are available.  */
   if (IS_SPE_PSEUDOREG (tdep, regno))
     {
@@ -1955,6 +2103,36 @@
       return dfp128_regnames[regno - tdep->ppc_dl0_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];
+    }
+
   return tdesc_register_name (gdbarch, regno);
 }
 
@@ -1968,14 +2146,22 @@
 
   /* These are the only pseudo-registers we support.  */
   gdb_assert (IS_SPE_PSEUDOREG (tdep, regnum)
-	      || IS_DFP_PSEUDOREG (tdep, regnum));
+	      || IS_DFP_PSEUDOREG (tdep, regnum)
+	      || IS_VSX_PSEUDOREG (tdep, regnum)
+	      || IS_EFP_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))
+    /* PPC decimal128 pseudo-registers.  */
     return builtin_type (gdbarch)->builtin_declong;
+  else if (IS_VSX_PSEUDOREG (tdep, regnum))
+    /* POWER7 VSX pseudo-registers.  */
+    return rs6000_builtin_type_vec128 (gdbarch);
+  else
+    /* POWER7 Extended FP pseudo-registers.  */
+    return builtin_type_ieee_double;
 }
 
 /* Is REGNUM a member of REGGROUP?  */
@@ -1987,13 +2173,15 @@
 
   /* These are the only pseudo-registers we support.  */
   gdb_assert (IS_SPE_PSEUDOREG (tdep, regnum)
-	      || IS_DFP_PSEUDOREG (tdep, regnum));
+	      || IS_DFP_PSEUDOREG (tdep, regnum)
+	      || IS_VSX_PSEUDOREG (tdep, regnum)
+	      || IS_EFP_PSEUDOREG (tdep, regnum));
 
-  /* These are the e500 pseudo-registers.  */
-  if (IS_SPE_PSEUDOREG (tdep, regnum))
+  /* These are the e500 pseudo-registers or the POWER7 VSX registers.  */
+  if (IS_SPE_PSEUDOREG (tdep, regnum) || IS_VSX_PSEUDOREG (tdep, regnum))
     return group == all_reggroup || group == vector_reggroup;
   else
-    /* Could only be the ppc decimal128 pseudo-registers.  */
+    /* PPC decimal128 or Extended FP pseudo-registers.  */
     return group == all_reggroup || group == float_reggroup;
 }
 
@@ -2107,10 +2295,9 @@
 			 regcache, reg_nr, (gdb_byte *) buffer);
 }
 
-/* Read method for PPC pseudo-registers. Currently this is handling the
-   16 decimal128 registers that map into 16 pairs of FP registers.  */
+/* Read method for DFP pseudo-registers.  */
 static void
-ppc_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+dfp_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 			   int reg_nr, gdb_byte *buffer)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
@@ -2133,10 +2320,9 @@
     }
 }
 
-/* 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);
@@ -2160,6 +2346,92 @@
     }
 }
 
+/* Read method for POWER7 VSX pseudo-registers.  */
+static void
+vsx_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+			   int reg_nr, gdb_byte *buffer)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int reg_index = reg_nr - tdep->ppc_vsr0_regnum;
+
+  /* Read the portion that overlaps the VMX registers.  */
+  if (reg_index > 31)
+    regcache_raw_read (regcache, tdep->ppc_vr0_regnum +
+			reg_index - 32, buffer);
+  else
+    /* Read the portion that overlaps the FPR registers.  */
+    if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+      {
+	regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+			reg_index, buffer);
+	regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
+			reg_index, buffer + 8);
+      }
+    else
+      {
+	regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+			reg_index, buffer + 8);
+	regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
+			reg_index, buffer);
+      }
+}
+
+/* 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 = reg_nr - tdep->ppc_vsr0_regnum;
+
+  /* Write the portion that overlaps the VMX registers.  */
+  if (reg_index > 31)
+    regcache_raw_write (regcache, tdep->ppc_vr0_regnum +
+			reg_index - 32, buffer);
+  else
+    /* Write the portion that overlaps the FPR registers.  */
+    if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+      {
+	regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
+			reg_index, buffer);
+	regcache_raw_write (regcache, tdep->ppc_vsr0_upper_regnum +
+			reg_index, buffer + 8);
+      }
+    else
+      {
+	regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
+			reg_index, buffer + 8);
+	regcache_raw_write (regcache, tdep->ppc_vsr0_upper_regnum +
+			reg_index, buffer);
+      }
+}
+
+/* Read method for POWER7 Extended FP pseudo-registers.  */
+static void
+efpr_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+			   int reg_nr, gdb_byte *buffer)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int reg_index = reg_nr - tdep->ppc_efpr0_regnum;
+
+  /* Read the portion that overlaps the VMX registers.  */
+  regcache_raw_read (regcache, tdep->ppc_vr0_regnum +
+		     reg_index, buffer);
+}
+
+/* Write method for POWER7 Extended FP pseudo-registers.  */
+static void
+efpr_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+			    int reg_nr, const gdb_byte *buffer)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int reg_index = reg_nr - tdep->ppc_efpr0_regnum;
+
+  /* Write the portion that overlaps the VMX registers.  */
+  regcache_raw_write (regcache, tdep->ppc_vr0_regnum +
+		      reg_index, buffer);
+}
+
 static void
 rs6000_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 			     int reg_nr, gdb_byte *buffer)
@@ -2172,7 +2444,11 @@
   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);
+    dfp_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+  else if (IS_VSX_PSEUDOREG (tdep, reg_nr))
+    vsx_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+  else if (IS_EFP_PSEUDOREG (tdep, reg_nr))
+    efpr_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
   else
     internal_error (__FILE__, __LINE__,
 		    _("rs6000_pseudo_register_read: "
@@ -2193,7 +2469,11 @@
   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);
+    dfp_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+  else if (IS_VSX_PSEUDOREG (tdep, reg_nr))
+    vsx_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+  else if (IS_EFP_PSEUDOREG (tdep, reg_nr))
+    efpr_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
   else
     internal_error (__FILE__, __LINE__,
 		    _("rs6000_pseudo_register_write: "
@@ -2776,7 +3056,8 @@
   enum auto_boolean soft_float_flag = powerpc_soft_float_global;
   int soft_float;
   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;
+  int have_fpu = 1, have_spe = 0, have_mq = 0, have_altivec = 0, have_dfp = 0,
+      have_vsx = 0;
   int tdesc_wordsize = -1;
   const struct target_desc *tdesc = info.target_desc;
   struct tdesc_arch_data *tdesc_data = NULL;
@@ -2975,6 +3256,38 @@
       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", "vs32h"
+	  };
+
+	  valid_p = 1;
+
+	  for (i = 0; i < ppc_num_gprs; i++)
+	    valid_p &= tdesc_numbered_register (feature, tdesc_data,
+						PPC_VSR0_UPPER_REGNUM + i,
+						vsx_regs[i]);
+	  if (!valid_p)
+	    {
+	      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
@@ -3158,6 +3471,7 @@
 
   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;
@@ -3186,7 +3500,7 @@
   else
     tdep->lr_frame_offset = 4;
 
-  if (have_spe || have_dfp)
+  if (have_spe || have_dfp || have_vsx)
     {
       set_gdbarch_pseudo_register_read (gdbarch, rs6000_pseudo_register_read);
       set_gdbarch_pseudo_register_write (gdbarch, rs6000_pseudo_register_write);
@@ -3206,6 +3520,9 @@
     num_pseudoregs += 32;
   if (have_dfp)
     num_pseudoregs += 16;
+  if (have_vsx)
+    /* Include both VSX and Extended FP registers.  */
+    num_pseudoregs += 96;
 
   set_gdbarch_num_pseudo_regs (gdbarch, num_pseudoregs);
 
@@ -3307,9 +3624,26 @@
   /* Set the register number for _Decimal128 pseudo-registers.  */
   tdep->ppc_dl0_regnum = have_dfp? gdbarch_num_regs (gdbarch) : -1;
 
+  /* Set the register number for VSX pseudo-registers.  */
+  tdep->ppc_vsr0_regnum = have_vsx? gdbarch_num_regs (gdbarch) : -1;
+  tdep->ppc_efpr0_regnum = have_vsx? gdbarch_num_regs (gdbarch) : -1;
+
   if (have_dfp && have_spe)
-    /* Put the _Decimal128 pseudo-registers after the SPE registers.  */
-    tdep->ppc_dl0_regnum += 32;
+    {
+      /* Put the _Decimal128 pseudo-registers after the SPE registers.  */
+      tdep->ppc_dl0_regnum += 32;
+
+      if (have_vsx)
+	{
+	  tdep->ppc_vsr0_regnum += 48;
+	  tdep->ppc_efpr0_regnum += 112;
+	}
+    }
+  else if (have_dfp && have_vsx)
+    {
+      tdep->ppc_vsr0_regnum += 16;
+      tdep->ppc_efpr0_regnum += 80;
+    }
 
   /* Setup displaced stepping.  */
   set_gdbarch_displaced_step_copy_insn (gdbarch,
@@ -3404,6 +3738,7 @@
   /* 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_505 ();
@@ -3413,6 +3748,7 @@
   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 ();
Index: gdb/ppc-linux-nat.c
===================================================================
--- gdb.orig/ppc-linux-nat.c	2008-05-03 10:16:43.000000000 -0700
+++ gdb/ppc-linux-nat.c	2008-07-25 09:52:04.000000000 -0700
@@ -68,6 +68,11 @@
 #define PTRACE_SETVRREGS 19
 #endif
 
+/* PTRACE requests for POWER7 VSX registers.  */
+#ifndef PTRACE_GETVSXREGS
+#define PTRACE_GETVSXREGS 27
+#define PTRACE_SETVSXREGS 28
+#endif
 
 /* Similarly for the ptrace requests for getting / setting the SPE
    registers (ev0 -- ev31, acc, and spefscr).  See the description of
@@ -119,6 +124,41 @@
 
 typedef char gdb_vrregset_t[SIZEOF_VRREGS];
 
+/* This is the layout of the POWER7 VSX registers and the way they overlap
+   with the existing FPR and VMX registers.
+
+                    VSR doubleword 0               VSR doubleword 1
+           ----------------------------------------------------------------
+   VSR[0]  |             FPR[0]            |                              |
+           ----------------------------------------------------------------
+   VSR[1]  |             FPR[1]            |                              |
+           ----------------------------------------------------------------
+           |              ...              |                              |
+           |              ...              |                              |
+           ----------------------------------------------------------------
+   VSR[30] |             FPR[30]           |                              |
+           ----------------------------------------------------------------
+   VSR[31] |             FPR[31]           |                              |
+           ----------------------------------------------------------------
+   VSR[32] |                             VR[0]                            |
+           ----------------------------------------------------------------
+   VSR[33] |                             VR[1]                            |
+           ----------------------------------------------------------------
+           |                              ...                             |
+           |                              ...                             |
+           ----------------------------------------------------------------
+   VSR[62] |                             VR[30]                           |
+           ----------------------------------------------------------------
+   VSR[63] |                             VR[31]                           |
+          ----------------------------------------------------------------
+
+   VSX has 64 128bit registers.  The first 32 registers overlap with
+   the FP registers (doubleword 0) and hence extend them with additional
+   64 bits (doubleword 1).  The other 32 regs overlap with the VMX
+   registers.  */
+#define SIZEOF_VSXREGS 32*8
+
+typedef char gdb_vsxregset_t[SIZEOF_VSXREGS];
 
 /* On PPC processors that support the the Signal Processing Extension
    (SPE) APU, the general-purpose registers are 64 bits long.
@@ -144,6 +184,12 @@
   unsigned long spefscr;
 };
 
+/* Non-zero if our kernel may support the PTRACE_GETVSXREGS and
+   PTRACE_SETVSXREGS requests, for reading and writing the VSX
+   POWER7 registers 0 through 31.  Zero if we've tried one of them and
+   gotten an error.  Note that VSX registers 32 through 63 overlap
+   with VR registers 0 through 31.  */
+int have_ptrace_getsetvsxregs = 1;
 
 /* Non-zero if our kernel may support the PTRACE_GETVRREGS and
    PTRACE_SETVRREGS requests, for reading and writing the Altivec
@@ -231,6 +277,34 @@
   return u_addr;
 }
 
+/* The Linux kernel ptrace interface for POWER7 VSX registers uses the
+   registers set mechanism, as opposed to the interface for all the
+   other registers, that stores/fetches each register individually.  */
+static void
+fetch_vsx_register (struct regcache *regcache, int tid, int regno)
+{
+  int ret;
+  gdb_vsxregset_t regs;
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum);
+
+  ret = ptrace (PTRACE_GETVSXREGS, tid, 0, &regs);
+  if (ret < 0)
+    {
+      if (errno == EIO)
+	{
+	  have_ptrace_getsetvsxregs = 0;
+	  return;
+	}
+      perror_with_name (_("Unable to fetch VSX register"));
+    }
+
+  regcache_raw_supply (regcache, regno,
+		       regs + (regno - tdep->ppc_vsr0_upper_regnum)
+		       * vsxregsize);
+}
+
 /* The Linux kernel ptrace interface for AltiVec registers uses the
    registers set mechanism, as opposed to the interface for all the
    other registers, that stores/fetches each register individually.  */
@@ -365,6 +439,14 @@
         AltiVec registers, fall through and return zeroes, because
         regaddr will be -1 in this case.  */
     }
+  if (vsx_register_p (gdbarch, regno))
+    {
+      if (have_ptrace_getsetvsxregs)
+	{
+	  fetch_vsx_register (regcache, tid, regno);
+	  return;
+	}
+    }
   else if (spe_register_p (gdbarch, regno))
     {
       fetch_spe_register (regcache, tid, regno);
@@ -421,6 +503,22 @@
 }
 
 static void
+supply_vsxregset (struct regcache *regcache, gdb_vsxregset_t *vsxregsetp)
+{
+  int i;
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int num_of_vsxregs = 32;
+  int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum);
+
+  for (i = 0; i < num_of_vsxregs; i++)
+    {
+	regcache_raw_supply (regcache, tdep->ppc_vsr0_upper_regnum + i,
+			     *vsxregsetp + i * vsxregsize);
+    }
+}
+
+static void
 supply_vrregset (struct regcache *regcache, gdb_vrregset_t *vrregsetp)
 {
   int i;
@@ -446,6 +544,25 @@
 }
 
 static void
+fetch_vsx_registers (struct regcache *regcache, int tid)
+{
+  int ret;
+  gdb_vsxregset_t regs;
+
+  ret = ptrace (PTRACE_GETVSXREGS, tid, 0, &regs);
+  if (ret < 0)
+    {
+      if (errno == EIO)
+	{
+	  have_ptrace_getsetvsxregs = 0;
+	  return;
+	}
+      perror_with_name (_("Unable to fetch VSX registers"));
+    }
+  supply_vsxregset (regcache, &regs);
+}
+
+static void
 fetch_altivec_registers (struct regcache *regcache, int tid)
 {
   int ret;
@@ -499,6 +616,9 @@
   if (have_ptrace_getvrregs)
     if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
       fetch_altivec_registers (regcache, tid);
+  if (have_ptrace_getsetvsxregs)
+    if (tdep->ppc_vsr0_upper_regnum != -1)
+      fetch_vsx_registers (regcache, tid);
   if (tdep->ppc_ev0_upper_regnum >= 0)
     fetch_spe_register (regcache, tid, -1);
 }
@@ -522,6 +642,36 @@
     fetch_register (regcache, tid, regno);
 }
 
+/* Store one VSX register. */
+static void
+store_vsx_register (const struct regcache *regcache, int tid, int regno)
+{
+  int ret;
+  int offset = 0;
+  gdb_vsxregset_t regs;
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum);
+
+  ret = ptrace (PTRACE_SETVSXREGS, tid, 0, &regs);
+  if (ret < 0)
+    {
+      if (errno == EIO)
+	{
+	  have_ptrace_getsetvsxregs = 0;
+	  return;
+	}
+      perror_with_name (_("Unable to fetch VSX register"));
+    }
+
+  regcache_raw_collect (regcache, regno, regs +
+			(regno - tdep->ppc_vsr0_upper_regnum) * vsxregsize);
+
+  ret = ptrace (PTRACE_SETVSXREGS, tid, 0, &regs);
+  if (ret < 0)
+    perror_with_name (_("Unable to store VSX register"));
+}
+
 /* Store one register. */
 static void
 store_altivec_register (const struct regcache *regcache, int tid, int regno)
@@ -660,6 +810,11 @@
       store_altivec_register (regcache, tid, regno);
       return;
     }
+  if (vsx_register_p (gdbarch, regno))
+    {
+      store_vsx_register (regcache, tid, regno);
+      return;
+    }
   else if (spe_register_p (gdbarch, regno))
     {
       store_spe_register (regcache, tid, regno);
@@ -714,6 +869,20 @@
 }
 
 static void
+fill_vsxregset (const struct regcache *regcache, gdb_vsxregset_t *vsxregsetp)
+{
+  int i;
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int num_of_vsxregs = 32;
+  int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum);
+
+  for (i = 0; i < num_of_vsxregs; i++)
+    regcache_raw_collect (regcache, tdep->ppc_vsr0_upper_regnum + i,
+			  *vsxregsetp + i * vsxregsize);
+}
+
+static void
 fill_vrregset (const struct regcache *regcache, gdb_vrregset_t *vrregsetp)
 {
   int i;
@@ -737,6 +906,29 @@
 }
 
 static void
+store_vsx_registers (const struct regcache *regcache, int tid)
+{
+  int ret;
+  gdb_vsxregset_t regs;
+
+  ret = ptrace (PTRACE_GETVSXREGS, tid, 0, &regs);
+  if (ret < 0)
+    {
+      if (errno == EIO)
+	{
+	  have_ptrace_getsetvsxregs = 0;
+	  return;
+	}
+      perror_with_name (_("Couldn't get VSX registers"));
+    }
+
+  fill_vsxregset (regcache, &regs);
+
+  if (ptrace (PTRACE_SETVSXREGS, tid, 0, &regs) < 0)
+    perror_with_name (_("Couldn't write VSX registers"));
+}
+
+static void
 store_altivec_registers (const struct regcache *regcache, int tid)
 {
   int ret;
@@ -794,6 +986,9 @@
   if (have_ptrace_getvrregs)
     if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
       store_altivec_registers (regcache, tid);
+  if (have_ptrace_getsetvsxregs)
+    if (tdep->ppc_vsr0_upper_regnum != -1)
+      store_vsx_registers (regcache, tid);
   if (tdep->ppc_ev0_upper_regnum >= 0)
     store_spe_register (regcache, tid, -1);
 }
@@ -989,6 +1184,7 @@
 ppc_linux_read_description (struct target_ops *ops)
 {
   int altivec = 0;
+  int vsx = 0;
 
   int tid = TIDGET (inferior_ptid);
   if (tid == 0)
@@ -1007,6 +1203,19 @@
 	perror_with_name (_("Unable to fetch SPE registers"));
     }
 
+  if (have_ptrace_getsetvsxregs)
+    {
+      gdb_vsxregset_t vsxregset;
+
+      if (ptrace (PTRACE_GETVSXREGS, tid, 0, &vsxregset) >= 0)
+	vsx = 1;
+
+      /* EIO means that the PTRACE_GETVSXREGS request isn't supported.
+	 Anything else needs to be reported.  */
+      else if (errno != EIO)
+	perror_with_name (_("Unable to fetch VSX registers"));
+    }
+
   if (have_ptrace_getvrregs)
     {
       gdb_vrregset_t vrregset;
@@ -1028,11 +1237,23 @@
     errno = 0;
     msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0);
     if (errno == 0 && msr < 0)
-      return altivec? tdesc_powerpc_altivec64l : tdesc_powerpc_64l;
+      {
+	if (vsx)
+	  return tdesc_powerpc_vsx64l;
+	else if (altivec)
+	  return tdesc_powerpc_altivec64l;
+
+	return tdesc_powerpc_64l;
+      }
   }
 #endif
 
-  return altivec? tdesc_powerpc_altivec32l : tdesc_powerpc_32l;
+  if (vsx)
+    return tdesc_powerpc_vsx32l;
+  else if (altivec)
+    return tdesc_powerpc_altivec32l;
+
+  return tdesc_powerpc_32l;
 }
 
 void _initialize_ppc_linux_nat (void);
Index: gdb/ppc-tdep.h
===================================================================
--- gdb.orig/ppc-tdep.h	2008-05-16 05:49:47.000000000 -0700
+++ gdb/ppc-tdep.h	2008-07-25 09:47:33.000000000 -0700
@@ -63,6 +63,7 @@
 
 /* From rs6000-tdep.c... */
 int altivec_register_p (struct gdbarch *gdbarch, int regno);
+int vsx_register_p (struct gdbarch *gdbarch, int regno);
 int spe_register_p (struct gdbarch *gdbarch, int regno);
 
 /* Return non-zero if the architecture described by GDBARCH has
@@ -73,6 +74,9 @@
    Altivec registers (vr0 --- vr31, vrsave and vscr).  */
 int ppc_altivec_support_p (struct gdbarch *gdbarch);
 
+/* Return non-zero if the architecture described by GDBARCH has
+   VSX registers (vsr0 --- vsr63).  */
+int vsx_support_p (struct gdbarch *gdbarch);
 int ppc_deal_with_atomic_sequence (struct frame_info *frame);
 

@@ -133,6 +137,14 @@
 				 struct regcache *regcache,
 				 int regnum, const void *vrregs, size_t len);
 
+/* Supply register REGNUM in the VSX register set REGSET
+   from the buffer specified by VSXREGS and LEN to register cache
+   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
+
+extern void ppc_supply_vsxregset (const struct regset *regset,
+				 struct regcache *regcache,
+				 int regnum, const void *vsxregs, size_t len);
+
 /* 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
@@ -160,6 +172,15 @@
 				  const struct regcache *regcache,
 				  int regnum, void *vrregs, size_t len);
 
+/* Collect register REGNUM in the VSX register set
+   REGSET from register cache REGCACHE into the buffer specified by
+   VSXREGS and LEN.  If REGNUM is -1, do this for all registers in
+   REGSET.  */
+
+extern void ppc_collect_vsxregset (const struct regset *regset,
+				  const struct regcache *regcache,
+				  int regnum, void *vsxregs, size_t len);
+
 /* Private data that this module attaches to struct gdbarch. */
 
 /* Vector ABI used by the inferior.  */
@@ -199,6 +220,11 @@
     /* Multiplier-Quotient Register (older POWER architectures only).  */
     int ppc_mq_regnum;
 
+    /* POWER7 VSX registers.  */
+    int ppc_vsr0_regnum;	/* First VSX register.  */
+    int ppc_vsr0_upper_regnum;  /* First right most dword vsx register.  */
+    int ppc_efpr0_regnum;	/* First Extended FP register.  */
+
     /* Altivec registers.  */
     int ppc_vr0_regnum;		/* First AltiVec register */
     int ppc_vrsave_regnum;	/* Last AltiVec register */
@@ -222,16 +248,19 @@
 
     /* ISA-specific types.  */
     struct type *ppc_builtin_type_vec64;
+    struct type *ppc_builtin_type_vec128;
 };
 

 /* Constants for register set sizes.  */
 enum
   {
-    ppc_num_gprs = 32,          /* 32 general-purpose registers */
-    ppc_num_fprs = 32,          /* 32 floating-point registers */
-    ppc_num_srs = 16,           /* 16 segment registers */
-    ppc_num_vrs = 32            /* 32 Altivec vector registers */
+    ppc_num_gprs = 32,		/* 32 general-purpose registers.  */
+    ppc_num_fprs = 32,		/* 32 floating-point registers.  */
+    ppc_num_srs = 16,		/* 16 segment registers.  */
+    ppc_num_vrs = 32,		/* 32 Altivec vector registers.  */
+    ppc_num_vsrs = 64,		/* 64 VSX vector registers.  */
+    ppc_num_efprs = 32		/* 32 Extended FP registers.  */
   };
 

@@ -257,6 +286,8 @@
   PPC_VR0_REGNUM = 106,
   PPC_VSCR_REGNUM = 138,
   PPC_VRSAVE_REGNUM = 139,
+  PPC_VSR0_UPPER_REGNUM = 140,
+  PPC_VSR31_UPPER_REGNUM = 171,
   PPC_NUM_REGS
 };
 
Index: gdb/ppc-linux-tdep.c
===================================================================
--- gdb.orig/ppc-linux-tdep.c	2008-05-24 09:32:01.000000000 -0700
+++ gdb/ppc-linux-tdep.c	2008-07-25 09:47:33.000000000 -0700
@@ -41,8 +41,10 @@
 
 #include "features/rs6000/powerpc-32l.c"
 #include "features/rs6000/powerpc-altivec32l.c"
+#include "features/rs6000/powerpc-vsx32l.c"
 #include "features/rs6000/powerpc-64l.c"
 #include "features/rs6000/powerpc-altivec64l.c"
+#include "features/rs6000/powerpc-vsx64l.c"
 #include "features/rs6000/powerpc-e500l.c"
 

@@ -1095,7 +1097,9 @@
   /* Initialize the Linux target descriptions.  */
   initialize_tdesc_powerpc_32l ();
   initialize_tdesc_powerpc_altivec32l ();
+  initialize_tdesc_powerpc_vsx32l ();
   initialize_tdesc_powerpc_64l ();
   initialize_tdesc_powerpc_altivec64l ();
+  initialize_tdesc_powerpc_vsx64l ();
   initialize_tdesc_powerpc_e500l ();
 }
Index: gdb/ppc-linux-tdep.h
===================================================================
--- gdb.orig/ppc-linux-tdep.h	2008-05-03 10:16:43.000000000 -0700
+++ gdb/ppc-linux-tdep.h	2008-07-25 09:47:33.000000000 -0700
@@ -41,8 +41,9 @@
 /* Linux target descriptions.  */
 extern struct target_desc *tdesc_powerpc_32l;
 extern struct target_desc *tdesc_powerpc_altivec32l;
+extern struct target_desc *tdesc_powerpc_vsx32l;
 extern struct target_desc *tdesc_powerpc_e500l;
 extern struct target_desc *tdesc_powerpc_64l;
 extern struct target_desc *tdesc_powerpc_altivec64l;
-
+extern struct target_desc *tdesc_powerpc_vsx64l;
 #endif /* PPC_LINUX_TDEP_H */



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH-ppc 1/5] Add basic support for new VSX register set
       [not found] ` <1217646694.26214.3.camel@localhost.localdomain>
@ 2008-08-08 15:12   ` Luis Machado
  2008-08-08 15:22     ` Luis Machado
  2008-08-14 19:50     ` Ulrich Weigand
  0 siblings, 2 replies; 8+ messages in thread
From: Luis Machado @ 2008-08-08 15:12 UTC (permalink / raw)
  To: Thiago Jung Bauermann; +Cc: gdb-patches

Patch updated.

> >  /* Constants for register set sizes.  */
> >  enum
> >    {
> > -    ppc_num_gprs = 32,          /* 32 general-purpose registers */
> > -    ppc_num_fprs = 32,          /* 32 floating-point registers */
> > -    ppc_num_srs = 16,           /* 16 segment registers */
> > -    ppc_num_vrs = 32            /* 32 Altivec vector registers */
> > +    ppc_num_gprs = 32,         /* 32 general-purpose registers.  */
> > +    ppc_num_fprs = 32,         /* 32 floating-point registers.  */
> > +    ppc_num_srs = 16,          /* 16 segment registers.  */
> > +    ppc_num_vrs = 32,          /* 32 Altivec vector registers.  */
> > +    ppc_num_vsrs = 64,         /* 64 VSX vector registers.  */
> > +    ppc_num_efprs = 32         /* 32 Extended FP registers.  */
> >    };
> 
> Why change the column of all the comments here?

Identation is broken (mixed tab/blank space). They're fixed now. If you
want, i can leave it broken and fix only the ones i care for this patch.

> >  /* Linux target descriptions.  */
> >  extern struct target_desc *tdesc_powerpc_32l;
> >  extern struct target_desc *tdesc_powerpc_altivec32l;
> > +extern struct target_desc *tdesc_powerpc_vsx32l;
> >  extern struct target_desc *tdesc_powerpc_e500l;
> >  extern struct target_desc *tdesc_powerpc_64l;
> >  extern struct target_desc *tdesc_powerpc_altivec64l;
> > -
> > +extern struct target_desc *tdesc_powerpc_vsx64l;
> >  #endif /* PPC_LINUX_TDEP_H */
> 
> I know this is very picky, but I'd preserve the blank line before
> #endif.

The blank line is back.


---
2008-08-08  Luis Machado  <luisgpm@br.ibm.com>

	* rs6000-tdep: Include "features/rs6000/powerpc-vsx32.c".
	Include "features/rs6000/powerpc-vsx64.c".
	(ppc_supply_vsxregset): New function.
	(ppc_collect_vsxregset): New function.
	(IS_VSX_PSEUDOREG): New macro.
	(IS_EFP_PSEUDOREG): New macro.
	(vsx_register_p): New function.
	(ppc_vsx_support_p): New function.
	(rs6000_builtin_type_vec128): New function.
	(rs6000_register_name): Hide upper halves of vs0~vs31.  Return
	correct names for VSX registers and EFPR registers.
	(rs6000_pseudo_register_type): Return correct types for VSX
	and EFPR registers.
	(rs6000_pseudo_register_reggroup_p): Return correct group for
	VSX and EFPR registers.
	(ppc_pseudo_register_read): Rename to dfp_pseudo_register_read.
	(ppc_pseudo_register_write): Rename to dfp_pseudo_register_write.
	(vsx_pseudo_register_read): New function.
	(vsx_pseudo_register_write): New function.
	(efpr_pseudo_register_read): New function.
	(efpr_pseudo_register_write): New function.
	(rs6000_pseudo_register_read): Call new VSX and EFPR read functions.
	(rs6000_pseudo_register_write): Call new VSX and EFPR write functions.
	(rs6000_gdbarch_init): Declare have_vsx.
	Initialize new upper half VSX registers.
	Initialize VSX-related and EFPR-related pseudo-registers variables.
	Adjust the number of pseudo registers accordingly.
	
	* ppc-linux-nat.c: Define PTRACE_GETVSXREGS, PTRACE_SETVSXREGS
	and SIZEOF_VSRREGS.
	(gdb_vsxregset_t): New type.
	(have_ptrace_getsetvsxregs): New variable.
	(fetch_vsx_register): New function.	
	(fetch_register): Handle VSX registers.
	(fetch_vsx_registers): New function.
	(fetch_ppc_registers): Handle VSX registers.
	(store_ppc_registers): Handle VSX registers.
	(store_vsx_register): New function.	
	(store_register): Handle VSX registers.
	(store_vsx_registers): New function.
	(ppc_linux_read_description): Handle VSX-enabled inferiors.
	(gdb_vsxregset_t): New type.
	(supply_vsxregset): New function.
	(fill_vsxregset): New function.

	* ppc-tdep.h (vsx_register_p): New prototype.
	(vsx_support_p): New prototype.
	(ppc_vsr0_regnum): New variable.
	(ppc_vsr0_upper_regnum): Likewise.
	(ppc_efpr0_regnum): Likewise.
	(ppc_builtin_type_vec128): New type.
	(ppc_num_vsrs): New constant.
	(ppc_num_efprs): Likewise.
	Define POWERPC_VEC_VSX PPC_VSR0_UPPER_REGNUM and PPC_VSR31_UPPER_REGNUM.
	(ppc_supply_vsxregset): New prototype.
	(ppc_collect_vsxregset): New prototype.

	* ppc-linux-tdep.c: Include "features/rs6000/powerpc-vsx32l.c"
	Include "features/rs6000/powerpc-vsx64l.c".
	(_initialize_ppc_linux_tdep): Initialize VSX-enabled targets.

	* ppc-linux-tdep.h: Declare *tdesc_powerpc_vsx32l
	Declare tdesc_powerpc_vsx64l

Index: gdb/rs6000-tdep.c
===================================================================
--- gdb.orig/rs6000-tdep.c	2008-08-08 07:17:03.000000000 -0700
+++ gdb/rs6000-tdep.c	2008-08-08 07:17:47.000000000 -0700
@@ -63,6 +63,7 @@
 
 #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-505.c"
@@ -72,6 +73,7 @@
 #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"
@@ -88,6 +90,16 @@
     && (regnum) >= (tdep)->ppc_dl0_regnum \
     && (regnum) < (tdep)->ppc_dl0_regnum + 16)
 
+/* 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_fprs)
+
 /* The list of available "set powerpc ..." and "show powerpc ..."
    commands.  */
 static struct cmd_list_element *setpowerpccmdlist = NULL;
@@ -133,6 +145,18 @@
   };
 
 
+/* 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
 altivec_register_p (struct gdbarch *gdbarch, int regno)
@@ -188,6 +212,16 @@
 }
 
 /* Return non-zero if the architecture described by GDBARCH has
+   VSX registers (vsr0 --- vsr63).  */
+int
+ppc_vsx_support_p (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  return tdep->ppc_vsr0_regnum >= 0;
+}
+
+/* Return non-zero if the architecture described by GDBARCH has
    Altivec registers (vr0 --- vr31, vrsave and vscr).  */
 int
 ppc_altivec_support_p (struct gdbarch *gdbarch)
@@ -539,6 +573,37 @@
 		  regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8);
 }
 
+/* Supply register REGNUM in the VSX register set REGSET
+   from the buffer specified by VSRREGS and LEN to register cache
+   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
+
+void
+ppc_supply_vsxregset (const struct regset *regset, struct regcache *regcache,
+		     int regnum, const void *vsxregs, size_t len)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep;
+
+  if (!ppc_vsx_support_p (gdbarch))
+    return;
+
+  tdep = gdbarch_tdep (gdbarch);
+
+  if (regnum == -1)
+    {
+      int i;
+
+      for (i = tdep->ppc_vsr0_upper_regnum;
+	   i < tdep->ppc_vsr0_upper_regnum + 32;
+	   i++)
+	ppc_supply_reg (regcache, i, vsxregs, 0, 8);
+
+      return;
+    }
+  else
+    ppc_supply_reg (regcache, regnum, 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.  */
@@ -669,6 +734,40 @@
 		   regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8);
 }
 
+/* Collect register REGNUM in the VSX register set
+   REGSET from register cache REGCACHE into the buffer specified by
+   VSRREGS and LEN.  If REGNUM is -1, do this for all registers in
+   REGSET.  */
+
+void
+ppc_collect_vsxregset (const struct regset *regset,
+		      const struct regcache *regcache,
+		      int regnum, void *vsxregs, size_t len)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep;
+
+  if (!ppc_vsx_support_p (gdbarch))
+    return;
+
+  tdep = gdbarch_tdep (gdbarch);
+
+  if (regnum == -1)
+    {
+      int i;
+
+      for (i = tdep->ppc_vsr0_upper_regnum;
+	   i < tdep->ppc_vsr0_upper_regnum + 32;
+	   i++)
+	ppc_collect_reg (regcache, i, vsxregs, 0, 8);
+
+      return;
+    }
+  else
+    ppc_collect_reg (regcache, regnum, 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
@@ -1915,6 +2014,47 @@
   return tdep->ppc_builtin_type_vec64;
 }
 
+/* Vector 128 type.  */
+
+static struct type *
+rs6000_builtin_type_vec128 (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (!tdep->ppc_builtin_type_vec128)
+    {
+      /* The type we're building is this
+
+	 type = union __ppc_builtin_type_vec128 {
+	     uint128_t uint128;
+	     float v4_float[4];
+	     int32_t v4_int32[4];
+	     int16_t v8_int16[8];
+	     int8_t v16_int8[16];
+	 }
+      */
+
+      struct type *t;
+
+      t = init_composite_type ("__ppc_builtin_type_vec128", TYPE_CODE_UNION);
+      append_composite_type_field (t, "uint128", builtin_type_uint128);
+      append_composite_type_field (t, "v4_float",
+				   init_vector_type (builtin_type_float, 4));
+      append_composite_type_field (t, "v4_int32",
+				   init_vector_type (builtin_type_int32, 4));
+      append_composite_type_field (t, "v8_int16",
+				   init_vector_type (builtin_type_int16, 8));
+      append_composite_type_field (t, "v16_int8",
+				   init_vector_type (builtin_type_int8, 16));
+
+      TYPE_FLAGS (t) |= TYPE_FLAG_VECTOR;
+      TYPE_NAME (t) = "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
    is an anonymous register.  */
 
@@ -1931,6 +2071,12 @@
       && 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 "";
+
   /* Check if the SPE pseudo registers are available.  */
   if (IS_SPE_PSEUDOREG (tdep, regno))
     {
@@ -1955,6 +2101,36 @@
       return dfp128_regnames[regno - tdep->ppc_dl0_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];
+    }
+
   return tdesc_register_name (gdbarch, regno);
 }
 
@@ -1968,14 +2144,22 @@
 
   /* These are the only pseudo-registers we support.  */
   gdb_assert (IS_SPE_PSEUDOREG (tdep, regnum)
-	      || IS_DFP_PSEUDOREG (tdep, regnum));
+	      || IS_DFP_PSEUDOREG (tdep, regnum)
+	      || IS_VSX_PSEUDOREG (tdep, regnum)
+	      || IS_EFP_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))
+    /* PPC decimal128 pseudo-registers.  */
     return builtin_type (gdbarch)->builtin_declong;
+  else if (IS_VSX_PSEUDOREG (tdep, regnum))
+    /* POWER7 VSX pseudo-registers.  */
+    return rs6000_builtin_type_vec128 (gdbarch);
+  else
+    /* POWER7 Extended FP pseudo-registers.  */
+    return builtin_type_ieee_double;
 }
 
 /* Is REGNUM a member of REGGROUP?  */
@@ -1987,13 +2171,15 @@
 
   /* These are the only pseudo-registers we support.  */
   gdb_assert (IS_SPE_PSEUDOREG (tdep, regnum)
-	      || IS_DFP_PSEUDOREG (tdep, regnum));
+	      || IS_DFP_PSEUDOREG (tdep, regnum)
+	      || IS_VSX_PSEUDOREG (tdep, regnum)
+	      || IS_EFP_PSEUDOREG (tdep, regnum));
 
-  /* These are the e500 pseudo-registers.  */
-  if (IS_SPE_PSEUDOREG (tdep, regnum))
+  /* These are the e500 pseudo-registers or the POWER7 VSX registers.  */
+  if (IS_SPE_PSEUDOREG (tdep, regnum) || IS_VSX_PSEUDOREG (tdep, regnum))
     return group == all_reggroup || group == vector_reggroup;
   else
-    /* Could only be the ppc decimal128 pseudo-registers.  */
+    /* PPC decimal128 or Extended FP pseudo-registers.  */
     return group == all_reggroup || group == float_reggroup;
 }
 
@@ -2107,10 +2293,9 @@
 			 regcache, reg_nr, (gdb_byte *) buffer);
 }
 
-/* Read method for PPC pseudo-registers. Currently this is handling the
-   16 decimal128 registers that map into 16 pairs of FP registers.  */
+/* Read method for DFP pseudo-registers.  */
 static void
-ppc_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+dfp_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 			   int reg_nr, gdb_byte *buffer)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
@@ -2133,10 +2318,9 @@
     }
 }
 
-/* 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);
@@ -2160,6 +2344,92 @@
     }
 }
 
+/* Read method for POWER7 VSX pseudo-registers.  */
+static void
+vsx_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+			   int reg_nr, gdb_byte *buffer)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int reg_index = reg_nr - tdep->ppc_vsr0_regnum;
+
+  /* Read the portion that overlaps the VMX registers.  */
+  if (reg_index > 31)
+    regcache_raw_read (regcache, tdep->ppc_vr0_regnum +
+			reg_index - 32, buffer);
+  else
+    /* Read the portion that overlaps the FPR registers.  */
+    if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+      {
+	regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+			reg_index, buffer);
+	regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
+			reg_index, buffer + 8);
+      }
+    else
+      {
+	regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+			reg_index, buffer + 8);
+	regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
+			reg_index, buffer);
+      }
+}
+
+/* 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 = reg_nr - tdep->ppc_vsr0_regnum;
+
+  /* Write the portion that overlaps the VMX registers.  */
+  if (reg_index > 31)
+    regcache_raw_write (regcache, tdep->ppc_vr0_regnum +
+			reg_index - 32, buffer);
+  else
+    /* Write the portion that overlaps the FPR registers.  */
+    if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+      {
+	regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
+			reg_index, buffer);
+	regcache_raw_write (regcache, tdep->ppc_vsr0_upper_regnum +
+			reg_index, buffer + 8);
+      }
+    else
+      {
+	regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
+			reg_index, buffer + 8);
+	regcache_raw_write (regcache, tdep->ppc_vsr0_upper_regnum +
+			reg_index, buffer);
+      }
+}
+
+/* Read method for POWER7 Extended FP pseudo-registers.  */
+static void
+efpr_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+			   int reg_nr, gdb_byte *buffer)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int reg_index = reg_nr - tdep->ppc_efpr0_regnum;
+
+  /* Read the portion that overlaps the VMX registers.  */
+  regcache_raw_read (regcache, tdep->ppc_vr0_regnum +
+		     reg_index, buffer);
+}
+
+/* Write method for POWER7 Extended FP pseudo-registers.  */
+static void
+efpr_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+			    int reg_nr, const gdb_byte *buffer)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int reg_index = reg_nr - tdep->ppc_efpr0_regnum;
+
+  /* Write the portion that overlaps the VMX registers.  */
+  regcache_raw_write (regcache, tdep->ppc_vr0_regnum +
+		      reg_index, buffer);
+}
+
 static void
 rs6000_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 			     int reg_nr, gdb_byte *buffer)
@@ -2172,7 +2442,11 @@
   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);
+    dfp_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+  else if (IS_VSX_PSEUDOREG (tdep, reg_nr))
+    vsx_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+  else if (IS_EFP_PSEUDOREG (tdep, reg_nr))
+    efpr_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
   else
     internal_error (__FILE__, __LINE__,
 		    _("rs6000_pseudo_register_read: "
@@ -2193,7 +2467,11 @@
   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);
+    dfp_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+  else if (IS_VSX_PSEUDOREG (tdep, reg_nr))
+    vsx_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+  else if (IS_EFP_PSEUDOREG (tdep, reg_nr))
+    efpr_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
   else
     internal_error (__FILE__, __LINE__,
 		    _("rs6000_pseudo_register_write: "
@@ -2776,7 +3054,8 @@
   enum auto_boolean soft_float_flag = powerpc_soft_float_global;
   int soft_float;
   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;
+  int have_fpu = 1, have_spe = 0, have_mq = 0, have_altivec = 0, have_dfp = 0,
+      have_vsx = 0;
   int tdesc_wordsize = -1;
   const struct target_desc *tdesc = info.target_desc;
   struct tdesc_arch_data *tdesc_data = NULL;
@@ -2975,6 +3254,38 @@
       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)
+	    {
+	      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
@@ -3158,6 +3469,7 @@
 
   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;
@@ -3186,7 +3498,7 @@
   else
     tdep->lr_frame_offset = 4;
 
-  if (have_spe || have_dfp)
+  if (have_spe || have_dfp || have_vsx)
     {
       set_gdbarch_pseudo_register_read (gdbarch, rs6000_pseudo_register_read);
       set_gdbarch_pseudo_register_write (gdbarch, rs6000_pseudo_register_write);
@@ -3206,6 +3518,9 @@
     num_pseudoregs += 32;
   if (have_dfp)
     num_pseudoregs += 16;
+  if (have_vsx)
+    /* Include both VSX and Extended FP registers.  */
+    num_pseudoregs += 96;
 
   set_gdbarch_num_pseudo_regs (gdbarch, num_pseudoregs);
 
@@ -3307,9 +3622,26 @@
   /* Set the register number for _Decimal128 pseudo-registers.  */
   tdep->ppc_dl0_regnum = have_dfp? gdbarch_num_regs (gdbarch) : -1;
 
+  /* Set the register number for VSX pseudo-registers.  */
+  tdep->ppc_vsr0_regnum = have_vsx? gdbarch_num_regs (gdbarch) : -1;
+  tdep->ppc_efpr0_regnum = have_vsx? gdbarch_num_regs (gdbarch) : -1;
+
   if (have_dfp && have_spe)
-    /* Put the _Decimal128 pseudo-registers after the SPE registers.  */
-    tdep->ppc_dl0_regnum += 32;
+    {
+      /* Put the _Decimal128 pseudo-registers after the SPE registers.  */
+      tdep->ppc_dl0_regnum += 32;
+
+      if (have_vsx)
+	{
+	  tdep->ppc_vsr0_regnum += 48;
+	  tdep->ppc_efpr0_regnum += 112;
+	}
+    }
+  else if (have_dfp && have_vsx)
+    {
+      tdep->ppc_vsr0_regnum += 16;
+      tdep->ppc_efpr0_regnum += 80;
+    }
 
   /* Setup displaced stepping.  */
   set_gdbarch_displaced_step_copy_insn (gdbarch,
@@ -3404,6 +3736,7 @@
   /* 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_505 ();
@@ -3413,6 +3746,7 @@
   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 ();
Index: gdb/ppc-linux-nat.c
===================================================================
--- gdb.orig/ppc-linux-nat.c	2008-08-08 07:17:03.000000000 -0700
+++ gdb/ppc-linux-nat.c	2008-08-08 07:17:47.000000000 -0700
@@ -68,6 +68,11 @@
 #define PTRACE_SETVRREGS 19
 #endif
 
+/* PTRACE requests for POWER7 VSX registers.  */
+#ifndef PTRACE_GETVSXREGS
+#define PTRACE_GETVSXREGS 27
+#define PTRACE_SETVSXREGS 28
+#endif
 
 /* Similarly for the ptrace requests for getting / setting the SPE
    registers (ev0 -- ev31, acc, and spefscr).  See the description of
@@ -119,6 +124,41 @@
 
 typedef char gdb_vrregset_t[SIZEOF_VRREGS];
 
+/* This is the layout of the POWER7 VSX registers and the way they overlap
+   with the existing FPR and VMX registers.
+
+                    VSR doubleword 0               VSR doubleword 1
+           ----------------------------------------------------------------
+   VSR[0]  |             FPR[0]            |                              |
+           ----------------------------------------------------------------
+   VSR[1]  |             FPR[1]            |                              |
+           ----------------------------------------------------------------
+           |              ...              |                              |
+           |              ...              |                              |
+           ----------------------------------------------------------------
+   VSR[30] |             FPR[30]           |                              |
+           ----------------------------------------------------------------
+   VSR[31] |             FPR[31]           |                              |
+           ----------------------------------------------------------------
+   VSR[32] |                             VR[0]                            |
+           ----------------------------------------------------------------
+   VSR[33] |                             VR[1]                            |
+           ----------------------------------------------------------------
+           |                              ...                             |
+           |                              ...                             |
+           ----------------------------------------------------------------
+   VSR[62] |                             VR[30]                           |
+           ----------------------------------------------------------------
+   VSR[63] |                             VR[31]                           |
+          ----------------------------------------------------------------
+
+   VSX has 64 128bit registers.  The first 32 registers overlap with
+   the FP registers (doubleword 0) and hence extend them with additional
+   64 bits (doubleword 1).  The other 32 regs overlap with the VMX
+   registers.  */
+#define SIZEOF_VSXREGS 32*8
+
+typedef char gdb_vsxregset_t[SIZEOF_VSXREGS];
 
 /* On PPC processors that support the the Signal Processing Extension
    (SPE) APU, the general-purpose registers are 64 bits long.
@@ -144,6 +184,12 @@
   unsigned long spefscr;
 };
 
+/* Non-zero if our kernel may support the PTRACE_GETVSXREGS and
+   PTRACE_SETVSXREGS requests, for reading and writing the VSX
+   POWER7 registers 0 through 31.  Zero if we've tried one of them and
+   gotten an error.  Note that VSX registers 32 through 63 overlap
+   with VR registers 0 through 31.  */
+int have_ptrace_getsetvsxregs = 1;
 
 /* Non-zero if our kernel may support the PTRACE_GETVRREGS and
    PTRACE_SETVRREGS requests, for reading and writing the Altivec
@@ -231,6 +277,34 @@
   return u_addr;
 }
 
+/* The Linux kernel ptrace interface for POWER7 VSX registers uses the
+   registers set mechanism, as opposed to the interface for all the
+   other registers, that stores/fetches each register individually.  */
+static void
+fetch_vsx_register (struct regcache *regcache, int tid, int regno)
+{
+  int ret;
+  gdb_vsxregset_t regs;
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum);
+
+  ret = ptrace (PTRACE_GETVSXREGS, tid, 0, &regs);
+  if (ret < 0)
+    {
+      if (errno == EIO)
+	{
+	  have_ptrace_getsetvsxregs = 0;
+	  return;
+	}
+      perror_with_name (_("Unable to fetch VSX register"));
+    }
+
+  regcache_raw_supply (regcache, regno,
+		       regs + (regno - tdep->ppc_vsr0_upper_regnum)
+		       * vsxregsize);
+}
+
 /* The Linux kernel ptrace interface for AltiVec registers uses the
    registers set mechanism, as opposed to the interface for all the
    other registers, that stores/fetches each register individually.  */
@@ -365,6 +439,14 @@
         AltiVec registers, fall through and return zeroes, because
         regaddr will be -1 in this case.  */
     }
+  if (vsx_register_p (gdbarch, regno))
+    {
+      if (have_ptrace_getsetvsxregs)
+	{
+	  fetch_vsx_register (regcache, tid, regno);
+	  return;
+	}
+    }
   else if (spe_register_p (gdbarch, regno))
     {
       fetch_spe_register (regcache, tid, regno);
@@ -421,6 +503,21 @@
 }
 
 static void
+supply_vsxregset (struct regcache *regcache, gdb_vsxregset_t *vsxregsetp)
+{
+  int i;
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum);
+
+  for (i = 0; i < ppc_num_vshrs; i++)
+    {
+	regcache_raw_supply (regcache, tdep->ppc_vsr0_upper_regnum + i,
+			     *vsxregsetp + i * vsxregsize);
+    }
+}
+
+static void
 supply_vrregset (struct regcache *regcache, gdb_vrregset_t *vrregsetp)
 {
   int i;
@@ -446,6 +543,25 @@
 }
 
 static void
+fetch_vsx_registers (struct regcache *regcache, int tid)
+{
+  int ret;
+  gdb_vsxregset_t regs;
+
+  ret = ptrace (PTRACE_GETVSXREGS, tid, 0, &regs);
+  if (ret < 0)
+    {
+      if (errno == EIO)
+	{
+	  have_ptrace_getsetvsxregs = 0;
+	  return;
+	}
+      perror_with_name (_("Unable to fetch VSX registers"));
+    }
+  supply_vsxregset (regcache, &regs);
+}
+
+static void
 fetch_altivec_registers (struct regcache *regcache, int tid)
 {
   int ret;
@@ -499,6 +615,9 @@
   if (have_ptrace_getvrregs)
     if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
       fetch_altivec_registers (regcache, tid);
+  if (have_ptrace_getsetvsxregs)
+    if (tdep->ppc_vsr0_upper_regnum != -1)
+      fetch_vsx_registers (regcache, tid);
   if (tdep->ppc_ev0_upper_regnum >= 0)
     fetch_spe_register (regcache, tid, -1);
 }
@@ -522,6 +641,35 @@
     fetch_register (regcache, tid, regno);
 }
 
+/* Store one VSX register. */
+static void
+store_vsx_register (const struct regcache *regcache, int tid, int regno)
+{
+  int ret;
+  gdb_vsxregset_t regs;
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum);
+
+  ret = ptrace (PTRACE_SETVSXREGS, tid, 0, &regs);
+  if (ret < 0)
+    {
+      if (errno == EIO)
+	{
+	  have_ptrace_getsetvsxregs = 0;
+	  return;
+	}
+      perror_with_name (_("Unable to fetch VSX register"));
+    }
+
+  regcache_raw_collect (regcache, regno, regs +
+			(regno - tdep->ppc_vsr0_upper_regnum) * vsxregsize);
+
+  ret = ptrace (PTRACE_SETVSXREGS, tid, 0, &regs);
+  if (ret < 0)
+    perror_with_name (_("Unable to store VSX register"));
+}
+
 /* Store one register. */
 static void
 store_altivec_register (const struct regcache *regcache, int tid, int regno)
@@ -660,6 +808,11 @@
       store_altivec_register (regcache, tid, regno);
       return;
     }
+  if (vsx_register_p (gdbarch, regno))
+    {
+      store_vsx_register (regcache, tid, regno);
+      return;
+    }
   else if (spe_register_p (gdbarch, regno))
     {
       store_spe_register (regcache, tid, regno);
@@ -714,6 +867,19 @@
 }
 
 static void
+fill_vsxregset (const struct regcache *regcache, gdb_vsxregset_t *vsxregsetp)
+{
+  int i;
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum);
+
+  for (i = 0; i < ppc_num_vshrs; i++)
+    regcache_raw_collect (regcache, tdep->ppc_vsr0_upper_regnum + i,
+			  *vsxregsetp + i * vsxregsize);
+}
+
+static void
 fill_vrregset (const struct regcache *regcache, gdb_vrregset_t *vrregsetp)
 {
   int i;
@@ -737,6 +903,29 @@
 }
 
 static void
+store_vsx_registers (const struct regcache *regcache, int tid)
+{
+  int ret;
+  gdb_vsxregset_t regs;
+
+  ret = ptrace (PTRACE_GETVSXREGS, tid, 0, &regs);
+  if (ret < 0)
+    {
+      if (errno == EIO)
+	{
+	  have_ptrace_getsetvsxregs = 0;
+	  return;
+	}
+      perror_with_name (_("Couldn't get VSX registers"));
+    }
+
+  fill_vsxregset (regcache, &regs);
+
+  if (ptrace (PTRACE_SETVSXREGS, tid, 0, &regs) < 0)
+    perror_with_name (_("Couldn't write VSX registers"));
+}
+
+static void
 store_altivec_registers (const struct regcache *regcache, int tid)
 {
   int ret;
@@ -794,6 +983,9 @@
   if (have_ptrace_getvrregs)
     if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
       store_altivec_registers (regcache, tid);
+  if (have_ptrace_getsetvsxregs)
+    if (tdep->ppc_vsr0_upper_regnum != -1)
+      store_vsx_registers (regcache, tid);
   if (tdep->ppc_ev0_upper_regnum >= 0)
     store_spe_register (regcache, tid, -1);
 }
@@ -989,6 +1181,7 @@
 ppc_linux_read_description (struct target_ops *ops)
 {
   int altivec = 0;
+  int vsx = 0;
 
   int tid = TIDGET (inferior_ptid);
   if (tid == 0)
@@ -1007,6 +1200,19 @@
 	perror_with_name (_("Unable to fetch SPE registers"));
     }
 
+  if (have_ptrace_getsetvsxregs)
+    {
+      gdb_vsxregset_t vsxregset;
+
+      if (ptrace (PTRACE_GETVSXREGS, tid, 0, &vsxregset) >= 0)
+	vsx = 1;
+
+      /* EIO means that the PTRACE_GETVSXREGS request isn't supported.
+	 Anything else needs to be reported.  */
+      else if (errno != EIO)
+	perror_with_name (_("Unable to fetch VSX registers"));
+    }
+
   if (have_ptrace_getvrregs)
     {
       gdb_vrregset_t vrregset;
@@ -1028,11 +1234,23 @@
     errno = 0;
     msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0);
     if (errno == 0 && msr < 0)
-      return altivec? tdesc_powerpc_altivec64l : tdesc_powerpc_64l;
+      {
+	if (vsx)
+	  return tdesc_powerpc_vsx64l;
+	else if (altivec)
+	  return tdesc_powerpc_altivec64l;
+
+	return tdesc_powerpc_64l;
+      }
   }
 #endif
 
-  return altivec? tdesc_powerpc_altivec32l : tdesc_powerpc_32l;
+  if (vsx)
+    return tdesc_powerpc_vsx32l;
+  else if (altivec)
+    return tdesc_powerpc_altivec32l;
+
+  return tdesc_powerpc_32l;
 }
 
 void _initialize_ppc_linux_nat (void);
Index: gdb/ppc-tdep.h
===================================================================
--- gdb.orig/ppc-tdep.h	2008-08-08 07:17:03.000000000 -0700
+++ gdb/ppc-tdep.h	2008-08-08 07:17:47.000000000 -0700
@@ -63,6 +63,7 @@
 
 /* From rs6000-tdep.c... */
 int altivec_register_p (struct gdbarch *gdbarch, int regno);
+int vsx_register_p (struct gdbarch *gdbarch, int regno);
 int spe_register_p (struct gdbarch *gdbarch, int regno);
 
 /* Return non-zero if the architecture described by GDBARCH has
@@ -73,6 +74,9 @@
    Altivec registers (vr0 --- vr31, vrsave and vscr).  */
 int ppc_altivec_support_p (struct gdbarch *gdbarch);
 
+/* Return non-zero if the architecture described by GDBARCH has
+   VSX registers (vsr0 --- vsr63).  */
+int vsx_support_p (struct gdbarch *gdbarch);
 int ppc_deal_with_atomic_sequence (struct frame_info *frame);
 
 
@@ -133,6 +137,14 @@
 				 struct regcache *regcache,
 				 int regnum, const void *vrregs, size_t len);
 
+/* Supply register REGNUM in the VSX register set REGSET
+   from the buffer specified by VSXREGS and LEN to register cache
+   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
+
+extern void ppc_supply_vsxregset (const struct regset *regset,
+				 struct regcache *regcache,
+				 int regnum, const void *vsxregs, size_t len);
+
 /* 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
@@ -160,6 +172,15 @@
 				  const struct regcache *regcache,
 				  int regnum, void *vrregs, size_t len);
 
+/* Collect register REGNUM in the VSX register set
+   REGSET from register cache REGCACHE into the buffer specified by
+   VSXREGS and LEN.  If REGNUM is -1, do this for all registers in
+   REGSET.  */
+
+extern void ppc_collect_vsxregset (const struct regset *regset,
+				  const struct regcache *regcache,
+				  int regnum, void *vsxregs, size_t len);
+
 /* Private data that this module attaches to struct gdbarch. */
 
 /* Vector ABI used by the inferior.  */
@@ -199,6 +220,11 @@
     /* Multiplier-Quotient Register (older POWER architectures only).  */
     int ppc_mq_regnum;
 
+    /* POWER7 VSX registers.  */
+    int ppc_vsr0_regnum;	/* First VSX register.  */
+    int ppc_vsr0_upper_regnum;  /* First right most dword vsx register.  */
+    int ppc_efpr0_regnum;	/* First Extended FP register.  */
+
     /* Altivec registers.  */
     int ppc_vr0_regnum;		/* First AltiVec register */
     int ppc_vrsave_regnum;	/* Last AltiVec register */
@@ -222,16 +248,20 @@
 
     /* ISA-specific types.  */
     struct type *ppc_builtin_type_vec64;
+    struct type *ppc_builtin_type_vec128;
 };
 
 
 /* Constants for register set sizes.  */
 enum
   {
-    ppc_num_gprs = 32,          /* 32 general-purpose registers */
-    ppc_num_fprs = 32,          /* 32 floating-point registers */
-    ppc_num_srs = 16,           /* 16 segment registers */
-    ppc_num_vrs = 32            /* 32 Altivec vector registers */
+    ppc_num_gprs = 32,		/* 32 general-purpose registers.  */
+    ppc_num_fprs = 32,		/* 32 floating-point registers.  */
+    ppc_num_srs = 16,		/* 16 segment registers.  */
+    ppc_num_vrs = 32,		/* 32 Altivec vector registers.  */
+    ppc_num_vshrs = 32,	/* 32 doublewords (dword 1 of vs0~vs31).  */
+    ppc_num_vsrs = 64,		/* 64 VSX vector registers.  */
+    ppc_num_efprs = 32		/* 32 Extended FP registers.  */
   };
 
 
@@ -257,6 +287,8 @@
   PPC_VR0_REGNUM = 106,
   PPC_VSCR_REGNUM = 138,
   PPC_VRSAVE_REGNUM = 139,
+  PPC_VSR0_UPPER_REGNUM = 140,
+  PPC_VSR31_UPPER_REGNUM = 171,
   PPC_NUM_REGS
 };
 
Index: gdb/ppc-linux-tdep.c
===================================================================
--- gdb.orig/ppc-linux-tdep.c	2008-08-08 07:17:03.000000000 -0700
+++ gdb/ppc-linux-tdep.c	2008-08-08 07:17:47.000000000 -0700
@@ -41,8 +41,10 @@
 
 #include "features/rs6000/powerpc-32l.c"
 #include "features/rs6000/powerpc-altivec32l.c"
+#include "features/rs6000/powerpc-vsx32l.c"
 #include "features/rs6000/powerpc-64l.c"
 #include "features/rs6000/powerpc-altivec64l.c"
+#include "features/rs6000/powerpc-vsx64l.c"
 #include "features/rs6000/powerpc-e500l.c"
 
 
@@ -1095,7 +1097,9 @@
   /* Initialize the Linux target descriptions.  */
   initialize_tdesc_powerpc_32l ();
   initialize_tdesc_powerpc_altivec32l ();
+  initialize_tdesc_powerpc_vsx32l ();
   initialize_tdesc_powerpc_64l ();
   initialize_tdesc_powerpc_altivec64l ();
+  initialize_tdesc_powerpc_vsx64l ();
   initialize_tdesc_powerpc_e500l ();
 }
Index: gdb/ppc-linux-tdep.h
===================================================================
--- gdb.orig/ppc-linux-tdep.h	2008-08-08 07:17:03.000000000 -0700
+++ gdb/ppc-linux-tdep.h	2008-08-08 07:17:47.000000000 -0700
@@ -41,8 +41,10 @@
 /* Linux target descriptions.  */
 extern struct target_desc *tdesc_powerpc_32l;
 extern struct target_desc *tdesc_powerpc_altivec32l;
+extern struct target_desc *tdesc_powerpc_vsx32l;
 extern struct target_desc *tdesc_powerpc_e500l;
 extern struct target_desc *tdesc_powerpc_64l;
 extern struct target_desc *tdesc_powerpc_altivec64l;
+extern struct target_desc *tdesc_powerpc_vsx64l;
 
 #endif /* PPC_LINUX_TDEP_H */



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH-ppc 1/5] Add basic support for new VSX register set
  2008-08-08 15:12   ` Luis Machado
@ 2008-08-08 15:22     ` Luis Machado
  2008-08-14 19:50     ` Ulrich Weigand
  1 sibling, 0 replies; 8+ messages in thread
From: Luis Machado @ 2008-08-08 15:22 UTC (permalink / raw)
  To: Thiago Jung Bauermann; +Cc: gdb-patches

The changelog is a bit bogus in here, i forgot to include the new
"ppc_num_vshrs" constant i defined. I have that fixed already though.
Will send it again after some comments.

On Fri, 2008-08-08 at 12:10 -0300, Luis Machado wrote:
> Patch updated.
> 
> > >  /* Constants for register set sizes.  */
> > >  enum
> > >    {
> > > -    ppc_num_gprs = 32,          /* 32 general-purpose registers */
> > > -    ppc_num_fprs = 32,          /* 32 floating-point registers */
> > > -    ppc_num_srs = 16,           /* 16 segment registers */
> > > -    ppc_num_vrs = 32            /* 32 Altivec vector registers */
> > > +    ppc_num_gprs = 32,         /* 32 general-purpose registers.  */
> > > +    ppc_num_fprs = 32,         /* 32 floating-point registers.  */
> > > +    ppc_num_srs = 16,          /* 16 segment registers.  */
> > > +    ppc_num_vrs = 32,          /* 32 Altivec vector registers.  */
> > > +    ppc_num_vsrs = 64,         /* 64 VSX vector registers.  */
> > > +    ppc_num_efprs = 32         /* 32 Extended FP registers.  */
> > >    };
> > 
> > Why change the column of all the comments here?
> 
> Identation is broken (mixed tab/blank space). They're fixed now. If you
> want, i can leave it broken and fix only the ones i care for this patch.
> 
> > >  /* Linux target descriptions.  */
> > >  extern struct target_desc *tdesc_powerpc_32l;
> > >  extern struct target_desc *tdesc_powerpc_altivec32l;
> > > +extern struct target_desc *tdesc_powerpc_vsx32l;
> > >  extern struct target_desc *tdesc_powerpc_e500l;
> > >  extern struct target_desc *tdesc_powerpc_64l;
> > >  extern struct target_desc *tdesc_powerpc_altivec64l;
> > > -
> > > +extern struct target_desc *tdesc_powerpc_vsx64l;
> > >  #endif /* PPC_LINUX_TDEP_H */
> > 
> > I know this is very picky, but I'd preserve the blank line before
> > #endif.
> 
> The blank line is back.
> 
> 
> ---
> 2008-08-08  Luis Machado  <luisgpm@br.ibm.com>
> 
> 	* rs6000-tdep: Include "features/rs6000/powerpc-vsx32.c".
> 	Include "features/rs6000/powerpc-vsx64.c".
> 	(ppc_supply_vsxregset): New function.
> 	(ppc_collect_vsxregset): New function.
> 	(IS_VSX_PSEUDOREG): New macro.
> 	(IS_EFP_PSEUDOREG): New macro.
> 	(vsx_register_p): New function.
> 	(ppc_vsx_support_p): New function.
> 	(rs6000_builtin_type_vec128): New function.
> 	(rs6000_register_name): Hide upper halves of vs0~vs31.  Return
> 	correct names for VSX registers and EFPR registers.
> 	(rs6000_pseudo_register_type): Return correct types for VSX
> 	and EFPR registers.
> 	(rs6000_pseudo_register_reggroup_p): Return correct group for
> 	VSX and EFPR registers.
> 	(ppc_pseudo_register_read): Rename to dfp_pseudo_register_read.
> 	(ppc_pseudo_register_write): Rename to dfp_pseudo_register_write.
> 	(vsx_pseudo_register_read): New function.
> 	(vsx_pseudo_register_write): New function.
> 	(efpr_pseudo_register_read): New function.
> 	(efpr_pseudo_register_write): New function.
> 	(rs6000_pseudo_register_read): Call new VSX and EFPR read functions.
> 	(rs6000_pseudo_register_write): Call new VSX and EFPR write functions.
> 	(rs6000_gdbarch_init): Declare have_vsx.
> 	Initialize new upper half VSX registers.
> 	Initialize VSX-related and EFPR-related pseudo-registers variables.
> 	Adjust the number of pseudo registers accordingly.
> 	
> 	* ppc-linux-nat.c: Define PTRACE_GETVSXREGS, PTRACE_SETVSXREGS
> 	and SIZEOF_VSRREGS.
> 	(gdb_vsxregset_t): New type.
> 	(have_ptrace_getsetvsxregs): New variable.
> 	(fetch_vsx_register): New function.	
> 	(fetch_register): Handle VSX registers.
> 	(fetch_vsx_registers): New function.
> 	(fetch_ppc_registers): Handle VSX registers.
> 	(store_ppc_registers): Handle VSX registers.
> 	(store_vsx_register): New function.	
> 	(store_register): Handle VSX registers.
> 	(store_vsx_registers): New function.
> 	(ppc_linux_read_description): Handle VSX-enabled inferiors.
> 	(gdb_vsxregset_t): New type.
> 	(supply_vsxregset): New function.
> 	(fill_vsxregset): New function.
> 
> 	* ppc-tdep.h (vsx_register_p): New prototype.
> 	(vsx_support_p): New prototype.
> 	(ppc_vsr0_regnum): New variable.
> 	(ppc_vsr0_upper_regnum): Likewise.
> 	(ppc_efpr0_regnum): Likewise.
> 	(ppc_builtin_type_vec128): New type.
> 	(ppc_num_vsrs): New constant.
> 	(ppc_num_efprs): Likewise.
> 	Define POWERPC_VEC_VSX PPC_VSR0_UPPER_REGNUM and PPC_VSR31_UPPER_REGNUM.
> 	(ppc_supply_vsxregset): New prototype.
> 	(ppc_collect_vsxregset): New prototype.
> 
> 	* ppc-linux-tdep.c: Include "features/rs6000/powerpc-vsx32l.c"
> 	Include "features/rs6000/powerpc-vsx64l.c".
> 	(_initialize_ppc_linux_tdep): Initialize VSX-enabled targets.
> 
> 	* ppc-linux-tdep.h: Declare *tdesc_powerpc_vsx32l
> 	Declare tdesc_powerpc_vsx64l
> 
> Index: gdb/rs6000-tdep.c
> ===================================================================
> --- gdb.orig/rs6000-tdep.c	2008-08-08 07:17:03.000000000 -0700
> +++ gdb/rs6000-tdep.c	2008-08-08 07:17:47.000000000 -0700
> @@ -63,6 +63,7 @@
> 
>  #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-505.c"
> @@ -72,6 +73,7 @@
>  #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"
> @@ -88,6 +90,16 @@
>      && (regnum) >= (tdep)->ppc_dl0_regnum \
>      && (regnum) < (tdep)->ppc_dl0_regnum + 16)
> 
> +/* 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_fprs)
> +
>  /* The list of available "set powerpc ..." and "show powerpc ..."
>     commands.  */
>  static struct cmd_list_element *setpowerpccmdlist = NULL;
> @@ -133,6 +145,18 @@
>    };
> 
> 
> +/* 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
>  altivec_register_p (struct gdbarch *gdbarch, int regno)
> @@ -188,6 +212,16 @@
>  }
> 
>  /* Return non-zero if the architecture described by GDBARCH has
> +   VSX registers (vsr0 --- vsr63).  */
> +int
> +ppc_vsx_support_p (struct gdbarch *gdbarch)
> +{
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +
> +  return tdep->ppc_vsr0_regnum >= 0;
> +}
> +
> +/* Return non-zero if the architecture described by GDBARCH has
>     Altivec registers (vr0 --- vr31, vrsave and vscr).  */
>  int
>  ppc_altivec_support_p (struct gdbarch *gdbarch)
> @@ -539,6 +573,37 @@
>  		  regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8);
>  }
> 
> +/* Supply register REGNUM in the VSX register set REGSET
> +   from the buffer specified by VSRREGS and LEN to register cache
> +   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
> +
> +void
> +ppc_supply_vsxregset (const struct regset *regset, struct regcache *regcache,
> +		     int regnum, const void *vsxregs, size_t len)
> +{
> +  struct gdbarch *gdbarch = get_regcache_arch (regcache);
> +  struct gdbarch_tdep *tdep;
> +
> +  if (!ppc_vsx_support_p (gdbarch))
> +    return;
> +
> +  tdep = gdbarch_tdep (gdbarch);
> +
> +  if (regnum == -1)
> +    {
> +      int i;
> +
> +      for (i = tdep->ppc_vsr0_upper_regnum;
> +	   i < tdep->ppc_vsr0_upper_regnum + 32;
> +	   i++)
> +	ppc_supply_reg (regcache, i, vsxregs, 0, 8);
> +
> +      return;
> +    }
> +  else
> +    ppc_supply_reg (regcache, regnum, 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.  */
> @@ -669,6 +734,40 @@
>  		   regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8);
>  }
> 
> +/* Collect register REGNUM in the VSX register set
> +   REGSET from register cache REGCACHE into the buffer specified by
> +   VSRREGS and LEN.  If REGNUM is -1, do this for all registers in
> +   REGSET.  */
> +
> +void
> +ppc_collect_vsxregset (const struct regset *regset,
> +		      const struct regcache *regcache,
> +		      int regnum, void *vsxregs, size_t len)
> +{
> +  struct gdbarch *gdbarch = get_regcache_arch (regcache);
> +  struct gdbarch_tdep *tdep;
> +
> +  if (!ppc_vsx_support_p (gdbarch))
> +    return;
> +
> +  tdep = gdbarch_tdep (gdbarch);
> +
> +  if (regnum == -1)
> +    {
> +      int i;
> +
> +      for (i = tdep->ppc_vsr0_upper_regnum;
> +	   i < tdep->ppc_vsr0_upper_regnum + 32;
> +	   i++)
> +	ppc_collect_reg (regcache, i, vsxregs, 0, 8);
> +
> +      return;
> +    }
> +  else
> +    ppc_collect_reg (regcache, regnum, 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
> @@ -1915,6 +2014,47 @@
>    return tdep->ppc_builtin_type_vec64;
>  }
> 
> +/* Vector 128 type.  */
> +
> +static struct type *
> +rs6000_builtin_type_vec128 (struct gdbarch *gdbarch)
> +{
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +
> +  if (!tdep->ppc_builtin_type_vec128)
> +    {
> +      /* The type we're building is this
> +
> +	 type = union __ppc_builtin_type_vec128 {
> +	     uint128_t uint128;
> +	     float v4_float[4];
> +	     int32_t v4_int32[4];
> +	     int16_t v8_int16[8];
> +	     int8_t v16_int8[16];
> +	 }
> +      */
> +
> +      struct type *t;
> +
> +      t = init_composite_type ("__ppc_builtin_type_vec128", TYPE_CODE_UNION);
> +      append_composite_type_field (t, "uint128", builtin_type_uint128);
> +      append_composite_type_field (t, "v4_float",
> +				   init_vector_type (builtin_type_float, 4));
> +      append_composite_type_field (t, "v4_int32",
> +				   init_vector_type (builtin_type_int32, 4));
> +      append_composite_type_field (t, "v8_int16",
> +				   init_vector_type (builtin_type_int16, 8));
> +      append_composite_type_field (t, "v16_int8",
> +				   init_vector_type (builtin_type_int8, 16));
> +
> +      TYPE_FLAGS (t) |= TYPE_FLAG_VECTOR;
> +      TYPE_NAME (t) = "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
>     is an anonymous register.  */
> 
> @@ -1931,6 +2071,12 @@
>        && 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 "";
> +
>    /* Check if the SPE pseudo registers are available.  */
>    if (IS_SPE_PSEUDOREG (tdep, regno))
>      {
> @@ -1955,6 +2101,36 @@
>        return dfp128_regnames[regno - tdep->ppc_dl0_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];
> +    }
> +
>    return tdesc_register_name (gdbarch, regno);
>  }
> 
> @@ -1968,14 +2144,22 @@
> 
>    /* These are the only pseudo-registers we support.  */
>    gdb_assert (IS_SPE_PSEUDOREG (tdep, regnum)
> -	      || IS_DFP_PSEUDOREG (tdep, regnum));
> +	      || IS_DFP_PSEUDOREG (tdep, regnum)
> +	      || IS_VSX_PSEUDOREG (tdep, regnum)
> +	      || IS_EFP_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))
> +    /* PPC decimal128 pseudo-registers.  */
>      return builtin_type (gdbarch)->builtin_declong;
> +  else if (IS_VSX_PSEUDOREG (tdep, regnum))
> +    /* POWER7 VSX pseudo-registers.  */
> +    return rs6000_builtin_type_vec128 (gdbarch);
> +  else
> +    /* POWER7 Extended FP pseudo-registers.  */
> +    return builtin_type_ieee_double;
>  }
> 
>  /* Is REGNUM a member of REGGROUP?  */
> @@ -1987,13 +2171,15 @@
> 
>    /* These are the only pseudo-registers we support.  */
>    gdb_assert (IS_SPE_PSEUDOREG (tdep, regnum)
> -	      || IS_DFP_PSEUDOREG (tdep, regnum));
> +	      || IS_DFP_PSEUDOREG (tdep, regnum)
> +	      || IS_VSX_PSEUDOREG (tdep, regnum)
> +	      || IS_EFP_PSEUDOREG (tdep, regnum));
> 
> -  /* These are the e500 pseudo-registers.  */
> -  if (IS_SPE_PSEUDOREG (tdep, regnum))
> +  /* These are the e500 pseudo-registers or the POWER7 VSX registers.  */
> +  if (IS_SPE_PSEUDOREG (tdep, regnum) || IS_VSX_PSEUDOREG (tdep, regnum))
>      return group == all_reggroup || group == vector_reggroup;
>    else
> -    /* Could only be the ppc decimal128 pseudo-registers.  */
> +    /* PPC decimal128 or Extended FP pseudo-registers.  */
>      return group == all_reggroup || group == float_reggroup;
>  }
> 
> @@ -2107,10 +2293,9 @@
>  			 regcache, reg_nr, (gdb_byte *) buffer);
>  }
> 
> -/* Read method for PPC pseudo-registers. Currently this is handling the
> -   16 decimal128 registers that map into 16 pairs of FP registers.  */
> +/* Read method for DFP pseudo-registers.  */
>  static void
> -ppc_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
> +dfp_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
>  			   int reg_nr, gdb_byte *buffer)
>  {
>    struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> @@ -2133,10 +2318,9 @@
>      }
>  }
> 
> -/* 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);
> @@ -2160,6 +2344,92 @@
>      }
>  }
> 
> +/* Read method for POWER7 VSX pseudo-registers.  */
> +static void
> +vsx_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
> +			   int reg_nr, gdb_byte *buffer)
> +{
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +  int reg_index = reg_nr - tdep->ppc_vsr0_regnum;
> +
> +  /* Read the portion that overlaps the VMX registers.  */
> +  if (reg_index > 31)
> +    regcache_raw_read (regcache, tdep->ppc_vr0_regnum +
> +			reg_index - 32, buffer);
> +  else
> +    /* Read the portion that overlaps the FPR registers.  */
> +    if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
> +      {
> +	regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
> +			reg_index, buffer);
> +	regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
> +			reg_index, buffer + 8);
> +      }
> +    else
> +      {
> +	regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
> +			reg_index, buffer + 8);
> +	regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
> +			reg_index, buffer);
> +      }
> +}
> +
> +/* 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 = reg_nr - tdep->ppc_vsr0_regnum;
> +
> +  /* Write the portion that overlaps the VMX registers.  */
> +  if (reg_index > 31)
> +    regcache_raw_write (regcache, tdep->ppc_vr0_regnum +
> +			reg_index - 32, buffer);
> +  else
> +    /* Write the portion that overlaps the FPR registers.  */
> +    if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
> +      {
> +	regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
> +			reg_index, buffer);
> +	regcache_raw_write (regcache, tdep->ppc_vsr0_upper_regnum +
> +			reg_index, buffer + 8);
> +      }
> +    else
> +      {
> +	regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
> +			reg_index, buffer + 8);
> +	regcache_raw_write (regcache, tdep->ppc_vsr0_upper_regnum +
> +			reg_index, buffer);
> +      }
> +}
> +
> +/* Read method for POWER7 Extended FP pseudo-registers.  */
> +static void
> +efpr_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
> +			   int reg_nr, gdb_byte *buffer)
> +{
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +  int reg_index = reg_nr - tdep->ppc_efpr0_regnum;
> +
> +  /* Read the portion that overlaps the VMX registers.  */
> +  regcache_raw_read (regcache, tdep->ppc_vr0_regnum +
> +		     reg_index, buffer);
> +}
> +
> +/* Write method for POWER7 Extended FP pseudo-registers.  */
> +static void
> +efpr_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
> +			    int reg_nr, const gdb_byte *buffer)
> +{
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +  int reg_index = reg_nr - tdep->ppc_efpr0_regnum;
> +
> +  /* Write the portion that overlaps the VMX registers.  */
> +  regcache_raw_write (regcache, tdep->ppc_vr0_regnum +
> +		      reg_index, buffer);
> +}
> +
>  static void
>  rs6000_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
>  			     int reg_nr, gdb_byte *buffer)
> @@ -2172,7 +2442,11 @@
>    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);
> +    dfp_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
> +  else if (IS_VSX_PSEUDOREG (tdep, reg_nr))
> +    vsx_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
> +  else if (IS_EFP_PSEUDOREG (tdep, reg_nr))
> +    efpr_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
>    else
>      internal_error (__FILE__, __LINE__,
>  		    _("rs6000_pseudo_register_read: "
> @@ -2193,7 +2467,11 @@
>    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);
> +    dfp_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
> +  else if (IS_VSX_PSEUDOREG (tdep, reg_nr))
> +    vsx_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
> +  else if (IS_EFP_PSEUDOREG (tdep, reg_nr))
> +    efpr_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
>    else
>      internal_error (__FILE__, __LINE__,
>  		    _("rs6000_pseudo_register_write: "
> @@ -2776,7 +3054,8 @@
>    enum auto_boolean soft_float_flag = powerpc_soft_float_global;
>    int soft_float;
>    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;
> +  int have_fpu = 1, have_spe = 0, have_mq = 0, have_altivec = 0, have_dfp = 0,
> +      have_vsx = 0;
>    int tdesc_wordsize = -1;
>    const struct target_desc *tdesc = info.target_desc;
>    struct tdesc_arch_data *tdesc_data = NULL;
> @@ -2975,6 +3254,38 @@
>        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)
> +	    {
> +	      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
> @@ -3158,6 +3469,7 @@
> 
>    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;
> @@ -3186,7 +3498,7 @@
>    else
>      tdep->lr_frame_offset = 4;
> 
> -  if (have_spe || have_dfp)
> +  if (have_spe || have_dfp || have_vsx)
>      {
>        set_gdbarch_pseudo_register_read (gdbarch, rs6000_pseudo_register_read);
>        set_gdbarch_pseudo_register_write (gdbarch, rs6000_pseudo_register_write);
> @@ -3206,6 +3518,9 @@
>      num_pseudoregs += 32;
>    if (have_dfp)
>      num_pseudoregs += 16;
> +  if (have_vsx)
> +    /* Include both VSX and Extended FP registers.  */
> +    num_pseudoregs += 96;
> 
>    set_gdbarch_num_pseudo_regs (gdbarch, num_pseudoregs);
> 
> @@ -3307,9 +3622,26 @@
>    /* Set the register number for _Decimal128 pseudo-registers.  */
>    tdep->ppc_dl0_regnum = have_dfp? gdbarch_num_regs (gdbarch) : -1;
> 
> +  /* Set the register number for VSX pseudo-registers.  */
> +  tdep->ppc_vsr0_regnum = have_vsx? gdbarch_num_regs (gdbarch) : -1;
> +  tdep->ppc_efpr0_regnum = have_vsx? gdbarch_num_regs (gdbarch) : -1;
> +
>    if (have_dfp && have_spe)
> -    /* Put the _Decimal128 pseudo-registers after the SPE registers.  */
> -    tdep->ppc_dl0_regnum += 32;
> +    {
> +      /* Put the _Decimal128 pseudo-registers after the SPE registers.  */
> +      tdep->ppc_dl0_regnum += 32;
> +
> +      if (have_vsx)
> +	{
> +	  tdep->ppc_vsr0_regnum += 48;
> +	  tdep->ppc_efpr0_regnum += 112;
> +	}
> +    }
> +  else if (have_dfp && have_vsx)
> +    {
> +      tdep->ppc_vsr0_regnum += 16;
> +      tdep->ppc_efpr0_regnum += 80;
> +    }
> 
>    /* Setup displaced stepping.  */
>    set_gdbarch_displaced_step_copy_insn (gdbarch,
> @@ -3404,6 +3736,7 @@
>    /* 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_505 ();
> @@ -3413,6 +3746,7 @@
>    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 ();
> Index: gdb/ppc-linux-nat.c
> ===================================================================
> --- gdb.orig/ppc-linux-nat.c	2008-08-08 07:17:03.000000000 -0700
> +++ gdb/ppc-linux-nat.c	2008-08-08 07:17:47.000000000 -0700
> @@ -68,6 +68,11 @@
>  #define PTRACE_SETVRREGS 19
>  #endif
> 
> +/* PTRACE requests for POWER7 VSX registers.  */
> +#ifndef PTRACE_GETVSXREGS
> +#define PTRACE_GETVSXREGS 27
> +#define PTRACE_SETVSXREGS 28
> +#endif
> 
>  /* Similarly for the ptrace requests for getting / setting the SPE
>     registers (ev0 -- ev31, acc, and spefscr).  See the description of
> @@ -119,6 +124,41 @@
> 
>  typedef char gdb_vrregset_t[SIZEOF_VRREGS];
> 
> +/* This is the layout of the POWER7 VSX registers and the way they overlap
> +   with the existing FPR and VMX registers.
> +
> +                    VSR doubleword 0               VSR doubleword 1
> +           ----------------------------------------------------------------
> +   VSR[0]  |             FPR[0]            |                              |
> +           ----------------------------------------------------------------
> +   VSR[1]  |             FPR[1]            |                              |
> +           ----------------------------------------------------------------
> +           |              ...              |                              |
> +           |              ...              |                              |
> +           ----------------------------------------------------------------
> +   VSR[30] |             FPR[30]           |                              |
> +           ----------------------------------------------------------------
> +   VSR[31] |             FPR[31]           |                              |
> +           ----------------------------------------------------------------
> +   VSR[32] |                             VR[0]                            |
> +           ----------------------------------------------------------------
> +   VSR[33] |                             VR[1]                            |
> +           ----------------------------------------------------------------
> +           |                              ...                             |
> +           |                              ...                             |
> +           ----------------------------------------------------------------
> +   VSR[62] |                             VR[30]                           |
> +           ----------------------------------------------------------------
> +   VSR[63] |                             VR[31]                           |
> +          ----------------------------------------------------------------
> +
> +   VSX has 64 128bit registers.  The first 32 registers overlap with
> +   the FP registers (doubleword 0) and hence extend them with additional
> +   64 bits (doubleword 1).  The other 32 regs overlap with the VMX
> +   registers.  */
> +#define SIZEOF_VSXREGS 32*8
> +
> +typedef char gdb_vsxregset_t[SIZEOF_VSXREGS];
> 
>  /* On PPC processors that support the the Signal Processing Extension
>     (SPE) APU, the general-purpose registers are 64 bits long.
> @@ -144,6 +184,12 @@
>    unsigned long spefscr;
>  };
> 
> +/* Non-zero if our kernel may support the PTRACE_GETVSXREGS and
> +   PTRACE_SETVSXREGS requests, for reading and writing the VSX
> +   POWER7 registers 0 through 31.  Zero if we've tried one of them and
> +   gotten an error.  Note that VSX registers 32 through 63 overlap
> +   with VR registers 0 through 31.  */
> +int have_ptrace_getsetvsxregs = 1;
> 
>  /* Non-zero if our kernel may support the PTRACE_GETVRREGS and
>     PTRACE_SETVRREGS requests, for reading and writing the Altivec
> @@ -231,6 +277,34 @@
>    return u_addr;
>  }
> 
> +/* The Linux kernel ptrace interface for POWER7 VSX registers uses the
> +   registers set mechanism, as opposed to the interface for all the
> +   other registers, that stores/fetches each register individually.  */
> +static void
> +fetch_vsx_register (struct regcache *regcache, int tid, int regno)
> +{
> +  int ret;
> +  gdb_vsxregset_t regs;
> +  struct gdbarch *gdbarch = get_regcache_arch (regcache);
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +  int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum);
> +
> +  ret = ptrace (PTRACE_GETVSXREGS, tid, 0, &regs);
> +  if (ret < 0)
> +    {
> +      if (errno == EIO)
> +	{
> +	  have_ptrace_getsetvsxregs = 0;
> +	  return;
> +	}
> +      perror_with_name (_("Unable to fetch VSX register"));
> +    }
> +
> +  regcache_raw_supply (regcache, regno,
> +		       regs + (regno - tdep->ppc_vsr0_upper_regnum)
> +		       * vsxregsize);
> +}
> +
>  /* The Linux kernel ptrace interface for AltiVec registers uses the
>     registers set mechanism, as opposed to the interface for all the
>     other registers, that stores/fetches each register individually.  */
> @@ -365,6 +439,14 @@
>          AltiVec registers, fall through and return zeroes, because
>          regaddr will be -1 in this case.  */
>      }
> +  if (vsx_register_p (gdbarch, regno))
> +    {
> +      if (have_ptrace_getsetvsxregs)
> +	{
> +	  fetch_vsx_register (regcache, tid, regno);
> +	  return;
> +	}
> +    }
>    else if (spe_register_p (gdbarch, regno))
>      {
>        fetch_spe_register (regcache, tid, regno);
> @@ -421,6 +503,21 @@
>  }
> 
>  static void
> +supply_vsxregset (struct regcache *regcache, gdb_vsxregset_t *vsxregsetp)
> +{
> +  int i;
> +  struct gdbarch *gdbarch = get_regcache_arch (regcache);
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +  int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum);
> +
> +  for (i = 0; i < ppc_num_vshrs; i++)
> +    {
> +	regcache_raw_supply (regcache, tdep->ppc_vsr0_upper_regnum + i,
> +			     *vsxregsetp + i * vsxregsize);
> +    }
> +}
> +
> +static void
>  supply_vrregset (struct regcache *regcache, gdb_vrregset_t *vrregsetp)
>  {
>    int i;
> @@ -446,6 +543,25 @@
>  }
> 
>  static void
> +fetch_vsx_registers (struct regcache *regcache, int tid)
> +{
> +  int ret;
> +  gdb_vsxregset_t regs;
> +
> +  ret = ptrace (PTRACE_GETVSXREGS, tid, 0, &regs);
> +  if (ret < 0)
> +    {
> +      if (errno == EIO)
> +	{
> +	  have_ptrace_getsetvsxregs = 0;
> +	  return;
> +	}
> +      perror_with_name (_("Unable to fetch VSX registers"));
> +    }
> +  supply_vsxregset (regcache, &regs);
> +}
> +
> +static void
>  fetch_altivec_registers (struct regcache *regcache, int tid)
>  {
>    int ret;
> @@ -499,6 +615,9 @@
>    if (have_ptrace_getvrregs)
>      if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
>        fetch_altivec_registers (regcache, tid);
> +  if (have_ptrace_getsetvsxregs)
> +    if (tdep->ppc_vsr0_upper_regnum != -1)
> +      fetch_vsx_registers (regcache, tid);
>    if (tdep->ppc_ev0_upper_regnum >= 0)
>      fetch_spe_register (regcache, tid, -1);
>  }
> @@ -522,6 +641,35 @@
>      fetch_register (regcache, tid, regno);
>  }
> 
> +/* Store one VSX register. */
> +static void
> +store_vsx_register (const struct regcache *regcache, int tid, int regno)
> +{
> +  int ret;
> +  gdb_vsxregset_t regs;
> +  struct gdbarch *gdbarch = get_regcache_arch (regcache);
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +  int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum);
> +
> +  ret = ptrace (PTRACE_SETVSXREGS, tid, 0, &regs);
> +  if (ret < 0)
> +    {
> +      if (errno == EIO)
> +	{
> +	  have_ptrace_getsetvsxregs = 0;
> +	  return;
> +	}
> +      perror_with_name (_("Unable to fetch VSX register"));
> +    }
> +
> +  regcache_raw_collect (regcache, regno, regs +
> +			(regno - tdep->ppc_vsr0_upper_regnum) * vsxregsize);
> +
> +  ret = ptrace (PTRACE_SETVSXREGS, tid, 0, &regs);
> +  if (ret < 0)
> +    perror_with_name (_("Unable to store VSX register"));
> +}
> +
>  /* Store one register. */
>  static void
>  store_altivec_register (const struct regcache *regcache, int tid, int regno)
> @@ -660,6 +808,11 @@
>        store_altivec_register (regcache, tid, regno);
>        return;
>      }
> +  if (vsx_register_p (gdbarch, regno))
> +    {
> +      store_vsx_register (regcache, tid, regno);
> +      return;
> +    }
>    else if (spe_register_p (gdbarch, regno))
>      {
>        store_spe_register (regcache, tid, regno);
> @@ -714,6 +867,19 @@
>  }
> 
>  static void
> +fill_vsxregset (const struct regcache *regcache, gdb_vsxregset_t *vsxregsetp)
> +{
> +  int i;
> +  struct gdbarch *gdbarch = get_regcache_arch (regcache);
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +  int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum);
> +
> +  for (i = 0; i < ppc_num_vshrs; i++)
> +    regcache_raw_collect (regcache, tdep->ppc_vsr0_upper_regnum + i,
> +			  *vsxregsetp + i * vsxregsize);
> +}
> +
> +static void
>  fill_vrregset (const struct regcache *regcache, gdb_vrregset_t *vrregsetp)
>  {
>    int i;
> @@ -737,6 +903,29 @@
>  }
> 
>  static void
> +store_vsx_registers (const struct regcache *regcache, int tid)
> +{
> +  int ret;
> +  gdb_vsxregset_t regs;
> +
> +  ret = ptrace (PTRACE_GETVSXREGS, tid, 0, &regs);
> +  if (ret < 0)
> +    {
> +      if (errno == EIO)
> +	{
> +	  have_ptrace_getsetvsxregs = 0;
> +	  return;
> +	}
> +      perror_with_name (_("Couldn't get VSX registers"));
> +    }
> +
> +  fill_vsxregset (regcache, &regs);
> +
> +  if (ptrace (PTRACE_SETVSXREGS, tid, 0, &regs) < 0)
> +    perror_with_name (_("Couldn't write VSX registers"));
> +}
> +
> +static void
>  store_altivec_registers (const struct regcache *regcache, int tid)
>  {
>    int ret;
> @@ -794,6 +983,9 @@
>    if (have_ptrace_getvrregs)
>      if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
>        store_altivec_registers (regcache, tid);
> +  if (have_ptrace_getsetvsxregs)
> +    if (tdep->ppc_vsr0_upper_regnum != -1)
> +      store_vsx_registers (regcache, tid);
>    if (tdep->ppc_ev0_upper_regnum >= 0)
>      store_spe_register (regcache, tid, -1);
>  }
> @@ -989,6 +1181,7 @@
>  ppc_linux_read_description (struct target_ops *ops)
>  {
>    int altivec = 0;
> +  int vsx = 0;
> 
>    int tid = TIDGET (inferior_ptid);
>    if (tid == 0)
> @@ -1007,6 +1200,19 @@
>  	perror_with_name (_("Unable to fetch SPE registers"));
>      }
> 
> +  if (have_ptrace_getsetvsxregs)
> +    {
> +      gdb_vsxregset_t vsxregset;
> +
> +      if (ptrace (PTRACE_GETVSXREGS, tid, 0, &vsxregset) >= 0)
> +	vsx = 1;
> +
> +      /* EIO means that the PTRACE_GETVSXREGS request isn't supported.
> +	 Anything else needs to be reported.  */
> +      else if (errno != EIO)
> +	perror_with_name (_("Unable to fetch VSX registers"));
> +    }
> +
>    if (have_ptrace_getvrregs)
>      {
>        gdb_vrregset_t vrregset;
> @@ -1028,11 +1234,23 @@
>      errno = 0;
>      msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0);
>      if (errno == 0 && msr < 0)
> -      return altivec? tdesc_powerpc_altivec64l : tdesc_powerpc_64l;
> +      {
> +	if (vsx)
> +	  return tdesc_powerpc_vsx64l;
> +	else if (altivec)
> +	  return tdesc_powerpc_altivec64l;
> +
> +	return tdesc_powerpc_64l;
> +      }
>    }
>  #endif
> 
> -  return altivec? tdesc_powerpc_altivec32l : tdesc_powerpc_32l;
> +  if (vsx)
> +    return tdesc_powerpc_vsx32l;
> +  else if (altivec)
> +    return tdesc_powerpc_altivec32l;
> +
> +  return tdesc_powerpc_32l;
>  }
> 
>  void _initialize_ppc_linux_nat (void);
> Index: gdb/ppc-tdep.h
> ===================================================================
> --- gdb.orig/ppc-tdep.h	2008-08-08 07:17:03.000000000 -0700
> +++ gdb/ppc-tdep.h	2008-08-08 07:17:47.000000000 -0700
> @@ -63,6 +63,7 @@
> 
>  /* From rs6000-tdep.c... */
>  int altivec_register_p (struct gdbarch *gdbarch, int regno);
> +int vsx_register_p (struct gdbarch *gdbarch, int regno);
>  int spe_register_p (struct gdbarch *gdbarch, int regno);
> 
>  /* Return non-zero if the architecture described by GDBARCH has
> @@ -73,6 +74,9 @@
>     Altivec registers (vr0 --- vr31, vrsave and vscr).  */
>  int ppc_altivec_support_p (struct gdbarch *gdbarch);
> 
> +/* Return non-zero if the architecture described by GDBARCH has
> +   VSX registers (vsr0 --- vsr63).  */
> +int vsx_support_p (struct gdbarch *gdbarch);
>  int ppc_deal_with_atomic_sequence (struct frame_info *frame);
> 
> 
> @@ -133,6 +137,14 @@
>  				 struct regcache *regcache,
>  				 int regnum, const void *vrregs, size_t len);
> 
> +/* Supply register REGNUM in the VSX register set REGSET
> +   from the buffer specified by VSXREGS and LEN to register cache
> +   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
> +
> +extern void ppc_supply_vsxregset (const struct regset *regset,
> +				 struct regcache *regcache,
> +				 int regnum, const void *vsxregs, size_t len);
> +
>  /* 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
> @@ -160,6 +172,15 @@
>  				  const struct regcache *regcache,
>  				  int regnum, void *vrregs, size_t len);
> 
> +/* Collect register REGNUM in the VSX register set
> +   REGSET from register cache REGCACHE into the buffer specified by
> +   VSXREGS and LEN.  If REGNUM is -1, do this for all registers in
> +   REGSET.  */
> +
> +extern void ppc_collect_vsxregset (const struct regset *regset,
> +				  const struct regcache *regcache,
> +				  int regnum, void *vsxregs, size_t len);
> +
>  /* Private data that this module attaches to struct gdbarch. */
> 
>  /* Vector ABI used by the inferior.  */
> @@ -199,6 +220,11 @@
>      /* Multiplier-Quotient Register (older POWER architectures only).  */
>      int ppc_mq_regnum;
> 
> +    /* POWER7 VSX registers.  */
> +    int ppc_vsr0_regnum;	/* First VSX register.  */
> +    int ppc_vsr0_upper_regnum;  /* First right most dword vsx register.  */
> +    int ppc_efpr0_regnum;	/* First Extended FP register.  */
> +
>      /* Altivec registers.  */
>      int ppc_vr0_regnum;		/* First AltiVec register */
>      int ppc_vrsave_regnum;	/* Last AltiVec register */
> @@ -222,16 +248,20 @@
> 
>      /* ISA-specific types.  */
>      struct type *ppc_builtin_type_vec64;
> +    struct type *ppc_builtin_type_vec128;
>  };
> 
> 
>  /* Constants for register set sizes.  */
>  enum
>    {
> -    ppc_num_gprs = 32,          /* 32 general-purpose registers */
> -    ppc_num_fprs = 32,          /* 32 floating-point registers */
> -    ppc_num_srs = 16,           /* 16 segment registers */
> -    ppc_num_vrs = 32            /* 32 Altivec vector registers */
> +    ppc_num_gprs = 32,		/* 32 general-purpose registers.  */
> +    ppc_num_fprs = 32,		/* 32 floating-point registers.  */
> +    ppc_num_srs = 16,		/* 16 segment registers.  */
> +    ppc_num_vrs = 32,		/* 32 Altivec vector registers.  */
> +    ppc_num_vshrs = 32,	/* 32 doublewords (dword 1 of vs0~vs31).  */
> +    ppc_num_vsrs = 64,		/* 64 VSX vector registers.  */
> +    ppc_num_efprs = 32		/* 32 Extended FP registers.  */
>    };
> 
> 
> @@ -257,6 +287,8 @@
>    PPC_VR0_REGNUM = 106,
>    PPC_VSCR_REGNUM = 138,
>    PPC_VRSAVE_REGNUM = 139,
> +  PPC_VSR0_UPPER_REGNUM = 140,
> +  PPC_VSR31_UPPER_REGNUM = 171,
>    PPC_NUM_REGS
>  };
> 
> Index: gdb/ppc-linux-tdep.c
> ===================================================================
> --- gdb.orig/ppc-linux-tdep.c	2008-08-08 07:17:03.000000000 -0700
> +++ gdb/ppc-linux-tdep.c	2008-08-08 07:17:47.000000000 -0700
> @@ -41,8 +41,10 @@
> 
>  #include "features/rs6000/powerpc-32l.c"
>  #include "features/rs6000/powerpc-altivec32l.c"
> +#include "features/rs6000/powerpc-vsx32l.c"
>  #include "features/rs6000/powerpc-64l.c"
>  #include "features/rs6000/powerpc-altivec64l.c"
> +#include "features/rs6000/powerpc-vsx64l.c"
>  #include "features/rs6000/powerpc-e500l.c"
> 
> 
> @@ -1095,7 +1097,9 @@
>    /* Initialize the Linux target descriptions.  */
>    initialize_tdesc_powerpc_32l ();
>    initialize_tdesc_powerpc_altivec32l ();
> +  initialize_tdesc_powerpc_vsx32l ();
>    initialize_tdesc_powerpc_64l ();
>    initialize_tdesc_powerpc_altivec64l ();
> +  initialize_tdesc_powerpc_vsx64l ();
>    initialize_tdesc_powerpc_e500l ();
>  }
> Index: gdb/ppc-linux-tdep.h
> ===================================================================
> --- gdb.orig/ppc-linux-tdep.h	2008-08-08 07:17:03.000000000 -0700
> +++ gdb/ppc-linux-tdep.h	2008-08-08 07:17:47.000000000 -0700
> @@ -41,8 +41,10 @@
>  /* Linux target descriptions.  */
>  extern struct target_desc *tdesc_powerpc_32l;
>  extern struct target_desc *tdesc_powerpc_altivec32l;
> +extern struct target_desc *tdesc_powerpc_vsx32l;
>  extern struct target_desc *tdesc_powerpc_e500l;
>  extern struct target_desc *tdesc_powerpc_64l;
>  extern struct target_desc *tdesc_powerpc_altivec64l;
> +extern struct target_desc *tdesc_powerpc_vsx64l;
> 
>  #endif /* PPC_LINUX_TDEP_H */
> 
> 


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH-ppc 1/5] Add basic support for new VSX register set
  2008-08-08 15:12   ` Luis Machado
  2008-08-08 15:22     ` Luis Machado
@ 2008-08-14 19:50     ` Ulrich Weigand
  2008-08-14 20:01       ` Ulrich Weigand
  2008-08-15  5:11       ` Luis Machado
  1 sibling, 2 replies; 8+ messages in thread
From: Ulrich Weigand @ 2008-08-14 19:50 UTC (permalink / raw)
  To: luisgpm; +Cc: Thiago Jung Bauermann, gdb-patches

Luis Machado wrote:

> 2008-08-08  Luis Machado  <luisgpm@br.ibm.com>
> 
> 	* rs6000-tdep: Include "features/rs6000/powerpc-vsx32.c".
> 	Include "features/rs6000/powerpc-vsx64.c".
> 	(ppc_supply_vsxregset): New function.
> 	(ppc_collect_vsxregset): New function.
> 	(IS_VSX_PSEUDOREG): New macro.
> 	(IS_EFP_PSEUDOREG): New macro.
> 	(vsx_register_p): New function.
> 	(ppc_vsx_support_p): New function.
> 	(rs6000_builtin_type_vec128): New function.
> 	(rs6000_register_name): Hide upper halves of vs0~vs31.  Return
> 	correct names for VSX registers and EFPR registers.
> 	(rs6000_pseudo_register_type): Return correct types for VSX
> 	and EFPR registers.
> 	(rs6000_pseudo_register_reggroup_p): Return correct group for
> 	VSX and EFPR registers.
> 	(ppc_pseudo_register_read): Rename to dfp_pseudo_register_read.
> 	(ppc_pseudo_register_write): Rename to dfp_pseudo_register_write.
> 	(vsx_pseudo_register_read): New function.
> 	(vsx_pseudo_register_write): New function.
> 	(efpr_pseudo_register_read): New function.
> 	(efpr_pseudo_register_write): New function.
> 	(rs6000_pseudo_register_read): Call new VSX and EFPR read functions.
> 	(rs6000_pseudo_register_write): Call new VSX and EFPR write functions.
> 	(rs6000_gdbarch_init): Declare have_vsx.
> 	Initialize new upper half VSX registers.
> 	Initialize VSX-related and EFPR-related pseudo-registers variables.
> 	Adjust the number of pseudo registers accordingly.
> 	
> 	* ppc-linux-nat.c: Define PTRACE_GETVSXREGS, PTRACE_SETVSXREGS
> 	and SIZEOF_VSRREGS.
> 	(gdb_vsxregset_t): New type.
> 	(have_ptrace_getsetvsxregs): New variable.
> 	(fetch_vsx_register): New function.	
> 	(fetch_register): Handle VSX registers.
> 	(fetch_vsx_registers): New function.
> 	(fetch_ppc_registers): Handle VSX registers.
> 	(store_ppc_registers): Handle VSX registers.
> 	(store_vsx_register): New function.	
> 	(store_register): Handle VSX registers.
> 	(store_vsx_registers): New function.
> 	(ppc_linux_read_description): Handle VSX-enabled inferiors.
> 	(gdb_vsxregset_t): New type.
> 	(supply_vsxregset): New function.
> 	(fill_vsxregset): New function.
> 
> 	* ppc-tdep.h (vsx_register_p): New prototype.
> 	(vsx_support_p): New prototype.
> 	(ppc_vsr0_regnum): New variable.
> 	(ppc_vsr0_upper_regnum): Likewise.
> 	(ppc_efpr0_regnum): Likewise.
> 	(ppc_builtin_type_vec128): New type.
> 	(ppc_num_vsrs): New constant.
> 	(ppc_num_efprs): Likewise.
> 	Define POWERPC_VEC_VSX PPC_VSR0_UPPER_REGNUM and PPC_VSR31_UPPER_REGNUM.
> 	(ppc_supply_vsxregset): New prototype.
> 	(ppc_collect_vsxregset): New prototype.
> 
> 	* ppc-linux-tdep.c: Include "features/rs6000/powerpc-vsx32l.c"
> 	Include "features/rs6000/powerpc-vsx64l.c".
> 	(_initialize_ppc_linux_tdep): Initialize VSX-enabled targets.
> 
> 	* ppc-linux-tdep.h: Declare *tdesc_powerpc_vsx32l
> 	Declare tdesc_powerpc_vsx64l



> +/* Supply register REGNUM in the VSX register set REGSET
> +   from the buffer specified by VSRREGS and LEN to register cache
VSXREGS
> +   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */

> +/* Collect register REGNUM in the VSX register set
> +   REGSET from register cache REGCACHE into the buffer specified by
> +   VSRREGS and LEN.  If REGNUM is -1, do this for all registers in
VSXREGS
> +   REGSET.  */

> +      t = init_composite_type ("__ppc_builtin_type_vec128", TYPE_CODE_UNION);
> +      append_composite_type_field (t, "uint128", builtin_type_uint128);
> +      append_composite_type_field (t, "v4_float",
> +				   init_vector_type (builtin_type_float, 4));
> +      append_composite_type_field (t, "v4_int32",
> +				   init_vector_type (builtin_type_int32, 4));
> +      append_composite_type_field (t, "v8_int16",
> +				   init_vector_type (builtin_type_int16, 8));
> +      append_composite_type_field (t, "v16_int8",
> +				   init_vector_type (builtin_type_int8, 16));

Please use builtin_type (gdbarch)->builtin_... instead of builtin_type_...
I'm just trying to get rid of those ...

> @@ -3307,9 +3622,26 @@
>    /* Set the register number for _Decimal128 pseudo-registers.  */
>    tdep->ppc_dl0_regnum = have_dfp? gdbarch_num_regs (gdbarch) : -1;
>  
> +  /* Set the register number for VSX pseudo-registers.  */
> +  tdep->ppc_vsr0_regnum = have_vsx? gdbarch_num_regs (gdbarch) : -1;
> +  tdep->ppc_efpr0_regnum = have_vsx? gdbarch_num_regs (gdbarch) : -1;
> +
>    if (have_dfp && have_spe)
> -    /* Put the _Decimal128 pseudo-registers after the SPE registers.  */
> -    tdep->ppc_dl0_regnum += 32;
> +    {
> +      /* Put the _Decimal128 pseudo-registers after the SPE registers.  */
> +      tdep->ppc_dl0_regnum += 32;
> +
> +      if (have_vsx)
> +	{
> +	  tdep->ppc_vsr0_regnum += 48;
> +	  tdep->ppc_efpr0_regnum += 112;
> +	}
> +    }
> +  else if (have_dfp && have_vsx)
> +    {
> +      tdep->ppc_vsr0_regnum += 16;
> +      tdep->ppc_efpr0_regnum += 80;
> +    }

This logic seems a bit convoluted.   Why not something along those lines:

  /* Choose register numbers for all supported pseudo-registers.  */
  tdep->ppc_ev0_regnum = -1;
  tdep->ppc_dl0_regnum = -1;
  tdep->ppc_vsr0_regnum = -1;
  tdep->ppc_epf0_regnum = -1;

  cur_reg = gdbarch_num_regs (gdbarch);

  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_vsx)
    {
      tdep->ppc_vsr0_regnum = cur_reg;
      cur_reg += 64;
      tdep->ppc_efpr0_regnum = cur_reg;
      cur_reg += 32;
    }

  gdb_assert (gdbarch_num_regs (gdbarch)
	      + gdbarch_num_pseudo_reg (gdbarch) == cur_reg);


Otherwise, this looks good to me.

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH-ppc 1/5] Add basic support for new VSX register set
  2008-08-14 19:50     ` Ulrich Weigand
@ 2008-08-14 20:01       ` Ulrich Weigand
  2008-08-15  5:11       ` Luis Machado
  1 sibling, 0 replies; 8+ messages in thread
From: Ulrich Weigand @ 2008-08-14 20:01 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: luisgpm, Thiago Jung Bauermann, gdb-patches

> > +      t = init_composite_type ("__ppc_builtin_type_vec128", TYPE_CODE_UNION);
> > +      append_composite_type_field (t, "uint128", builtin_type_uint128);
> > +      append_composite_type_field (t, "v4_float",
> > +				   init_vector_type (builtin_type_float, 4));
> > +      append_composite_type_field (t, "v4_int32",
> > +				   init_vector_type (builtin_type_int32, 4));
> > +      append_composite_type_field (t, "v8_int16",
> > +				   init_vector_type (builtin_type_int16, 8));
> > +      append_composite_type_field (t, "v16_int8",
> > +				   init_vector_type (builtin_type_int8, 16));
> 
> Please use builtin_type (gdbarch)->builtin_... instead of builtin_type_...
> I'm just trying to get rid of those ...

This might have been a bit confusing: the platform-independent types like
builtin_type_int8 are of course fine to use.  I was referring to the
platform-dependent types like builtin_type_float (and builtin_type_double
that you're using elsewhere).

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH-ppc 1/5] Add basic support for new VSX register set
  2008-08-14 19:50     ` Ulrich Weigand
  2008-08-14 20:01       ` Ulrich Weigand
@ 2008-08-15  5:11       ` Luis Machado
  2008-08-15 11:17         ` Ulrich Weigand
  1 sibling, 1 reply; 8+ messages in thread
From: Luis Machado @ 2008-08-15  5:11 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: Thiago Jung Bauermann, gdb-patches

Hi,

On Thu, 2008-08-14 at 21:49 +0200, Ulrich Weigand wrote:
> > +      t = init_composite_type ("__ppc_builtin_type_vec128", TYPE_CODE_UNION);
> > +      append_composite_type_field (t, "uint128", builtin_type_uint128);
> > +      append_composite_type_field (t, "v4_float",
> > +				   init_vector_type (builtin_type_float, 4));
> > +      append_composite_type_field (t, "v4_int32",
> > +				   init_vector_type (builtin_type_int32, 4));
> > +      append_composite_type_field (t, "v8_int16",
> > +				   init_vector_type (builtin_type_int16, 8));
> > +      append_composite_type_field (t, "v16_int8",
> > +				   init_vector_type (builtin_type_int8, 16));
> 
> Please use builtin_type (gdbarch)->builtin_... instead of builtin_type_...
> I'm just trying to get rid of those ...

Like the following updated patch?

> This logic seems a bit convoluted.   Why not something along those lines:

I've switched to your suggestion. Thanks.

Regards,
Luis


---

2008-08-15  Luis Machado  <luisgpm@br.ibm.com>

	* rs6000-tdep: Include "features/rs6000/powerpc-vsx32.c".
	Include "features/rs6000/powerpc-vsx64.c".
	(ppc_supply_vsxregset): New function.
	(ppc_collect_vsxregset): New function.
	(IS_VSX_PSEUDOREG): New macro.
	(IS_EFP_PSEUDOREG): New macro.
	(vsx_register_p): New function.
	(ppc_vsx_support_p): New function.
	(rs6000_builtin_type_vec128): New function.
	(rs6000_register_name): Hide upper halves of vs0~vs31.  Return
	correct names for VSX registers and EFPR registers.
	(rs6000_pseudo_register_type): Return correct types for VSX
	and EFPR registers.
	(rs6000_pseudo_register_reggroup_p): Return correct group for
	VSX and EFPR registers.
	(ppc_pseudo_register_read): Rename to dfp_pseudo_register_read.
	(ppc_pseudo_register_write): Rename to dfp_pseudo_register_write.
	(vsx_pseudo_register_read): New function.
	(vsx_pseudo_register_write): New function.
	(efpr_pseudo_register_read): New function.
	(efpr_pseudo_register_write): New function.
	(rs6000_pseudo_register_read): Call new VSX and EFPR read functions.
	(rs6000_pseudo_register_write): Call new VSX and EFPR write functions.
	(rs6000_gdbarch_init): Declare have_vsx.
	Initialize new upper half VSX registers.
	Initialize VSX-related and EFPR-related pseudo-registers variables.
	Adjust the number of pseudo registers accordingly.
	
	* ppc-linux-nat.c: Define PTRACE_GETVSXREGS, PTRACE_SETVSXREGS
	and SIZEOF_VSRREGS.
	(gdb_vsxregset_t): New type.
	(have_ptrace_getsetvsxregs): New variable.
	(fetch_vsx_register): New function.	
	(fetch_register): Handle VSX registers.
	(fetch_vsx_registers): New function.
	(fetch_ppc_registers): Handle VSX registers.
	(store_ppc_registers): Handle VSX registers.
	(store_vsx_register): New function.	
	(store_register): Handle VSX registers.
	(store_vsx_registers): New function.
	(ppc_linux_read_description): Handle VSX-enabled inferiors.
	(gdb_vsxregset_t): New type.
	(supply_vsxregset): New function.
	(fill_vsxregset): New function.

	* ppc-tdep.h (vsx_register_p): New prototype.
	(vsx_support_p): New prototype.
	(ppc_vsr0_regnum): New variable.
	(ppc_vsr0_upper_regnum): Likewise.
	(ppc_efpr0_regnum): Likewise.
	(ppc_builtin_type_vec128): New type.
	(ppc_num_vsrs): New constant.
	(ppc_num_vshrs): New constant.
	(ppc_num_efprs): Likewise.
	Define POWERPC_VEC_VSX PPC_VSR0_UPPER_REGNUM and PPC_VSR31_UPPER_REGNUM.
	(ppc_supply_vsxregset): New prototype.
	(ppc_collect_vsxregset): New prototype.

	* ppc-linux-tdep.c: Include "features/rs6000/powerpc-vsx32l.c"
	Include "features/rs6000/powerpc-vsx64l.c".
	(_initialize_ppc_linux_tdep): Initialize VSX-enabled targets.

	* ppc-linux-tdep.h: Declare *tdesc_powerpc_vsx32l
	Declare tdesc_powerpc_vsx64l

Index: gdb/rs6000-tdep.c
===================================================================
--- gdb.orig/rs6000-tdep.c	2008-08-14 21:49:44.000000000 -0700
+++ gdb/rs6000-tdep.c	2008-08-14 21:50:54.000000000 -0700
@@ -63,6 +63,7 @@
 
 #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-505.c"
@@ -72,6 +73,7 @@
 #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"
@@ -88,6 +90,16 @@
     && (regnum) >= (tdep)->ppc_dl0_regnum \
     && (regnum) < (tdep)->ppc_dl0_regnum + 16)
 
+/* 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_fprs)
+
 /* The list of available "set powerpc ..." and "show powerpc ..."
    commands.  */
 static struct cmd_list_element *setpowerpccmdlist = NULL;
@@ -133,6 +145,18 @@
   };
 
 
+/* 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
 altivec_register_p (struct gdbarch *gdbarch, int regno)
@@ -188,6 +212,16 @@
 }
 
 /* Return non-zero if the architecture described by GDBARCH has
+   VSX registers (vsr0 --- vsr63).  */
+int
+ppc_vsx_support_p (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  return tdep->ppc_vsr0_regnum >= 0;
+}
+
+/* Return non-zero if the architecture described by GDBARCH has
    Altivec registers (vr0 --- vr31, vrsave and vscr).  */
 int
 ppc_altivec_support_p (struct gdbarch *gdbarch)
@@ -539,6 +573,37 @@
 		  regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8);
 }
 
+/* Supply register REGNUM in the VSX register set REGSET
+   from the buffer specified by VSXREGS and LEN to register cache
+   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
+
+void
+ppc_supply_vsxregset (const struct regset *regset, struct regcache *regcache,
+		     int regnum, const void *vsxregs, size_t len)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep;
+
+  if (!ppc_vsx_support_p (gdbarch))
+    return;
+
+  tdep = gdbarch_tdep (gdbarch);
+
+  if (regnum == -1)
+    {
+      int i;
+
+      for (i = tdep->ppc_vsr0_upper_regnum;
+	   i < tdep->ppc_vsr0_upper_regnum + 32;
+	   i++)
+	ppc_supply_reg (regcache, i, vsxregs, 0, 8);
+
+      return;
+    }
+  else
+    ppc_supply_reg (regcache, regnum, 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.  */
@@ -669,6 +734,40 @@
 		   regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8);
 }
 
+/* Collect register REGNUM in the VSX register set
+   REGSET from register cache REGCACHE into the buffer specified by
+   VSXREGS and LEN.  If REGNUM is -1, do this for all registers in
+   REGSET.  */
+
+void
+ppc_collect_vsxregset (const struct regset *regset,
+		      const struct regcache *regcache,
+		      int regnum, void *vsxregs, size_t len)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep;
+
+  if (!ppc_vsx_support_p (gdbarch))
+    return;
+
+  tdep = gdbarch_tdep (gdbarch);
+
+  if (regnum == -1)
+    {
+      int i;
+
+      for (i = tdep->ppc_vsr0_upper_regnum;
+	   i < tdep->ppc_vsr0_upper_regnum + 32;
+	   i++)
+	ppc_collect_reg (regcache, i, vsxregs, 0, 8);
+
+      return;
+    }
+  else
+    ppc_collect_reg (regcache, regnum, 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
@@ -1964,6 +2063,47 @@
   return tdep->ppc_builtin_type_vec64;
 }
 
+/* Vector 128 type.  */
+
+static struct type *
+rs6000_builtin_type_vec128 (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (!tdep->ppc_builtin_type_vec128)
+    {
+      /* The type we're building is this
+
+	 type = union __ppc_builtin_type_vec128 {
+	     uint128_t uint128;
+	     float v4_float[4];
+	     int32_t v4_int32[4];
+	     int16_t v8_int16[8];
+	     int8_t v16_int8[16];
+	 }
+      */
+
+      struct type *t;
+
+      t = init_composite_type ("__ppc_builtin_type_vec128", TYPE_CODE_UNION);
+      append_composite_type_field (t, "uint128", builtin_type_uint128);
+      append_composite_type_field (t, "v4_float",
+				   init_vector_type (builtin_type (gdbarch)->builtin_float, 4));
+      append_composite_type_field (t, "v4_int32",
+				   init_vector_type (builtin_type_int32, 4));
+      append_composite_type_field (t, "v8_int16",
+				   init_vector_type (builtin_type_int16, 8));
+      append_composite_type_field (t, "v16_int8",
+				   init_vector_type (builtin_type_int8, 16));
+
+      TYPE_FLAGS (t) |= TYPE_FLAG_VECTOR;
+      TYPE_NAME (t) = "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
    is an anonymous register.  */
 
@@ -1980,6 +2120,12 @@
       && 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 "";
+
   /* Check if the SPE pseudo registers are available.  */
   if (IS_SPE_PSEUDOREG (tdep, regno))
     {
@@ -2004,6 +2150,36 @@
       return dfp128_regnames[regno - tdep->ppc_dl0_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];
+    }
+
   return tdesc_register_name (gdbarch, regno);
 }
 
@@ -2017,14 +2193,22 @@
 
   /* These are the only pseudo-registers we support.  */
   gdb_assert (IS_SPE_PSEUDOREG (tdep, regnum)
-	      || IS_DFP_PSEUDOREG (tdep, regnum));
+	      || IS_DFP_PSEUDOREG (tdep, regnum)
+	      || IS_VSX_PSEUDOREG (tdep, regnum)
+	      || IS_EFP_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))
+    /* PPC decimal128 pseudo-registers.  */
     return builtin_type (gdbarch)->builtin_declong;
+  else if (IS_VSX_PSEUDOREG (tdep, regnum))
+    /* POWER7 VSX pseudo-registers.  */
+    return rs6000_builtin_type_vec128 (gdbarch);
+  else
+    /* POWER7 Extended FP pseudo-registers.  */
+    return builtin_type (gdbarch)->builtin_double;
 }
 
 /* Is REGNUM a member of REGGROUP?  */
@@ -2036,13 +2220,15 @@
 
   /* These are the only pseudo-registers we support.  */
   gdb_assert (IS_SPE_PSEUDOREG (tdep, regnum)
-	      || IS_DFP_PSEUDOREG (tdep, regnum));
+	      || IS_DFP_PSEUDOREG (tdep, regnum)
+	      || IS_VSX_PSEUDOREG (tdep, regnum)
+	      || IS_EFP_PSEUDOREG (tdep, regnum));
 
-  /* These are the e500 pseudo-registers.  */
-  if (IS_SPE_PSEUDOREG (tdep, regnum))
+  /* These are the e500 pseudo-registers or the POWER7 VSX registers.  */
+  if (IS_SPE_PSEUDOREG (tdep, regnum) || IS_VSX_PSEUDOREG (tdep, regnum))
     return group == all_reggroup || group == vector_reggroup;
   else
-    /* Could only be the ppc decimal128 pseudo-registers.  */
+    /* PPC decimal128 or Extended FP pseudo-registers.  */
     return group == all_reggroup || group == float_reggroup;
 }
 
@@ -2156,10 +2342,9 @@
 			 regcache, reg_nr, (gdb_byte *) buffer);
 }
 
-/* Read method for PPC pseudo-registers. Currently this is handling the
-   16 decimal128 registers that map into 16 pairs of FP registers.  */
+/* Read method for DFP pseudo-registers.  */
 static void
-ppc_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+dfp_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 			   int reg_nr, gdb_byte *buffer)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
@@ -2182,10 +2367,9 @@
     }
 }
 
-/* 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);
@@ -2209,6 +2393,92 @@
     }
 }
 
+/* Read method for POWER7 VSX pseudo-registers.  */
+static void
+vsx_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+			   int reg_nr, gdb_byte *buffer)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int reg_index = reg_nr - tdep->ppc_vsr0_regnum;
+
+  /* Read the portion that overlaps the VMX registers.  */
+  if (reg_index > 31)
+    regcache_raw_read (regcache, tdep->ppc_vr0_regnum +
+			reg_index - 32, buffer);
+  else
+    /* Read the portion that overlaps the FPR registers.  */
+    if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+      {
+	regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+			reg_index, buffer);
+	regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
+			reg_index, buffer + 8);
+      }
+    else
+      {
+	regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+			reg_index, buffer + 8);
+	regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
+			reg_index, buffer);
+      }
+}
+
+/* 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 = reg_nr - tdep->ppc_vsr0_regnum;
+
+  /* Write the portion that overlaps the VMX registers.  */
+  if (reg_index > 31)
+    regcache_raw_write (regcache, tdep->ppc_vr0_regnum +
+			reg_index - 32, buffer);
+  else
+    /* Write the portion that overlaps the FPR registers.  */
+    if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+      {
+	regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
+			reg_index, buffer);
+	regcache_raw_write (regcache, tdep->ppc_vsr0_upper_regnum +
+			reg_index, buffer + 8);
+      }
+    else
+      {
+	regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
+			reg_index, buffer + 8);
+	regcache_raw_write (regcache, tdep->ppc_vsr0_upper_regnum +
+			reg_index, buffer);
+      }
+}
+
+/* Read method for POWER7 Extended FP pseudo-registers.  */
+static void
+efpr_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+			   int reg_nr, gdb_byte *buffer)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int reg_index = reg_nr - tdep->ppc_efpr0_regnum;
+
+  /* Read the portion that overlaps the VMX registers.  */
+  regcache_raw_read (regcache, tdep->ppc_vr0_regnum +
+		     reg_index, buffer);
+}
+
+/* Write method for POWER7 Extended FP pseudo-registers.  */
+static void
+efpr_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+			    int reg_nr, const gdb_byte *buffer)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int reg_index = reg_nr - tdep->ppc_efpr0_regnum;
+
+  /* Write the portion that overlaps the VMX registers.  */
+  regcache_raw_write (regcache, tdep->ppc_vr0_regnum +
+		      reg_index, buffer);
+}
+
 static void
 rs6000_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 			     int reg_nr, gdb_byte *buffer)
@@ -2221,7 +2491,11 @@
   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);
+    dfp_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+  else if (IS_VSX_PSEUDOREG (tdep, reg_nr))
+    vsx_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+  else if (IS_EFP_PSEUDOREG (tdep, reg_nr))
+    efpr_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
   else
     internal_error (__FILE__, __LINE__,
 		    _("rs6000_pseudo_register_read: "
@@ -2242,7 +2516,11 @@
   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);
+    dfp_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+  else if (IS_VSX_PSEUDOREG (tdep, reg_nr))
+    vsx_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+  else if (IS_EFP_PSEUDOREG (tdep, reg_nr))
+    efpr_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
   else
     internal_error (__FILE__, __LINE__,
 		    _("rs6000_pseudo_register_write: "
@@ -2825,11 +3103,13 @@
   enum auto_boolean soft_float_flag = powerpc_soft_float_global;
   int soft_float;
   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;
+  int have_fpu = 1, have_spe = 0, have_mq = 0, have_altivec = 0, have_dfp = 0,
+      have_vsx = 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;
@@ -3024,6 +3304,38 @@
       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)
+	    {
+	      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
@@ -3207,6 +3519,7 @@
 
   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;
@@ -3235,7 +3548,7 @@
   else
     tdep->lr_frame_offset = 4;
 
-  if (have_spe || have_dfp)
+  if (have_spe || have_dfp || have_vsx)
     {
       set_gdbarch_pseudo_register_read (gdbarch, rs6000_pseudo_register_read);
       set_gdbarch_pseudo_register_write (gdbarch, rs6000_pseudo_register_write);
@@ -3255,6 +3568,9 @@
     num_pseudoregs += 32;
   if (have_dfp)
     num_pseudoregs += 16;
+  if (have_vsx)
+    /* Include both VSX and Extended FP registers.  */
+    num_pseudoregs += 96;
 
   set_gdbarch_num_pseudo_regs (gdbarch, num_pseudoregs);
 
@@ -3357,9 +3673,38 @@
   /* Set the register number for _Decimal128 pseudo-registers.  */
   tdep->ppc_dl0_regnum = have_dfp? gdbarch_num_regs (gdbarch) : -1;
 
-  if (have_dfp && have_spe)
-    /* Put the _Decimal128 pseudo-registers after the SPE registers.  */
-    tdep->ppc_dl0_regnum += 32;
+  /* Set the register number for VSX pseudo-registers.  */
+  tdep->ppc_vsr0_regnum = have_vsx? gdbarch_num_regs (gdbarch) : -1;
+  tdep->ppc_efpr0_regnum = have_vsx? 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_vsr0_regnum = -1;
+  tdep->ppc_efpr0_regnum = -1;
+
+  cur_reg = gdbarch_num_regs (gdbarch);
+
+  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_vsx)
+    {
+      tdep->ppc_vsr0_regnum = cur_reg;
+      cur_reg += 64;
+      tdep->ppc_efpr0_regnum = cur_reg;
+      cur_reg += 32;
+    }
+
+  gdb_assert (gdbarch_num_regs (gdbarch)
+	      + gdbarch_num_pseudo_regs (gdbarch) == cur_reg);
 
   /* Setup displaced stepping.  */
   set_gdbarch_displaced_step_copy_insn (gdbarch,
@@ -3454,6 +3799,7 @@
   /* 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_505 ();
@@ -3463,6 +3809,7 @@
   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 ();
Index: gdb/ppc-linux-nat.c
===================================================================
--- gdb.orig/ppc-linux-nat.c	2008-08-14 21:49:44.000000000 -0700
+++ gdb/ppc-linux-nat.c	2008-08-14 21:49:46.000000000 -0700
@@ -76,6 +76,11 @@
 #define PTRACE_SETVRREGS 19
 #endif
 
+/* PTRACE requests for POWER7 VSX registers.  */
+#ifndef PTRACE_GETVSXREGS
+#define PTRACE_GETVSXREGS 27
+#define PTRACE_SETVSXREGS 28
+#endif
 
 /* Similarly for the ptrace requests for getting / setting the SPE
    registers (ev0 -- ev31, acc, and spefscr).  See the description of
@@ -127,6 +132,41 @@
 
 typedef char gdb_vrregset_t[SIZEOF_VRREGS];
 
+/* This is the layout of the POWER7 VSX registers and the way they overlap
+   with the existing FPR and VMX registers.
+
+                    VSR doubleword 0               VSR doubleword 1
+           ----------------------------------------------------------------
+   VSR[0]  |             FPR[0]            |                              |
+           ----------------------------------------------------------------
+   VSR[1]  |             FPR[1]            |                              |
+           ----------------------------------------------------------------
+           |              ...              |                              |
+           |              ...              |                              |
+           ----------------------------------------------------------------
+   VSR[30] |             FPR[30]           |                              |
+           ----------------------------------------------------------------
+   VSR[31] |             FPR[31]           |                              |
+           ----------------------------------------------------------------
+   VSR[32] |                             VR[0]                            |
+           ----------------------------------------------------------------
+   VSR[33] |                             VR[1]                            |
+           ----------------------------------------------------------------
+           |                              ...                             |
+           |                              ...                             |
+           ----------------------------------------------------------------
+   VSR[62] |                             VR[30]                           |
+           ----------------------------------------------------------------
+   VSR[63] |                             VR[31]                           |
+          ----------------------------------------------------------------
+
+   VSX has 64 128bit registers.  The first 32 registers overlap with
+   the FP registers (doubleword 0) and hence extend them with additional
+   64 bits (doubleword 1).  The other 32 regs overlap with the VMX
+   registers.  */
+#define SIZEOF_VSXREGS 32*8
+
+typedef char gdb_vsxregset_t[SIZEOF_VSXREGS];
 
 /* On PPC processors that support the the Signal Processing Extension
    (SPE) APU, the general-purpose registers are 64 bits long.
@@ -152,6 +192,12 @@
   unsigned long spefscr;
 };
 
+/* Non-zero if our kernel may support the PTRACE_GETVSXREGS and
+   PTRACE_SETVSXREGS requests, for reading and writing the VSX
+   POWER7 registers 0 through 31.  Zero if we've tried one of them and
+   gotten an error.  Note that VSX registers 32 through 63 overlap
+   with VR registers 0 through 31.  */
+int have_ptrace_getsetvsxregs = 1;
 
 /* Non-zero if our kernel may support the PTRACE_GETVRREGS and
    PTRACE_SETVRREGS requests, for reading and writing the Altivec
@@ -239,6 +285,34 @@
   return u_addr;
 }
 
+/* The Linux kernel ptrace interface for POWER7 VSX registers uses the
+   registers set mechanism, as opposed to the interface for all the
+   other registers, that stores/fetches each register individually.  */
+static void
+fetch_vsx_register (struct regcache *regcache, int tid, int regno)
+{
+  int ret;
+  gdb_vsxregset_t regs;
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum);
+
+  ret = ptrace (PTRACE_GETVSXREGS, tid, 0, &regs);
+  if (ret < 0)
+    {
+      if (errno == EIO)
+	{
+	  have_ptrace_getsetvsxregs = 0;
+	  return;
+	}
+      perror_with_name (_("Unable to fetch VSX register"));
+    }
+
+  regcache_raw_supply (regcache, regno,
+		       regs + (regno - tdep->ppc_vsr0_upper_regnum)
+		       * vsxregsize);
+}
+
 /* The Linux kernel ptrace interface for AltiVec registers uses the
    registers set mechanism, as opposed to the interface for all the
    other registers, that stores/fetches each register individually.  */
@@ -373,6 +447,14 @@
         AltiVec registers, fall through and return zeroes, because
         regaddr will be -1 in this case.  */
     }
+  if (vsx_register_p (gdbarch, regno))
+    {
+      if (have_ptrace_getsetvsxregs)
+	{
+	  fetch_vsx_register (regcache, tid, regno);
+	  return;
+	}
+    }
   else if (spe_register_p (gdbarch, regno))
     {
       fetch_spe_register (regcache, tid, regno);
@@ -429,6 +511,21 @@
 }
 
 static void
+supply_vsxregset (struct regcache *regcache, gdb_vsxregset_t *vsxregsetp)
+{
+  int i;
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum);
+
+  for (i = 0; i < ppc_num_vshrs; i++)
+    {
+	regcache_raw_supply (regcache, tdep->ppc_vsr0_upper_regnum + i,
+			     *vsxregsetp + i * vsxregsize);
+    }
+}
+
+static void
 supply_vrregset (struct regcache *regcache, gdb_vrregset_t *vrregsetp)
 {
   int i;
@@ -454,6 +551,25 @@
 }
 
 static void
+fetch_vsx_registers (struct regcache *regcache, int tid)
+{
+  int ret;
+  gdb_vsxregset_t regs;
+
+  ret = ptrace (PTRACE_GETVSXREGS, tid, 0, &regs);
+  if (ret < 0)
+    {
+      if (errno == EIO)
+	{
+	  have_ptrace_getsetvsxregs = 0;
+	  return;
+	}
+      perror_with_name (_("Unable to fetch VSX registers"));
+    }
+  supply_vsxregset (regcache, &regs);
+}
+
+static void
 fetch_altivec_registers (struct regcache *regcache, int tid)
 {
   int ret;
@@ -507,6 +623,9 @@
   if (have_ptrace_getvrregs)
     if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
       fetch_altivec_registers (regcache, tid);
+  if (have_ptrace_getsetvsxregs)
+    if (tdep->ppc_vsr0_upper_regnum != -1)
+      fetch_vsx_registers (regcache, tid);
   if (tdep->ppc_ev0_upper_regnum >= 0)
     fetch_spe_register (regcache, tid, -1);
 }
@@ -530,6 +649,35 @@
     fetch_register (regcache, tid, regno);
 }
 
+/* Store one VSX register. */
+static void
+store_vsx_register (const struct regcache *regcache, int tid, int regno)
+{
+  int ret;
+  gdb_vsxregset_t regs;
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum);
+
+  ret = ptrace (PTRACE_SETVSXREGS, tid, 0, &regs);
+  if (ret < 0)
+    {
+      if (errno == EIO)
+	{
+	  have_ptrace_getsetvsxregs = 0;
+	  return;
+	}
+      perror_with_name (_("Unable to fetch VSX register"));
+    }
+
+  regcache_raw_collect (regcache, regno, regs +
+			(regno - tdep->ppc_vsr0_upper_regnum) * vsxregsize);
+
+  ret = ptrace (PTRACE_SETVSXREGS, tid, 0, &regs);
+  if (ret < 0)
+    perror_with_name (_("Unable to store VSX register"));
+}
+
 /* Store one register. */
 static void
 store_altivec_register (const struct regcache *regcache, int tid, int regno)
@@ -668,6 +816,11 @@
       store_altivec_register (regcache, tid, regno);
       return;
     }
+  if (vsx_register_p (gdbarch, regno))
+    {
+      store_vsx_register (regcache, tid, regno);
+      return;
+    }
   else if (spe_register_p (gdbarch, regno))
     {
       store_spe_register (regcache, tid, regno);
@@ -722,6 +875,19 @@
 }
 
 static void
+fill_vsxregset (const struct regcache *regcache, gdb_vsxregset_t *vsxregsetp)
+{
+  int i;
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum);
+
+  for (i = 0; i < ppc_num_vshrs; i++)
+    regcache_raw_collect (regcache, tdep->ppc_vsr0_upper_regnum + i,
+			  *vsxregsetp + i * vsxregsize);
+}
+
+static void
 fill_vrregset (const struct regcache *regcache, gdb_vrregset_t *vrregsetp)
 {
   int i;
@@ -745,6 +911,29 @@
 }
 
 static void
+store_vsx_registers (const struct regcache *regcache, int tid)
+{
+  int ret;
+  gdb_vsxregset_t regs;
+
+  ret = ptrace (PTRACE_GETVSXREGS, tid, 0, &regs);
+  if (ret < 0)
+    {
+      if (errno == EIO)
+	{
+	  have_ptrace_getsetvsxregs = 0;
+	  return;
+	}
+      perror_with_name (_("Couldn't get VSX registers"));
+    }
+
+  fill_vsxregset (regcache, &regs);
+
+  if (ptrace (PTRACE_SETVSXREGS, tid, 0, &regs) < 0)
+    perror_with_name (_("Couldn't write VSX registers"));
+}
+
+static void
 store_altivec_registers (const struct regcache *regcache, int tid)
 {
   int ret;
@@ -802,6 +991,9 @@
   if (have_ptrace_getvrregs)
     if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
       store_altivec_registers (regcache, tid);
+  if (have_ptrace_getsetvsxregs)
+    if (tdep->ppc_vsr0_upper_regnum != -1)
+      store_vsx_registers (regcache, tid);
   if (tdep->ppc_ev0_upper_regnum >= 0)
     store_spe_register (regcache, tid, -1);
 }
@@ -1037,6 +1229,7 @@
 ppc_linux_read_description (struct target_ops *ops)
 {
   int altivec = 0;
+  int vsx = 0;
 
   int tid = TIDGET (inferior_ptid);
   if (tid == 0)
@@ -1055,6 +1248,19 @@
 	perror_with_name (_("Unable to fetch SPE registers"));
     }
 
+  if (have_ptrace_getsetvsxregs)
+    {
+      gdb_vsxregset_t vsxregset;
+
+      if (ptrace (PTRACE_GETVSXREGS, tid, 0, &vsxregset) >= 0)
+	vsx = 1;
+
+      /* EIO means that the PTRACE_GETVSXREGS request isn't supported.
+	 Anything else needs to be reported.  */
+      else if (errno != EIO)
+	perror_with_name (_("Unable to fetch VSX registers"));
+    }
+
   if (have_ptrace_getvrregs)
     {
       gdb_vrregset_t vrregset;
@@ -1076,11 +1282,23 @@
     errno = 0;
     msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0);
     if (errno == 0 && msr < 0)
-      return altivec? tdesc_powerpc_altivec64l : tdesc_powerpc_64l;
+      {
+	if (vsx)
+	  return tdesc_powerpc_vsx64l;
+	else if (altivec)
+	  return tdesc_powerpc_altivec64l;
+
+	return tdesc_powerpc_64l;
+      }
   }
 #endif
 
-  return altivec? tdesc_powerpc_altivec32l : tdesc_powerpc_32l;
+  if (vsx)
+    return tdesc_powerpc_vsx32l;
+  else if (altivec)
+    return tdesc_powerpc_altivec32l;
+
+  return tdesc_powerpc_32l;
 }
 
 void _initialize_ppc_linux_nat (void);
Index: gdb/ppc-tdep.h
===================================================================
--- gdb.orig/ppc-tdep.h	2008-08-14 21:49:44.000000000 -0700
+++ gdb/ppc-tdep.h	2008-08-14 21:49:46.000000000 -0700
@@ -63,6 +63,7 @@
 
 /* From rs6000-tdep.c... */
 int altivec_register_p (struct gdbarch *gdbarch, int regno);
+int vsx_register_p (struct gdbarch *gdbarch, int regno);
 int spe_register_p (struct gdbarch *gdbarch, int regno);
 
 /* Return non-zero if the architecture described by GDBARCH has
@@ -73,6 +74,9 @@
    Altivec registers (vr0 --- vr31, vrsave and vscr).  */
 int ppc_altivec_support_p (struct gdbarch *gdbarch);
 
+/* Return non-zero if the architecture described by GDBARCH has
+   VSX registers (vsr0 --- vsr63).  */
+int vsx_support_p (struct gdbarch *gdbarch);
 int ppc_deal_with_atomic_sequence (struct frame_info *frame);
 
 
@@ -133,6 +137,14 @@
 				 struct regcache *regcache,
 				 int regnum, const void *vrregs, size_t len);
 
+/* Supply register REGNUM in the VSX register set REGSET
+   from the buffer specified by VSXREGS and LEN to register cache
+   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
+
+extern void ppc_supply_vsxregset (const struct regset *regset,
+				 struct regcache *regcache,
+				 int regnum, const void *vsxregs, size_t len);
+
 /* 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
@@ -160,6 +172,15 @@
 				  const struct regcache *regcache,
 				  int regnum, void *vrregs, size_t len);
 
+/* Collect register REGNUM in the VSX register set
+   REGSET from register cache REGCACHE into the buffer specified by
+   VSXREGS and LEN.  If REGNUM is -1, do this for all registers in
+   REGSET.  */
+
+extern void ppc_collect_vsxregset (const struct regset *regset,
+				  const struct regcache *regcache,
+				  int regnum, void *vsxregs, size_t len);
+
 /* Private data that this module attaches to struct gdbarch. */
 
 /* Vector ABI used by the inferior.  */
@@ -199,6 +220,11 @@
     /* Multiplier-Quotient Register (older POWER architectures only).  */
     int ppc_mq_regnum;
 
+    /* POWER7 VSX registers.  */
+    int ppc_vsr0_regnum;	/* First VSX register.  */
+    int ppc_vsr0_upper_regnum;  /* First right most dword vsx register.  */
+    int ppc_efpr0_regnum;	/* First Extended FP register.  */
+
     /* Altivec registers.  */
     int ppc_vr0_regnum;		/* First AltiVec register */
     int ppc_vrsave_regnum;	/* Last AltiVec register */
@@ -222,16 +248,20 @@
 
     /* ISA-specific types.  */
     struct type *ppc_builtin_type_vec64;
+    struct type *ppc_builtin_type_vec128;
 };
 
 
 /* Constants for register set sizes.  */
 enum
   {
-    ppc_num_gprs = 32,          /* 32 general-purpose registers */
-    ppc_num_fprs = 32,          /* 32 floating-point registers */
-    ppc_num_srs = 16,           /* 16 segment registers */
-    ppc_num_vrs = 32            /* 32 Altivec vector registers */
+    ppc_num_gprs = 32,		/* 32 general-purpose registers.  */
+    ppc_num_fprs = 32,		/* 32 floating-point registers.  */
+    ppc_num_srs = 16,		/* 16 segment registers.  */
+    ppc_num_vrs = 32,		/* 32 Altivec vector registers.  */
+    ppc_num_vshrs = 32,		/* 32 doublewords (dword 1 of vs0~vs31).  */
+    ppc_num_vsrs = 64,		/* 64 VSX vector registers.  */
+    ppc_num_efprs = 32		/* 32 Extended FP registers.  */
   };
 
 
@@ -257,6 +287,8 @@
   PPC_VR0_REGNUM = 106,
   PPC_VSCR_REGNUM = 138,
   PPC_VRSAVE_REGNUM = 139,
+  PPC_VSR0_UPPER_REGNUM = 140,
+  PPC_VSR31_UPPER_REGNUM = 171,
   PPC_NUM_REGS
 };
 
Index: gdb/ppc-linux-tdep.c
===================================================================
--- gdb.orig/ppc-linux-tdep.c	2008-08-14 21:49:44.000000000 -0700
+++ gdb/ppc-linux-tdep.c	2008-08-14 21:49:46.000000000 -0700
@@ -41,8 +41,10 @@
 
 #include "features/rs6000/powerpc-32l.c"
 #include "features/rs6000/powerpc-altivec32l.c"
+#include "features/rs6000/powerpc-vsx32l.c"
 #include "features/rs6000/powerpc-64l.c"
 #include "features/rs6000/powerpc-altivec64l.c"
+#include "features/rs6000/powerpc-vsx64l.c"
 #include "features/rs6000/powerpc-e500l.c"
 
 
@@ -1095,7 +1097,9 @@
   /* Initialize the Linux target descriptions.  */
   initialize_tdesc_powerpc_32l ();
   initialize_tdesc_powerpc_altivec32l ();
+  initialize_tdesc_powerpc_vsx32l ();
   initialize_tdesc_powerpc_64l ();
   initialize_tdesc_powerpc_altivec64l ();
+  initialize_tdesc_powerpc_vsx64l ();
   initialize_tdesc_powerpc_e500l ();
 }
Index: gdb/ppc-linux-tdep.h
===================================================================
--- gdb.orig/ppc-linux-tdep.h	2008-08-14 21:49:44.000000000 -0700
+++ gdb/ppc-linux-tdep.h	2008-08-14 21:49:46.000000000 -0700
@@ -41,8 +41,10 @@
 /* Linux target descriptions.  */
 extern struct target_desc *tdesc_powerpc_32l;
 extern struct target_desc *tdesc_powerpc_altivec32l;
+extern struct target_desc *tdesc_powerpc_vsx32l;
 extern struct target_desc *tdesc_powerpc_e500l;
 extern struct target_desc *tdesc_powerpc_64l;
 extern struct target_desc *tdesc_powerpc_altivec64l;
+extern struct target_desc *tdesc_powerpc_vsx64l;
 
 #endif /* PPC_LINUX_TDEP_H */



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH-ppc 1/5] Add basic support for new VSX register set
  2008-08-15  5:11       ` Luis Machado
@ 2008-08-15 11:17         ` Ulrich Weigand
  2008-08-15 15:27           ` Luis Machado
  0 siblings, 1 reply; 8+ messages in thread
From: Ulrich Weigand @ 2008-08-15 11:17 UTC (permalink / raw)
  To: luisgpm; +Cc: Thiago Jung Bauermann, gdb-patches

Luis Machado wrote:

> > Please use builtin_type (gdbarch)->builtin_... instead of builtin_type_...
> > I'm just trying to get rid of those ...
> 
> Like the following updated patch?

Yes, thanks.

> 2008-08-15  Luis Machado  <luisgpm@br.ibm.com>
> 
> 	* rs6000-tdep: Include "features/rs6000/powerpc-vsx32.c".
> 	Include "features/rs6000/powerpc-vsx64.c".
> 	(ppc_supply_vsxregset): New function.
> 	(ppc_collect_vsxregset): New function.
> 	(IS_VSX_PSEUDOREG): New macro.
> 	(IS_EFP_PSEUDOREG): New macro.
> 	(vsx_register_p): New function.
> 	(ppc_vsx_support_p): New function.
> 	(rs6000_builtin_type_vec128): New function.
> 	(rs6000_register_name): Hide upper halves of vs0~vs31.  Return
> 	correct names for VSX registers and EFPR registers.
> 	(rs6000_pseudo_register_type): Return correct types for VSX
> 	and EFPR registers.
> 	(rs6000_pseudo_register_reggroup_p): Return correct group for
> 	VSX and EFPR registers.
> 	(ppc_pseudo_register_read): Rename to dfp_pseudo_register_read.
> 	(ppc_pseudo_register_write): Rename to dfp_pseudo_register_write.
> 	(vsx_pseudo_register_read): New function.
> 	(vsx_pseudo_register_write): New function.
> 	(efpr_pseudo_register_read): New function.
> 	(efpr_pseudo_register_write): New function.
> 	(rs6000_pseudo_register_read): Call new VSX and EFPR read functions.
> 	(rs6000_pseudo_register_write): Call new VSX and EFPR write functions.
> 	(rs6000_gdbarch_init): Declare have_vsx.
> 	Initialize new upper half VSX registers.
> 	Initialize VSX-related and EFPR-related pseudo-registers variables.
> 	Adjust the number of pseudo registers accordingly.
> 	
> 	* ppc-linux-nat.c: Define PTRACE_GETVSXREGS, PTRACE_SETVSXREGS
> 	and SIZEOF_VSRREGS.
> 	(gdb_vsxregset_t): New type.
> 	(have_ptrace_getsetvsxregs): New variable.
> 	(fetch_vsx_register): New function.	
> 	(fetch_register): Handle VSX registers.
> 	(fetch_vsx_registers): New function.
> 	(fetch_ppc_registers): Handle VSX registers.
> 	(store_ppc_registers): Handle VSX registers.
> 	(store_vsx_register): New function.	
> 	(store_register): Handle VSX registers.
> 	(store_vsx_registers): New function.
> 	(ppc_linux_read_description): Handle VSX-enabled inferiors.
> 	(gdb_vsxregset_t): New type.
> 	(supply_vsxregset): New function.
> 	(fill_vsxregset): New function.
> 
> 	* ppc-tdep.h (vsx_register_p): New prototype.
> 	(vsx_support_p): New prototype.
> 	(ppc_vsr0_regnum): New variable.
> 	(ppc_vsr0_upper_regnum): Likewise.
> 	(ppc_efpr0_regnum): Likewise.
> 	(ppc_builtin_type_vec128): New type.
> 	(ppc_num_vsrs): New constant.
> 	(ppc_num_vshrs): New constant.
> 	(ppc_num_efprs): Likewise.
> 	Define POWERPC_VEC_VSX PPC_VSR0_UPPER_REGNUM and PPC_VSR31_UPPER_REGNUM.
> 	(ppc_supply_vsxregset): New prototype.
> 	(ppc_collect_vsxregset): New prototype.
> 
> 	* ppc-linux-tdep.c: Include "features/rs6000/powerpc-vsx32l.c"
> 	Include "features/rs6000/powerpc-vsx64l.c".
> 	(_initialize_ppc_linux_tdep): Initialize VSX-enabled targets.
> 
> 	* ppc-linux-tdep.h: Declare *tdesc_powerpc_vsx32l
> 	Declare tdesc_powerpc_vsx64l

This is OK, except:

> @@ -3357,9 +3673,38 @@
>    /* Set the register number for _Decimal128 pseudo-registers.  */
>    tdep->ppc_dl0_regnum = have_dfp? gdbarch_num_regs (gdbarch) : -1;
>  
> -  if (have_dfp && have_spe)
> -    /* Put the _Decimal128 pseudo-registers after the SPE registers.  */
> -    tdep->ppc_dl0_regnum += 32;
> +  /* Set the register number for VSX pseudo-registers.  */
> +  tdep->ppc_vsr0_regnum = have_vsx? gdbarch_num_regs (gdbarch) : -1;
> +  tdep->ppc_efpr0_regnum = have_vsx? gdbarch_num_regs (gdbarch) : -1;

All the above is now obsolete if you use the new code below:

> +  /* Choose register numbers for all supported pseudo-registers.  */
> +  tdep->ppc_ev0_regnum = -1;
> +  tdep->ppc_dl0_regnum = -1;
> +  tdep->ppc_vsr0_regnum = -1;
> +  tdep->ppc_efpr0_regnum = -1;

...

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH-ppc 1/5] Add basic support for new VSX register set
  2008-08-15 11:17         ` Ulrich Weigand
@ 2008-08-15 15:27           ` Luis Machado
  0 siblings, 0 replies; 8+ messages in thread
From: Luis Machado @ 2008-08-15 15:27 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: Thiago Jung Bauermann, gdb-patches

> All the above is now obsolete if you use the new code below:

Oops. Of course. Fixed that and checked in.

Thanks,
Luis


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2008-08-15 15:27 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-07-25 20:16 [PATCH-ppc 1/5] Add basic support for new VSX register set Luis Machado
     [not found] ` <1217646694.26214.3.camel@localhost.localdomain>
2008-08-08 15:12   ` Luis Machado
2008-08-08 15:22     ` Luis Machado
2008-08-14 19:50     ` Ulrich Weigand
2008-08-14 20:01       ` Ulrich Weigand
2008-08-15  5:11       ` Luis Machado
2008-08-15 11:17         ` Ulrich Weigand
2008-08-15 15:27           ` Luis Machado

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox