* [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, ®s);
+ 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, ®s);
+ if (ret < 0)
+ {
+ if (errno == EIO)
+ {
+ have_ptrace_getsetvsxregs = 0;
+ return;
+ }
+ perror_with_name (_("Unable to fetch VSX registers"));
+ }
+ supply_vsxregset (regcache, ®s);
+}
+
+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, ®s);
+ 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, ®s);
+ 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, ®s);
+ if (ret < 0)
+ {
+ if (errno == EIO)
+ {
+ have_ptrace_getsetvsxregs = 0;
+ return;
+ }
+ perror_with_name (_("Couldn't get VSX registers"));
+ }
+
+ fill_vsxregset (regcache, ®s);
+
+ if (ptrace (PTRACE_SETVSXREGS, tid, 0, ®s) < 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[parent not found: <1217646694.26214.3.camel@localhost.localdomain>]
* 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, ®s); + 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, ®s); + if (ret < 0) + { + if (errno == EIO) + { + have_ptrace_getsetvsxregs = 0; + return; + } + perror_with_name (_("Unable to fetch VSX registers")); + } + supply_vsxregset (regcache, ®s); +} + +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, ®s); + 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, ®s); + 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, ®s); + if (ret < 0) + { + if (errno == EIO) + { + have_ptrace_getsetvsxregs = 0; + return; + } + perror_with_name (_("Couldn't get VSX registers")); + } + + fill_vsxregset (regcache, ®s); + + if (ptrace (PTRACE_SETVSXREGS, tid, 0, ®s) < 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, ®s); > + 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, ®s); > + if (ret < 0) > + { > + if (errno == EIO) > + { > + have_ptrace_getsetvsxregs = 0; > + return; > + } > + perror_with_name (_("Unable to fetch VSX registers")); > + } > + supply_vsxregset (regcache, ®s); > +} > + > +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, ®s); > + 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, ®s); > + 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, ®s); > + if (ret < 0) > + { > + if (errno == EIO) > + { > + have_ptrace_getsetvsxregs = 0; > + return; > + } > + perror_with_name (_("Couldn't get VSX registers")); > + } > + > + fill_vsxregset (regcache, ®s); > + > + if (ptrace (PTRACE_SETVSXREGS, tid, 0, ®s) < 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, ®s); + 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, ®s); + if (ret < 0) + { + if (errno == EIO) + { + have_ptrace_getsetvsxregs = 0; + return; + } + perror_with_name (_("Unable to fetch VSX registers")); + } + supply_vsxregset (regcache, ®s); +} + +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, ®s); + 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, ®s); + 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, ®s); + if (ret < 0) + { + if (errno == EIO) + { + have_ptrace_getsetvsxregs = 0; + return; + } + perror_with_name (_("Couldn't get VSX registers")); + } + + fill_vsxregset (regcache, ®s); + + if (ptrace (PTRACE_SETVSXREGS, tid, 0, ®s) < 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