public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 4/8] [PowerPC] Consolidate linux vector regset sizes
  2018-05-10 19:59 [PATCH 0/8] [PowerPC] Miscellaneous fixes for register access Pedro Franco de Carvalho
@ 2018-05-10 19:59 ` Pedro Franco de Carvalho
  2018-05-16 16:35   ` Ulrich Weigand
  2018-05-10 19:59 ` [PATCH 3/8] [PowerPC] Disable regsets using zero sizes in gdbserver Pedro Franco de Carvalho
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-10 19:59 UTC (permalink / raw)
  To: gdb-patches

This patch defines constants for the sizes of the two vector
regsets (vector-scalar registers and regular vector registers).

The native, gdbserver and core file targets are changed to use these
constants.

The Linux ptrace calls return (or read) a smaller regset than the one
found in core files for vector registers, because ptrace uses a single
4-byte quantity for vrsave at the end of the regset, while the
core-file regset uses a full 16-byte field for vrsave. For simplicity,
the larger size is used in both cases, and so a buffer with 12 unused
additional bytes is passed to ptrace in the native target.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* arch/ppc-linux-common.h (PPC_LINUX_SIZEOF_VRREGSET)
	(PPC_LINUX_SIZEOF_VSXREGSET): Define.
	* ppc-linux-nat.c (SIZEOF_VSXREGS, SIZEOF_VRREGS): Remove.
	(gdb_vrregset_t): Change array type size to
	PPC_LINUX_SIZEOF_VRREGSET.
	(gdb_vsxregset_t): Change array type size to
	PPC_LINUX_SIZEOF_VSXREGSET.
	* ppc-linux-tdep.c (ppc_linux_iterate_over_regset_sections):
	Change integer literals to PPC_LINUX_SIZEOF_VRREGSET and
	PPC_LINUX_SIZEOF_VSXREGSET.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* linux-ppc-low.c (SIZEOF_VSXREGS, SIZEOF_VRREGS): Remove.
	(ppc_arch_setup): Change SIZEOF_VRREGS and SIZEOF_VSXREGS to
	PPC_LINUX_SIZEOF_VRREGSET and PPC_LINUX_SIZEOF_VSXREGSET.
---
 gdb/arch/ppc-linux-common.h   | 9 +++++++++
 gdb/gdbserver/linux-ppc-low.c | 8 ++------
 gdb/ppc-linux-nat.c           | 8 ++------
 gdb/ppc-linux-tdep.c          | 6 ++++--
 4 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/gdb/arch/ppc-linux-common.h b/gdb/arch/ppc-linux-common.h
index a25f74f7f7..d0849e7c04 100644
--- a/gdb/arch/ppc-linux-common.h
+++ b/gdb/arch/ppc-linux-common.h
@@ -22,6 +22,15 @@
 
 struct target_desc;
 
+/* The core file VMX regset has 34 16-byte fields (32 16-byte vector
+   registers, plus two fields containing 4-byte registers, VSCR and
+   VRSAVE), while the ptrace calls return or read 33 16-byte fields
+   plus a 4-byte field for VRSAVE. For simplicity we use the longer
+   length for both cases.  */
+#define PPC_LINUX_SIZEOF_VRREGSET 544
+
+#define PPC_LINUX_SIZEOF_VSXREGSET 256
+
 /* Check if the hwcap auxv entry indicates that isa205 is supported.  */
 bool ppc_linux_has_isa205 (unsigned long hwcap);
 
diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c
index 825b46219c..ed48fa7850 100644
--- a/gdb/gdbserver/linux-ppc-low.c
+++ b/gdb/gdbserver/linux-ppc-low.c
@@ -459,8 +459,6 @@ static void ppc_fill_gregset (struct regcache *regcache, void *buf)
     ppc_collect_ptrace_register (regcache, i, (char *) buf + ppc_regmap[i]);
 }
 
-#define SIZEOF_VSXREGS 32*8
-
 static void
 ppc_fill_vsxregset (struct regcache *regcache, void *buf)
 {
@@ -483,8 +481,6 @@ ppc_store_vsxregset (struct regcache *regcache, const void *buf)
     supply_register (regcache, base + i, &regset[i * 8]);
 }
 
-#define SIZEOF_VRREGS 33*16+4
-
 static void
 ppc_fill_vrregset (struct regcache *regcache, void *buf)
 {
@@ -660,10 +656,10 @@ ppc_arch_setup (void)
     switch (regset->get_request)
       {
       case PTRACE_GETVRREGS:
-	regset->size = features.altivec ? SIZEOF_VRREGS : 0;
+	regset->size = features.altivec ? PPC_LINUX_SIZEOF_VRREGSET : 0;
 	break;
       case PTRACE_GETVSXREGS:
-	regset->size = features.vsx ? SIZEOF_VSXREGS : 0;
+	regset->size = features.vsx ? PPC_LINUX_SIZEOF_VSXREGSET : 0;
 	break;
       case PTRACE_GETEVRREGS:
 	if (ppc_hwcap & PPC_FEATURE_HAS_SPE)
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index 07ec53d1ea..554aba662e 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -174,9 +174,7 @@ struct ppc_hw_breakpoint
 */
 /* *INDENT-ON* */
 
-#define SIZEOF_VRREGS 33*16+4
-
-typedef char gdb_vrregset_t[SIZEOF_VRREGS];
+typedef char gdb_vrregset_t[PPC_LINUX_SIZEOF_VRREGSET];
 
 /* This is the layout of the POWER7 VSX registers and the way they overlap
    with the existing FPR and VMX registers.
@@ -210,9 +208,7 @@ typedef char gdb_vrregset_t[SIZEOF_VRREGS];
    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];
+typedef char gdb_vsxregset_t[PPC_LINUX_SIZEOF_VSXREGSET];
 
 /* On PPC processors that support the Signal Processing Extension
    (SPE) APU, the general-purpose registers are 64 bits long.
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 1d3b019c30..344069d752 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -557,10 +557,12 @@ ppc_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
   cb (".reg2", 264, &ppc32_linux_fpregset, NULL, cb_data);
 
   if (have_altivec)
-    cb (".reg-ppc-vmx", 544, &ppc32_linux_vrregset, "ppc Altivec", cb_data);
+    cb (".reg-ppc-vmx", PPC_LINUX_SIZEOF_VRREGSET, &ppc32_linux_vrregset,
+	"ppc Altivec", cb_data);
 
   if (have_vsx)
-    cb (".reg-ppc-vsx", 256, &ppc32_linux_vsxregset, "POWER7 VSX", cb_data);
+    cb (".reg-ppc-vsx", PPC_LINUX_SIZEOF_VSXREGSET,
+	&ppc32_linux_vsxregset, "POWER7 VSX", cb_data);
 }
 
 static void
-- 
2.13.6

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

* [PATCH 3/8] [PowerPC] Disable regsets using zero sizes in gdbserver
  2018-05-10 19:59 [PATCH 0/8] [PowerPC] Miscellaneous fixes for register access Pedro Franco de Carvalho
  2018-05-10 19:59 ` [PATCH 4/8] [PowerPC] Consolidate linux vector regset sizes Pedro Franco de Carvalho
@ 2018-05-10 19:59 ` Pedro Franco de Carvalho
  2018-05-16 16:17   ` Ulrich Weigand
  2018-05-10 19:59 ` [PATCH 1/8] [PowerPC] Consolidate linux target description selection Pedro Franco de Carvalho
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-10 19:59 UTC (permalink / raw)
  To: gdb-patches

Currently the linux-ppc-low.c fill/store functions for extended
regsets check whether they should execute by using the global hwcap
variable.

This patch explicitly sets the regset sizes to zero when needed to
disable them instead, so that the fill/store functions are not called
in the first place by regsets_fetch_inferior_registers in linux-low.c.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* linux-ppc-low.c (ppc_fill_vsxregset): Remove ppc_hwcap check.
	(ppc_store_vsxregset): Likewise.
	(ppc_fill_vrregset): Likewise.
	(ppc_store_vrregset): Likewise.
	(ppc_fill_evrregset): Likewise.
	(ppc_store_evrregset): Likewise.
	(ppc_regsets): Set VSX/VR/EVR regset sizes to 0.
	(ppc_arch_setup): Iterate through ppc_regsets and set sizes when
	needed.
---
 gdb/gdbserver/linux-ppc-low.c | 42 +++++++++++++++++++++---------------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c
index a4182633d7..825b46219c 100644
--- a/gdb/gdbserver/linux-ppc-low.c
+++ b/gdb/gdbserver/linux-ppc-low.c
@@ -467,9 +467,6 @@ ppc_fill_vsxregset (struct regcache *regcache, void *buf)
   int i, base;
   char *regset = (char *) buf;
 
-  if (!(ppc_hwcap & PPC_FEATURE_HAS_VSX))
-    return;
-
   base = find_regno (regcache->tdesc, "vs0h");
   for (i = 0; i < 32; i++)
     collect_register (regcache, base + i, &regset[i * 8]);
@@ -481,9 +478,6 @@ ppc_store_vsxregset (struct regcache *regcache, const void *buf)
   int i, base;
   const char *regset = (const char *) buf;
 
-  if (!(ppc_hwcap & PPC_FEATURE_HAS_VSX))
-    return;
-
   base = find_regno (regcache->tdesc, "vs0h");
   for (i = 0; i < 32; i++)
     supply_register (regcache, base + i, &regset[i * 8]);
@@ -497,9 +491,6 @@ ppc_fill_vrregset (struct regcache *regcache, void *buf)
   int i, base;
   char *regset = (char *) buf;
 
-  if (!(ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC))
-    return;
-
   base = find_regno (regcache->tdesc, "vr0");
   for (i = 0; i < 32; i++)
     collect_register (regcache, base + i, &regset[i * 16]);
@@ -514,9 +505,6 @@ ppc_store_vrregset (struct regcache *regcache, const void *buf)
   int i, base;
   const char *regset = (const char *) buf;
 
-  if (!(ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC))
-    return;
-
   base = find_regno (regcache->tdesc, "vr0");
   for (i = 0; i < 32; i++)
     supply_register (regcache, base + i, &regset[i * 16]);
@@ -538,9 +526,6 @@ ppc_fill_evrregset (struct regcache *regcache, void *buf)
   int i, ev0;
   struct gdb_evrregset_t *regset = (struct gdb_evrregset_t *) buf;
 
-  if (!(ppc_hwcap & PPC_FEATURE_HAS_SPE))
-    return;
-
   ev0 = find_regno (regcache->tdesc, "ev0h");
   for (i = 0; i < 32; i++)
     collect_register (regcache, ev0 + i, &regset->evr[i]);
@@ -555,9 +540,6 @@ ppc_store_evrregset (struct regcache *regcache, const void *buf)
   int i, ev0;
   const struct gdb_evrregset_t *regset = (const struct gdb_evrregset_t *) buf;
 
-  if (!(ppc_hwcap & PPC_FEATURE_HAS_SPE))
-    return;
-
   ev0 = find_regno (regcache->tdesc, "ev0h");
   for (i = 0; i < 32; i++)
     supply_register (regcache, ev0 + i, &regset->evr[i]);
@@ -579,11 +561,11 @@ static struct regset_info ppc_regsets[] = {
      fetch them every time, but still fall back to PTRACE_PEEKUSER for the
      general registers.  Some kernels support these, but not the newer
      PPC_PTRACE_GETREGS.  */
-  { PTRACE_GETVSXREGS, PTRACE_SETVSXREGS, 0, SIZEOF_VSXREGS, EXTENDED_REGS,
+  { PTRACE_GETVSXREGS, PTRACE_SETVSXREGS, 0, 0, EXTENDED_REGS,
   ppc_fill_vsxregset, ppc_store_vsxregset },
-  { PTRACE_GETVRREGS, PTRACE_SETVRREGS, 0, SIZEOF_VRREGS, EXTENDED_REGS,
+  { PTRACE_GETVRREGS, PTRACE_SETVRREGS, 0, 0, EXTENDED_REGS,
     ppc_fill_vrregset, ppc_store_vrregset },
-  { PTRACE_GETEVRREGS, PTRACE_SETEVRREGS, 0, 32 * 4 + 8 + 4, EXTENDED_REGS,
+  { PTRACE_GETEVRREGS, PTRACE_SETEVRREGS, 0, 0, EXTENDED_REGS,
     ppc_fill_evrregset, ppc_store_evrregset },
   { 0, 0, 0, 0, GENERAL_REGS, ppc_fill_gregset, NULL },
   NULL_REGSET
@@ -620,6 +602,7 @@ ppc_arch_setup (void)
 {
   const struct target_desc *tdesc;
   struct ppc_linux_features features = ppc_linux_no_features;
+  struct regset_info *regset;
 
   int tid = lwpid_of (current_thread);
 
@@ -672,6 +655,23 @@ ppc_arch_setup (void)
 #endif
 
   current_process ()->tdesc = tdesc;
+
+  for (regset = ppc_regsets; regset->size >= 0; regset++)
+    switch (regset->get_request)
+      {
+      case PTRACE_GETVRREGS:
+	regset->size = features.altivec ? SIZEOF_VRREGS : 0;
+	break;
+      case PTRACE_GETVSXREGS:
+	regset->size = features.vsx ? SIZEOF_VSXREGS : 0;
+	break;
+      case PTRACE_GETEVRREGS:
+	if (ppc_hwcap & PPC_FEATURE_HAS_SPE)
+	  regset->size = 32 * 4 + 8 + 4;
+	break;
+      default:
+	break;
+      }
 }
 
 /* Implementation of linux_target_ops method "supports_tracepoints".  */
-- 
2.13.6

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

* [PATCH 0/8] [PowerPC] Miscellaneous fixes for register access
@ 2018-05-10 19:59 Pedro Franco de Carvalho
  2018-05-10 19:59 ` [PATCH 4/8] [PowerPC] Consolidate linux vector regset sizes Pedro Franco de Carvalho
                   ` (8 more replies)
  0 siblings, 9 replies; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-10 19:59 UTC (permalink / raw)
  To: gdb-patches

This patch series fixes some issues with register access on ppc linux
targets and refactors related code.

Paches #1-#4 are for refactoring. Patch #1 changes all ppc linux
targets (native, core file and gdbserver) so that they use the same
code for selecting a target description. Patch #2 simplifies the
arch_setup code by reusing the native target function for determining
the target wordsize. Patch #3 disables regsets by setting their sizes
to 0 to reduce the number of references to the hwcap global. Patch #4
changes all the targets to use the same size constants for the vector
regset sizes.

Patch #5 fixes an outdated assumption of big-endianess made to access
the vector control register, and refactors the native functions for
accessing the vector regset. Patch #6 fixes the code used to get
vector-scalar registers from core files, and refactors the native
functions for accessing these same registers, in a way similar to
patch #5.

Patch #7 changes the gdbarch_init function so that decimal
floating-point pseudo registers are only added to the architecture
when they exist.

Patch #8 changes the read_description function for core files to use
the full set of target descriptions available in the native target.

Pedro Franco de Carvalho (8):
  [PowerPC] Consolidate linux target description selection
  [PowerPC] Consolidate wordsize getter between native and gdbserver
  [PowerPC] Disable regsets using zero sizes in gdbserver
  [PowerPC] Consolidate linux vector regset sizes
  [PowerPC] Fix access to VSCR in linux targets
  [PowerPC] Fix VSX registers in linux core files
  [PowerPC] Fix inclusion of dfp pseudoregs in tdep
  [PowerPC] Recognize isa205 in linux core files

 gdb/Makefile.in                                    |   3 +
 gdb/arch/ppc-linux-common.c                        |  85 +++++
 gdb/arch/ppc-linux-common.h                        |  60 ++++
 gdb/arch/ppc-linux-tdesc.h                         |  42 +++
 gdb/configure.nat                                  |   2 +-
 gdb/configure.tgt                                  |   3 +-
 gdb/gdbserver/Makefile.in                          |   1 +
 gdb/gdbserver/configure.srv                        |   1 +
 gdb/gdbserver/linux-ppc-ipa.c                      |   3 +-
 gdb/gdbserver/linux-ppc-low.c                      | 151 ++++-----
 .../{linux-ppc-tdesc.h => linux-ppc-tdesc-init.h}  |  15 -
 gdb/nat/ppc-linux.c                                |  20 ++
 gdb/nat/ppc-linux.h                                |   3 +
 gdb/ppc-linux-nat.c                                | 357 ++++-----------------
 gdb/ppc-linux-tdep.c                               | 128 ++++++--
 gdb/ppc-linux-tdep.h                               |  21 +-
 gdb/rs6000-tdep.c                                  |  85 +----
 gdb/testsuite/gdb.arch/powerpc-fpscr-gcore.exp     |  93 ++++++
 gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp       |  90 ++++++
 19 files changed, 642 insertions(+), 521 deletions(-)
 create mode 100644 gdb/arch/ppc-linux-common.c
 create mode 100644 gdb/arch/ppc-linux-common.h
 create mode 100644 gdb/arch/ppc-linux-tdesc.h
 rename gdb/gdbserver/{linux-ppc-tdesc.h => linux-ppc-tdesc-init.h} (76%)
 create mode 100644 gdb/testsuite/gdb.arch/powerpc-fpscr-gcore.exp
 create mode 100644 gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp

-- 
2.13.6

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

* [PATCH 1/8] [PowerPC] Consolidate linux target description selection
  2018-05-10 19:59 [PATCH 0/8] [PowerPC] Miscellaneous fixes for register access Pedro Franco de Carvalho
  2018-05-10 19:59 ` [PATCH 4/8] [PowerPC] Consolidate linux vector regset sizes Pedro Franco de Carvalho
  2018-05-10 19:59 ` [PATCH 3/8] [PowerPC] Disable regsets using zero sizes in gdbserver Pedro Franco de Carvalho
@ 2018-05-10 19:59 ` Pedro Franco de Carvalho
  2018-05-16 14:05   ` Ulrich Weigand
  2018-05-10 20:00 ` [PATCH 8/8] [PowerPC] Recognize isa205 in linux core files Pedro Franco de Carvalho
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-10 19:59 UTC (permalink / raw)
  To: gdb-patches

Share target description declarations and selection among ppc linux
native targets, core files, gdbserver and IPA.

To avoid complicated define guards, gdbserver and IPA now have
declarations for all descriptions, including 64-bit generated
descriptions when compiled in 32-bit mode. These have always been
linked into the gdbserver and IPA binaries. Because they might be
uninitialized, the selection function checks that the selected
description is initialized.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* arch/ppc-linux-common.c: New file.
	* arch/ppc-linux-common.h: New file.
	* arch/ppc-linux-tdesc.h: New file.
	* configure.tgt (powerpc*-*-linux*): Add arch/ppc-linux-common.o.
	* Makefile.in (ALL_TARGET_OBS): Add arch/ppc-linux-common.o.
	(HFILES_NO_SRCDIR): Add arch/ppc-linux-common.h and
	arch/ppc-linux-tdesc.h.
	* ppc-linux-nat.c: Include arch/ppc-linux-common.h and
	arch/ppc-linux-tdesc.h.
	(ppc_linux_nat_target::read_description): Remove target
	description matching code. Fill a ppc_linux_features struct and
	call ppc_linux_match_description with it. Move comment about ISA
	2.05 to ppc-linux-common.c.
	* ppc-linux-tdep.c: Include arch/ppc-linux-common.h and
	arch/ppc-linux-tdesc.h.
	(ppc_linux_core_read_description): Remove target description
	matching code. Fill a ppc_linux_features struct and call
	ppc_linux_match_description with it.
	* ppc-linux-tdep.h (tdesc_powerpc_32l, tdesc_powerpc_64l)
	(tdesc_powerpc_altivec32l, tdesc_powerpc_altivec64l)
	(tdesc_powerpc_cell32l, tdesc_powerpc_cell64l)
	(tdesc_powerpc_vsx32l, tdesc_powerpc_vsx64l)
	(tdesc_powerpc_isa205_32l, tdesc_powerpc_isa205_64l)
	(tdesc_powerpc_isa205_altivec32l, tdesc_powerpc_isa205_altivec64l)
	(tdesc_powerpc_isa205_vsx32l, tdesc_powerpc_isa205_vsx64l)
	(tdesc_powerpc_e500l): Remove.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* configure.srv (srv_tgtobj): Add arch/ppc-linux-common.o.
	* Makefile.in (SFILES): Add arch/ppc-linux-common.c.
	* linux-ppc-tdesc.h: Rename to linux-ppc-tdesc-init.h.
	* linux-ppc-tdesc-init.h (tdesc_powerpc_32l, tdesc_powerpc_64l)
	(tdesc_powerpc_altivec32l, tdesc_powerpc_altivec64l)
	(tdesc_powerpc_cell32l, tdesc_powerpc_cell64l)
	(tdesc_powerpc_vsx32l, tdesc_powerpc_vsx64l)
	(tdesc_powerpc_isa205_32l, tdesc_powerpc_isa205_64l)
	(tdesc_powerpc_isa205_altivec32l, tdesc_powerpc_isa205_altivec64l)
	(tdesc_powerpc_isa205_vsx32l, tdesc_powerpc_isa205_vsx64l)
	(tdesc_powerpc_e500l): Remove.
	* linux-ppc-ipa.c: Include arch/ppc-linux-tdesc.h and
	linux-ppc-tdesc-init.h. Don't include linux-ppc-tdesc.h.
	* linux-ppc-low.c: Include arch/ppc-linux-common.h,
	arch/ppc-linux-tdesc.h, and linux-ppc-tdesc-init.h. Don't include
	linux-ppc-tdesc.h.
	(ppc_arch_setup): Remove target description matching code. Fill a
	ppc_linux_features struct and call ppc_linux_match_description
	with it.
---
 gdb/Makefile.in                                    |  3 +
 gdb/arch/ppc-linux-common.c                        | 85 ++++++++++++++++++++++
 gdb/arch/ppc-linux-common.h                        | 51 +++++++++++++
 gdb/arch/ppc-linux-tdesc.h                         | 42 +++++++++++
 gdb/configure.tgt                                  |  3 +-
 gdb/gdbserver/Makefile.in                          |  1 +
 gdb/gdbserver/configure.srv                        |  1 +
 gdb/gdbserver/linux-ppc-ipa.c                      |  3 +-
 gdb/gdbserver/linux-ppc-low.c                      | 73 +++++++------------
 .../{linux-ppc-tdesc.h => linux-ppc-tdesc-init.h}  | 15 ----
 gdb/ppc-linux-nat.c                                | 55 ++++----------
 gdb/ppc-linux-tdep.c                               | 37 +++++-----
 gdb/ppc-linux-tdep.h                               | 17 -----
 13 files changed, 248 insertions(+), 138 deletions(-)
 create mode 100644 gdb/arch/ppc-linux-common.c
 create mode 100644 gdb/arch/ppc-linux-common.h
 create mode 100644 gdb/arch/ppc-linux-tdesc.h
 rename gdb/gdbserver/{linux-ppc-tdesc.h => linux-ppc-tdesc-init.h} (76%)

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 87d74a7703..8109c0c6ba 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -678,6 +678,7 @@ ALL_TARGET_OBS = \
 	arch/arm-get-next-pcs.o \
 	arch/arm-linux.o \
 	arch/i386.o \
+	arch/ppc-linux-common.o \
 	arm-bsd-tdep.o \
 	arm-fbsd-tdep.o \
 	arm-linux-tdep.o \
@@ -1411,6 +1412,8 @@ HFILES_NO_SRCDIR = \
 	arch/aarch64-insn.h \
 	arch/arm.h \
 	arch/i386.h \
+	arch/ppc-linux-common.h \
+	arch/ppc-linux-tdesc.h \
 	cli/cli-cmds.h \
 	cli/cli-decode.h \
 	cli/cli-script.h \
diff --git a/gdb/arch/ppc-linux-common.c b/gdb/arch/ppc-linux-common.c
new file mode 100644
index 0000000000..cef9283121
--- /dev/null
+++ b/gdb/arch/ppc-linux-common.c
@@ -0,0 +1,85 @@
+/* Common target dependent code for GNU/Linux on PPC systems.
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "common-defs.h"
+#include "arch/ppc-linux-common.h"
+#include "arch/ppc-linux-tdesc.h"
+
+/* Decimal Floating Point bit in AT_HWCAP.
+
+   This file can be used by a host with another architecture, e.g.
+   when debugging core files, which might not provide this constant.  */
+
+#ifndef PPC_FEATURE_HAS_DFP
+#define PPC_FEATURE_HAS_DFP	0x00000400
+#endif
+
+bool
+ppc_linux_has_isa205 (unsigned long hwcap)
+{
+  /* Power ISA 2.05 (implemented by Power 6 and newer processors)
+     increases the FPSCR from 32 bits to 64 bits.  Even though Power 7
+     supports this ISA version, it doesn't have PPC_FEATURE_ARCH_2_05
+     set, only PPC_FEATURE_ARCH_2_06.  Since for now the only bits
+     used in the higher half of the register are for Decimal Floating
+     Point, we check if that feature is available to decide the size
+     of the FPSCR.  */
+  return ((hwcap & PPC_FEATURE_HAS_DFP) != 0);
+}
+
+const struct target_desc *
+ppc_linux_match_description(struct ppc_linux_features features)
+{
+  struct target_desc *tdesc = NULL;
+
+  if (features.wordsize == 8)
+    {
+      if (features.cell)
+	tdesc = tdesc_powerpc_cell64l;
+      else if (features.vsx)
+	tdesc = features.isa205
+	  ? tdesc_powerpc_isa205_vsx64l : tdesc_powerpc_vsx64l;
+      else if (features.altivec)
+	tdesc = features.isa205
+	  ? tdesc_powerpc_isa205_altivec64l : tdesc_powerpc_altivec64l;
+      else
+	tdesc = features.isa205?
+	  tdesc_powerpc_isa205_64l : tdesc_powerpc_64l;
+    }
+  else
+    {
+      gdb_assert (features.wordsize == 4);
+
+      if (features.cell)
+	tdesc = tdesc_powerpc_cell32l;
+      else if (features.vsx)
+	tdesc = features.isa205
+	  ? tdesc_powerpc_isa205_vsx32l : tdesc_powerpc_vsx32l;
+      else if (features.altivec)
+	tdesc = features.isa205
+	  ? tdesc_powerpc_isa205_altivec32l : tdesc_powerpc_altivec32l;
+      else
+	tdesc = features.isa205
+	  ? tdesc_powerpc_isa205_32l : tdesc_powerpc_32l;
+    }
+
+  gdb_assert (tdesc != NULL);
+
+  return tdesc;
+}
diff --git a/gdb/arch/ppc-linux-common.h b/gdb/arch/ppc-linux-common.h
new file mode 100644
index 0000000000..a25f74f7f7
--- /dev/null
+++ b/gdb/arch/ppc-linux-common.h
@@ -0,0 +1,51 @@
+/* Common target dependent code for GNU/Linux on PPC systems.
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef ARCH_PPC_LINUX_COMMON_H
+#define ARCH_PPC_LINUX_COMMON_H
+
+struct target_desc;
+
+/* Check if the hwcap auxv entry indicates that isa205 is supported.  */
+bool ppc_linux_has_isa205 (unsigned long hwcap);
+
+/* Features used to determine the target description.  */
+struct ppc_linux_features
+{
+  unsigned int wordsize;
+  bool altivec;
+  bool vsx;
+  bool isa205;
+  bool cell;
+};
+
+/* Base value for ppc_linux_features variables.  */
+const struct ppc_linux_features ppc_linux_no_features = {
+  4,
+  false,
+  false,
+  false,
+  false,
+};
+
+/* Return a target description that matches FEATURES.  */
+const struct target_desc * ppc_linux_match_description
+(struct ppc_linux_features features);
+
+#endif /* ARCH_PPC_LINUX_COMMON_H */
diff --git a/gdb/arch/ppc-linux-tdesc.h b/gdb/arch/ppc-linux-tdesc.h
new file mode 100644
index 0000000000..594c7c7c7c
--- /dev/null
+++ b/gdb/arch/ppc-linux-tdesc.h
@@ -0,0 +1,42 @@
+/* Target description declarations shared between gdb, gdbserver and IPA.
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef ARCH_PPC_LINUX_TDESC_H
+#define ARCH_PPC_LINUX_TDESC_H
+
+struct target_desc;
+
+extern struct target_desc *tdesc_powerpc_32l;
+extern struct target_desc *tdesc_powerpc_altivec32l;
+extern struct target_desc *tdesc_powerpc_cell32l;
+extern struct target_desc *tdesc_powerpc_vsx32l;
+extern struct target_desc *tdesc_powerpc_isa205_32l;
+extern struct target_desc *tdesc_powerpc_isa205_altivec32l;
+extern struct target_desc *tdesc_powerpc_isa205_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_cell64l;
+extern struct target_desc *tdesc_powerpc_vsx64l;
+extern struct target_desc *tdesc_powerpc_isa205_64l;
+extern struct target_desc *tdesc_powerpc_isa205_altivec64l;
+extern struct target_desc *tdesc_powerpc_isa205_vsx64l;
+
+#endif /* ARCH_PPC_LINUX_TDESC_H */
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index e9a2704ebc..b4bc770617 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -492,7 +492,8 @@ powerpc*-*-linux*)
 			spu-multiarch.o \
 			glibc-tdep.o symfile-mem.o linux-tdep.o \
 			ravenscar-thread.o ppc-ravenscar-thread.o \
-			linux-record.o "
+			linux-record.o \
+			arch/ppc-linux-common.o"
 	gdb_sim=../sim/ppc/libsim.a
 	build_gdbserver=yes
 	;;
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index c377378809..675faa4364 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -196,6 +196,7 @@ SFILES = \
 	$(srcdir)/arch/arm.c \
 	$(srcdir)/arch/arm-get-next-pcs.c \
 	$(srcdir)/arch/arm-linux.c \
+	$(srcdir)/arch/ppc-linux-common.c \
 	$(srcdir)/common/btrace-common.c \
 	$(srcdir)/common/buffer.c \
 	$(srcdir)/common/cleanups.c \
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index ffeefb9b92..7153ff339d 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -225,6 +225,7 @@ case "${target}" in
 			srv_regobj="${srv_regobj} powerpc-isa205-altivec64l.o"
 			srv_regobj="${srv_regobj} powerpc-isa205-vsx64l.o"
 			srv_tgtobj="$srv_linux_obj linux-ppc-low.o ppc-linux.o"
+			srv_tgtobj="${srv_tgtobj} arch/ppc-linux-common.o"
 			srv_xmlfiles="rs6000/powerpc-32l.xml"
 			srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-altivec32l.xml"
 			srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-cell32l.xml"
diff --git a/gdb/gdbserver/linux-ppc-ipa.c b/gdb/gdbserver/linux-ppc-ipa.c
index c993e76315..f6861f0d98 100644
--- a/gdb/gdbserver/linux-ppc-ipa.c
+++ b/gdb/gdbserver/linux-ppc-ipa.c
@@ -21,7 +21,8 @@
 #include "server.h"
 #include <sys/mman.h>
 #include "tracepoint.h"
-#include "linux-ppc-tdesc.h"
+#include "arch/ppc-linux-tdesc.h"
+#include "linux-ppc-tdesc-init.h"
 #include <elf.h>
 #ifdef HAVE_GETAUXVAL
 #include <sys/auxv.h>
diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c
index 36bd373c88..a442a51273 100644
--- a/gdb/gdbserver/linux-ppc-low.c
+++ b/gdb/gdbserver/linux-ppc-low.c
@@ -23,8 +23,10 @@
 #include <elf.h>
 #include <asm/ptrace.h>
 
+#include "arch/ppc-linux-common.h"
+#include "arch/ppc-linux-tdesc.h"
 #include "nat/ppc-linux.h"
-#include "linux-ppc-tdesc.h"
+#include "linux-ppc-tdesc-init.h"
 #include "ax.h"
 #include "tracepoint.h"
 
@@ -617,6 +619,8 @@ static void
 ppc_arch_setup (void)
 {
   const struct target_desc *tdesc;
+  struct ppc_linux_features features = ppc_linux_no_features;
+
 #ifdef __powerpc64__
   long msr;
   struct regcache *regcache;
@@ -634,57 +638,33 @@ ppc_arch_setup (void)
   free_register_cache (regcache);
   if (ppc64_64bit_inferior_p (msr))
     {
-      ppc_get_auxv (AT_HWCAP, &ppc_hwcap);
-      if (ppc_hwcap & PPC_FEATURE_CELL)
-	tdesc = tdesc_powerpc_cell64l;
-      else if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
-	{
-	  /* Power ISA 2.05 (implemented by Power 6 and newer processors)
-	     increases the FPSCR from 32 bits to 64 bits. Even though Power 7
-	     supports this ISA version, it doesn't have PPC_FEATURE_ARCH_2_05
-	     set, only PPC_FEATURE_ARCH_2_06.  Since for now the only bits
-	     used in the higher half of the register are for Decimal Floating
-	     Point, we check if that feature is available to decide the size
-	     of the FPSCR.  */
-	  if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
-	    tdesc = tdesc_powerpc_isa205_vsx64l;
-	  else
-	    tdesc = tdesc_powerpc_vsx64l;
-	}
-      else if (ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC)
-	{
-	  if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
-	    tdesc = tdesc_powerpc_isa205_altivec64l;
-	  else
-	    tdesc = tdesc_powerpc_altivec64l;
-	}
-
-      current_process ()->tdesc = tdesc;
-      return;
+      features.wordsize = 8;
     }
 #endif
 
-  /* OK, we have a 32-bit inferior.  */
-  tdesc = tdesc_powerpc_32l;
-  current_process ()->tdesc = tdesc;
+  if (features.wordsize == 4)
+    {
+      /* OK, we have a 32-bit inferior.  */
+      tdesc = tdesc_powerpc_32l;
+      current_process ()->tdesc = tdesc;
+    }
 
+  /* The value of current_process ()->tdesc needs to be set for this
+     call.  */
   ppc_get_auxv (AT_HWCAP, &ppc_hwcap);
+
+  features.isa205 = ppc_linux_has_isa205 (ppc_hwcap);
+
+  if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
+    features.vsx = true;
+
+  if (ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC)
+    features.altivec = true;
+
   if (ppc_hwcap & PPC_FEATURE_CELL)
-    tdesc = tdesc_powerpc_cell32l;
-  else if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
-    {
-      if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
-	tdesc = tdesc_powerpc_isa205_vsx32l;
-      else
-	tdesc = tdesc_powerpc_vsx32l;
-    }
-  else if (ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC)
-    {
-      if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
-	tdesc = tdesc_powerpc_isa205_altivec32l;
-      else
-	tdesc = tdesc_powerpc_altivec32l;
-    }
+    features.cell = true;
+
+  tdesc = ppc_linux_match_description (features);
 
   /* On 32-bit machines, check for SPE registers.
      Set the low target's regmap field as appropriately.  */
@@ -707,6 +687,7 @@ ppc_arch_setup (void)
       ppc_regmap_adjusted = 1;
    }
 #endif
+
   current_process ()->tdesc = tdesc;
 }
 
diff --git a/gdb/gdbserver/linux-ppc-tdesc.h b/gdb/gdbserver/linux-ppc-tdesc-init.h
similarity index 76%
rename from gdb/gdbserver/linux-ppc-tdesc.h
rename to gdb/gdbserver/linux-ppc-tdesc-init.h
index 4a561f5e37..422e7bd9c4 100644
--- a/gdb/gdbserver/linux-ppc-tdesc.h
+++ b/gdb/gdbserver/linux-ppc-tdesc-init.h
@@ -36,35 +36,27 @@ enum ppc_linux_tdesc {
 
 /* Defined in auto-generated file powerpc-32l.c.  */
 void init_registers_powerpc_32l (void);
-extern const struct target_desc *tdesc_powerpc_32l;
 
 /* Defined in auto-generated file powerpc-altivec32l.c.  */
 void init_registers_powerpc_altivec32l (void);
-extern const struct target_desc *tdesc_powerpc_altivec32l;
 
 /* Defined in auto-generated file powerpc-cell32l.c.  */
 void init_registers_powerpc_cell32l (void);
-extern const struct target_desc *tdesc_powerpc_cell32l;
 
 /* Defined in auto-generated file powerpc-vsx32l.c.  */
 void init_registers_powerpc_vsx32l (void);
-extern const struct target_desc *tdesc_powerpc_vsx32l;
 
 /* Defined in auto-generated file powerpc-isa205-32l.c.  */
 void init_registers_powerpc_isa205_32l (void);
-extern const struct target_desc *tdesc_powerpc_isa205_32l;
 
 /* Defined in auto-generated file powerpc-isa205-altivec32l.c.  */
 void init_registers_powerpc_isa205_altivec32l (void);
-extern const struct target_desc *tdesc_powerpc_isa205_altivec32l;
 
 /* Defined in auto-generated file powerpc-isa205-vsx32l.c.  */
 void init_registers_powerpc_isa205_vsx32l (void);
-extern const struct target_desc *tdesc_powerpc_isa205_vsx32l;
 
 /* Defined in auto-generated file powerpc-e500l.c.  */
 void init_registers_powerpc_e500l (void);
-extern const struct target_desc *tdesc_powerpc_e500l;
 
 #endif
 
@@ -72,30 +64,23 @@ extern const struct target_desc *tdesc_powerpc_e500l;
 
 /* Defined in auto-generated file powerpc-64l.c.  */
 void init_registers_powerpc_64l (void);
-extern const struct target_desc *tdesc_powerpc_64l;
 
 /* Defined in auto-generated file powerpc-altivec64l.c.  */
 void init_registers_powerpc_altivec64l (void);
-extern const struct target_desc *tdesc_powerpc_altivec64l;
 
 /* Defined in auto-generated file powerpc-cell64l.c.  */
 void init_registers_powerpc_cell64l (void);
-extern const struct target_desc *tdesc_powerpc_cell64l;
 
 /* Defined in auto-generated file powerpc-vsx64l.c.  */
 void init_registers_powerpc_vsx64l (void);
-extern const struct target_desc *tdesc_powerpc_vsx64l;
 
 /* Defined in auto-generated file powerpc-isa205-64l.c.  */
 void init_registers_powerpc_isa205_64l (void);
-extern const struct target_desc *tdesc_powerpc_isa205_64l;
 
 /* Defined in auto-generated file powerpc-isa205-altivec64l.c.  */
 void init_registers_powerpc_isa205_altivec64l (void);
-extern const struct target_desc *tdesc_powerpc_isa205_altivec64l;
 
 /* Defined in auto-generated file powerpc-isa205-vsx64l.c.  */
 void init_registers_powerpc_isa205_vsx64l (void);
-extern const struct target_desc *tdesc_powerpc_isa205_vsx64l;
 
 #endif
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index 1423339339..af59761cd6 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -45,6 +45,8 @@
 #include "elf/common.h"
 #include "auxv.h"
 
+#include "arch/ppc-linux-common.h"
+#include "arch/ppc-linux-tdesc.h"
 #include "nat/ppc-linux.h"
 
 /* Similarly for the hardware watchpoint support.  These requests are used
@@ -2416,11 +2418,6 @@ ppc_linux_nat_target::auxv_parse (gdb_byte **readptr,
 const struct target_desc *
 ppc_linux_nat_target::read_description ()
 {
-  int altivec = 0;
-  int vsx = 0;
-  int isa205 = 0;
-  int cell = 0;
-
   int tid = ptid_get_lwp (inferior_ptid);
   if (tid == 0)
     tid = ptid_get_pid (inferior_ptid);
@@ -2438,13 +2435,18 @@ ppc_linux_nat_target::read_description ()
 	perror_with_name (_("Unable to fetch SPE registers"));
     }
 
+  struct ppc_linux_features features = ppc_linux_no_features;
+  unsigned long hwcap = ppc_linux_get_hwcap ();
+
+  features.wordsize = ppc_linux_target_wordsize ();
+
   if (have_ptrace_getsetvsxregs
-      && (ppc_linux_get_hwcap () & PPC_FEATURE_HAS_VSX))
+      && (hwcap & PPC_FEATURE_HAS_VSX))
     {
       gdb_vsxregset_t vsxregset;
 
       if (ptrace (PTRACE_GETVSXREGS, tid, 0, &vsxregset) >= 0)
-	vsx = 1;
+	features.vsx = true;
 
       /* EIO means that the PTRACE_GETVSXREGS request isn't supported.
 	 Anything else needs to be reported.  */
@@ -2453,12 +2455,12 @@ ppc_linux_nat_target::read_description ()
     }
 
   if (have_ptrace_getvrregs
-      && (ppc_linux_get_hwcap () & PPC_FEATURE_HAS_ALTIVEC))
+      && (hwcap & PPC_FEATURE_HAS_ALTIVEC))
     {
       gdb_vrregset_t vrregset;
 
       if (ptrace (PTRACE_GETVRREGS, tid, 0, &vrregset) >= 0)
-        altivec = 1;
+        features.altivec = true;
 
       /* EIO means that the PTRACE_GETVRREGS request isn't supported.
 	 Anything else needs to be reported.  */
@@ -2466,39 +2468,12 @@ ppc_linux_nat_target::read_description ()
 	perror_with_name (_("Unable to fetch AltiVec registers"));
     }
 
-  /* Power ISA 2.05 (implemented by Power 6 and newer processors) increases
-     the FPSCR from 32 bits to 64 bits.  Even though Power 7 supports this
-     ISA version, it doesn't have PPC_FEATURE_ARCH_2_05 set, only
-     PPC_FEATURE_ARCH_2_06.  Since for now the only bits used in the higher
-     half of the register are for Decimal Floating Point, we check if that
-     feature is available to decide the size of the FPSCR.  */
-  if (ppc_linux_get_hwcap () & PPC_FEATURE_HAS_DFP)
-    isa205 = 1;
-
-  if (ppc_linux_get_hwcap () & PPC_FEATURE_CELL)
-    cell = 1;
-
-  if (ppc_linux_target_wordsize () == 8)
-    {
-      if (cell)
-	return tdesc_powerpc_cell64l;
-      else if (vsx)
-	return isa205? tdesc_powerpc_isa205_vsx64l : tdesc_powerpc_vsx64l;
-      else if (altivec)
-	return isa205
-	  ? tdesc_powerpc_isa205_altivec64l : tdesc_powerpc_altivec64l;
-
-      return isa205? tdesc_powerpc_isa205_64l : tdesc_powerpc_64l;
-    }
+  if (hwcap & PPC_FEATURE_CELL)
+    features.cell = true;
 
-  if (cell)
-    return tdesc_powerpc_cell32l;
-  else if (vsx)
-    return isa205? tdesc_powerpc_isa205_vsx32l : tdesc_powerpc_vsx32l;
-  else if (altivec)
-    return isa205? tdesc_powerpc_isa205_altivec32l : tdesc_powerpc_altivec32l;
+  features.isa205 = ppc_linux_has_isa205 (hwcap);
 
-  return isa205? tdesc_powerpc_isa205_32l : tdesc_powerpc_32l;
+  return ppc_linux_match_description (features);
 }
 
 void
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 6d3a64c4f0..1d3b019c30 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -37,6 +37,8 @@
 #include "ppc-tdep.h"
 #include "ppc64-tdep.h"
 #include "ppc-linux-tdep.h"
+#include "arch/ppc-linux-common.h"
+#include "arch/ppc-linux-tdesc.h"
 #include "glibc-tdep.h"
 #include "trad-frame.h"
 #include "frame-unwind.h"
@@ -966,38 +968,37 @@ ppc_linux_core_read_description (struct gdbarch *gdbarch,
 				 struct target_ops *target,
 				 bfd *abfd)
 {
+  struct ppc_linux_features features = ppc_linux_no_features;
   asection *cell = bfd_sections_find_if (abfd, ppc_linux_spu_section, NULL);
   asection *altivec = bfd_get_section_by_name (abfd, ".reg-ppc-vmx");
   asection *vsx = bfd_get_section_by_name (abfd, ".reg-ppc-vsx");
   asection *section = bfd_get_section_by_name (abfd, ".reg");
+
   if (! section)
     return NULL;
 
   switch (bfd_section_size (abfd, section))
     {
     case 48 * 4:
-      if (cell)
-	return tdesc_powerpc_cell32l;
-      else if (vsx)
-	return tdesc_powerpc_vsx32l;
-      else if (altivec)
-	return tdesc_powerpc_altivec32l;
-      else
-	return tdesc_powerpc_32l;
-
+      features.wordsize = 4;
+      break;
     case 48 * 8:
-      if (cell)
-	return tdesc_powerpc_cell64l;
-      else if (vsx)
-	return tdesc_powerpc_vsx64l;
-      else if (altivec)
-	return tdesc_powerpc_altivec64l;
-      else
-	return tdesc_powerpc_64l;
-
+      features.wordsize = 8;
+      break;
     default:
       return NULL;
     }
+
+  if (cell)
+    features.cell = true;
+
+  if (altivec)
+    features.altivec = true;
+
+  if (vsx)
+    features.vsx = true;
+
+  return ppc_linux_match_description (features);
 }
 
 
diff --git a/gdb/ppc-linux-tdep.h b/gdb/ppc-linux-tdep.h
index 465f9ff932..5e7c4be16b 100644
--- a/gdb/ppc-linux-tdep.h
+++ b/gdb/ppc-linux-tdep.h
@@ -40,21 +40,4 @@ enum {
 /* Return 1 if PPC_ORIG_R3_REGNUM and PPC_TRAP_REGNUM are usable.  */
 int ppc_linux_trap_reg_p (struct gdbarch *gdbarch);
 
-/* Linux target descriptions.  */
-extern struct target_desc *tdesc_powerpc_32l;
-extern struct target_desc *tdesc_powerpc_altivec32l;
-extern struct target_desc *tdesc_powerpc_cell32l;
-extern struct target_desc *tdesc_powerpc_vsx32l;
-extern struct target_desc *tdesc_powerpc_isa205_32l;
-extern struct target_desc *tdesc_powerpc_isa205_altivec32l;
-extern struct target_desc *tdesc_powerpc_isa205_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_cell64l;
-extern struct target_desc *tdesc_powerpc_vsx64l;
-extern struct target_desc *tdesc_powerpc_isa205_64l;
-extern struct target_desc *tdesc_powerpc_isa205_altivec64l;
-extern struct target_desc *tdesc_powerpc_isa205_vsx64l;
-
 #endif /* PPC_LINUX_TDEP_H */
-- 
2.13.6

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

* [PATCH 8/8] [PowerPC] Recognize isa205 in linux core files
  2018-05-10 19:59 [PATCH 0/8] [PowerPC] Miscellaneous fixes for register access Pedro Franco de Carvalho
                   ` (2 preceding siblings ...)
  2018-05-10 19:59 ` [PATCH 1/8] [PowerPC] Consolidate linux target description selection Pedro Franco de Carvalho
@ 2018-05-10 20:00 ` Pedro Franco de Carvalho
  2018-05-16 15:53   ` Ulrich Weigand
  2018-05-10 20:33 ` [PATCH 6/8] [PowerPC] Fix VSX registers " Pedro Franco de Carvalho
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-10 20:00 UTC (permalink / raw)
  To: gdb-patches

Currently the ppc linux core file target doesn't return target
descriptions with the lager FPSCR introduced in isa205.

This patch changes the core file target so that the auxv is read from
the core file to determine the size of FPSCR, so that the appropriate
target description is selected.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* arch/ppc-linux-common.c (ppc_linux_has_isa205): Change the
	parameter type to CORE_ADDR.
	* arch/ppc-linux-common.h (ppc_linux_has_isa205): Change the
	parameter type in declaration to CORE_ADDR.
	* ppc-linux-tdep.c (ppc_linux_core_read_description): Call
	target_auxv_search to get AT_HWCAP and use the result to get the
	target description.
	* ppc-linux-nat.c (ppc_linux_get_hwcap): Change the return type to
	CORE_ADDR. Remove the cast of the return value to unsigned
	long. Check if target_auxv_search returns a value greater than
	zero instead of non-zero.
	(ppc_linux_nat_target::read_description): Change the type of the
	hwcap variable to CORE_ADDR.

gdb/testsuite/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* gdb.arch/powerpc-fpscr-gcore.exp: New file.
---
 gdb/arch/ppc-linux-common.c                    |  2 +-
 gdb/arch/ppc-linux-common.h                    |  2 +-
 gdb/ppc-linux-nat.c                            |  9 +--
 gdb/ppc-linux-tdep.c                           |  6 ++
 gdb/testsuite/gdb.arch/powerpc-fpscr-gcore.exp | 93 ++++++++++++++++++++++++++
 5 files changed, 106 insertions(+), 6 deletions(-)
 create mode 100644 gdb/testsuite/gdb.arch/powerpc-fpscr-gcore.exp

diff --git a/gdb/arch/ppc-linux-common.c b/gdb/arch/ppc-linux-common.c
index cef9283121..e04e807ecb 100644
--- a/gdb/arch/ppc-linux-common.c
+++ b/gdb/arch/ppc-linux-common.c
@@ -31,7 +31,7 @@
 #endif
 
 bool
-ppc_linux_has_isa205 (unsigned long hwcap)
+ppc_linux_has_isa205 (CORE_ADDR hwcap)
 {
   /* Power ISA 2.05 (implemented by Power 6 and newer processors)
      increases the FPSCR from 32 bits to 64 bits.  Even though Power 7
diff --git a/gdb/arch/ppc-linux-common.h b/gdb/arch/ppc-linux-common.h
index d0849e7c04..90519ff3fa 100644
--- a/gdb/arch/ppc-linux-common.h
+++ b/gdb/arch/ppc-linux-common.h
@@ -32,7 +32,7 @@ struct target_desc;
 #define PPC_LINUX_SIZEOF_VSXREGSET 256
 
 /* Check if the hwcap auxv entry indicates that isa205 is supported.  */
-bool ppc_linux_has_isa205 (unsigned long hwcap);
+bool ppc_linux_has_isa205 (CORE_ADDR hwcap);
 
 /* Features used to determine the target description.  */
 struct ppc_linux_features
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index 59c5f0c4b9..c79fcd4ab3 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -1165,13 +1165,13 @@ store_ppc_registers (const struct regcache *regcache, int tid)
 }
 
 /* Fetch the AT_HWCAP entry from the aux vector.  */
-static unsigned long
+static CORE_ADDR
 ppc_linux_get_hwcap (void)
 {
   CORE_ADDR field;
 
-  if (target_auxv_search (target_stack, AT_HWCAP, &field))
-    return (unsigned long) field;
+  if (target_auxv_search (target_stack, AT_HWCAP, &field) > 0)
+    return field;
 
   return 0;
 }
@@ -2233,7 +2233,8 @@ ppc_linux_nat_target::read_description ()
     }
 
   struct ppc_linux_features features = ppc_linux_no_features;
-  unsigned long hwcap = ppc_linux_get_hwcap ();
+
+  CORE_ADDR hwcap = ppc_linux_get_hwcap ();
 
   features.wordsize = ppc_linux_target_wordsize (tid);
 
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 54de34d0b7..df8e04cd90 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -1065,6 +1065,12 @@ ppc_linux_core_read_description (struct gdbarch *gdbarch,
   if (vsx)
     features.vsx = true;
 
+  CORE_ADDR hwcap = 0;
+
+  target_auxv_search (target, AT_HWCAP, &hwcap);
+
+  features.isa205 = ppc_linux_has_isa205 (hwcap);
+
   return ppc_linux_match_description (features);
 }
 
diff --git a/gdb/testsuite/gdb.arch/powerpc-fpscr-gcore.exp b/gdb/testsuite/gdb.arch/powerpc-fpscr-gcore.exp
new file mode 100644
index 0000000000..d5db5320b6
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/powerpc-fpscr-gcore.exp
@@ -0,0 +1,93 @@
+# Copyright (C) 2018 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the gdb testsuite.
+
+# This tests checks that generating and loading a core file preserves
+# the correct FPSCR size.
+
+if {![istarget "powerpc*-*-linux*"]} then {
+    verbose "Skipping PowerPC test for corefiles with FPSCR."
+    return
+}
+
+standard_testfile .c
+
+set gen_src [standard_output_file $srcfile]
+
+gdb_produce_source $gen_src {
+	int main() {
+	    return 0;
+	}
+}
+
+if {[build_executable "compile" $binfile $gen_src] == -1} {
+    return -1
+}
+
+clean_restart $binfile
+
+if ![runto_main] then {
+    fail "could not run to main"
+    return -1
+}
+
+# Check if our target has FPSCR
+proc check_fpscr_access {} {
+    global gdb_prompt
+
+    set test "fpscr register access"
+    gdb_test_multiple "info reg fpscr" "$test" {
+	-re "Invalid register.*\r\n$gdb_prompt $" {
+	    unsupported "$test"
+	    return 0
+	}
+	-re "\r\nfpscr.*\r\n$gdb_prompt $" {
+	    pass "$test"
+	    return 1
+	}
+    }
+    return 0
+}
+
+if { ![check_fpscr_access] } {
+    return -1
+}
+
+set fpscr_size_process [get_integer_valueof "sizeof(\$fpscr)" -1]
+
+set core_filename [standard_output_file "$testfile.core"]
+set core_generated [gdb_gcore_cmd "$core_filename" "generate core file"]
+
+if { !$core_generated } {
+    return -1
+}
+
+clean_restart
+
+set core_loaded [gdb_core_cmd "$core_filename" "load core file"]
+
+if { $core_loaded != 1 } {
+    return -1
+}
+
+set fpscr_size_corefile [get_integer_valueof "sizeof(\$fpscr)" -2]
+
+set test "fpscr size matches"
+if {$fpscr_size_process == $fpscr_size_corefile} {
+    pass $test
+} else {
+    fail $test
+}
-- 
2.13.6

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

* [PATCH 6/8] [PowerPC] Fix VSX registers in linux core files
  2018-05-10 19:59 [PATCH 0/8] [PowerPC] Miscellaneous fixes for register access Pedro Franco de Carvalho
                   ` (3 preceding siblings ...)
  2018-05-10 20:00 ` [PATCH 8/8] [PowerPC] Recognize isa205 in linux core files Pedro Franco de Carvalho
@ 2018-05-10 20:33 ` Pedro Franco de Carvalho
  2018-05-16 14:18   ` Ulrich Weigand
  2018-05-10 20:33 ` [PATCH 2/8] [PowerPC] Consolidate wordsize getter between native and gdbserver Pedro Franco de Carvalho
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-10 20:33 UTC (permalink / raw)
  To: gdb-patches

The functions used by the VSX regset to collect and supply registers
from core files where incorrect. This patch changes the regset to use
the standard regset collect/supply functions to fix this. The native
target is also changed to use the same regset.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* ppc-linux-tdep.c (ppc_linux_vsxregset): New function.
	(ppc32_linux_vsxregmap): New global.
	(ppc32_linux_vsxregset): Initialize with ppc32_linux_vsxregmap,
	regcache_supply_regset, and regcache_collect_regset.
	* ppc-linux-tdep.h (ppc_linux_vsxregset): Declare.
	* ppc-linux-nat.c (supply_vsxregset, fill_vsxregset): Remove.
	(fetch_vsx_register, store_vsx_register): Remove.
	(fetch_vsx_registers): Add regno parameter. Get regset using
	ppc_linux_vsxregset. Use regset to supply registers.
	(store_vsx_registers): Add regno parameter. Get regset using
	ppc_linux_vsxregset. Use regset to collect registers.
	(fetch_register): Call fetch_vsx_registers instead of
	fetch_vsx_register.
	(store_register): Call store_vsx_registers instead of
	store_vsx_register.
	(fetch_ppc_registers): Call fetch_vsx_registers with -1 for the
	new regno parameter.
	(store_ppc_registers): Call store_vsx_registers with -1 for the
	new regno parameter.
	* rs6000-tdep.c (ppc_vsx_support_p, ppc_supply_vsxreget)
	(ppc_collect_vsxregset): Remove.

gdb/testsuite/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* gdb.arch/powerpc-vsx-gcore.exp: New file.
---
 gdb/ppc-linux-nat.c                          | 106 ++++-----------------------
 gdb/ppc-linux-tdep.c                         |  18 ++++-
 gdb/ppc-linux-tdep.h                         |   1 +
 gdb/rs6000-tdep.c                            |  75 -------------------
 gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp |  90 +++++++++++++++++++++++
 5 files changed, 121 insertions(+), 169 deletions(-)
 create mode 100644 gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp

diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index 85cd08cd8e..59c5f0c4b9 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -409,13 +409,11 @@ ppc_register_u_addr (struct gdbarch *gdbarch, int regno)
    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)
+fetch_vsx_registers (struct regcache *regcache, int tid, int regno)
 {
   int ret;
   gdb_vsxregset_t regs;
-  struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum);
+  const struct regset *vsxregset = ppc_linux_vsxregset ();
 
   ret = ptrace (PTRACE_GETVSXREGS, tid, 0, &regs);
   if (ret < 0)
@@ -425,12 +423,11 @@ fetch_vsx_register (struct regcache *regcache, int tid, int regno)
 	  have_ptrace_getsetvsxregs = 0;
 	  return;
 	}
-      perror_with_name (_("Unable to fetch VSX register"));
+      perror_with_name (_("Unable to fetch VSX registers"));
     }
 
-  regcache_raw_supply (regcache, regno,
-		       regs + (regno - tdep->ppc_vsr0_upper_regnum)
-		       * vsxregsize);
+  vsxregset->supply_regset(vsxregset, regcache, regno, &regs,
+			   PPC_LINUX_SIZEOF_VSXREGSET);
 }
 
 /* The Linux kernel ptrace interface for AltiVec registers uses the
@@ -563,7 +560,7 @@ fetch_register (struct regcache *regcache, int tid, int regno)
     {
       if (have_ptrace_getsetvsxregs)
 	{
-	  fetch_vsx_register (regcache, tid, regno);
+	  fetch_vsx_registers (regcache, tid, regno);
 	  return;
 	}
     }
@@ -624,40 +621,6 @@ fetch_register (struct regcache *regcache, int tid, int regno)
                     gdbarch_byte_order (gdbarch));
 }
 
-static void
-supply_vsxregset (struct regcache *regcache, gdb_vsxregset_t *vsxregsetp)
-{
-  int i;
-  struct gdbarch *gdbarch = regcache->arch ();
-  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
-fetch_vsx_registers (struct regcache *regcache, int tid)
-{
-  int ret;
-  gdb_vsxregset_t regs;
-
-  ret = ptrace (PTRACE_GETVSXREGS, tid, 0, &regs);
-  if (ret < 0)
-    {
-      if (errno == EIO)
-	{
-	  have_ptrace_getsetvsxregs = 0;
-	  return;
-	}
-      perror_with_name (_("Unable to fetch VSX registers"));
-    }
-  supply_vsxregset (regcache, &regs);
-}
-
 /* This function actually issues the request to ptrace, telling
    it to get all general-purpose registers and put them into the
    specified regset.
@@ -799,7 +762,7 @@ fetch_ppc_registers (struct regcache *regcache, int tid)
       fetch_altivec_registers (regcache, tid, -1);
   if (have_ptrace_getsetvsxregs)
     if (tdep->ppc_vsr0_upper_regnum != -1)
-      fetch_vsx_registers (regcache, tid);
+      fetch_vsx_registers (regcache, tid, -1);
   if (tdep->ppc_ev0_upper_regnum >= 0)
     fetch_spe_register (regcache, tid, -1);
 }
@@ -818,15 +781,12 @@ ppc_linux_nat_target::fetch_registers (struct regcache *regcache, int regno)
     fetch_register (regcache, tid, regno);
 }
 
-/* Store one VSX register.  */
 static void
-store_vsx_register (const struct regcache *regcache, int tid, int regno)
+store_vsx_registers (const struct regcache *regcache, int tid, int regno)
 {
   int ret;
   gdb_vsxregset_t regs;
-  struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum);
+  const struct regset *vsxregset = ppc_linux_vsxregset ();
 
   ret = ptrace (PTRACE_GETVSXREGS, tid, 0, &regs);
   if (ret < 0)
@@ -836,15 +796,15 @@ store_vsx_register (const struct regcache *regcache, int tid, int regno)
 	  have_ptrace_getsetvsxregs = 0;
 	  return;
 	}
-      perror_with_name (_("Unable to fetch VSX register"));
+      perror_with_name (_("Unable to fetch VSX registers"));
     }
 
-  regcache_raw_collect (regcache, regno, regs +
-			(regno - tdep->ppc_vsr0_upper_regnum) * vsxregsize);
+  vsxregset->collect_regset (vsxregset, regcache, regno, &regs,
+			     PPC_LINUX_SIZEOF_VSXREGSET);
 
   ret = ptrace (PTRACE_SETVSXREGS, tid, 0, &regs);
   if (ret < 0)
-    perror_with_name (_("Unable to store VSX register"));
+    perror_with_name (_("Unable to store VSX registers"));
 }
 
 static void
@@ -980,7 +940,7 @@ store_register (const struct regcache *regcache, int tid, int regno)
     }
   if (vsx_register_p (gdbarch, regno))
     {
-      store_vsx_register (regcache, tid, regno);
+      store_vsx_registers (regcache, tid, regno);
       return;
     }
   else if (spe_register_p (gdbarch, regno))
@@ -1038,42 +998,6 @@ store_register (const struct regcache *regcache, int tid, int regno)
     }
 }
 
-static void
-fill_vsxregset (const struct regcache *regcache, gdb_vsxregset_t *vsxregsetp)
-{
-  int i;
-  struct gdbarch *gdbarch = regcache->arch ();
-  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
-store_vsx_registers (const struct regcache *regcache, int tid)
-{
-  int ret;
-  gdb_vsxregset_t regs;
-
-  ret = ptrace (PTRACE_GETVSXREGS, tid, 0, &regs);
-  if (ret < 0)
-    {
-      if (errno == EIO)
-	{
-	  have_ptrace_getsetvsxregs = 0;
-	  return;
-	}
-      perror_with_name (_("Couldn't get VSX registers"));
-    }
-
-  fill_vsxregset (regcache, &regs);
-
-  if (ptrace (PTRACE_SETVSXREGS, tid, 0, &regs) < 0)
-    perror_with_name (_("Couldn't write VSX registers"));
-}
-
 /* This function actually issues the request to ptrace, telling
    it to store all general-purpose registers present in the specified
    regset.
@@ -1235,7 +1159,7 @@ store_ppc_registers (const struct regcache *regcache, int tid)
       store_altivec_registers (regcache, tid, -1);
   if (have_ptrace_getsetvsxregs)
     if (tdep->ppc_vsr0_upper_regnum != -1)
-      store_vsx_registers (regcache, tid);
+      store_vsx_registers (regcache, tid, -1);
   if (tdep->ppc_ev0_upper_regnum >= 0)
     store_spe_register (regcache, tid, -1);
 }
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 3c8ba26f8e..54de34d0b7 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -560,10 +560,16 @@ static const struct regset ppc32_be_linux_vrregset = {
   ppc_linux_collect_vrregset
 };
 
+static const struct regcache_map_entry ppc32_linux_vsxregmap[] =
+  {
+      { 32, PPC_VSR0_UPPER_REGNUM, 8 },
+      { 0 }
+  };
+
 static const struct regset ppc32_linux_vsxregset = {
-  &ppc32_linux_reg_offsets,
-  ppc_supply_vsxregset,
-  ppc_collect_vsxregset
+  ppc32_linux_vsxregmap,
+  regcache_supply_regset,
+  regcache_collect_regset
 };
 
 const struct regset *
@@ -587,6 +593,12 @@ ppc_linux_vrregset (struct gdbarch *gdbarch)
     return &ppc32_le_linux_vrregset;
 }
 
+const struct regset *
+ppc_linux_vsxregset (void)
+{
+  return &ppc32_linux_vsxregset;
+}
+
 /* Iterate over supported core file register note sections. */
 
 static void
diff --git a/gdb/ppc-linux-tdep.h b/gdb/ppc-linux-tdep.h
index a8715bd418..51f4b506a1 100644
--- a/gdb/ppc-linux-tdep.h
+++ b/gdb/ppc-linux-tdep.h
@@ -30,6 +30,7 @@ const struct regset *ppc_linux_fpregset (void);
 
 /* Get the vector regset that matches the target byte order.  */
 const struct regset *ppc_linux_vrregset (struct gdbarch *gdbarch);
+const struct regset *ppc_linux_vsxregset (void);
 
 /* Extra register number constants.  The Linux kernel stores a
    "trap" code and the original value of r3 into special "registers";
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index c5b49c5f46..3f0b7f77a1 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -224,16 +224,6 @@ ppc_floating_point_unit_p (struct gdbarch *gdbarch)
 }
 
 /* Return non-zero if the architecture described by GDBARCH has
-   VSX registers (vsr0 --- vsr63).  */
-static int
-ppc_vsx_support_p (struct gdbarch *gdbarch)
-{
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-
-  return tdep->ppc_vsr0_regnum >= 0;
-}
-
-/* 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)
@@ -591,37 +581,6 @@ ppc_supply_fpregset (const struct regset *regset, struct regcache *regcache,
 		  regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8);
 }
 
-/* Supply register REGNUM in the VSX register set REGSET
-   from the buffer specified by VSXREGS and LEN to register cache
-   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
-
-void
-ppc_supply_vsxregset (const struct regset *regset, struct regcache *regcache,
-		     int regnum, const void *vsxregs, size_t len)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep;
-
-  if (!ppc_vsx_support_p (gdbarch))
-    return;
-
-  tdep = gdbarch_tdep (gdbarch);
-
-  if (regnum == -1)
-    {
-      int i;
-
-      for (i = tdep->ppc_vsr0_upper_regnum;
-	   i < tdep->ppc_vsr0_upper_regnum + 32;
-	   i++)
-	ppc_supply_reg (regcache, i, (const gdb_byte *) vsxregs, 0, 8);
-
-      return;
-    }
-  else
-    ppc_supply_reg (regcache, regnum, (const gdb_byte *) vsxregs, 0, 8);
-}
-
 /* Supply register REGNUM in the Altivec register set REGSET
    from the buffer specified by VRREGS and LEN to register cache
    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
@@ -757,40 +716,6 @@ ppc_collect_fpregset (const struct regset *regset,
 		   regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8);
 }
 
-/* Collect register REGNUM in the VSX register set
-   REGSET from register cache REGCACHE into the buffer specified by
-   VSXREGS and LEN.  If REGNUM is -1, do this for all registers in
-   REGSET.  */
-
-void
-ppc_collect_vsxregset (const struct regset *regset,
-		      const struct regcache *regcache,
-		      int regnum, void *vsxregs, size_t len)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep;
-
-  if (!ppc_vsx_support_p (gdbarch))
-    return;
-
-  tdep = gdbarch_tdep (gdbarch);
-
-  if (regnum == -1)
-    {
-      int i;
-
-      for (i = tdep->ppc_vsr0_upper_regnum;
-	   i < tdep->ppc_vsr0_upper_regnum + 32;
-	   i++)
-	ppc_collect_reg (regcache, i, (gdb_byte *) vsxregs, 0, 8);
-
-      return;
-    }
-  else
-    ppc_collect_reg (regcache, regnum, (gdb_byte *) vsxregs, 0, 8);
-}
-
-
 /* Collect register REGNUM in the Altivec register set
    REGSET from register cache REGCACHE into the buffer specified by
    VRREGS and LEN.  If REGNUM is -1, do this for all registers in
diff --git a/gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp b/gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp
new file mode 100644
index 0000000000..e9bdfcdd44
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp
@@ -0,0 +1,90 @@
+# Copyright (C) 2018 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the gdb testsuite.
+
+# This test checks that generating and loading a core file preserves
+# the correct VSX register state.
+
+if {![istarget "powerpc*-*-linux*"] || [skip_vsx_tests]} then {
+    verbose "Skipping PowerPC test for corefiles with VSX registers."
+    return
+}
+
+standard_testfile .c
+
+set gen_src [standard_output_file $srcfile]
+
+gdb_produce_source $gen_src {
+	int main() {
+	    return 0;
+	}
+}
+
+if {[build_executable "compile" $binfile $gen_src] == -1} {
+    return -1
+}
+
+clean_restart $binfile
+
+if ![runto_main] then {
+    fail "could not run to main"
+    return -1
+}
+
+# Check if VSX register access through gdb is supported
+proc check_vsx_access {} {
+    global gdb_prompt
+
+    set test "vsx register access"
+    gdb_test_multiple "info reg vs0" "$test" {
+	-re "Invalid register.*\r\n$gdb_prompt $" {
+	    unsupported "$test"
+	    return 0
+	}
+	-re "\r\nvs0.*\r\n$gdb_prompt $" {
+	    pass "$test"
+	    return 1
+	}
+    }
+    return 0
+}
+
+if { ![check_vsx_access] } {
+    return -1
+}
+
+for {set i 0} {$i < 64} {incr i 1} {
+    gdb_test_no_output "set \$vs$i.uint128 = $i"
+}
+
+set core_filename [standard_output_file "$testfile.core"]
+set core_generated [gdb_gcore_cmd "$core_filename" "generate core file"]
+
+if { !$core_generated } {
+    return -1
+}
+
+clean_restart
+
+set core_loaded [gdb_core_cmd "$core_filename" "load core file"]
+
+if { $core_loaded != 1 } {
+    return -1
+}
+
+for {set i 0} {$i < 64} {incr i 1} {
+    gdb_test "print \$vs$i.uint128" ".* = $i" "print vs$i"
+}
-- 
2.13.6

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

* [PATCH 2/8] [PowerPC] Consolidate wordsize getter between native and gdbserver
  2018-05-10 19:59 [PATCH 0/8] [PowerPC] Miscellaneous fixes for register access Pedro Franco de Carvalho
                   ` (4 preceding siblings ...)
  2018-05-10 20:33 ` [PATCH 6/8] [PowerPC] Fix VSX registers " Pedro Franco de Carvalho
@ 2018-05-10 20:33 ` Pedro Franco de Carvalho
  2018-05-16 15:54   ` Ulrich Weigand
  2018-05-10 21:46 ` [PATCH 5/8] [PowerPC] Fix access to VSCR in linux targets Pedro Franco de Carvalho
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-10 20:33 UTC (permalink / raw)
  To: gdb-patches

This patch moves the native target wordsize getter for ppc linux to
nat/ so that it can be used to simplify ppc_arch_setup in
gdbserver. The ptrace call used to get MSR for this is ultimately the
same as before, but it is no longer necessary to create a temporary
regcache to call fetch_inferior_registers.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* configure.nat <linux powerpc>: Add ppc-linux.o to NATDEPFILES.
	* ppc-linux-nat.c (ppc_linux_target_wordsize): Move to
	nat/ppc-linux.c.
	(ppc_linux_nat_target::auxv_parse): Get thread id tid. Call
	ppc_linux_target wordsize with tid.
	(ppc_linux_nat_target::read_description): Call ppc_linux_target
	wordsize with tid.
	* nat/ppc-linux.c: Include nat/gdb_ptrace.h.
	(ppc_linux_target_wordsize): Move here from ppc-linux-nat.c. Add
	tid parameter. Remove static specifier.
	* nat/ppc-linux.h (ppc_linux_target_wordsize): New declaration.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* linux-ppc-low.c (ppc_arch_setup): Remove code for getting the
	wordsize of the inferior. Call ppc_linux_target_wordsize.
---
 gdb/configure.nat             |  2 +-
 gdb/gdbserver/linux-ppc-low.c | 29 ++++++-----------------------
 gdb/nat/ppc-linux.c           | 20 ++++++++++++++++++++
 gdb/nat/ppc-linux.h           |  3 +++
 gdb/ppc-linux-nat.c           | 30 ++++++------------------------
 5 files changed, 36 insertions(+), 48 deletions(-)

diff --git a/gdb/configure.nat b/gdb/configure.nat
index 6b0f44fede..bcaeaf4583 100644
--- a/gdb/configure.nat
+++ b/gdb/configure.nat
@@ -264,7 +264,7 @@ case ${gdb_host} in
 		;;
 	    powerpc)
 		# Host: PowerPC, running Linux
-		NATDEPFILES="${NATDEPFILES} ppc-linux-nat.o"
+		NATDEPFILES="${NATDEPFILES} ppc-linux-nat.o ppc-linux.o"
 		;;
 	    s390)
 		# Host: S390, running Linux
diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c
index a442a51273..a4182633d7 100644
--- a/gdb/gdbserver/linux-ppc-low.c
+++ b/gdb/gdbserver/linux-ppc-low.c
@@ -621,33 +621,16 @@ ppc_arch_setup (void)
   const struct target_desc *tdesc;
   struct ppc_linux_features features = ppc_linux_no_features;
 
-#ifdef __powerpc64__
-  long msr;
-  struct regcache *regcache;
-
-  /* On a 64-bit host, assume 64-bit inferior process with no
-     AltiVec registers.  Reset ppc_hwcap to ensure that the
-     collect_register call below does not fail.  */
-  tdesc = tdesc_powerpc_64l;
-  current_process ()->tdesc = tdesc;
-  ppc_hwcap = 0;
+  int tid = lwpid_of (current_thread);
 
-  regcache = new_register_cache (tdesc);
-  fetch_inferior_registers (regcache, find_regno (tdesc, "msr"));
-  collect_register_by_name (regcache, "msr", &msr);
-  free_register_cache (regcache);
-  if (ppc64_64bit_inferior_p (msr))
-    {
-      features.wordsize = 8;
-    }
-#endif
+  features.wordsize = ppc_linux_target_wordsize (tid);
 
   if (features.wordsize == 4)
-    {
-      /* OK, we have a 32-bit inferior.  */
       tdesc = tdesc_powerpc_32l;
-      current_process ()->tdesc = tdesc;
-    }
+  else
+      tdesc = tdesc_powerpc_64l;
+
+  current_process ()->tdesc = tdesc;
 
   /* The value of current_process ()->tdesc needs to be set for this
      call.  */
diff --git a/gdb/nat/ppc-linux.c b/gdb/nat/ppc-linux.c
index 7ab6551316..b87625e3f6 100644
--- a/gdb/nat/ppc-linux.c
+++ b/gdb/nat/ppc-linux.c
@@ -17,6 +17,7 @@
 
 #include "common-defs.h"
 #include "ppc-linux.h"
+#include "nat/gdb_ptrace.h"
 #include <elf.h>
 
 #ifdef HAVE_GETAUXVAL
@@ -73,3 +74,22 @@ ppc64_64bit_inferior_p (long msr)
 }
 
 #endif
+
+int
+ppc_linux_target_wordsize (int tid)
+{
+  int wordsize = 4;
+
+  /* Check for 64-bit inferior process.  This is the case when the host is
+     64-bit, and in addition the top bit of the MSR register is set.  */
+#ifdef __powerpc64__
+  long msr;
+
+  errno = 0;
+  msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0);
+  if (errno == 0 && ppc64_64bit_inferior_p (msr))
+    wordsize = 8;
+#endif
+
+  return wordsize;
+}
diff --git a/gdb/nat/ppc-linux.h b/gdb/nat/ppc-linux.h
index 76a5d181df..d91d3f2a9c 100644
--- a/gdb/nat/ppc-linux.h
+++ b/gdb/nat/ppc-linux.h
@@ -88,4 +88,7 @@
 int ppc64_64bit_inferior_p (long msr);
 #endif
 
+/* Return the wordsize of the target, either 4 or 8 bytes.  */
+int ppc_linux_target_wordsize (int tid);
+
 #endif
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index af59761cd6..07ec53d1ea 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -2368,35 +2368,17 @@ fill_fpregset (const struct regcache *regcache,
 			fpregsetp, sizeof (*fpregsetp));
 }
 
-static int
-ppc_linux_target_wordsize (void)
+int
+ppc_linux_nat_target::auxv_parse (gdb_byte **readptr,
+				  gdb_byte *endptr, CORE_ADDR *typep,
+				  CORE_ADDR *valp)
 {
-  int wordsize = 4;
-
-  /* Check for 64-bit inferior process.  This is the case when the host is
-     64-bit, and in addition the top bit of the MSR register is set.  */
-#ifdef __powerpc64__
-  long msr;
-
   int tid = ptid_get_lwp (inferior_ptid);
   if (tid == 0)
     tid = ptid_get_pid (inferior_ptid);
 
-  errno = 0;
-  msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0);
-  if (errno == 0 && ppc64_64bit_inferior_p (msr))
-    wordsize = 8;
-#endif
-
-  return wordsize;
-}
+  int sizeof_auxv_field = ppc_linux_target_wordsize (tid);
 
-int
-ppc_linux_nat_target::auxv_parse (gdb_byte **readptr,
-				  gdb_byte *endptr, CORE_ADDR *typep,
-				  CORE_ADDR *valp)
-{
-  int sizeof_auxv_field = ppc_linux_target_wordsize ();
   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
   gdb_byte *ptr = *readptr;
 
@@ -2438,7 +2420,7 @@ ppc_linux_nat_target::read_description ()
   struct ppc_linux_features features = ppc_linux_no_features;
   unsigned long hwcap = ppc_linux_get_hwcap ();
 
-  features.wordsize = ppc_linux_target_wordsize ();
+  features.wordsize = ppc_linux_target_wordsize (tid);
 
   if (have_ptrace_getsetvsxregs
       && (hwcap & PPC_FEATURE_HAS_VSX))
-- 
2.13.6

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

* [PATCH 5/8] [PowerPC] Fix access to VSCR in linux targets
  2018-05-10 19:59 [PATCH 0/8] [PowerPC] Miscellaneous fixes for register access Pedro Franco de Carvalho
                   ` (5 preceding siblings ...)
  2018-05-10 20:33 ` [PATCH 2/8] [PowerPC] Consolidate wordsize getter between native and gdbserver Pedro Franco de Carvalho
@ 2018-05-10 21:46 ` Pedro Franco de Carvalho
  2018-05-16 14:06   ` Ulrich Weigand
  2018-05-10 22:25 ` [PATCH 7/8] [PowerPC] Fix inclusion of dfp pseudoregs in tdep Pedro Franco de Carvalho
  2018-05-21 20:46 ` [PATCH v2 1/8] [PowerPC] Consolidate linux target description selection Pedro Franco de Carvalho
  8 siblings, 1 reply; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-10 21:46 UTC (permalink / raw)
  To: gdb-patches

The 4-byte VSCR register is found inside a 16-byte field in the regset
returned by ptrace and in core files. The position of VSCR depends on
the endianess of the target, which was previously assumed to be
big-endian for the purpose of getting VSCR. This patch removes this
assumption to fix access to VSCR in little-endian mode.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* ppc-linux-tdep.c (ppc_linux_collect_vrregset): New function.
	(ppc_linux_vrregset) : New function.
	(ppc32_le_linux_vrregmap, ppc32_be_linux_vrregmap)
	(ppc32_le_linux_vrregset, ppc32_be_linux_vrregset): New globals.
	(ppc32_linux_vrregset): Remove.
	(ppc_linux_iterate_over_regset_sections): Call ppc_linux_vrregset
	and use result instead of ppc32_linux_vrregset.
	* ppc-linux-tdep.h (ppc_linux_vrregset): New declaration.
	* ppc-linux-nat.c: Include regset.h.
	(gdb_vrregset_t): Adjust comment to account for little-endian
	mode.
	(supply_vrregset, fill_vrregset): Remove.
	(fetch_altivec_register, store_altivec_register): Remove.
	(fetch_altivec_registers): Add regno parameter. Get regset using
	ppc_linux_vrregset. Use regset to supply registers.
	(store_altivec_registers): Add regno parameter. Get regset using
	ppc_linux_vrregset. Use regset to collect registers.
	(fetch_register): Call fetch_altivec_registers instead of
	fetch_altivec_register.
	(store_register): Call store_altivec_registers instead of
	store_altivec_register.
	(fetch_ppc_registers): Call fetch_altivec_registers with -1 for
	the new regno parameter.
	(store_ppc_registers): Call store_altivec_registers with -1 for
	the new regno parameter.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* linux-ppc-low.c (ppc_fill_vrregset): Add vscr_offset variable.
	Set vscr_offset to 0 in little-endian mode and 12 in big-endian
	mode. Call collect_register_by_name with vscr using
	vscr_offset. Zero-pad vscr and vrsave fields in collector buffer.
	(ppc_store_vrregset): Add and set vscr_offset variable as in
	ppc_fill_vrregset. Call supply_register_by_name with vscr using
	vscr_offset.
---
 gdb/gdbserver/linux-ppc-low.c |  19 +++++-
 gdb/ppc-linux-nat.c           | 153 +++++++-----------------------------------
 gdb/ppc-linux-tdep.c          |  65 ++++++++++++++++--
 gdb/ppc-linux-tdep.h          |   3 +
 4 files changed, 103 insertions(+), 137 deletions(-)

diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c
index ed48fa7850..91e6625121 100644
--- a/gdb/gdbserver/linux-ppc-low.c
+++ b/gdb/gdbserver/linux-ppc-low.c
@@ -486,12 +486,22 @@ ppc_fill_vrregset (struct regcache *regcache, void *buf)
 {
   int i, base;
   char *regset = (char *) buf;
+  int vscr_offset = 0;
 
   base = find_regno (regcache->tdesc, "vr0");
   for (i = 0; i < 32; i++)
     collect_register (regcache, base + i, &regset[i * 16]);
 
-  collect_register_by_name (regcache, "vscr", &regset[32 * 16 + 12]);
+  if (__BYTE_ORDER == __BIG_ENDIAN)
+    vscr_offset = 12;
+
+  /* Zero-pad the unused bytes in the fields for vscr and vrsave in
+     case they get displayed somewhere.  */
+  memset (&regset[32 * 16], 0, 16);
+  collect_register_by_name (regcache, "vscr",
+			    &regset[32 * 16 + vscr_offset]);
+
+  memset (&regset[33 * 16], 0, 16);
   collect_register_by_name (regcache, "vrsave", &regset[33 * 16]);
 }
 
@@ -500,12 +510,17 @@ ppc_store_vrregset (struct regcache *regcache, const void *buf)
 {
   int i, base;
   const char *regset = (const char *) buf;
+  int vscr_offset = 0;
 
   base = find_regno (regcache->tdesc, "vr0");
   for (i = 0; i < 32; i++)
     supply_register (regcache, base + i, &regset[i * 16]);
 
-  supply_register_by_name (regcache, "vscr", &regset[32 * 16 + 12]);
+  if (__BYTE_ORDER == __BIG_ENDIAN)
+    vscr_offset = 12;
+
+  supply_register_by_name (regcache, "vscr",
+			   &regset[32 * 16 + vscr_offset]);
   supply_register_by_name (regcache, "vrsave", &regset[33 * 16]);
 }
 
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index 554aba662e..85cd08cd8e 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -24,6 +24,7 @@
 #include "gdbthread.h"
 #include "gdbcore.h"
 #include "regcache.h"
+#include "regset.h"
 #include "target.h"
 #include "linux-nat.h"
 #include <sys/types.h>
@@ -160,17 +161,18 @@ struct ppc_hw_breakpoint
    Even though this vrsave register is not included in the regset
    typedef, it is handled by the ptrace requests.
 
-   Note that GNU/Linux doesn't support little endian PPC hardware,
-   therefore the offset at which the real value of the VSCR register
-   is located will be always 12 bytes.
-
    The layout is like this (where x is the actual value of the vscr reg): */
 
 /* *INDENT-OFF* */
 /*
+Big-Endian:
    |.|.|.|.|.....|.|.|.|.||.|.|.|x||.|
    <------->     <-------><-------><->
      VR0           VR31     VSCR    VRSAVE
+Little-Endian:
+   |.|.|.|.|.....|.|.|.|.||X|.|.|.||.|
+   <------->     <-------><-------><->
+     VR0           VR31     VSCR    VRSAVE
 */
 /* *INDENT-ON* */
 
@@ -435,14 +437,13 @@ fetch_vsx_register (struct regcache *regcache, int tid, int regno)
    registers set mechanism, as opposed to the interface for all the
    other registers, that stores/fetches each register individually.  */
 static void
-fetch_altivec_register (struct regcache *regcache, int tid, int regno)
+fetch_altivec_registers (struct regcache *regcache, int tid,
+			 int regno)
 {
   int ret;
-  int offset = 0;
   gdb_vrregset_t regs;
   struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int vrregsize = register_size (gdbarch, tdep->ppc_vr0_regnum);
+  const struct regset *vrregset = ppc_linux_vrregset (gdbarch);
 
   ret = ptrace (PTRACE_GETVRREGS, tid, 0, &regs);
   if (ret < 0)
@@ -452,19 +453,11 @@ fetch_altivec_register (struct regcache *regcache, int tid, int regno)
           have_ptrace_getvrregs = 0;
           return;
         }
-      perror_with_name (_("Unable to fetch AltiVec register"));
+      perror_with_name (_("Unable to fetch AltiVec registers"));
     }
- 
-  /* VSCR is fetched as a 16 bytes quantity, but it is really 4 bytes
-     long on the hardware.  We deal only with the lower 4 bytes of the
-     vector.  VRSAVE is at the end of the array in a 4 bytes slot, so
-     there is no need to define an offset for it.  */
-  if (regno == (tdep->ppc_vrsave_regnum - 1))
-    offset = vrregsize - register_size (gdbarch, tdep->ppc_vrsave_regnum);
-  
-  regcache_raw_supply (regcache, regno,
-		       regs + (regno
-			       - tdep->ppc_vr0_regnum) * vrregsize + offset);
+
+  vrregset->supply_regset(vrregset, regcache, regno, &regs,
+			  PPC_LINUX_SIZEOF_VRREGSET);
 }
 
 /* Fetch the top 32 bits of TID's general-purpose registers and the
@@ -559,7 +552,7 @@ fetch_register (struct regcache *regcache, int tid, int regno)
          register.  */
       if (have_ptrace_getvrregs)
        {
-         fetch_altivec_register (regcache, tid, regno);
+         fetch_altivec_registers (regcache, tid, regno);
          return;
        }
      /* If we have discovered that there is no ptrace support for
@@ -647,31 +640,6 @@ supply_vsxregset (struct regcache *regcache, gdb_vsxregset_t *vsxregsetp)
 }
 
 static void
-supply_vrregset (struct regcache *regcache, gdb_vrregset_t *vrregsetp)
-{
-  int i;
-  struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int num_of_vrregs = tdep->ppc_vrsave_regnum - tdep->ppc_vr0_regnum + 1;
-  int vrregsize = register_size (gdbarch, tdep->ppc_vr0_regnum);
-  int offset = vrregsize - register_size (gdbarch, tdep->ppc_vrsave_regnum);
-
-  for (i = 0; i < num_of_vrregs; i++)
-    {
-      /* The last 2 registers of this set are only 32 bit long, not
-         128.  However an offset is necessary only for VSCR because it
-         occupies a whole vector, while VRSAVE occupies a full 4 bytes
-         slot.  */
-      if (i == (num_of_vrregs - 2))
-        regcache_raw_supply (regcache, tdep->ppc_vr0_regnum + i,
-			     *vrregsetp + i * vrregsize + offset);
-      else
-        regcache_raw_supply (regcache, tdep->ppc_vr0_regnum + i,
-			     *vrregsetp + i * vrregsize);
-    }
-}
-
-static void
 fetch_vsx_registers (struct regcache *regcache, int tid)
 {
   int ret;
@@ -690,25 +658,6 @@ fetch_vsx_registers (struct regcache *regcache, int tid)
   supply_vsxregset (regcache, &regs);
 }
 
-static void
-fetch_altivec_registers (struct regcache *regcache, int tid)
-{
-  int ret;
-  gdb_vrregset_t regs;
-  
-  ret = ptrace (PTRACE_GETVRREGS, tid, 0, &regs);
-  if (ret < 0)
-    {
-      if (errno == EIO)
-	{
-          have_ptrace_getvrregs = 0;
-	  return;
-	}
-      perror_with_name (_("Unable to fetch AltiVec registers"));
-    }
-  supply_vrregset (regcache, &regs);
-}
-
 /* This function actually issues the request to ptrace, telling
    it to get all general-purpose registers and put them into the
    specified regset.
@@ -847,7 +796,7 @@ fetch_ppc_registers (struct regcache *regcache, int tid)
     fetch_register (regcache, tid, tdep->ppc_fpscr_regnum);
   if (have_ptrace_getvrregs)
     if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
-      fetch_altivec_registers (regcache, tid);
+      fetch_altivec_registers (regcache, tid, -1);
   if (have_ptrace_getsetvsxregs)
     if (tdep->ppc_vsr0_upper_regnum != -1)
       fetch_vsx_registers (regcache, tid);
@@ -898,16 +847,14 @@ store_vsx_register (const struct regcache *regcache, int tid, int regno)
     perror_with_name (_("Unable to store VSX register"));
 }
 
-/* Store one register.  */
 static void
-store_altivec_register (const struct regcache *regcache, int tid, int regno)
+store_altivec_registers (const struct regcache *regcache, int tid,
+			 int regno)
 {
   int ret;
-  int offset = 0;
   gdb_vrregset_t regs;
   struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int vrregsize = register_size (gdbarch, tdep->ppc_vr0_regnum);
+  const struct regset *vrregset = ppc_linux_vrregset (gdbarch);
 
   ret = ptrace (PTRACE_GETVRREGS, tid, 0, &regs);
   if (ret < 0)
@@ -917,21 +864,15 @@ store_altivec_register (const struct regcache *regcache, int tid, int regno)
           have_ptrace_getvrregs = 0;
           return;
         }
-      perror_with_name (_("Unable to fetch AltiVec register"));
+      perror_with_name (_("Unable to fetch AltiVec registers"));
     }
 
-  /* VSCR is fetched as a 16 bytes quantity, but it is really 4 bytes
-     long on the hardware.  */
-  if (regno == (tdep->ppc_vrsave_regnum - 1))
-    offset = vrregsize - register_size (gdbarch, tdep->ppc_vrsave_regnum);
-
-  regcache_raw_collect (regcache, regno,
-			regs + (regno
-				- tdep->ppc_vr0_regnum) * vrregsize + offset);
+  vrregset->collect_regset (vrregset, regcache, regno, &regs,
+			    PPC_LINUX_SIZEOF_VRREGSET);
 
   ret = ptrace (PTRACE_SETVRREGS, tid, 0, &regs);
   if (ret < 0)
-    perror_with_name (_("Unable to store AltiVec register"));
+    perror_with_name (_("Unable to store AltiVec registers"));
 }
 
 /* Assuming TID referrs to an SPE process, set the top halves of TID's
@@ -1034,7 +975,7 @@ store_register (const struct regcache *regcache, int tid, int regno)
 
   if (altivec_register_p (gdbarch, regno))
     {
-      store_altivec_register (regcache, tid, regno);
+      store_altivec_registers (regcache, tid, regno);
       return;
     }
   if (vsx_register_p (gdbarch, regno))
@@ -1111,29 +1052,6 @@ fill_vsxregset (const struct regcache *regcache, gdb_vsxregset_t *vsxregsetp)
 }
 
 static void
-fill_vrregset (const struct regcache *regcache, gdb_vrregset_t *vrregsetp)
-{
-  int i;
-  struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int num_of_vrregs = tdep->ppc_vrsave_regnum - tdep->ppc_vr0_regnum + 1;
-  int vrregsize = register_size (gdbarch, tdep->ppc_vr0_regnum);
-  int offset = vrregsize - register_size (gdbarch, tdep->ppc_vrsave_regnum);
-
-  for (i = 0; i < num_of_vrregs; i++)
-    {
-      /* The last 2 registers of this set are only 32 bit long, not
-         128, but only VSCR is fetched as a 16 bytes quantity.  */
-      if (i == (num_of_vrregs - 2))
-        regcache_raw_collect (regcache, tdep->ppc_vr0_regnum + i,
-			      *vrregsetp + i * vrregsize + offset);
-      else
-        regcache_raw_collect (regcache, tdep->ppc_vr0_regnum + i,
-			      *vrregsetp + i * vrregsize);
-    }
-}
-
-static void
 store_vsx_registers (const struct regcache *regcache, int tid)
 {
   int ret;
@@ -1156,29 +1074,6 @@ store_vsx_registers (const struct regcache *regcache, int tid)
     perror_with_name (_("Couldn't write VSX registers"));
 }
 
-static void
-store_altivec_registers (const struct regcache *regcache, int tid)
-{
-  int ret;
-  gdb_vrregset_t regs;
-
-  ret = ptrace (PTRACE_GETVRREGS, tid, 0, &regs);
-  if (ret < 0)
-    {
-      if (errno == EIO)
-        {
-          have_ptrace_getvrregs = 0;
-          return;
-        }
-      perror_with_name (_("Couldn't get AltiVec registers"));
-    }
-
-  fill_vrregset (regcache, &regs);
-  
-  if (ptrace (PTRACE_SETVRREGS, tid, 0, &regs) < 0)
-    perror_with_name (_("Couldn't write AltiVec registers"));
-}
-
 /* This function actually issues the request to ptrace, telling
    it to store all general-purpose registers present in the specified
    regset.
@@ -1337,7 +1232,7 @@ store_ppc_registers (const struct regcache *regcache, int tid)
     }
   if (have_ptrace_getvrregs)
     if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
-      store_altivec_registers (regcache, tid);
+      store_altivec_registers (regcache, tid, -1);
   if (have_ptrace_getsetvsxregs)
     if (tdep->ppc_vsr0_upper_regnum != -1)
       store_vsx_registers (regcache, tid);
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 344069d752..3c8ba26f8e 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -444,6 +444,24 @@ ppc_linux_collect_gregset (const struct regset *regset,
     }
 }
 
+static void
+ppc_linux_collect_vrregset (const struct regset *regset,
+			    const struct regcache *regcache,
+			    int regnum, void *buf, size_t len)
+{
+  gdb_byte *vrregs = (gdb_byte *) buf;
+
+  /* Zero-pad the unused bytes in the fields for vscr and vrsave
+     in case they get displayed somewhere (e.g. in core files).  */
+  if (regnum == PPC_VSCR_REGNUM || regnum == -1)
+    memset (&vrregs[32 * 16], 0, 16);
+
+  if (regnum == PPC_VRSAVE_REGNUM || regnum == -1)
+    memset (&vrregs[33 * 16], 0, 16);
+
+  regcache_collect_regset (regset, regcache, regnum, buf, len);
+}
+
 /* Regset descriptions.  */
 static const struct ppc_reg_offsets ppc32_linux_reg_offsets =
   {
@@ -513,10 +531,33 @@ static const struct regset ppc32_linux_fpregset = {
   ppc_collect_fpregset
 };
 
-static const struct regset ppc32_linux_vrregset = {
-  &ppc32_linux_reg_offsets,
-  ppc_supply_vrregset,
-  ppc_collect_vrregset
+static const struct regcache_map_entry ppc32_le_linux_vrregmap[] =
+  {
+      { 32, PPC_VR0_REGNUM, 16 },
+      { 1, PPC_VSCR_REGNUM, 16 },
+      { 1, PPC_VRSAVE_REGNUM, 16 },
+      { 0 }
+  };
+
+static const struct regcache_map_entry ppc32_be_linux_vrregmap[] =
+  {
+      { 32, PPC_VR0_REGNUM, 16 },
+      { 1, REGCACHE_MAP_SKIP, 12},
+      { 1, PPC_VSCR_REGNUM, 4 },
+      { 1, PPC_VRSAVE_REGNUM, 16 },
+      { 0 }
+  };
+
+static const struct regset ppc32_le_linux_vrregset = {
+  ppc32_le_linux_vrregmap,
+  regcache_supply_regset,
+  ppc_linux_collect_vrregset
+};
+
+static const struct regset ppc32_be_linux_vrregset = {
+  ppc32_be_linux_vrregmap,
+  regcache_supply_regset,
+  ppc_linux_collect_vrregset
 };
 
 static const struct regset ppc32_linux_vsxregset = {
@@ -537,6 +578,15 @@ ppc_linux_fpregset (void)
   return &ppc32_linux_fpregset;
 }
 
+const struct regset *
+ppc_linux_vrregset (struct gdbarch *gdbarch)
+{
+  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+    return &ppc32_be_linux_vrregset;
+  else
+    return &ppc32_le_linux_vrregset;
+}
+
 /* Iterate over supported core file register note sections. */
 
 static void
@@ -557,8 +607,11 @@ ppc_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
   cb (".reg2", 264, &ppc32_linux_fpregset, NULL, cb_data);
 
   if (have_altivec)
-    cb (".reg-ppc-vmx", PPC_LINUX_SIZEOF_VRREGSET, &ppc32_linux_vrregset,
-	"ppc Altivec", cb_data);
+    {
+      const struct regset *vrregset = ppc_linux_vrregset(gdbarch);
+      cb (".reg-ppc-vmx", PPC_LINUX_SIZEOF_VRREGSET, vrregset,
+	  "ppc Altivec", cb_data);
+    }
 
   if (have_vsx)
     cb (".reg-ppc-vsx", PPC_LINUX_SIZEOF_VSXREGSET,
diff --git a/gdb/ppc-linux-tdep.h b/gdb/ppc-linux-tdep.h
index 5e7c4be16b..a8715bd418 100644
--- a/gdb/ppc-linux-tdep.h
+++ b/gdb/ppc-linux-tdep.h
@@ -28,6 +28,9 @@ struct regset;
 const struct regset *ppc_linux_gregset (int);
 const struct regset *ppc_linux_fpregset (void);
 
+/* Get the vector regset that matches the target byte order.  */
+const struct regset *ppc_linux_vrregset (struct gdbarch *gdbarch);
+
 /* Extra register number constants.  The Linux kernel stores a
    "trap" code and the original value of r3 into special "registers";
    these need to be saved and restored when performing an inferior
-- 
2.13.6

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

* [PATCH 7/8] [PowerPC] Fix inclusion of dfp pseudoregs in tdep
  2018-05-10 19:59 [PATCH 0/8] [PowerPC] Miscellaneous fixes for register access Pedro Franco de Carvalho
                   ` (6 preceding siblings ...)
  2018-05-10 21:46 ` [PATCH 5/8] [PowerPC] Fix access to VSCR in linux targets Pedro Franco de Carvalho
@ 2018-05-10 22:25 ` Pedro Franco de Carvalho
  2018-05-16 14:18   ` Ulrich Weigand
  2018-05-21 20:46 ` [PATCH v2 1/8] [PowerPC] Consolidate linux target description selection Pedro Franco de Carvalho
  8 siblings, 1 reply; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-10 22:25 UTC (permalink / raw)
  To: gdb-patches

Previously, decimal floating point pseudoregisters were always included
in the target if it had a floating point unit.

This patch changes this to only include them if the target description
indicates that they are present, i.e. if the FPSCR register has more
than 32 bits.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* rs6000-tdep.c (rs6000_gdbarch_init): Assign 1 to have_dfp only
	if the size of fpscr is larger than 32 bits.
---
 gdb/rs6000-tdep.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index 3f0b7f77a1..7e4662b337 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -6090,14 +6090,16 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 	      return NULL;
 	    }
 	  have_fpu = 1;
+
+	  /* The fpscr register was expanded in isa 2.05 to 64 bits
+	     along with the addition of the decimal floating point
+	     facility.  */
+	  if (tdesc_register_size(feature, "fpscr") > 32)
+	    have_dfp = 1;
 	}
       else
 	have_fpu = 0;
 
-      /* The DFP pseudo-registers will be available when there are floating
-         point registers.  */
-      have_dfp = have_fpu;
-
       feature = tdesc_find_feature (tdesc,
 				    "org.gnu.gdb.power.altivec");
       if (feature != NULL)
-- 
2.13.6

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

* Re: [PATCH 1/8] [PowerPC] Consolidate linux target description selection
  2018-05-10 19:59 ` [PATCH 1/8] [PowerPC] Consolidate linux target description selection Pedro Franco de Carvalho
@ 2018-05-16 14:05   ` Ulrich Weigand
  2018-05-16 22:50     ` Pedro Franco de Carvalho
  0 siblings, 1 reply; 44+ messages in thread
From: Ulrich Weigand @ 2018-05-16 14:05 UTC (permalink / raw)
  To: Pedro Franco de Carvalho; +Cc: gdb-patches

Pedro Franco de Carvalho wrote:

> gdb/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* arch/ppc-linux-common.c: New file.
> 	* arch/ppc-linux-common.h: New file.
> 	* arch/ppc-linux-tdesc.h: New file.
> 	* configure.tgt (powerpc*-*-linux*): Add arch/ppc-linux-common.o.
> 	* Makefile.in (ALL_TARGET_OBS): Add arch/ppc-linux-common.o.
> 	(HFILES_NO_SRCDIR): Add arch/ppc-linux-common.h and
> 	arch/ppc-linux-tdesc.h.
> 	* ppc-linux-nat.c: Include arch/ppc-linux-common.h and
> 	arch/ppc-linux-tdesc.h.
> 	(ppc_linux_nat_target::read_description): Remove target
> 	description matching code. Fill a ppc_linux_features struct and
> 	call ppc_linux_match_description with it. Move comment about ISA
> 	2.05 to ppc-linux-common.c.
> 	* ppc-linux-tdep.c: Include arch/ppc-linux-common.h and
> 	arch/ppc-linux-tdesc.h.
> 	(ppc_linux_core_read_description): Remove target description
> 	matching code. Fill a ppc_linux_features struct and call
> 	ppc_linux_match_description with it.
> 	* ppc-linux-tdep.h (tdesc_powerpc_32l, tdesc_powerpc_64l)
> 	(tdesc_powerpc_altivec32l, tdesc_powerpc_altivec64l)
> 	(tdesc_powerpc_cell32l, tdesc_powerpc_cell64l)
> 	(tdesc_powerpc_vsx32l, tdesc_powerpc_vsx64l)
> 	(tdesc_powerpc_isa205_32l, tdesc_powerpc_isa205_64l)
> 	(tdesc_powerpc_isa205_altivec32l, tdesc_powerpc_isa205_altivec64l)
> 	(tdesc_powerpc_isa205_vsx32l, tdesc_powerpc_isa205_vsx64l)
> 	(tdesc_powerpc_e500l): Remove.
> 
> gdb/gdbserver/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* configure.srv (srv_tgtobj): Add arch/ppc-linux-common.o.
> 	* Makefile.in (SFILES): Add arch/ppc-linux-common.c.
> 	* linux-ppc-tdesc.h: Rename to linux-ppc-tdesc-init.h.
> 	* linux-ppc-tdesc-init.h (tdesc_powerpc_32l, tdesc_powerpc_64l)
> 	(tdesc_powerpc_altivec32l, tdesc_powerpc_altivec64l)
> 	(tdesc_powerpc_cell32l, tdesc_powerpc_cell64l)
> 	(tdesc_powerpc_vsx32l, tdesc_powerpc_vsx64l)
> 	(tdesc_powerpc_isa205_32l, tdesc_powerpc_isa205_64l)
> 	(tdesc_powerpc_isa205_altivec32l, tdesc_powerpc_isa205_altivec64l)
> 	(tdesc_powerpc_isa205_vsx32l, tdesc_powerpc_isa205_vsx64l)
> 	(tdesc_powerpc_e500l): Remove.
> 	* linux-ppc-ipa.c: Include arch/ppc-linux-tdesc.h and
> 	linux-ppc-tdesc-init.h. Don't include linux-ppc-tdesc.h.
> 	* linux-ppc-low.c: Include arch/ppc-linux-common.h,
> 	arch/ppc-linux-tdesc.h, and linux-ppc-tdesc-init.h. Don't include
> 	linux-ppc-tdesc.h.
> 	(ppc_arch_setup): Remove target description matching code. Fill a
> 	ppc_linux_features struct and call ppc_linux_match_description
> 	with it.

Thanks for doing this rework!  The patch is mostly OK with me,
except for this one bit:

> +/* Base value for ppc_linux_features variables.  */
> +const struct ppc_linux_features ppc_linux_no_features = {
> +  4,
> +  false,
> +  false,
> +  false,
> +  false,
> +};

I'm not sure it makes much sense to declare "4" the default wordsize
-- there's not really a default between 4 and 8.  Maybe it would be
clearer to just force all users to explicitly set the wordsize.

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH 5/8] [PowerPC] Fix access to VSCR in linux targets
  2018-05-10 21:46 ` [PATCH 5/8] [PowerPC] Fix access to VSCR in linux targets Pedro Franco de Carvalho
@ 2018-05-16 14:06   ` Ulrich Weigand
  2018-05-17 21:25     ` Pedro Franco de Carvalho
  2018-05-21 20:46     ` Pedro Franco de Carvalho
  0 siblings, 2 replies; 44+ messages in thread
From: Ulrich Weigand @ 2018-05-16 14:06 UTC (permalink / raw)
  To: Pedro Franco de Carvalho; +Cc: gdb-patches

Pedro Franco de Carvalho wrote:

> gdb/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* ppc-linux-tdep.c (ppc_linux_collect_vrregset): New function.
> 	(ppc_linux_vrregset) : New function.
> 	(ppc32_le_linux_vrregmap, ppc32_be_linux_vrregmap)
> 	(ppc32_le_linux_vrregset, ppc32_be_linux_vrregset): New globals.
> 	(ppc32_linux_vrregset): Remove.
> 	(ppc_linux_iterate_over_regset_sections): Call ppc_linux_vrregset
> 	and use result instead of ppc32_linux_vrregset.
> 	* ppc-linux-tdep.h (ppc_linux_vrregset): New declaration.
> 	* ppc-linux-nat.c: Include regset.h.
> 	(gdb_vrregset_t): Adjust comment to account for little-endian
> 	mode.
> 	(supply_vrregset, fill_vrregset): Remove.
> 	(fetch_altivec_register, store_altivec_register): Remove.
> 	(fetch_altivec_registers): Add regno parameter. Get regset using
> 	ppc_linux_vrregset. Use regset to supply registers.
> 	(store_altivec_registers): Add regno parameter. Get regset using
> 	ppc_linux_vrregset. Use regset to collect registers.
> 	(fetch_register): Call fetch_altivec_registers instead of
> 	fetch_altivec_register.
> 	(store_register): Call store_altivec_registers instead of
> 	store_altivec_register.
> 	(fetch_ppc_registers): Call fetch_altivec_registers with -1 for
> 	the new regno parameter.
> 	(store_ppc_registers): Call store_altivec_registers with -1 for
> 	the new regno parameter.
> 
> gdb/gdbserver/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* linux-ppc-low.c (ppc_fill_vrregset): Add vscr_offset variable.
> 	Set vscr_offset to 0 in little-endian mode and 12 in big-endian
> 	mode. Call collect_register_by_name with vscr using
> 	vscr_offset. Zero-pad vscr and vrsave fields in collector buffer.
> 	(ppc_store_vrregset): Add and set vscr_offset variable as in
> 	ppc_fill_vrregset. Call supply_register_by_name with vscr using
> 	vscr_offset.

I agree with the general direction of this patch.  A few comments:

> +  vrregset->supply_regset(vrregset, regcache, regno, &regs,
> +			  PPC_LINUX_SIZEOF_VRREGSET);

Formatting (space before '(').

> +static void
> +ppc_linux_collect_vrregset (const struct regset *regset,
> +			    const struct regcache *regcache,
> +			    int regnum, void *buf, size_t len)
> +{
> +  gdb_byte *vrregs = (gdb_byte *) buf;
> +
> +  /* Zero-pad the unused bytes in the fields for vscr and vrsave
> +     in case they get displayed somewhere (e.g. in core files).  */
> +  if (regnum == PPC_VSCR_REGNUM || regnum == -1)
> +    memset (&vrregs[32 * 16], 0, 16);
> +
> +  if (regnum == PPC_VRSAVE_REGNUM || regnum == -1)
> +    memset (&vrregs[33 * 16], 0, 16);
> +
> +  regcache_collect_regset (regset, regcache, regnum, buf, len);
> +}

I'm wondering if we shouldn't have the common regcache_collect_regset
routine zero out areas covered by REGCACHE_MAP_SKIP?  Then we wouldn't
need this extra routine here.

> -static const struct regset ppc32_linux_vrregset = {
> -  &ppc32_linux_reg_offsets,
> -  ppc_supply_vrregset,
> -  ppc_collect_vrregset

This removes all users of ppc_supply_vrregset / ppc_collect_vrregset,
right?  Then those functions should go away as well, together with
all their associates data, in particular the v*_offset fields in
struct ppc_reg_offsets ...

> +static const struct regcache_map_entry ppc32_le_linux_vrregmap[] =
> +  {
> +      { 32, PPC_VR0_REGNUM, 16 },
> +      { 1, PPC_VSCR_REGNUM, 16 },
> +      { 1, PPC_VRSAVE_REGNUM, 16 },
> +      { 0 }
> +  };
> +
> +static const struct regcache_map_entry ppc32_be_linux_vrregmap[] =
> +  {
> +      { 32, PPC_VR0_REGNUM, 16 },
> +      { 1, REGCACHE_MAP_SKIP, 12},
> +      { 1, PPC_VSCR_REGNUM, 4 },
> +      { 1, PPC_VRSAVE_REGNUM, 16 },
> +      { 0 }
> +  };

This looks weirdly asymmetric ... shouldn't we then use
REGCACHE_MAP_SKIP for both LE and BE cases?  In fact, it would
probably make sense to make VRSAVE also a 4-byte field + skip.

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH 7/8] [PowerPC] Fix inclusion of dfp pseudoregs in tdep
  2018-05-10 22:25 ` [PATCH 7/8] [PowerPC] Fix inclusion of dfp pseudoregs in tdep Pedro Franco de Carvalho
@ 2018-05-16 14:18   ` Ulrich Weigand
  0 siblings, 0 replies; 44+ messages in thread
From: Ulrich Weigand @ 2018-05-16 14:18 UTC (permalink / raw)
  To: Pedro Franco de Carvalho; +Cc: gdb-patches

Pedro Franco de Carvalho wrote:

> gdb/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* rs6000-tdep.c (rs6000_gdbarch_init): Assign 1 to have_dfp only
> 	if the size of fpscr is larger than 32 bits.

> +	  /* The fpscr register was expanded in isa 2.05 to 64 bits
> +	     along with the addition of the decimal floating point
> +	     facility.  */
> +	  if (tdesc_register_size(feature, "fpscr") > 32)
> +	    have_dfp = 1;

Formatting again.  Otherwise this is OK.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH 6/8] [PowerPC] Fix VSX registers in linux core files
  2018-05-10 20:33 ` [PATCH 6/8] [PowerPC] Fix VSX registers " Pedro Franco de Carvalho
@ 2018-05-16 14:18   ` Ulrich Weigand
  0 siblings, 0 replies; 44+ messages in thread
From: Ulrich Weigand @ 2018-05-16 14:18 UTC (permalink / raw)
  To: Pedro Franco de Carvalho; +Cc: gdb-patches

Pedro Franco de Carvalho wrote:

> gdb/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* ppc-linux-tdep.c (ppc_linux_vsxregset): New function.
> 	(ppc32_linux_vsxregmap): New global.
> 	(ppc32_linux_vsxregset): Initialize with ppc32_linux_vsxregmap,
> 	regcache_supply_regset, and regcache_collect_regset.
> 	* ppc-linux-tdep.h (ppc_linux_vsxregset): Declare.
> 	* ppc-linux-nat.c (supply_vsxregset, fill_vsxregset): Remove.
> 	(fetch_vsx_register, store_vsx_register): Remove.
> 	(fetch_vsx_registers): Add regno parameter. Get regset using
> 	ppc_linux_vsxregset. Use regset to supply registers.
> 	(store_vsx_registers): Add regno parameter. Get regset using
> 	ppc_linux_vsxregset. Use regset to collect registers.
> 	(fetch_register): Call fetch_vsx_registers instead of
> 	fetch_vsx_register.
> 	(store_register): Call store_vsx_registers instead of
> 	store_vsx_register.
> 	(fetch_ppc_registers): Call fetch_vsx_registers with -1 for the
> 	new regno parameter.
> 	(store_ppc_registers): Call store_vsx_registers with -1 for the
> 	new regno parameter.
> 	* rs6000-tdep.c (ppc_vsx_support_p, ppc_supply_vsxreget)
> 	(ppc_collect_vsxregset): Remove.
> 
> gdb/testsuite/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* gdb.arch/powerpc-vsx-gcore.exp: New file.


> +  vsxregset->supply_regset(vsxregset, regcache, regno, &regs,
> +			   PPC_LINUX_SIZEOF_VSXREGSET);

Formatting.

Otherwise, this is OK.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH 8/8] [PowerPC] Recognize isa205 in linux core files
  2018-05-10 20:00 ` [PATCH 8/8] [PowerPC] Recognize isa205 in linux core files Pedro Franco de Carvalho
@ 2018-05-16 15:53   ` Ulrich Weigand
  2018-05-16 23:32     ` Pedro Franco de Carvalho
  0 siblings, 1 reply; 44+ messages in thread
From: Ulrich Weigand @ 2018-05-16 15:53 UTC (permalink / raw)
  To: Pedro Franco de Carvalho; +Cc: gdb-patches

Pedro Franco de Carvalho wrote:

> gdb/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* arch/ppc-linux-common.c (ppc_linux_has_isa205): Change the
> 	parameter type to CORE_ADDR.
> 	* arch/ppc-linux-common.h (ppc_linux_has_isa205): Change the
> 	parameter type in declaration to CORE_ADDR.
> 	* ppc-linux-tdep.c (ppc_linux_core_read_description): Call
> 	target_auxv_search to get AT_HWCAP and use the result to get the
> 	target description.
> 	* ppc-linux-nat.c (ppc_linux_get_hwcap): Change the return type to
> 	CORE_ADDR. Remove the cast of the return value to unsigned
> 	long. Check if target_auxv_search returns a value greater than
> 	zero instead of non-zero.
> 	(ppc_linux_nat_target::read_description): Change the type of the
> 	hwcap variable to CORE_ADDR.
> 
> gdb/testsuite/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* gdb.arch/powerpc-fpscr-gcore.exp: New file.

>  /* Fetch the AT_HWCAP entry from the aux vector.  */
> -static unsigned long
> +static CORE_ADDR
>  ppc_linux_get_hwcap (void)
>  {
>    CORE_ADDR field;
>  
> -  if (target_auxv_search (target_stack, AT_HWCAP, &field))
> -    return (unsigned long) field;
> +  if (target_auxv_search (target_stack, AT_HWCAP, &field) > 0)
> +    return field;
>  
>    return 0;
>  }

Maybe this routine should now be moved to ppc-linux-tdep.c ...

> +  CORE_ADDR hwcap = 0;
> +
> +  target_auxv_search (target, AT_HWCAP, &hwcap);
> +
> +  features.isa205 = ppc_linux_has_isa205 (hwcap);

... so it can be reused here?

Otherwise this looks OK to me.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH 2/8] [PowerPC] Consolidate wordsize getter between native and gdbserver
  2018-05-10 20:33 ` [PATCH 2/8] [PowerPC] Consolidate wordsize getter between native and gdbserver Pedro Franco de Carvalho
@ 2018-05-16 15:54   ` Ulrich Weigand
  0 siblings, 0 replies; 44+ messages in thread
From: Ulrich Weigand @ 2018-05-16 15:54 UTC (permalink / raw)
  To: Pedro Franco de Carvalho; +Cc: gdb-patches

Pedro Franco de Carvalho wrote:

> gdb/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* configure.nat <linux powerpc>: Add ppc-linux.o to NATDEPFILES.
> 	* ppc-linux-nat.c (ppc_linux_target_wordsize): Move to
> 	nat/ppc-linux.c.
> 	(ppc_linux_nat_target::auxv_parse): Get thread id tid. Call
> 	ppc_linux_target wordsize with tid.
> 	(ppc_linux_nat_target::read_description): Call ppc_linux_target
> 	wordsize with tid.
> 	* nat/ppc-linux.c: Include nat/gdb_ptrace.h.
> 	(ppc_linux_target_wordsize): Move here from ppc-linux-nat.c. Add
> 	tid parameter. Remove static specifier.
> 	* nat/ppc-linux.h (ppc_linux_target_wordsize): New declaration.
> 
> gdb/gdbserver/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* linux-ppc-low.c (ppc_arch_setup): Remove code for getting the
> 	wordsize of the inferior. Call ppc_linux_target_wordsize.


> +int
> +ppc_linux_target_wordsize (int tid)
> +{
> +  int wordsize = 4;
> +
> +  /* Check for 64-bit inferior process.  This is the case when the host is
> +     64-bit, and in addition the top bit of the MSR register is set.  */
> +#ifdef __powerpc64__
> +  long msr;
> +
> +  errno = 0;
> +  msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0);
> +  if (errno == 0 && ppc64_64bit_inferior_p (msr))
> +    wordsize = 8;
> +#endif
> +
> +  return wordsize;
> +}

Is this now the only remaining user of ppc64_64bit_inferior_p?  If so,
the function should be made static or even inlined here.

Otherwise, this is OK.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH 3/8] [PowerPC] Disable regsets using zero sizes in gdbserver
  2018-05-10 19:59 ` [PATCH 3/8] [PowerPC] Disable regsets using zero sizes in gdbserver Pedro Franco de Carvalho
@ 2018-05-16 16:17   ` Ulrich Weigand
  0 siblings, 0 replies; 44+ messages in thread
From: Ulrich Weigand @ 2018-05-16 16:17 UTC (permalink / raw)
  To: Pedro Franco de Carvalho; +Cc: gdb-patches

Pedro Franco de Carvalho wrote:

> gdb/gdbserver/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* linux-ppc-low.c (ppc_fill_vsxregset): Remove ppc_hwcap check.
> 	(ppc_store_vsxregset): Likewise.
> 	(ppc_fill_vrregset): Likewise.
> 	(ppc_store_vrregset): Likewise.
> 	(ppc_fill_evrregset): Likewise.
> 	(ppc_store_evrregset): Likewise.
> 	(ppc_regsets): Set VSX/VR/EVR regset sizes to 0.
> 	(ppc_arch_setup): Iterate through ppc_regsets and set sizes when
> 	needed.


> +  for (regset = ppc_regsets; regset->size >= 0; regset++)
> +    switch (regset->get_request)
> +      {
> +      case PTRACE_GETVRREGS:
> +	regset->size = features.altivec ? SIZEOF_VRREGS : 0;
> +	break;
> +      case PTRACE_GETVSXREGS:
> +	regset->size = features.vsx ? SIZEOF_VSXREGS : 0;
> +	break;
> +      case PTRACE_GETEVRREGS:
> +	if (ppc_hwcap & PPC_FEATURE_HAS_SPE)
> +	  regset->size = 32 * 4 + 8 + 4;

This should also zero out the size if the feature is not available,
just like the other cases.  Otherwise, this is OK.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH 4/8] [PowerPC] Consolidate linux vector regset sizes
  2018-05-10 19:59 ` [PATCH 4/8] [PowerPC] Consolidate linux vector regset sizes Pedro Franco de Carvalho
@ 2018-05-16 16:35   ` Ulrich Weigand
  0 siblings, 0 replies; 44+ messages in thread
From: Ulrich Weigand @ 2018-05-16 16:35 UTC (permalink / raw)
  To: Pedro Franco de Carvalho; +Cc: gdb-patches

Pedro Franco de Carvalho wrote:

> gdb/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* arch/ppc-linux-common.h (PPC_LINUX_SIZEOF_VRREGSET)
> 	(PPC_LINUX_SIZEOF_VSXREGSET): Define.
> 	* ppc-linux-nat.c (SIZEOF_VSXREGS, SIZEOF_VRREGS): Remove.
> 	(gdb_vrregset_t): Change array type size to
> 	PPC_LINUX_SIZEOF_VRREGSET.
> 	(gdb_vsxregset_t): Change array type size to
> 	PPC_LINUX_SIZEOF_VSXREGSET.
> 	* ppc-linux-tdep.c (ppc_linux_iterate_over_regset_sections):
> 	Change integer literals to PPC_LINUX_SIZEOF_VRREGSET and
> 	PPC_LINUX_SIZEOF_VSXREGSET.
> 
> gdb/gdbserver/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* linux-ppc-low.c (SIZEOF_VSXREGS, SIZEOF_VRREGS): Remove.
> 	(ppc_arch_setup): Change SIZEOF_VRREGS and SIZEOF_VSXREGS to
> 	PPC_LINUX_SIZEOF_VRREGSET and PPC_LINUX_SIZEOF_VSXREGSET.

This is OK.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH 1/8] [PowerPC] Consolidate linux target description selection
  2018-05-16 14:05   ` Ulrich Weigand
@ 2018-05-16 22:50     ` Pedro Franco de Carvalho
  2018-05-17  8:28       ` Ulrich Weigand
  0 siblings, 1 reply; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-16 22:50 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gdb-patches

Ulrich Weigand <uweigand@de.ibm.com> writes:

>> +/* Base value for ppc_linux_features variables.  */
>> +const struct ppc_linux_features ppc_linux_no_features = {
>> +  4,
>> +  false,
>> +  false,
>> +  false,
>> +  false,
>> +};
>
> I'm not sure it makes much sense to declare "4" the default wordsize
> -- there's not really a default between 4 and 8.  Maybe it would be
> clearer to just force all users to explicitly set the wordsize.

Is something like this a good style, or should I just initialize
wordsize to 0 and let the previous assert in ppc_match_description
ensure that the wordsize is either 4 or 8?

+/* Features used to determine the target description.  */
+class ppc_linux_features
+{
+public:
+  ppc_linux_features (int _wordsize)
+    : wordsize (_wordsize), altivec (false), vsx (false),
+      isa205 (false), cell (false)
+  {
+    gdb_assert (wordsize == 4 || wordsize == 8);
+  }
+
+  unsigned int wordsize;
+  bool altivec;
+  bool vsx;
+  bool isa205;
+  bool cell;
+};

I still have to rebase the other patches on this.

-- >8 --
Subject: [PATCH] [PowerPC] Consolidate linux target description selection

Share target description declarations and selection among ppc linux
native targets, core files, gdbserver and IPA.

To avoid complicated define guards, gdbserver and IPA now have
declarations for all descriptions, including 64-bit generated
descriptions when compiled in 32-bit mode. These have always been
linked into the gdbserver and IPA binaries. Because they might be
uninitialized, the selection function checks that the selected
description is initialized.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* arch/ppc-linux-common.c: New file.
	* arch/ppc-linux-common.h: New file.
	* arch/ppc-linux-tdesc.h: New file.
	* configure.tgt (powerpc*-*-linux*): Add arch/ppc-linux-common.o.
	* Makefile.in (ALL_TARGET_OBS): Add arch/ppc-linux-common.o.
	(HFILES_NO_SRCDIR): Add arch/ppc-linux-common.h and
	arch/ppc-linux-tdesc.h.
	* ppc-linux-nat.c: Include arch/ppc-linux-common.h and
	arch/ppc-linux-tdesc.h.
	(ppc_linux_nat_target::read_description): Remove target
	description matching code. Fill a ppc_linux_features struct and
	call ppc_linux_match_description with it. Move comment about ISA
	2.05 to ppc-linux-common.c.
	* ppc-linux-tdep.c: Include arch/ppc-linux-common.h and
	arch/ppc-linux-tdesc.h.
	(ppc_linux_core_read_description): Remove target description
	matching code. Fill a ppc_linux_features struct and call
	ppc_linux_match_description with it.
	* ppc-linux-tdep.h (tdesc_powerpc_32l, tdesc_powerpc_64l)
	(tdesc_powerpc_altivec32l, tdesc_powerpc_altivec64l)
	(tdesc_powerpc_cell32l, tdesc_powerpc_cell64l)
	(tdesc_powerpc_vsx32l, tdesc_powerpc_vsx64l)
	(tdesc_powerpc_isa205_32l, tdesc_powerpc_isa205_64l)
	(tdesc_powerpc_isa205_altivec32l, tdesc_powerpc_isa205_altivec64l)
	(tdesc_powerpc_isa205_vsx32l, tdesc_powerpc_isa205_vsx64l)
	(tdesc_powerpc_e500l): Remove.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* configure.srv (srv_tgtobj): Add arch/ppc-linux-common.o.
	* Makefile.in (SFILES): Add arch/ppc-linux-common.c.
	* linux-ppc-tdesc.h: Rename to linux-ppc-tdesc-init.h.
	* linux-ppc-tdesc-init.h (tdesc_powerpc_32l, tdesc_powerpc_64l)
	(tdesc_powerpc_altivec32l, tdesc_powerpc_altivec64l)
	(tdesc_powerpc_cell32l, tdesc_powerpc_cell64l)
	(tdesc_powerpc_vsx32l, tdesc_powerpc_vsx64l)
	(tdesc_powerpc_isa205_32l, tdesc_powerpc_isa205_64l)
	(tdesc_powerpc_isa205_altivec32l, tdesc_powerpc_isa205_altivec64l)
	(tdesc_powerpc_isa205_vsx32l, tdesc_powerpc_isa205_vsx64l)
	(tdesc_powerpc_e500l): Remove.
	* linux-ppc-ipa.c: Include arch/ppc-linux-tdesc.h and
	linux-ppc-tdesc-init.h. Don't include linux-ppc-tdesc.h.
	* linux-ppc-low.c: Include arch/ppc-linux-common.h,
	arch/ppc-linux-tdesc.h, and linux-ppc-tdesc-init.h. Don't include
	linux-ppc-tdesc.h.
	(ppc_arch_setup): Remove target description matching code. Fill a
	ppc_linux_features struct and call ppc_linux_match_description
	with it.
---
 gdb/Makefile.in                                    |  3 +
 gdb/arch/ppc-linux-common.c                        | 84 ++++++++++++++++++++++
 gdb/arch/ppc-linux-common.h                        | 50 +++++++++++++
 gdb/arch/ppc-linux-tdesc.h                         | 42 +++++++++++
 gdb/configure.tgt                                  |  3 +-
 gdb/gdbserver/Makefile.in                          |  1 +
 gdb/gdbserver/configure.srv                        |  1 +
 gdb/gdbserver/linux-ppc-ipa.c                      |  3 +-
 gdb/gdbserver/linux-ppc-low.c                      | 75 ++++++++-----------
 .../{linux-ppc-tdesc.h => linux-ppc-tdesc-init.h}  | 15 ----
 gdb/ppc-linux-nat.c                                | 54 ++++----------
 gdb/ppc-linux-tdep.c                               | 39 +++++-----
 gdb/ppc-linux-tdep.h                               | 17 -----
 13 files changed, 249 insertions(+), 138 deletions(-)
 create mode 100644 gdb/arch/ppc-linux-common.c
 create mode 100644 gdb/arch/ppc-linux-common.h
 create mode 100644 gdb/arch/ppc-linux-tdesc.h
 rename gdb/gdbserver/{linux-ppc-tdesc.h => linux-ppc-tdesc-init.h} (76%)

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 87d74a7703..8109c0c6ba 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -678,6 +678,7 @@ ALL_TARGET_OBS = \
 	arch/arm-get-next-pcs.o \
 	arch/arm-linux.o \
 	arch/i386.o \
+	arch/ppc-linux-common.o \
 	arm-bsd-tdep.o \
 	arm-fbsd-tdep.o \
 	arm-linux-tdep.o \
@@ -1411,6 +1412,8 @@ HFILES_NO_SRCDIR = \
 	arch/aarch64-insn.h \
 	arch/arm.h \
 	arch/i386.h \
+	arch/ppc-linux-common.h \
+	arch/ppc-linux-tdesc.h \
 	cli/cli-cmds.h \
 	cli/cli-decode.h \
 	cli/cli-script.h \
diff --git a/gdb/arch/ppc-linux-common.c b/gdb/arch/ppc-linux-common.c
new file mode 100644
index 0000000000..d7a61f7dfa
--- /dev/null
+++ b/gdb/arch/ppc-linux-common.c
@@ -0,0 +1,84 @@
+/* Common target dependent code for GNU/Linux on PPC systems.
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "common-defs.h"
+#include "arch/ppc-linux-common.h"
+#include "arch/ppc-linux-tdesc.h"
+
+/* Decimal Floating Point bit in AT_HWCAP.
+
+   This file can be used by a host with another architecture, e.g.
+   when debugging core files, which might not provide this constant.  */
+
+#ifndef PPC_FEATURE_HAS_DFP
+#define PPC_FEATURE_HAS_DFP	0x00000400
+#endif
+
+bool
+ppc_linux_has_isa205 (unsigned long hwcap)
+{
+  /* Power ISA 2.05 (implemented by Power 6 and newer processors)
+     increases the FPSCR from 32 bits to 64 bits.  Even though Power 7
+     supports this ISA version, it doesn't have PPC_FEATURE_ARCH_2_05
+     set, only PPC_FEATURE_ARCH_2_06.  Since for now the only bits
+     used in the higher half of the register are for Decimal Floating
+     Point, we check if that feature is available to decide the size
+     of the FPSCR.  */
+  return ((hwcap & PPC_FEATURE_HAS_DFP) != 0);
+}
+
+const struct target_desc *
+ppc_linux_match_description(struct ppc_linux_features features)
+{
+  struct target_desc *tdesc = NULL;
+
+  if (features.wordsize == 8)
+    {
+      if (features.cell)
+	tdesc = tdesc_powerpc_cell64l;
+      else if (features.vsx)
+	tdesc = features.isa205
+	  ? tdesc_powerpc_isa205_vsx64l : tdesc_powerpc_vsx64l;
+      else if (features.altivec)
+	tdesc = features.isa205
+	  ? tdesc_powerpc_isa205_altivec64l : tdesc_powerpc_altivec64l;
+      else
+	tdesc = features.isa205?
+	  tdesc_powerpc_isa205_64l : tdesc_powerpc_64l;
+    }
+  else
+    {
+      if (features.cell)
+	tdesc = tdesc_powerpc_cell32l;
+      else if (features.vsx)
+	tdesc = features.isa205
+	  ? tdesc_powerpc_isa205_vsx32l : tdesc_powerpc_vsx32l;
+      else if (features.altivec)
+	tdesc = features.isa205
+	  ? tdesc_powerpc_isa205_altivec32l : tdesc_powerpc_altivec32l;
+      else
+	tdesc = features.isa205
+	  ? tdesc_powerpc_isa205_32l : tdesc_powerpc_32l;
+    }
+
+  /* Make sure that the selected tdesc was initialized.  */
+  gdb_assert (tdesc != NULL);
+
+  return tdesc;
+}
diff --git a/gdb/arch/ppc-linux-common.h b/gdb/arch/ppc-linux-common.h
new file mode 100644
index 0000000000..8aa6d40703
--- /dev/null
+++ b/gdb/arch/ppc-linux-common.h
@@ -0,0 +1,50 @@
+/* Common target dependent code for GNU/Linux on PPC systems.
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef ARCH_PPC_LINUX_COMMON_H
+#define ARCH_PPC_LINUX_COMMON_H
+
+struct target_desc;
+
+/* Check if the hwcap auxv entry indicates that isa205 is supported.  */
+bool ppc_linux_has_isa205 (unsigned long hwcap);
+
+/* Features used to determine the target description.  */
+class ppc_linux_features
+{
+public:
+  ppc_linux_features (int _wordsize)
+    : wordsize (_wordsize), altivec (false), vsx (false),
+      isa205 (false), cell (false)
+  {
+    gdb_assert (wordsize == 4 || wordsize == 8);
+  }
+
+  unsigned int wordsize;
+  bool altivec;
+  bool vsx;
+  bool isa205;
+  bool cell;
+};
+
+/* Return a target description that matches FEATURES.  */
+const struct target_desc * ppc_linux_match_description
+(struct ppc_linux_features features);
+
+#endif /* ARCH_PPC_LINUX_COMMON_H */
diff --git a/gdb/arch/ppc-linux-tdesc.h b/gdb/arch/ppc-linux-tdesc.h
new file mode 100644
index 0000000000..594c7c7c7c
--- /dev/null
+++ b/gdb/arch/ppc-linux-tdesc.h
@@ -0,0 +1,42 @@
+/* Target description declarations shared between gdb, gdbserver and IPA.
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef ARCH_PPC_LINUX_TDESC_H
+#define ARCH_PPC_LINUX_TDESC_H
+
+struct target_desc;
+
+extern struct target_desc *tdesc_powerpc_32l;
+extern struct target_desc *tdesc_powerpc_altivec32l;
+extern struct target_desc *tdesc_powerpc_cell32l;
+extern struct target_desc *tdesc_powerpc_vsx32l;
+extern struct target_desc *tdesc_powerpc_isa205_32l;
+extern struct target_desc *tdesc_powerpc_isa205_altivec32l;
+extern struct target_desc *tdesc_powerpc_isa205_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_cell64l;
+extern struct target_desc *tdesc_powerpc_vsx64l;
+extern struct target_desc *tdesc_powerpc_isa205_64l;
+extern struct target_desc *tdesc_powerpc_isa205_altivec64l;
+extern struct target_desc *tdesc_powerpc_isa205_vsx64l;
+
+#endif /* ARCH_PPC_LINUX_TDESC_H */
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index e9a2704ebc..b4bc770617 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -492,7 +492,8 @@ powerpc*-*-linux*)
 			spu-multiarch.o \
 			glibc-tdep.o symfile-mem.o linux-tdep.o \
 			ravenscar-thread.o ppc-ravenscar-thread.o \
-			linux-record.o "
+			linux-record.o \
+			arch/ppc-linux-common.o"
 	gdb_sim=../sim/ppc/libsim.a
 	build_gdbserver=yes
 	;;
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index c377378809..675faa4364 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -196,6 +196,7 @@ SFILES = \
 	$(srcdir)/arch/arm.c \
 	$(srcdir)/arch/arm-get-next-pcs.c \
 	$(srcdir)/arch/arm-linux.c \
+	$(srcdir)/arch/ppc-linux-common.c \
 	$(srcdir)/common/btrace-common.c \
 	$(srcdir)/common/buffer.c \
 	$(srcdir)/common/cleanups.c \
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index ffeefb9b92..7153ff339d 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -225,6 +225,7 @@ case "${target}" in
 			srv_regobj="${srv_regobj} powerpc-isa205-altivec64l.o"
 			srv_regobj="${srv_regobj} powerpc-isa205-vsx64l.o"
 			srv_tgtobj="$srv_linux_obj linux-ppc-low.o ppc-linux.o"
+			srv_tgtobj="${srv_tgtobj} arch/ppc-linux-common.o"
 			srv_xmlfiles="rs6000/powerpc-32l.xml"
 			srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-altivec32l.xml"
 			srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-cell32l.xml"
diff --git a/gdb/gdbserver/linux-ppc-ipa.c b/gdb/gdbserver/linux-ppc-ipa.c
index c993e76315..f6861f0d98 100644
--- a/gdb/gdbserver/linux-ppc-ipa.c
+++ b/gdb/gdbserver/linux-ppc-ipa.c
@@ -21,7 +21,8 @@
 #include "server.h"
 #include <sys/mman.h>
 #include "tracepoint.h"
-#include "linux-ppc-tdesc.h"
+#include "arch/ppc-linux-tdesc.h"
+#include "linux-ppc-tdesc-init.h"
 #include <elf.h>
 #ifdef HAVE_GETAUXVAL
 #include <sys/auxv.h>
diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c
index 36bd373c88..f337ee3d09 100644
--- a/gdb/gdbserver/linux-ppc-low.c
+++ b/gdb/gdbserver/linux-ppc-low.c
@@ -23,8 +23,10 @@
 #include <elf.h>
 #include <asm/ptrace.h>
 
+#include "arch/ppc-linux-common.h"
+#include "arch/ppc-linux-tdesc.h"
 #include "nat/ppc-linux.h"
-#include "linux-ppc-tdesc.h"
+#include "linux-ppc-tdesc-init.h"
 #include "ax.h"
 #include "tracepoint.h"
 
@@ -617,6 +619,8 @@ static void
 ppc_arch_setup (void)
 {
   const struct target_desc *tdesc;
+  int wordsize = 4;
+
 #ifdef __powerpc64__
   long msr;
   struct regcache *regcache;
@@ -634,58 +638,36 @@ ppc_arch_setup (void)
   free_register_cache (regcache);
   if (ppc64_64bit_inferior_p (msr))
     {
-      ppc_get_auxv (AT_HWCAP, &ppc_hwcap);
-      if (ppc_hwcap & PPC_FEATURE_CELL)
-	tdesc = tdesc_powerpc_cell64l;
-      else if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
-	{
-	  /* Power ISA 2.05 (implemented by Power 6 and newer processors)
-	     increases the FPSCR from 32 bits to 64 bits. Even though Power 7
-	     supports this ISA version, it doesn't have PPC_FEATURE_ARCH_2_05
-	     set, only PPC_FEATURE_ARCH_2_06.  Since for now the only bits
-	     used in the higher half of the register are for Decimal Floating
-	     Point, we check if that feature is available to decide the size
-	     of the FPSCR.  */
-	  if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
-	    tdesc = tdesc_powerpc_isa205_vsx64l;
-	  else
-	    tdesc = tdesc_powerpc_vsx64l;
-	}
-      else if (ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC)
-	{
-	  if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
-	    tdesc = tdesc_powerpc_isa205_altivec64l;
-	  else
-	    tdesc = tdesc_powerpc_altivec64l;
-	}
-
-      current_process ()->tdesc = tdesc;
-      return;
+      wordsize = 8;
     }
 #endif
 
-  /* OK, we have a 32-bit inferior.  */
-  tdesc = tdesc_powerpc_32l;
-  current_process ()->tdesc = tdesc;
+  ppc_linux_features features (wordsize);
 
-  ppc_get_auxv (AT_HWCAP, &ppc_hwcap);
-  if (ppc_hwcap & PPC_FEATURE_CELL)
-    tdesc = tdesc_powerpc_cell32l;
-  else if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
+  if (features.wordsize == 4)
     {
-      if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
-	tdesc = tdesc_powerpc_isa205_vsx32l;
-      else
-	tdesc = tdesc_powerpc_vsx32l;
-    }
-  else if (ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC)
-    {
-      if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
-	tdesc = tdesc_powerpc_isa205_altivec32l;
-      else
-	tdesc = tdesc_powerpc_altivec32l;
+      /* OK, we have a 32-bit inferior.  */
+      tdesc = tdesc_powerpc_32l;
+      current_process ()->tdesc = tdesc;
     }
 
+  /* The value of current_process ()->tdesc needs to be set for this
+     call.  */
+  ppc_get_auxv (AT_HWCAP, &ppc_hwcap);
+
+  features.isa205 = ppc_linux_has_isa205 (ppc_hwcap);
+
+  if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
+    features.vsx = true;
+
+  if (ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC)
+    features.altivec = true;
+
+  if (ppc_hwcap & PPC_FEATURE_CELL)
+    features.cell = true;
+
+  tdesc = ppc_linux_match_description (features);
+
   /* On 32-bit machines, check for SPE registers.
      Set the low target's regmap field as appropriately.  */
 #ifndef __powerpc64__
@@ -707,6 +689,7 @@ ppc_arch_setup (void)
       ppc_regmap_adjusted = 1;
    }
 #endif
+
   current_process ()->tdesc = tdesc;
 }
 
diff --git a/gdb/gdbserver/linux-ppc-tdesc.h b/gdb/gdbserver/linux-ppc-tdesc-init.h
similarity index 76%
rename from gdb/gdbserver/linux-ppc-tdesc.h
rename to gdb/gdbserver/linux-ppc-tdesc-init.h
index 4a561f5e37..422e7bd9c4 100644
--- a/gdb/gdbserver/linux-ppc-tdesc.h
+++ b/gdb/gdbserver/linux-ppc-tdesc-init.h
@@ -36,35 +36,27 @@ enum ppc_linux_tdesc {
 
 /* Defined in auto-generated file powerpc-32l.c.  */
 void init_registers_powerpc_32l (void);
-extern const struct target_desc *tdesc_powerpc_32l;
 
 /* Defined in auto-generated file powerpc-altivec32l.c.  */
 void init_registers_powerpc_altivec32l (void);
-extern const struct target_desc *tdesc_powerpc_altivec32l;
 
 /* Defined in auto-generated file powerpc-cell32l.c.  */
 void init_registers_powerpc_cell32l (void);
-extern const struct target_desc *tdesc_powerpc_cell32l;
 
 /* Defined in auto-generated file powerpc-vsx32l.c.  */
 void init_registers_powerpc_vsx32l (void);
-extern const struct target_desc *tdesc_powerpc_vsx32l;
 
 /* Defined in auto-generated file powerpc-isa205-32l.c.  */
 void init_registers_powerpc_isa205_32l (void);
-extern const struct target_desc *tdesc_powerpc_isa205_32l;
 
 /* Defined in auto-generated file powerpc-isa205-altivec32l.c.  */
 void init_registers_powerpc_isa205_altivec32l (void);
-extern const struct target_desc *tdesc_powerpc_isa205_altivec32l;
 
 /* Defined in auto-generated file powerpc-isa205-vsx32l.c.  */
 void init_registers_powerpc_isa205_vsx32l (void);
-extern const struct target_desc *tdesc_powerpc_isa205_vsx32l;
 
 /* Defined in auto-generated file powerpc-e500l.c.  */
 void init_registers_powerpc_e500l (void);
-extern const struct target_desc *tdesc_powerpc_e500l;
 
 #endif
 
@@ -72,30 +64,23 @@ extern const struct target_desc *tdesc_powerpc_e500l;
 
 /* Defined in auto-generated file powerpc-64l.c.  */
 void init_registers_powerpc_64l (void);
-extern const struct target_desc *tdesc_powerpc_64l;
 
 /* Defined in auto-generated file powerpc-altivec64l.c.  */
 void init_registers_powerpc_altivec64l (void);
-extern const struct target_desc *tdesc_powerpc_altivec64l;
 
 /* Defined in auto-generated file powerpc-cell64l.c.  */
 void init_registers_powerpc_cell64l (void);
-extern const struct target_desc *tdesc_powerpc_cell64l;
 
 /* Defined in auto-generated file powerpc-vsx64l.c.  */
 void init_registers_powerpc_vsx64l (void);
-extern const struct target_desc *tdesc_powerpc_vsx64l;
 
 /* Defined in auto-generated file powerpc-isa205-64l.c.  */
 void init_registers_powerpc_isa205_64l (void);
-extern const struct target_desc *tdesc_powerpc_isa205_64l;
 
 /* Defined in auto-generated file powerpc-isa205-altivec64l.c.  */
 void init_registers_powerpc_isa205_altivec64l (void);
-extern const struct target_desc *tdesc_powerpc_isa205_altivec64l;
 
 /* Defined in auto-generated file powerpc-isa205-vsx64l.c.  */
 void init_registers_powerpc_isa205_vsx64l (void);
-extern const struct target_desc *tdesc_powerpc_isa205_vsx64l;
 
 #endif
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index 1423339339..24ab8fde04 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -45,6 +45,8 @@
 #include "elf/common.h"
 #include "auxv.h"
 
+#include "arch/ppc-linux-common.h"
+#include "arch/ppc-linux-tdesc.h"
 #include "nat/ppc-linux.h"
 
 /* Similarly for the hardware watchpoint support.  These requests are used
@@ -2416,11 +2418,6 @@ ppc_linux_nat_target::auxv_parse (gdb_byte **readptr,
 const struct target_desc *
 ppc_linux_nat_target::read_description ()
 {
-  int altivec = 0;
-  int vsx = 0;
-  int isa205 = 0;
-  int cell = 0;
-
   int tid = ptid_get_lwp (inferior_ptid);
   if (tid == 0)
     tid = ptid_get_pid (inferior_ptid);
@@ -2438,13 +2435,17 @@ ppc_linux_nat_target::read_description ()
 	perror_with_name (_("Unable to fetch SPE registers"));
     }
 
+  ppc_linux_features features (ppc_linux_target_wordsize (tid));
+
+  unsigned long hwcap = ppc_linux_get_hwcap ();
+
   if (have_ptrace_getsetvsxregs
-      && (ppc_linux_get_hwcap () & PPC_FEATURE_HAS_VSX))
+      && (hwcap & PPC_FEATURE_HAS_VSX))
     {
       gdb_vsxregset_t vsxregset;
 
       if (ptrace (PTRACE_GETVSXREGS, tid, 0, &vsxregset) >= 0)
-	vsx = 1;
+	features.vsx = true;
 
       /* EIO means that the PTRACE_GETVSXREGS request isn't supported.
 	 Anything else needs to be reported.  */
@@ -2453,12 +2454,12 @@ ppc_linux_nat_target::read_description ()
     }
 
   if (have_ptrace_getvrregs
-      && (ppc_linux_get_hwcap () & PPC_FEATURE_HAS_ALTIVEC))
+      && (hwcap & PPC_FEATURE_HAS_ALTIVEC))
     {
       gdb_vrregset_t vrregset;
 
       if (ptrace (PTRACE_GETVRREGS, tid, 0, &vrregset) >= 0)
-        altivec = 1;
+        features.altivec = true;
 
       /* EIO means that the PTRACE_GETVRREGS request isn't supported.
 	 Anything else needs to be reported.  */
@@ -2466,39 +2467,12 @@ ppc_linux_nat_target::read_description ()
 	perror_with_name (_("Unable to fetch AltiVec registers"));
     }
 
-  /* Power ISA 2.05 (implemented by Power 6 and newer processors) increases
-     the FPSCR from 32 bits to 64 bits.  Even though Power 7 supports this
-     ISA version, it doesn't have PPC_FEATURE_ARCH_2_05 set, only
-     PPC_FEATURE_ARCH_2_06.  Since for now the only bits used in the higher
-     half of the register are for Decimal Floating Point, we check if that
-     feature is available to decide the size of the FPSCR.  */
-  if (ppc_linux_get_hwcap () & PPC_FEATURE_HAS_DFP)
-    isa205 = 1;
-
-  if (ppc_linux_get_hwcap () & PPC_FEATURE_CELL)
-    cell = 1;
-
-  if (ppc_linux_target_wordsize () == 8)
-    {
-      if (cell)
-	return tdesc_powerpc_cell64l;
-      else if (vsx)
-	return isa205? tdesc_powerpc_isa205_vsx64l : tdesc_powerpc_vsx64l;
-      else if (altivec)
-	return isa205
-	  ? tdesc_powerpc_isa205_altivec64l : tdesc_powerpc_altivec64l;
-
-      return isa205? tdesc_powerpc_isa205_64l : tdesc_powerpc_64l;
-    }
+  if (hwcap & PPC_FEATURE_CELL)
+    features.cell = true;
 
-  if (cell)
-    return tdesc_powerpc_cell32l;
-  else if (vsx)
-    return isa205? tdesc_powerpc_isa205_vsx32l : tdesc_powerpc_vsx32l;
-  else if (altivec)
-    return isa205? tdesc_powerpc_isa205_altivec32l : tdesc_powerpc_altivec32l;
+  features.isa205 = ppc_linux_has_isa205 (hwcap);
 
-  return isa205? tdesc_powerpc_isa205_32l : tdesc_powerpc_32l;
+  return ppc_linux_match_description (features);
 }
 
 void
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 6d3a64c4f0..fd599fb4f5 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -37,6 +37,8 @@
 #include "ppc-tdep.h"
 #include "ppc64-tdep.h"
 #include "ppc-linux-tdep.h"
+#include "arch/ppc-linux-common.h"
+#include "arch/ppc-linux-tdesc.h"
 #include "glibc-tdep.h"
 #include "trad-frame.h"
 #include "frame-unwind.h"
@@ -966,38 +968,39 @@ ppc_linux_core_read_description (struct gdbarch *gdbarch,
 				 struct target_ops *target,
 				 bfd *abfd)
 {
+  int wordsize;
   asection *cell = bfd_sections_find_if (abfd, ppc_linux_spu_section, NULL);
   asection *altivec = bfd_get_section_by_name (abfd, ".reg-ppc-vmx");
   asection *vsx = bfd_get_section_by_name (abfd, ".reg-ppc-vsx");
   asection *section = bfd_get_section_by_name (abfd, ".reg");
+
   if (! section)
     return NULL;
 
   switch (bfd_section_size (abfd, section))
     {
     case 48 * 4:
-      if (cell)
-	return tdesc_powerpc_cell32l;
-      else if (vsx)
-	return tdesc_powerpc_vsx32l;
-      else if (altivec)
-	return tdesc_powerpc_altivec32l;
-      else
-	return tdesc_powerpc_32l;
-
+      wordsize = 4;
+      break;
     case 48 * 8:
-      if (cell)
-	return tdesc_powerpc_cell64l;
-      else if (vsx)
-	return tdesc_powerpc_vsx64l;
-      else if (altivec)
-	return tdesc_powerpc_altivec64l;
-      else
-	return tdesc_powerpc_64l;
-
+      wordsize = 8;
+      break;
     default:
       return NULL;
     }
+
+  ppc_linux_features features (wordsize);
+
+  if (cell)
+    features.cell = true;
+
+  if (altivec)
+    features.altivec = true;
+
+  if (vsx)
+    features.vsx = true;
+
+  return ppc_linux_match_description (features);
 }
 
 
diff --git a/gdb/ppc-linux-tdep.h b/gdb/ppc-linux-tdep.h
index 465f9ff932..5e7c4be16b 100644
--- a/gdb/ppc-linux-tdep.h
+++ b/gdb/ppc-linux-tdep.h
@@ -40,21 +40,4 @@ enum {
 /* Return 1 if PPC_ORIG_R3_REGNUM and PPC_TRAP_REGNUM are usable.  */
 int ppc_linux_trap_reg_p (struct gdbarch *gdbarch);
 
-/* Linux target descriptions.  */
-extern struct target_desc *tdesc_powerpc_32l;
-extern struct target_desc *tdesc_powerpc_altivec32l;
-extern struct target_desc *tdesc_powerpc_cell32l;
-extern struct target_desc *tdesc_powerpc_vsx32l;
-extern struct target_desc *tdesc_powerpc_isa205_32l;
-extern struct target_desc *tdesc_powerpc_isa205_altivec32l;
-extern struct target_desc *tdesc_powerpc_isa205_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_cell64l;
-extern struct target_desc *tdesc_powerpc_vsx64l;
-extern struct target_desc *tdesc_powerpc_isa205_64l;
-extern struct target_desc *tdesc_powerpc_isa205_altivec64l;
-extern struct target_desc *tdesc_powerpc_isa205_vsx64l;
-
 #endif /* PPC_LINUX_TDEP_H */
-- 
2.13.6


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

* Re: [PATCH 8/8] [PowerPC] Recognize isa205 in linux core files
  2018-05-16 15:53   ` Ulrich Weigand
@ 2018-05-16 23:32     ` Pedro Franco de Carvalho
  2018-05-17 10:22       ` Ulrich Weigand
  0 siblings, 1 reply; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-16 23:32 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gdb-patches

Ulrich Weigand <uweigand@de.ibm.com> writes:

> Maybe this routine should now be moved to ppc-linux-tdep.c ...
>
>> +  CORE_ADDR hwcap = 0;
>> +
>> +  target_auxv_search (target, AT_HWCAP, &hwcap);
>> +
>> +  features.isa205 = ppc_linux_has_isa205 (hwcap);
>
> ... so it can be reused here?
>
> Otherwise this looks OK to me.

Should the routine take a struct target_ops * parameter, so that
core_read_description can pass its target (for calling
target_auxv_search)? In this case all the calls in ppc_linux_nat.c would
also have to be updated.

Thanks!
Pedro

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

* Re: [PATCH 1/8] [PowerPC] Consolidate linux target description selection
  2018-05-16 22:50     ` Pedro Franco de Carvalho
@ 2018-05-17  8:28       ` Ulrich Weigand
  0 siblings, 0 replies; 44+ messages in thread
From: Ulrich Weigand @ 2018-05-17  8:28 UTC (permalink / raw)
  To: Pedro Franco de Carvalho; +Cc: gdb-patches

Pedro Franco de Carvalho wrote.
> Ulrich Weigand <uweigand@de.ibm.com> writes:
> 
> >> +/* Base value for ppc_linux_features variables.  */
> >> +const struct ppc_linux_features ppc_linux_no_features = {
> >> +  4,
> >> +  false,
> >> +  false,
> >> +  false,
> >> +  false,
> >> +};
> >
> > I'm not sure it makes much sense to declare "4" the default wordsize
> > -- there's not really a default between 4 and 8.  Maybe it would be
> > clearer to just force all users to explicitly set the wordsize.
> 
> Is something like this a good style, or should I just initialize
> wordsize to 0 and let the previous assert in ppc_match_description
> ensure that the wordsize is either 4 or 8?

If the members are all public anyway, I'm not sure it buys us much
to set wordsize in the constructor ... I'd just let the user set it
and then verify via an assert, as you suggest.

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH 8/8] [PowerPC] Recognize isa205 in linux core files
  2018-05-16 23:32     ` Pedro Franco de Carvalho
@ 2018-05-17 10:22       ` Ulrich Weigand
  2018-05-21 20:46         ` Pedro Franco de Carvalho
  0 siblings, 1 reply; 44+ messages in thread
From: Ulrich Weigand @ 2018-05-17 10:22 UTC (permalink / raw)
  To: Pedro Franco de Carvalho; +Cc: gdb-patches

Pedro Franco de Carvalho wrote:
> Ulrich Weigand <uweigand@de.ibm.com> writes:
> 
> > Maybe this routine should now be moved to ppc-linux-tdep.c ...
> >
> >> +  CORE_ADDR hwcap = 0;
> >> +
> >> +  target_auxv_search (target, AT_HWCAP, &hwcap);
> >> +
> >> +  features.isa205 = ppc_linux_has_isa205 (hwcap);
> >
> > ... so it can be reused here?
> >
> > Otherwise this looks OK to me.
> 
> Should the routine take a struct target_ops * parameter, so that
> core_read_description can pass its target (for calling
> target_auxv_search)? In this case all the calls in ppc_linux_nat.c would
> also have to be updated.

Right, I guess that makes sense.

(Another question is why ppp-linux-nat.c repeats this call all the
time, maybe it would be better to cache the result per inferior ...
But that's certainly a separate issue.)

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH 5/8] [PowerPC] Fix access to VSCR in linux targets
  2018-05-16 14:06   ` Ulrich Weigand
@ 2018-05-17 21:25     ` Pedro Franco de Carvalho
  2018-05-18 15:37       ` Ulrich Weigand
  2018-05-21 20:46     ` Pedro Franco de Carvalho
  1 sibling, 1 reply; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-17 21:25 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gdb-patches

Ulrich Weigand <uweigand@de.ibm.com> writes:

> I'm wondering if we shouldn't have the common regcache_collect_regset
> routine zero out areas covered by REGCACHE_MAP_SKIP?  Then we wouldn't
> need this extra routine here.
>
>> -static const struct regset ppc32_linux_vrregset = {
>> -  &ppc32_linux_reg_offsets,
>> -  ppc_supply_vrregset,
>> -  ppc_collect_vrregset

I think this might affect the s390 target: in s390-linux-nat,
fill_gregset uses collect_regset on a buffer that has already been
filled through ptrace (PTRACE_PEEKUSR_AREA), which is then used to
extract pswm, so it relies on collect_regset not changing the buffer on
the skipped slots.

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

* Re: [PATCH 5/8] [PowerPC] Fix access to VSCR in linux targets
  2018-05-17 21:25     ` Pedro Franco de Carvalho
@ 2018-05-18 15:37       ` Ulrich Weigand
  0 siblings, 0 replies; 44+ messages in thread
From: Ulrich Weigand @ 2018-05-18 15:37 UTC (permalink / raw)
  To: Pedro Franco de Carvalho; +Cc: gdb-patches

Pedro Franco de Carvalho wrote:
> Ulrich Weigand <uweigand@de.ibm.com> writes:
> 
> > I'm wondering if we shouldn't have the common regcache_collect_regset
> > routine zero out areas covered by REGCACHE_MAP_SKIP?  Then we wouldn't
> > need this extra routine here.
> 
> I think this might affect the s390 target: in s390-linux-nat,
> fill_gregset uses collect_regset on a buffer that has already been
> filled through ptrace (PTRACE_PEEKUSR_AREA), which is then used to
> extract pswm, so it relies on collect_regset not changing the buffer on
> the skipped slots.

Ah, I see.  Good catch!  I think your original approach is OK, then.

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH 5/8] [PowerPC] Fix access to VSCR in linux targets
  2018-05-16 14:06   ` Ulrich Weigand
  2018-05-17 21:25     ` Pedro Franco de Carvalho
@ 2018-05-21 20:46     ` Pedro Franco de Carvalho
  2018-05-22 12:56       ` Ulrich Weigand
  1 sibling, 1 reply; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-21 20:46 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gdb-patches

Ulrich Weigand <uweigand@de.ibm.com> writes:

> This removes all users of ppc_supply_vrregset / ppc_collect_vrregset,
> right?  Then those functions should go away as well, together with
> all their associates data, in particular the v*_offset fields in
> struct ppc_reg_offsets ...

In v2 I removed these. I did have to alter the ppc bsd and aix targets,
but I did not test these. The .tdep files were compiled (with
--enable-targets=all), but there is one native openbsd file that was
also altered.

Thanks!

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

* [PATCH v2 3/8] [PowerPC] Disable regsets using zero sizes in gdbserver
  2018-05-21 20:46 ` [PATCH v2 1/8] [PowerPC] Consolidate linux target description selection Pedro Franco de Carvalho
@ 2018-05-21 20:46   ` Pedro Franco de Carvalho
  2018-05-22 12:48     ` Ulrich Weigand
  2018-05-21 20:46   ` [PATCH v2 4/8] [PowerPC] Consolidate linux vector regset sizes Pedro Franco de Carvalho
                     ` (6 subsequent siblings)
  7 siblings, 1 reply; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-21 20:46 UTC (permalink / raw)
  To: gdb-patches; +Cc: uweigand

Currently the linux-ppc-low.c fill/store functions for extended
regsets check whether they should execute by using the global hwcap
variable.

This patch explicitly sets the regset sizes to zero when needed to
disable them instead, so that the fill/store functions are not called
in the first place by regsets_fetch_inferior_registers in linux-low.c.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* linux-ppc-low.c (ppc_fill_vsxregset): Remove ppc_hwcap check.
	(ppc_store_vsxregset): Likewise.
	(ppc_fill_vrregset): Likewise.
	(ppc_store_vrregset): Likewise.
	(ppc_fill_evrregset): Likewise.
	(ppc_store_evrregset): Likewise.
	(ppc_regsets): Set VSX/VR/EVR regset sizes to 0.
	(ppc_arch_setup): Iterate through ppc_regsets and set sizes when
	needed.
---
 gdb/gdbserver/linux-ppc-low.c | 45 +++++++++++++++++++++++--------------------
 1 file changed, 24 insertions(+), 21 deletions(-)

diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c
index 30fcd4115a..b440b0e0a7 100644
--- a/gdb/gdbserver/linux-ppc-low.c
+++ b/gdb/gdbserver/linux-ppc-low.c
@@ -467,9 +467,6 @@ ppc_fill_vsxregset (struct regcache *regcache, void *buf)
   int i, base;
   char *regset = (char *) buf;
 
-  if (!(ppc_hwcap & PPC_FEATURE_HAS_VSX))
-    return;
-
   base = find_regno (regcache->tdesc, "vs0h");
   for (i = 0; i < 32; i++)
     collect_register (regcache, base + i, &regset[i * 8]);
@@ -481,9 +478,6 @@ ppc_store_vsxregset (struct regcache *regcache, const void *buf)
   int i, base;
   const char *regset = (const char *) buf;
 
-  if (!(ppc_hwcap & PPC_FEATURE_HAS_VSX))
-    return;
-
   base = find_regno (regcache->tdesc, "vs0h");
   for (i = 0; i < 32; i++)
     supply_register (regcache, base + i, &regset[i * 8]);
@@ -497,9 +491,6 @@ ppc_fill_vrregset (struct regcache *regcache, void *buf)
   int i, base;
   char *regset = (char *) buf;
 
-  if (!(ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC))
-    return;
-
   base = find_regno (regcache->tdesc, "vr0");
   for (i = 0; i < 32; i++)
     collect_register (regcache, base + i, &regset[i * 16]);
@@ -514,9 +505,6 @@ ppc_store_vrregset (struct regcache *regcache, const void *buf)
   int i, base;
   const char *regset = (const char *) buf;
 
-  if (!(ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC))
-    return;
-
   base = find_regno (regcache->tdesc, "vr0");
   for (i = 0; i < 32; i++)
     supply_register (regcache, base + i, &regset[i * 16]);
@@ -538,9 +526,6 @@ ppc_fill_evrregset (struct regcache *regcache, void *buf)
   int i, ev0;
   struct gdb_evrregset_t *regset = (struct gdb_evrregset_t *) buf;
 
-  if (!(ppc_hwcap & PPC_FEATURE_HAS_SPE))
-    return;
-
   ev0 = find_regno (regcache->tdesc, "ev0h");
   for (i = 0; i < 32; i++)
     collect_register (regcache, ev0 + i, &regset->evr[i]);
@@ -555,9 +540,6 @@ ppc_store_evrregset (struct regcache *regcache, const void *buf)
   int i, ev0;
   const struct gdb_evrregset_t *regset = (const struct gdb_evrregset_t *) buf;
 
-  if (!(ppc_hwcap & PPC_FEATURE_HAS_SPE))
-    return;
-
   ev0 = find_regno (regcache->tdesc, "ev0h");
   for (i = 0; i < 32; i++)
     supply_register (regcache, ev0 + i, &regset->evr[i]);
@@ -579,11 +561,11 @@ static struct regset_info ppc_regsets[] = {
      fetch them every time, but still fall back to PTRACE_PEEKUSER for the
      general registers.  Some kernels support these, but not the newer
      PPC_PTRACE_GETREGS.  */
-  { PTRACE_GETVSXREGS, PTRACE_SETVSXREGS, 0, SIZEOF_VSXREGS, EXTENDED_REGS,
+  { PTRACE_GETVSXREGS, PTRACE_SETVSXREGS, 0, 0, EXTENDED_REGS,
   ppc_fill_vsxregset, ppc_store_vsxregset },
-  { PTRACE_GETVRREGS, PTRACE_SETVRREGS, 0, SIZEOF_VRREGS, EXTENDED_REGS,
+  { PTRACE_GETVRREGS, PTRACE_SETVRREGS, 0, 0, EXTENDED_REGS,
     ppc_fill_vrregset, ppc_store_vrregset },
-  { PTRACE_GETEVRREGS, PTRACE_SETEVRREGS, 0, 32 * 4 + 8 + 4, EXTENDED_REGS,
+  { PTRACE_GETEVRREGS, PTRACE_SETEVRREGS, 0, 0, EXTENDED_REGS,
     ppc_fill_evrregset, ppc_store_evrregset },
   { 0, 0, 0, 0, GENERAL_REGS, ppc_fill_gregset, NULL },
   NULL_REGSET
@@ -619,7 +601,9 @@ static void
 ppc_arch_setup (void)
 {
   const struct target_desc *tdesc;
+  struct regset_info *regset;
   struct ppc_linux_features features = ppc_linux_no_features;
+
   int tid = lwpid_of (current_thread);
 
   features.wordsize = ppc_linux_target_wordsize (tid);
@@ -671,6 +655,25 @@ ppc_arch_setup (void)
 #endif
 
   current_process ()->tdesc = tdesc;
+
+  for (regset = ppc_regsets; regset->size >= 0; regset++)
+    switch (regset->get_request)
+      {
+      case PTRACE_GETVRREGS:
+	regset->size = features.altivec ? SIZEOF_VRREGS : 0;
+	break;
+      case PTRACE_GETVSXREGS:
+	regset->size = features.vsx ? SIZEOF_VSXREGS : 0;
+	break;
+      case PTRACE_GETEVRREGS:
+	if (ppc_hwcap & PPC_FEATURE_HAS_SPE)
+	  regset->size = 32 * 4 + 8 + 4;
+	else
+	  regset->size = 0;
+	break;
+      default:
+	break;
+      }
 }
 
 /* Implementation of linux_target_ops method "supports_tracepoints".  */
-- 
2.13.6

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

* Re: [PATCH 8/8] [PowerPC] Recognize isa205 in linux core files
  2018-05-17 10:22       ` Ulrich Weigand
@ 2018-05-21 20:46         ` Pedro Franco de Carvalho
  2018-05-22 12:48           ` Ulrich Weigand
  0 siblings, 1 reply; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-21 20:46 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gdb-patches

Ulrich Weigand <uweigand@de.ibm.com> writes:

> Pedro Franco de Carvalho wrote:
>> Ulrich Weigand <uweigand@de.ibm.com> writes:
>> 
>> > Maybe this routine should now be moved to ppc-linux-tdep.c ...
>> >
>> >> +  CORE_ADDR hwcap = 0;
>> >> +
>> >> +  target_auxv_search (target, AT_HWCAP, &hwcap);
>> >> +
>> >> +  features.isa205 = ppc_linux_has_isa205 (hwcap);
>> >
>> > ... so it can be reused here?
>> >
>> > Otherwise this looks OK to me.
>> 
>> Should the routine take a struct target_ops * parameter, so that
>> core_read_description can pass its target (for calling
>> target_auxv_search)? In this case all the calls in ppc_linux_nat.c would
>> also have to be updated.
>
> Right, I guess that makes sense.
>
> (Another question is why ppp-linux-nat.c repeats this call all the
> time, maybe it would be better to cache the result per inferior ...
> But that's certainly a separate issue.)

Now I'm confused as to which target should be passed to
target_auxv_search. It uses the target parameter for reading the auxv
data but then it calls target_auxv_parse through the global
target_stack.

Should ppc-linux-tdep also also pass target_stack in
core_read_description, for consistency?

Or should ppc-linux-nat be changed to pass "this"? I can do this either
by moving ppc_linux_get_hwcap to ppc-linux-tdep.c and adding a target
parameter, and then change all the call sites in ppc-linux-nat.c, or I
can make ppc_linux_get_hwcap a private method of ppc_linux_nat_target
and pass "this" inside it (which wouldn't require changing the call
sites), and leave the bare call to target_auxv_search in
ppc-linux-tdep.c.

I haven't changed this in v2 yet. I did change how an error is checked
and handled to make it more explicit.

And it turns out that target_auxv_search already caches the whole auxv
for each inferior. This part could still be improved because
ppc_linux_nat_target::auxv_parse calls ppc_linux_target_wordsize (which
issues a ptrace call) a second time, and at the point were it is
called the wordsize is already known, but it's not clear how to pass the
wordsize to auxv_parse in read_description.

Thanks!
Pedro

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

* [PATCH v2 1/8] [PowerPC] Consolidate linux target description selection
  2018-05-10 19:59 [PATCH 0/8] [PowerPC] Miscellaneous fixes for register access Pedro Franco de Carvalho
                   ` (7 preceding siblings ...)
  2018-05-10 22:25 ` [PATCH 7/8] [PowerPC] Fix inclusion of dfp pseudoregs in tdep Pedro Franco de Carvalho
@ 2018-05-21 20:46 ` Pedro Franco de Carvalho
  2018-05-21 20:46   ` [PATCH v2 3/8] [PowerPC] Disable regsets using zero sizes in gdbserver Pedro Franco de Carvalho
                     ` (7 more replies)
  8 siblings, 8 replies; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-21 20:46 UTC (permalink / raw)
  To: gdb-patches; +Cc: uweigand

Share target description declarations and selection among ppc linux
native targets, core files, gdbserver and IPA.

To avoid complicated define guards, gdbserver and IPA now have
declarations for all descriptions, including 64-bit generated
descriptions when compiled in 32-bit mode. These have always been
linked into the gdbserver and IPA binaries. Because they might be
uninitialized, the selection function checks that the selected
description is initialized.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* arch/ppc-linux-common.c: New file.
	* arch/ppc-linux-common.h: New file.
	* arch/ppc-linux-tdesc.h: New file.
	* configure.tgt (powerpc*-*-linux*): Add arch/ppc-linux-common.o.
	* Makefile.in (ALL_TARGET_OBS): Add arch/ppc-linux-common.o.
	(HFILES_NO_SRCDIR): Add arch/ppc-linux-common.h and
	arch/ppc-linux-tdesc.h.
	* ppc-linux-nat.c: Include arch/ppc-linux-common.h and
	arch/ppc-linux-tdesc.h.
	(ppc_linux_nat_target::read_description): Remove target
	description matching code. Fill a ppc_linux_features struct and
	call ppc_linux_match_description with it. Move comment about ISA
	2.05 to ppc-linux-common.c.
	* ppc-linux-tdep.c: Include arch/ppc-linux-common.h and
	arch/ppc-linux-tdesc.h.
	(ppc_linux_core_read_description): Remove target description
	matching code. Fill a ppc_linux_features struct and call
	ppc_linux_match_description with it.
	* ppc-linux-tdep.h (tdesc_powerpc_32l, tdesc_powerpc_64l)
	(tdesc_powerpc_altivec32l, tdesc_powerpc_altivec64l)
	(tdesc_powerpc_cell32l, tdesc_powerpc_cell64l)
	(tdesc_powerpc_vsx32l, tdesc_powerpc_vsx64l)
	(tdesc_powerpc_isa205_32l, tdesc_powerpc_isa205_64l)
	(tdesc_powerpc_isa205_altivec32l, tdesc_powerpc_isa205_altivec64l)
	(tdesc_powerpc_isa205_vsx32l, tdesc_powerpc_isa205_vsx64l)
	(tdesc_powerpc_e500l): Remove.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* configure.srv (srv_tgtobj): Add arch/ppc-linux-common.o.
	* Makefile.in (SFILES): Add arch/ppc-linux-common.c.
	* linux-ppc-tdesc.h: Rename to linux-ppc-tdesc-init.h.
	* linux-ppc-tdesc-init.h (tdesc_powerpc_32l, tdesc_powerpc_64l)
	(tdesc_powerpc_altivec32l, tdesc_powerpc_altivec64l)
	(tdesc_powerpc_cell32l, tdesc_powerpc_cell64l)
	(tdesc_powerpc_vsx32l, tdesc_powerpc_vsx64l)
	(tdesc_powerpc_isa205_32l, tdesc_powerpc_isa205_64l)
	(tdesc_powerpc_isa205_altivec32l, tdesc_powerpc_isa205_altivec64l)
	(tdesc_powerpc_isa205_vsx32l, tdesc_powerpc_isa205_vsx64l)
	(tdesc_powerpc_e500l): Remove.
	* linux-ppc-ipa.c: Include arch/ppc-linux-tdesc.h and
	linux-ppc-tdesc-init.h. Don't include linux-ppc-tdesc.h.
	* linux-ppc-low.c: Include arch/ppc-linux-common.h,
	arch/ppc-linux-tdesc.h, and linux-ppc-tdesc-init.h. Don't include
	linux-ppc-tdesc.h.
	(ppc_arch_setup): Remove target description matching code. Fill a
	ppc_linux_features struct and call ppc_linux_match_description
	with it.
---
 gdb/Makefile.in                                    |  3 +
 gdb/arch/ppc-linux-common.c                        | 85 ++++++++++++++++++++++
 gdb/arch/ppc-linux-common.h                        | 51 +++++++++++++
 gdb/arch/ppc-linux-tdesc.h                         | 42 +++++++++++
 gdb/configure.tgt                                  |  3 +-
 gdb/gdbserver/Makefile.in                          |  1 +
 gdb/gdbserver/configure.srv                        |  1 +
 gdb/gdbserver/linux-ppc-ipa.c                      |  3 +-
 gdb/gdbserver/linux-ppc-low.c                      | 75 ++++++++-----------
 .../{linux-ppc-tdesc.h => linux-ppc-tdesc-init.h}  | 15 ----
 gdb/ppc-linux-nat.c                                | 56 ++++----------
 gdb/ppc-linux-tdep.c                               | 37 +++++-----
 gdb/ppc-linux-tdep.h                               | 17 -----
 13 files changed, 251 insertions(+), 138 deletions(-)
 create mode 100644 gdb/arch/ppc-linux-common.c
 create mode 100644 gdb/arch/ppc-linux-common.h
 create mode 100644 gdb/arch/ppc-linux-tdesc.h
 rename gdb/gdbserver/{linux-ppc-tdesc.h => linux-ppc-tdesc-init.h} (76%)

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 09a2ad2ca3..df6ebab851 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -679,6 +679,7 @@ ALL_TARGET_OBS = \
 	arch/arm-get-next-pcs.o \
 	arch/arm-linux.o \
 	arch/i386.o \
+	arch/ppc-linux-common.o \
 	arm-bsd-tdep.o \
 	arm-fbsd-tdep.o \
 	arm-linux-tdep.o \
@@ -1412,6 +1413,8 @@ HFILES_NO_SRCDIR = \
 	arch/aarch64-insn.h \
 	arch/arm.h \
 	arch/i386.h \
+	arch/ppc-linux-common.h \
+	arch/ppc-linux-tdesc.h \
 	cli/cli-cmds.h \
 	cli/cli-decode.h \
 	cli/cli-script.h \
diff --git a/gdb/arch/ppc-linux-common.c b/gdb/arch/ppc-linux-common.c
new file mode 100644
index 0000000000..87ccc42cae
--- /dev/null
+++ b/gdb/arch/ppc-linux-common.c
@@ -0,0 +1,85 @@
+/* Common target dependent code for GNU/Linux on PPC systems.
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "common-defs.h"
+#include "arch/ppc-linux-common.h"
+#include "arch/ppc-linux-tdesc.h"
+
+/* Decimal Floating Point bit in AT_HWCAP.
+
+   This file can be used by a host with another architecture, e.g.
+   when debugging core files, which might not provide this constant.  */
+
+#ifndef PPC_FEATURE_HAS_DFP
+#define PPC_FEATURE_HAS_DFP	0x00000400
+#endif
+
+bool
+ppc_linux_has_isa205 (unsigned long hwcap)
+{
+  /* Power ISA 2.05 (implemented by Power 6 and newer processors)
+     increases the FPSCR from 32 bits to 64 bits.  Even though Power 7
+     supports this ISA version, it doesn't have PPC_FEATURE_ARCH_2_05
+     set, only PPC_FEATURE_ARCH_2_06.  Since for now the only bits
+     used in the higher half of the register are for Decimal Floating
+     Point, we check if that feature is available to decide the size
+     of the FPSCR.  */
+  return ((hwcap & PPC_FEATURE_HAS_DFP) != 0);
+}
+
+const struct target_desc *
+ppc_linux_match_description (struct ppc_linux_features features)
+{
+  struct target_desc *tdesc = NULL;
+
+  if (features.wordsize == 8)
+    {
+      if (features.cell)
+	tdesc = tdesc_powerpc_cell64l;
+      else if (features.vsx)
+	tdesc = features.isa205
+	  ? tdesc_powerpc_isa205_vsx64l : tdesc_powerpc_vsx64l;
+      else if (features.altivec)
+	tdesc = features.isa205
+	  ? tdesc_powerpc_isa205_altivec64l : tdesc_powerpc_altivec64l;
+      else
+	tdesc = features.isa205?
+	  tdesc_powerpc_isa205_64l : tdesc_powerpc_64l;
+    }
+  else
+    {
+      gdb_assert (features.wordsize == 4);
+
+      if (features.cell)
+	tdesc = tdesc_powerpc_cell32l;
+      else if (features.vsx)
+	tdesc = features.isa205
+	  ? tdesc_powerpc_isa205_vsx32l : tdesc_powerpc_vsx32l;
+      else if (features.altivec)
+	tdesc = features.isa205
+	  ? tdesc_powerpc_isa205_altivec32l : tdesc_powerpc_altivec32l;
+      else
+	tdesc = features.isa205
+	  ? tdesc_powerpc_isa205_32l : tdesc_powerpc_32l;
+    }
+
+  gdb_assert (tdesc != NULL);
+
+  return tdesc;
+}
diff --git a/gdb/arch/ppc-linux-common.h b/gdb/arch/ppc-linux-common.h
new file mode 100644
index 0000000000..b82adc49d2
--- /dev/null
+++ b/gdb/arch/ppc-linux-common.h
@@ -0,0 +1,51 @@
+/* Common target dependent code for GNU/Linux on PPC systems.
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef ARCH_PPC_LINUX_COMMON_H
+#define ARCH_PPC_LINUX_COMMON_H
+
+struct target_desc;
+
+/* Check if the hwcap auxv entry indicates that isa205 is supported.  */
+bool ppc_linux_has_isa205 (unsigned long hwcap);
+
+/* Features used to determine the target description.  */
+struct ppc_linux_features
+{
+  unsigned int wordsize;
+  bool altivec;
+  bool vsx;
+  bool isa205;
+  bool cell;
+};
+
+/* Base value for ppc_linux_features variables.  */
+const struct ppc_linux_features ppc_linux_no_features = {
+  0,
+  false,
+  false,
+  false,
+  false,
+};
+
+/* Return a target description that matches FEATURES.  */
+const struct target_desc * ppc_linux_match_description
+(struct ppc_linux_features features);
+
+#endif /* ARCH_PPC_LINUX_COMMON_H */
diff --git a/gdb/arch/ppc-linux-tdesc.h b/gdb/arch/ppc-linux-tdesc.h
new file mode 100644
index 0000000000..594c7c7c7c
--- /dev/null
+++ b/gdb/arch/ppc-linux-tdesc.h
@@ -0,0 +1,42 @@
+/* Target description declarations shared between gdb, gdbserver and IPA.
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef ARCH_PPC_LINUX_TDESC_H
+#define ARCH_PPC_LINUX_TDESC_H
+
+struct target_desc;
+
+extern struct target_desc *tdesc_powerpc_32l;
+extern struct target_desc *tdesc_powerpc_altivec32l;
+extern struct target_desc *tdesc_powerpc_cell32l;
+extern struct target_desc *tdesc_powerpc_vsx32l;
+extern struct target_desc *tdesc_powerpc_isa205_32l;
+extern struct target_desc *tdesc_powerpc_isa205_altivec32l;
+extern struct target_desc *tdesc_powerpc_isa205_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_cell64l;
+extern struct target_desc *tdesc_powerpc_vsx64l;
+extern struct target_desc *tdesc_powerpc_isa205_64l;
+extern struct target_desc *tdesc_powerpc_isa205_altivec64l;
+extern struct target_desc *tdesc_powerpc_isa205_vsx64l;
+
+#endif /* ARCH_PPC_LINUX_TDESC_H */
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 02358298b5..f197160896 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -492,7 +492,8 @@ powerpc*-*-linux*)
 			spu-multiarch.o \
 			glibc-tdep.o symfile-mem.o linux-tdep.o \
 			ravenscar-thread.o ppc-ravenscar-thread.o \
-			linux-record.o "
+			linux-record.o \
+			arch/ppc-linux-common.o"
 	gdb_sim=../sim/ppc/libsim.a
 	build_gdbserver=yes
 	;;
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index c377378809..675faa4364 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -196,6 +196,7 @@ SFILES = \
 	$(srcdir)/arch/arm.c \
 	$(srcdir)/arch/arm-get-next-pcs.c \
 	$(srcdir)/arch/arm-linux.c \
+	$(srcdir)/arch/ppc-linux-common.c \
 	$(srcdir)/common/btrace-common.c \
 	$(srcdir)/common/buffer.c \
 	$(srcdir)/common/cleanups.c \
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index ffeefb9b92..7153ff339d 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -225,6 +225,7 @@ case "${target}" in
 			srv_regobj="${srv_regobj} powerpc-isa205-altivec64l.o"
 			srv_regobj="${srv_regobj} powerpc-isa205-vsx64l.o"
 			srv_tgtobj="$srv_linux_obj linux-ppc-low.o ppc-linux.o"
+			srv_tgtobj="${srv_tgtobj} arch/ppc-linux-common.o"
 			srv_xmlfiles="rs6000/powerpc-32l.xml"
 			srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-altivec32l.xml"
 			srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-cell32l.xml"
diff --git a/gdb/gdbserver/linux-ppc-ipa.c b/gdb/gdbserver/linux-ppc-ipa.c
index c993e76315..f6861f0d98 100644
--- a/gdb/gdbserver/linux-ppc-ipa.c
+++ b/gdb/gdbserver/linux-ppc-ipa.c
@@ -21,7 +21,8 @@
 #include "server.h"
 #include <sys/mman.h>
 #include "tracepoint.h"
-#include "linux-ppc-tdesc.h"
+#include "arch/ppc-linux-tdesc.h"
+#include "linux-ppc-tdesc-init.h"
 #include <elf.h>
 #ifdef HAVE_GETAUXVAL
 #include <sys/auxv.h>
diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c
index 36bd373c88..5361baf72a 100644
--- a/gdb/gdbserver/linux-ppc-low.c
+++ b/gdb/gdbserver/linux-ppc-low.c
@@ -23,8 +23,10 @@
 #include <elf.h>
 #include <asm/ptrace.h>
 
+#include "arch/ppc-linux-common.h"
+#include "arch/ppc-linux-tdesc.h"
 #include "nat/ppc-linux.h"
-#include "linux-ppc-tdesc.h"
+#include "linux-ppc-tdesc-init.h"
 #include "ax.h"
 #include "tracepoint.h"
 
@@ -617,6 +619,10 @@ static void
 ppc_arch_setup (void)
 {
   const struct target_desc *tdesc;
+  struct ppc_linux_features features = ppc_linux_no_features;
+
+  features.wordsize = 4;
+
 #ifdef __powerpc64__
   long msr;
   struct regcache *regcache;
@@ -634,57 +640,33 @@ ppc_arch_setup (void)
   free_register_cache (regcache);
   if (ppc64_64bit_inferior_p (msr))
     {
-      ppc_get_auxv (AT_HWCAP, &ppc_hwcap);
-      if (ppc_hwcap & PPC_FEATURE_CELL)
-	tdesc = tdesc_powerpc_cell64l;
-      else if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
-	{
-	  /* Power ISA 2.05 (implemented by Power 6 and newer processors)
-	     increases the FPSCR from 32 bits to 64 bits. Even though Power 7
-	     supports this ISA version, it doesn't have PPC_FEATURE_ARCH_2_05
-	     set, only PPC_FEATURE_ARCH_2_06.  Since for now the only bits
-	     used in the higher half of the register are for Decimal Floating
-	     Point, we check if that feature is available to decide the size
-	     of the FPSCR.  */
-	  if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
-	    tdesc = tdesc_powerpc_isa205_vsx64l;
-	  else
-	    tdesc = tdesc_powerpc_vsx64l;
-	}
-      else if (ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC)
-	{
-	  if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
-	    tdesc = tdesc_powerpc_isa205_altivec64l;
-	  else
-	    tdesc = tdesc_powerpc_altivec64l;
-	}
+      features.wordsize = 8;
+    }
+#endif
 
+  if (features.wordsize == 4)
+    {
+      /* OK, we have a 32-bit inferior.  */
+      tdesc = tdesc_powerpc_32l;
       current_process ()->tdesc = tdesc;
-      return;
     }
-#endif
-
-  /* OK, we have a 32-bit inferior.  */
-  tdesc = tdesc_powerpc_32l;
-  current_process ()->tdesc = tdesc;
 
+  /* The value of current_process ()->tdesc needs to be set for this
+     call.  */
   ppc_get_auxv (AT_HWCAP, &ppc_hwcap);
+
+  features.isa205 = ppc_linux_has_isa205 (ppc_hwcap);
+
+  if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
+    features.vsx = true;
+
+  if (ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC)
+    features.altivec = true;
+
   if (ppc_hwcap & PPC_FEATURE_CELL)
-    tdesc = tdesc_powerpc_cell32l;
-  else if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
-    {
-      if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
-	tdesc = tdesc_powerpc_isa205_vsx32l;
-      else
-	tdesc = tdesc_powerpc_vsx32l;
-    }
-  else if (ppc_hwcap & PPC_FEATURE_HAS_ALTIVEC)
-    {
-      if (ppc_hwcap & PPC_FEATURE_HAS_DFP)
-	tdesc = tdesc_powerpc_isa205_altivec32l;
-      else
-	tdesc = tdesc_powerpc_altivec32l;
-    }
+    features.cell = true;
+
+  tdesc = ppc_linux_match_description (features);
 
   /* On 32-bit machines, check for SPE registers.
      Set the low target's regmap field as appropriately.  */
@@ -707,6 +689,7 @@ ppc_arch_setup (void)
       ppc_regmap_adjusted = 1;
    }
 #endif
+
   current_process ()->tdesc = tdesc;
 }
 
diff --git a/gdb/gdbserver/linux-ppc-tdesc.h b/gdb/gdbserver/linux-ppc-tdesc-init.h
similarity index 76%
rename from gdb/gdbserver/linux-ppc-tdesc.h
rename to gdb/gdbserver/linux-ppc-tdesc-init.h
index 4a561f5e37..422e7bd9c4 100644
--- a/gdb/gdbserver/linux-ppc-tdesc.h
+++ b/gdb/gdbserver/linux-ppc-tdesc-init.h
@@ -36,35 +36,27 @@ enum ppc_linux_tdesc {
 
 /* Defined in auto-generated file powerpc-32l.c.  */
 void init_registers_powerpc_32l (void);
-extern const struct target_desc *tdesc_powerpc_32l;
 
 /* Defined in auto-generated file powerpc-altivec32l.c.  */
 void init_registers_powerpc_altivec32l (void);
-extern const struct target_desc *tdesc_powerpc_altivec32l;
 
 /* Defined in auto-generated file powerpc-cell32l.c.  */
 void init_registers_powerpc_cell32l (void);
-extern const struct target_desc *tdesc_powerpc_cell32l;
 
 /* Defined in auto-generated file powerpc-vsx32l.c.  */
 void init_registers_powerpc_vsx32l (void);
-extern const struct target_desc *tdesc_powerpc_vsx32l;
 
 /* Defined in auto-generated file powerpc-isa205-32l.c.  */
 void init_registers_powerpc_isa205_32l (void);
-extern const struct target_desc *tdesc_powerpc_isa205_32l;
 
 /* Defined in auto-generated file powerpc-isa205-altivec32l.c.  */
 void init_registers_powerpc_isa205_altivec32l (void);
-extern const struct target_desc *tdesc_powerpc_isa205_altivec32l;
 
 /* Defined in auto-generated file powerpc-isa205-vsx32l.c.  */
 void init_registers_powerpc_isa205_vsx32l (void);
-extern const struct target_desc *tdesc_powerpc_isa205_vsx32l;
 
 /* Defined in auto-generated file powerpc-e500l.c.  */
 void init_registers_powerpc_e500l (void);
-extern const struct target_desc *tdesc_powerpc_e500l;
 
 #endif
 
@@ -72,30 +64,23 @@ extern const struct target_desc *tdesc_powerpc_e500l;
 
 /* Defined in auto-generated file powerpc-64l.c.  */
 void init_registers_powerpc_64l (void);
-extern const struct target_desc *tdesc_powerpc_64l;
 
 /* Defined in auto-generated file powerpc-altivec64l.c.  */
 void init_registers_powerpc_altivec64l (void);
-extern const struct target_desc *tdesc_powerpc_altivec64l;
 
 /* Defined in auto-generated file powerpc-cell64l.c.  */
 void init_registers_powerpc_cell64l (void);
-extern const struct target_desc *tdesc_powerpc_cell64l;
 
 /* Defined in auto-generated file powerpc-vsx64l.c.  */
 void init_registers_powerpc_vsx64l (void);
-extern const struct target_desc *tdesc_powerpc_vsx64l;
 
 /* Defined in auto-generated file powerpc-isa205-64l.c.  */
 void init_registers_powerpc_isa205_64l (void);
-extern const struct target_desc *tdesc_powerpc_isa205_64l;
 
 /* Defined in auto-generated file powerpc-isa205-altivec64l.c.  */
 void init_registers_powerpc_isa205_altivec64l (void);
-extern const struct target_desc *tdesc_powerpc_isa205_altivec64l;
 
 /* Defined in auto-generated file powerpc-isa205-vsx64l.c.  */
 void init_registers_powerpc_isa205_vsx64l (void);
-extern const struct target_desc *tdesc_powerpc_isa205_vsx64l;
 
 #endif
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index 1423339339..e49a482c09 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -45,6 +45,8 @@
 #include "elf/common.h"
 #include "auxv.h"
 
+#include "arch/ppc-linux-common.h"
+#include "arch/ppc-linux-tdesc.h"
 #include "nat/ppc-linux.h"
 
 /* Similarly for the hardware watchpoint support.  These requests are used
@@ -2416,11 +2418,6 @@ ppc_linux_nat_target::auxv_parse (gdb_byte **readptr,
 const struct target_desc *
 ppc_linux_nat_target::read_description ()
 {
-  int altivec = 0;
-  int vsx = 0;
-  int isa205 = 0;
-  int cell = 0;
-
   int tid = ptid_get_lwp (inferior_ptid);
   if (tid == 0)
     tid = ptid_get_pid (inferior_ptid);
@@ -2438,13 +2435,19 @@ ppc_linux_nat_target::read_description ()
 	perror_with_name (_("Unable to fetch SPE registers"));
     }
 
+  struct ppc_linux_features features = ppc_linux_no_features;
+
+  features.wordsize = ppc_linux_target_wordsize ();
+
+  unsigned long hwcap = ppc_linux_get_hwcap ();
+
   if (have_ptrace_getsetvsxregs
-      && (ppc_linux_get_hwcap () & PPC_FEATURE_HAS_VSX))
+      && (hwcap & PPC_FEATURE_HAS_VSX))
     {
       gdb_vsxregset_t vsxregset;
 
       if (ptrace (PTRACE_GETVSXREGS, tid, 0, &vsxregset) >= 0)
-	vsx = 1;
+	features.vsx = true;
 
       /* EIO means that the PTRACE_GETVSXREGS request isn't supported.
 	 Anything else needs to be reported.  */
@@ -2453,12 +2456,12 @@ ppc_linux_nat_target::read_description ()
     }
 
   if (have_ptrace_getvrregs
-      && (ppc_linux_get_hwcap () & PPC_FEATURE_HAS_ALTIVEC))
+      && (hwcap & PPC_FEATURE_HAS_ALTIVEC))
     {
       gdb_vrregset_t vrregset;
 
       if (ptrace (PTRACE_GETVRREGS, tid, 0, &vrregset) >= 0)
-        altivec = 1;
+        features.altivec = true;
 
       /* EIO means that the PTRACE_GETVRREGS request isn't supported.
 	 Anything else needs to be reported.  */
@@ -2466,39 +2469,12 @@ ppc_linux_nat_target::read_description ()
 	perror_with_name (_("Unable to fetch AltiVec registers"));
     }
 
-  /* Power ISA 2.05 (implemented by Power 6 and newer processors) increases
-     the FPSCR from 32 bits to 64 bits.  Even though Power 7 supports this
-     ISA version, it doesn't have PPC_FEATURE_ARCH_2_05 set, only
-     PPC_FEATURE_ARCH_2_06.  Since for now the only bits used in the higher
-     half of the register are for Decimal Floating Point, we check if that
-     feature is available to decide the size of the FPSCR.  */
-  if (ppc_linux_get_hwcap () & PPC_FEATURE_HAS_DFP)
-    isa205 = 1;
+  if (hwcap & PPC_FEATURE_CELL)
+    features.cell = true;
 
-  if (ppc_linux_get_hwcap () & PPC_FEATURE_CELL)
-    cell = 1;
+  features.isa205 = ppc_linux_has_isa205 (hwcap);
 
-  if (ppc_linux_target_wordsize () == 8)
-    {
-      if (cell)
-	return tdesc_powerpc_cell64l;
-      else if (vsx)
-	return isa205? tdesc_powerpc_isa205_vsx64l : tdesc_powerpc_vsx64l;
-      else if (altivec)
-	return isa205
-	  ? tdesc_powerpc_isa205_altivec64l : tdesc_powerpc_altivec64l;
-
-      return isa205? tdesc_powerpc_isa205_64l : tdesc_powerpc_64l;
-    }
-
-  if (cell)
-    return tdesc_powerpc_cell32l;
-  else if (vsx)
-    return isa205? tdesc_powerpc_isa205_vsx32l : tdesc_powerpc_vsx32l;
-  else if (altivec)
-    return isa205? tdesc_powerpc_isa205_altivec32l : tdesc_powerpc_altivec32l;
-
-  return isa205? tdesc_powerpc_isa205_32l : tdesc_powerpc_32l;
+  return ppc_linux_match_description (features);
 }
 
 void
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 6d3a64c4f0..1d3b019c30 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -37,6 +37,8 @@
 #include "ppc-tdep.h"
 #include "ppc64-tdep.h"
 #include "ppc-linux-tdep.h"
+#include "arch/ppc-linux-common.h"
+#include "arch/ppc-linux-tdesc.h"
 #include "glibc-tdep.h"
 #include "trad-frame.h"
 #include "frame-unwind.h"
@@ -966,38 +968,37 @@ ppc_linux_core_read_description (struct gdbarch *gdbarch,
 				 struct target_ops *target,
 				 bfd *abfd)
 {
+  struct ppc_linux_features features = ppc_linux_no_features;
   asection *cell = bfd_sections_find_if (abfd, ppc_linux_spu_section, NULL);
   asection *altivec = bfd_get_section_by_name (abfd, ".reg-ppc-vmx");
   asection *vsx = bfd_get_section_by_name (abfd, ".reg-ppc-vsx");
   asection *section = bfd_get_section_by_name (abfd, ".reg");
+
   if (! section)
     return NULL;
 
   switch (bfd_section_size (abfd, section))
     {
     case 48 * 4:
-      if (cell)
-	return tdesc_powerpc_cell32l;
-      else if (vsx)
-	return tdesc_powerpc_vsx32l;
-      else if (altivec)
-	return tdesc_powerpc_altivec32l;
-      else
-	return tdesc_powerpc_32l;
-
+      features.wordsize = 4;
+      break;
     case 48 * 8:
-      if (cell)
-	return tdesc_powerpc_cell64l;
-      else if (vsx)
-	return tdesc_powerpc_vsx64l;
-      else if (altivec)
-	return tdesc_powerpc_altivec64l;
-      else
-	return tdesc_powerpc_64l;
-
+      features.wordsize = 8;
+      break;
     default:
       return NULL;
     }
+
+  if (cell)
+    features.cell = true;
+
+  if (altivec)
+    features.altivec = true;
+
+  if (vsx)
+    features.vsx = true;
+
+  return ppc_linux_match_description (features);
 }
 
 
diff --git a/gdb/ppc-linux-tdep.h b/gdb/ppc-linux-tdep.h
index 465f9ff932..5e7c4be16b 100644
--- a/gdb/ppc-linux-tdep.h
+++ b/gdb/ppc-linux-tdep.h
@@ -40,21 +40,4 @@ enum {
 /* Return 1 if PPC_ORIG_R3_REGNUM and PPC_TRAP_REGNUM are usable.  */
 int ppc_linux_trap_reg_p (struct gdbarch *gdbarch);
 
-/* Linux target descriptions.  */
-extern struct target_desc *tdesc_powerpc_32l;
-extern struct target_desc *tdesc_powerpc_altivec32l;
-extern struct target_desc *tdesc_powerpc_cell32l;
-extern struct target_desc *tdesc_powerpc_vsx32l;
-extern struct target_desc *tdesc_powerpc_isa205_32l;
-extern struct target_desc *tdesc_powerpc_isa205_altivec32l;
-extern struct target_desc *tdesc_powerpc_isa205_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_cell64l;
-extern struct target_desc *tdesc_powerpc_vsx64l;
-extern struct target_desc *tdesc_powerpc_isa205_64l;
-extern struct target_desc *tdesc_powerpc_isa205_altivec64l;
-extern struct target_desc *tdesc_powerpc_isa205_vsx64l;
-
 #endif /* PPC_LINUX_TDEP_H */
-- 
2.13.6

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

* [PATCH v2 4/8] [PowerPC] Consolidate linux vector regset sizes
  2018-05-21 20:46 ` [PATCH v2 1/8] [PowerPC] Consolidate linux target description selection Pedro Franco de Carvalho
  2018-05-21 20:46   ` [PATCH v2 3/8] [PowerPC] Disable regsets using zero sizes in gdbserver Pedro Franco de Carvalho
@ 2018-05-21 20:46   ` Pedro Franco de Carvalho
  2018-05-22 12:48     ` Ulrich Weigand
  2018-05-21 20:46   ` [PATCH v2 2/8] [PowerPC] Consolidate wordsize getter between native and gdbserver Pedro Franco de Carvalho
                     ` (5 subsequent siblings)
  7 siblings, 1 reply; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-21 20:46 UTC (permalink / raw)
  To: gdb-patches; +Cc: uweigand

This patch defines constants for the sizes of the two vector
regsets (vector-scalar registers and regular vector registers).

The native, gdbserver and core file targets are changed to use these
constants.

The Linux ptrace calls return (or read) a smaller regset than the one
found in core files for vector registers, because ptrace uses a single
4-byte quantity for vrsave at the end of the regset, while the
core-file regset uses a full 16-byte field for vrsave. For simplicity,
the larger size is used in both cases, and so a buffer with 12 unused
additional bytes is passed to ptrace in the native target.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* arch/ppc-linux-common.h (PPC_LINUX_SIZEOF_VRREGSET)
	(PPC_LINUX_SIZEOF_VSXREGSET): Define.
	* ppc-linux-nat.c (SIZEOF_VSXREGS, SIZEOF_VRREGS): Remove.
	(gdb_vrregset_t): Change array type size to
	PPC_LINUX_SIZEOF_VRREGSET.
	(gdb_vsxregset_t): Change array type size to
	PPC_LINUX_SIZEOF_VSXREGSET.
	* ppc-linux-tdep.c (ppc_linux_iterate_over_regset_sections):
	Change integer literals to PPC_LINUX_SIZEOF_VRREGSET and
	PPC_LINUX_SIZEOF_VSXREGSET.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* linux-ppc-low.c (SIZEOF_VSXREGS, SIZEOF_VRREGS): Remove.
	(ppc_arch_setup): Change SIZEOF_VRREGS and SIZEOF_VSXREGS to
	PPC_LINUX_SIZEOF_VRREGSET and PPC_LINUX_SIZEOF_VSXREGSET.
---
 gdb/arch/ppc-linux-common.h   | 9 +++++++++
 gdb/gdbserver/linux-ppc-low.c | 8 ++------
 gdb/ppc-linux-nat.c           | 8 ++------
 gdb/ppc-linux-tdep.c          | 6 ++++--
 4 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/gdb/arch/ppc-linux-common.h b/gdb/arch/ppc-linux-common.h
index b82adc49d2..798781cbf7 100644
--- a/gdb/arch/ppc-linux-common.h
+++ b/gdb/arch/ppc-linux-common.h
@@ -22,6 +22,15 @@
 
 struct target_desc;
 
+/* The core file VMX regset has 34 16-byte fields (32 16-byte vector
+   registers, plus two fields containing 4-byte registers, VSCR and
+   VRSAVE), while the ptrace calls return or read 33 16-byte fields
+   plus a 4-byte field for VRSAVE. For simplicity we use the longer
+   length for both cases.  */
+#define PPC_LINUX_SIZEOF_VRREGSET 544
+
+#define PPC_LINUX_SIZEOF_VSXREGSET 256
+
 /* Check if the hwcap auxv entry indicates that isa205 is supported.  */
 bool ppc_linux_has_isa205 (unsigned long hwcap);
 
diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c
index b440b0e0a7..367851836e 100644
--- a/gdb/gdbserver/linux-ppc-low.c
+++ b/gdb/gdbserver/linux-ppc-low.c
@@ -459,8 +459,6 @@ static void ppc_fill_gregset (struct regcache *regcache, void *buf)
     ppc_collect_ptrace_register (regcache, i, (char *) buf + ppc_regmap[i]);
 }
 
-#define SIZEOF_VSXREGS 32*8
-
 static void
 ppc_fill_vsxregset (struct regcache *regcache, void *buf)
 {
@@ -483,8 +481,6 @@ ppc_store_vsxregset (struct regcache *regcache, const void *buf)
     supply_register (regcache, base + i, &regset[i * 8]);
 }
 
-#define SIZEOF_VRREGS 33*16+4
-
 static void
 ppc_fill_vrregset (struct regcache *regcache, void *buf)
 {
@@ -660,10 +656,10 @@ ppc_arch_setup (void)
     switch (regset->get_request)
       {
       case PTRACE_GETVRREGS:
-	regset->size = features.altivec ? SIZEOF_VRREGS : 0;
+	regset->size = features.altivec ? PPC_LINUX_SIZEOF_VRREGSET : 0;
 	break;
       case PTRACE_GETVSXREGS:
-	regset->size = features.vsx ? SIZEOF_VSXREGS : 0;
+	regset->size = features.vsx ? PPC_LINUX_SIZEOF_VSXREGSET : 0;
 	break;
       case PTRACE_GETEVRREGS:
 	if (ppc_hwcap & PPC_FEATURE_HAS_SPE)
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index 7e96032d4c..a8f202dd33 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -174,9 +174,7 @@ struct ppc_hw_breakpoint
 */
 /* *INDENT-ON* */
 
-#define SIZEOF_VRREGS 33*16+4
-
-typedef char gdb_vrregset_t[SIZEOF_VRREGS];
+typedef char gdb_vrregset_t[PPC_LINUX_SIZEOF_VRREGSET];
 
 /* This is the layout of the POWER7 VSX registers and the way they overlap
    with the existing FPR and VMX registers.
@@ -210,9 +208,7 @@ typedef char gdb_vrregset_t[SIZEOF_VRREGS];
    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];
+typedef char gdb_vsxregset_t[PPC_LINUX_SIZEOF_VSXREGSET];
 
 /* On PPC processors that support the Signal Processing Extension
    (SPE) APU, the general-purpose registers are 64 bits long.
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 1d3b019c30..344069d752 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -557,10 +557,12 @@ ppc_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
   cb (".reg2", 264, &ppc32_linux_fpregset, NULL, cb_data);
 
   if (have_altivec)
-    cb (".reg-ppc-vmx", 544, &ppc32_linux_vrregset, "ppc Altivec", cb_data);
+    cb (".reg-ppc-vmx", PPC_LINUX_SIZEOF_VRREGSET, &ppc32_linux_vrregset,
+	"ppc Altivec", cb_data);
 
   if (have_vsx)
-    cb (".reg-ppc-vsx", 256, &ppc32_linux_vsxregset, "POWER7 VSX", cb_data);
+    cb (".reg-ppc-vsx", PPC_LINUX_SIZEOF_VSXREGSET,
+	&ppc32_linux_vsxregset, "POWER7 VSX", cb_data);
 }
 
 static void
-- 
2.13.6

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

* [PATCH v2 2/8] [PowerPC] Consolidate wordsize getter between native and gdbserver
  2018-05-21 20:46 ` [PATCH v2 1/8] [PowerPC] Consolidate linux target description selection Pedro Franco de Carvalho
  2018-05-21 20:46   ` [PATCH v2 3/8] [PowerPC] Disable regsets using zero sizes in gdbserver Pedro Franco de Carvalho
  2018-05-21 20:46   ` [PATCH v2 4/8] [PowerPC] Consolidate linux vector regset sizes Pedro Franco de Carvalho
@ 2018-05-21 20:46   ` Pedro Franco de Carvalho
  2018-05-22 12:56     ` Ulrich Weigand
  2018-05-21 23:45   ` [PATCH v2 5/8] [PowerPC] Fix access to VSCR in linux targets Pedro Franco de Carvalho
                     ` (4 subsequent siblings)
  7 siblings, 1 reply; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-21 20:46 UTC (permalink / raw)
  To: gdb-patches; +Cc: uweigand

This patch moves the native target wordsize getter for ppc linux to
nat/ so that it can be used to simplify ppc_arch_setup in
gdbserver. The ptrace call used to get MSR for this is ultimately the
same as before, but it is no longer necessary to create a temporary
regcache to call fetch_inferior_registers.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* configure.nat <linux powerpc>: Add ppc-linux.o to NATDEPFILES.
	* ppc-linux-nat.c (ppc_linux_target_wordsize): Move to
	nat/ppc-linux.c.
	(ppc_linux_nat_target::auxv_parse): Get thread id tid. Call
	ppc_linux_target_wordsize with tid.
	(ppc_linux_nat_target::read_description): Call ppc_linux_target
	wordsize with tid.
	* nat/ppc-linux.c: Include nat/gdb_ptrace.h.
	(ppc64_64bit_inferior_p): Add static and inline specifiers.
	(ppc_linux_target_wordsize): Move here from ppc-linux-nat.c. Add
	tid parameter. Remove static specifier.
	* nat/ppc-linux.h (ppc64_64bit_inferior_p): Remove declaration.
	(ppc_linux_target_wordsize): New declaration.

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* linux-ppc-low.c (ppc_arch_setup): Remove code for getting the
	wordsize of the inferior. Call ppc_linux_target_wordsize.
---
 gdb/configure.nat             |  2 +-
 gdb/gdbserver/linux-ppc-low.c | 32 ++++++--------------------------
 gdb/nat/ppc-linux.c           | 22 +++++++++++++++++++++-
 gdb/nat/ppc-linux.h           |  7 ++-----
 gdb/ppc-linux-nat.c           | 32 +++++++-------------------------
 5 files changed, 37 insertions(+), 58 deletions(-)

diff --git a/gdb/configure.nat b/gdb/configure.nat
index 6b0f44fede..bcaeaf4583 100644
--- a/gdb/configure.nat
+++ b/gdb/configure.nat
@@ -264,7 +264,7 @@ case ${gdb_host} in
 		;;
 	    powerpc)
 		# Host: PowerPC, running Linux
-		NATDEPFILES="${NATDEPFILES} ppc-linux-nat.o"
+		NATDEPFILES="${NATDEPFILES} ppc-linux-nat.o ppc-linux.o"
 		;;
 	    s390)
 		# Host: S390, running Linux
diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c
index 5361baf72a..30fcd4115a 100644
--- a/gdb/gdbserver/linux-ppc-low.c
+++ b/gdb/gdbserver/linux-ppc-low.c
@@ -620,36 +620,16 @@ ppc_arch_setup (void)
 {
   const struct target_desc *tdesc;
   struct ppc_linux_features features = ppc_linux_no_features;
+  int tid = lwpid_of (current_thread);
 
-  features.wordsize = 4;
-
-#ifdef __powerpc64__
-  long msr;
-  struct regcache *regcache;
-
-  /* On a 64-bit host, assume 64-bit inferior process with no
-     AltiVec registers.  Reset ppc_hwcap to ensure that the
-     collect_register call below does not fail.  */
-  tdesc = tdesc_powerpc_64l;
-  current_process ()->tdesc = tdesc;
-  ppc_hwcap = 0;
-
-  regcache = new_register_cache (tdesc);
-  fetch_inferior_registers (regcache, find_regno (tdesc, "msr"));
-  collect_register_by_name (regcache, "msr", &msr);
-  free_register_cache (regcache);
-  if (ppc64_64bit_inferior_p (msr))
-    {
-      features.wordsize = 8;
-    }
-#endif
+  features.wordsize = ppc_linux_target_wordsize (tid);
 
   if (features.wordsize == 4)
-    {
-      /* OK, we have a 32-bit inferior.  */
       tdesc = tdesc_powerpc_32l;
-      current_process ()->tdesc = tdesc;
-    }
+  else
+      tdesc = tdesc_powerpc_64l;
+
+  current_process ()->tdesc = tdesc;
 
   /* The value of current_process ()->tdesc needs to be set for this
      call.  */
diff --git a/gdb/nat/ppc-linux.c b/gdb/nat/ppc-linux.c
index 7ab6551316..1796ceb751 100644
--- a/gdb/nat/ppc-linux.c
+++ b/gdb/nat/ppc-linux.c
@@ -17,6 +17,7 @@
 
 #include "common-defs.h"
 #include "ppc-linux.h"
+#include "nat/gdb_ptrace.h"
 #include <elf.h>
 
 #ifdef HAVE_GETAUXVAL
@@ -53,7 +54,7 @@ ppc64_host_hwcap (unsigned long *valp)
 #endif /* HAVE_GETAUXVAL */
 }
 
-int
+static inline int
 ppc64_64bit_inferior_p (long msr)
 {
   unsigned long ppc_host_hwcap = 0;
@@ -73,3 +74,22 @@ ppc64_64bit_inferior_p (long msr)
 }
 
 #endif
+
+int
+ppc_linux_target_wordsize (int tid)
+{
+  int wordsize = 4;
+
+  /* Check for 64-bit inferior process.  This is the case when the host is
+     64-bit, and in addition the top bit of the MSR register is set.  */
+#ifdef __powerpc64__
+  long msr;
+
+  errno = 0;
+  msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0);
+  if (errno == 0 && ppc64_64bit_inferior_p (msr))
+    wordsize = 8;
+#endif
+
+  return wordsize;
+}
diff --git a/gdb/nat/ppc-linux.h b/gdb/nat/ppc-linux.h
index 76a5d181df..3d4d4fdc56 100644
--- a/gdb/nat/ppc-linux.h
+++ b/gdb/nat/ppc-linux.h
@@ -82,10 +82,7 @@
 #define PTRACE_SETEVRREGS 21
 #endif
 
-#ifdef __powerpc64__
-/* Return whether the inferior is 64bit or not by checking certain bit
-   in MSR.  */
-int ppc64_64bit_inferior_p (long msr);
-#endif
+/* Return the wordsize of the target, either 4 or 8 bytes.  */
+int ppc_linux_target_wordsize (int tid);
 
 #endif
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index e49a482c09..7e96032d4c 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -2368,35 +2368,17 @@ fill_fpregset (const struct regcache *regcache,
 			fpregsetp, sizeof (*fpregsetp));
 }
 
-static int
-ppc_linux_target_wordsize (void)
-{
-  int wordsize = 4;
-
-  /* Check for 64-bit inferior process.  This is the case when the host is
-     64-bit, and in addition the top bit of the MSR register is set.  */
-#ifdef __powerpc64__
-  long msr;
-
-  int tid = ptid_get_lwp (inferior_ptid);
-  if (tid == 0)
-    tid = ptid_get_pid (inferior_ptid);
-
-  errno = 0;
-  msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0);
-  if (errno == 0 && ppc64_64bit_inferior_p (msr))
-    wordsize = 8;
-#endif
-
-  return wordsize;
-}
-
 int
 ppc_linux_nat_target::auxv_parse (gdb_byte **readptr,
 				  gdb_byte *endptr, CORE_ADDR *typep,
 				  CORE_ADDR *valp)
 {
-  int sizeof_auxv_field = ppc_linux_target_wordsize ();
+  int tid = ptid_get_lwp (inferior_ptid);
+  if (tid == 0)
+    tid = ptid_get_pid (inferior_ptid);
+
+  int sizeof_auxv_field = ppc_linux_target_wordsize (tid);
+
   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
   gdb_byte *ptr = *readptr;
 
@@ -2437,7 +2419,7 @@ ppc_linux_nat_target::read_description ()
 
   struct ppc_linux_features features = ppc_linux_no_features;
 
-  features.wordsize = ppc_linux_target_wordsize ();
+  features.wordsize = ppc_linux_target_wordsize (tid);
 
   unsigned long hwcap = ppc_linux_get_hwcap ();
 
-- 
2.13.6

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

* [PATCH v2 5/8] [PowerPC] Fix access to VSCR in linux targets
  2018-05-21 20:46 ` [PATCH v2 1/8] [PowerPC] Consolidate linux target description selection Pedro Franco de Carvalho
                     ` (2 preceding siblings ...)
  2018-05-21 20:46   ` [PATCH v2 2/8] [PowerPC] Consolidate wordsize getter between native and gdbserver Pedro Franco de Carvalho
@ 2018-05-21 23:45   ` Pedro Franco de Carvalho
  2018-05-22 12:56     ` Ulrich Weigand
  2018-05-21 23:55   ` [PATCH v2 8/8] [PowerPC] Recognize isa205 in linux core files Pedro Franco de Carvalho
                     ` (3 subsequent siblings)
  7 siblings, 1 reply; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-21 23:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: uweigand

The 4-byte VSCR register is found inside a 16-byte field in the regset
returned by ptrace and in core files. The position of VSCR depends on
the endianess of the target, which was previously assumed to be
big-endian for the purpose of getting VSCR. This patch removes this
assumption to fix access to VSCR in little-endian mode.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

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

gdb/gdbserver/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* linux-ppc-low.c (ppc_fill_vrregset): Add vscr_offset variable.
	Set vscr_offset to 0 in little-endian mode and 12 in big-endian
	mode. Call collect_register_by_name with vscr using
	vscr_offset. Zero-pad vscr and vrsave fields in collector buffer.
	(ppc_store_vrregset): Add and set vscr_offset variable as in
	ppc_fill_vrregset. Call supply_register_by_name with vscr using
	vscr_offset.
---
 gdb/gdbserver/linux-ppc-low.c |  19 +++++-
 gdb/ppc-fbsd-tdep.c           |  16 +----
 gdb/ppc-linux-nat.c           | 153 +++++++-----------------------------------
 gdb/ppc-linux-tdep.c          |  82 +++++++++++++++++-----
 gdb/ppc-linux-tdep.h          |   3 +
 gdb/ppc-nbsd-tdep.c           |   4 --
 gdb/ppc-obsd-nat.c            |   5 --
 gdb/ppc-obsd-tdep.c           |   4 --
 gdb/ppc-tdep.h                |   5 --
 gdb/rs6000-aix-tdep.c         |  14 +---
 gdb/rs6000-tdep.c             | 110 ------------------------------
 11 files changed, 112 insertions(+), 303 deletions(-)

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

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

* [PATCH v2 8/8] [PowerPC] Recognize isa205 in linux core files
  2018-05-21 20:46 ` [PATCH v2 1/8] [PowerPC] Consolidate linux target description selection Pedro Franco de Carvalho
                     ` (3 preceding siblings ...)
  2018-05-21 23:45   ` [PATCH v2 5/8] [PowerPC] Fix access to VSCR in linux targets Pedro Franco de Carvalho
@ 2018-05-21 23:55   ` Pedro Franco de Carvalho
  2018-05-22 13:34     ` Ulrich Weigand
  2018-05-21 23:56   ` [PATCH v2 7/8] [PowerPC] Fix inclusion of dfp pseudoregs in tdep Pedro Franco de Carvalho
                     ` (2 subsequent siblings)
  7 siblings, 1 reply; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-21 23:55 UTC (permalink / raw)
  To: gdb-patches; +Cc: uweigand

Currently the ppc linux core file target doesn't return target
descriptions with the lager FPSCR introduced in isa205.

This patch changes the core file target so that the auxv is read from
the core file to determine the size of FPSCR, so that the appropriate
target description is selected.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* arch/ppc-linux-common.c (ppc_linux_has_isa205): Change the
	parameter type to CORE_ADDR.
	* arch/ppc-linux-common.h (ppc_linux_has_isa205): Change the
	parameter type in declaration to CORE_ADDR.
	* ppc-linux-tdep.c (ppc_linux_core_read_description): Call
	target_auxv_search to get AT_HWCAP and use the result to get the
	target description.
	* ppc-linux-nat.c (ppc_linux_get_hwcap): Change the return type
	to CORE_ADDR. Remove the cast of the return value to unsigned
	long. Fix error predicate of target_auxv_search.
	(ppc_linux_nat_target::read_description): Change the type of the
	hwcap variable to CORE_ADDR.

gdb/testsuite/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* gdb.arch/powerpc-fpscr-gcore.exp: New file.
---
 gdb/arch/ppc-linux-common.c                    |  2 +-
 gdb/arch/ppc-linux-common.h                    |  2 +-
 gdb/ppc-linux-nat.c                            | 10 +--
 gdb/ppc-linux-tdep.c                           |  7 ++
 gdb/testsuite/gdb.arch/powerpc-fpscr-gcore.exp | 93 ++++++++++++++++++++++++++
 5 files changed, 107 insertions(+), 7 deletions(-)
 create mode 100644 gdb/testsuite/gdb.arch/powerpc-fpscr-gcore.exp

diff --git a/gdb/arch/ppc-linux-common.c b/gdb/arch/ppc-linux-common.c
index 87ccc42cae..45da105de6 100644
--- a/gdb/arch/ppc-linux-common.c
+++ b/gdb/arch/ppc-linux-common.c
@@ -31,7 +31,7 @@
 #endif
 
 bool
-ppc_linux_has_isa205 (unsigned long hwcap)
+ppc_linux_has_isa205 (CORE_ADDR hwcap)
 {
   /* Power ISA 2.05 (implemented by Power 6 and newer processors)
      increases the FPSCR from 32 bits to 64 bits.  Even though Power 7
diff --git a/gdb/arch/ppc-linux-common.h b/gdb/arch/ppc-linux-common.h
index 798781cbf7..2f535e801d 100644
--- a/gdb/arch/ppc-linux-common.h
+++ b/gdb/arch/ppc-linux-common.h
@@ -32,7 +32,7 @@ struct target_desc;
 #define PPC_LINUX_SIZEOF_VSXREGSET 256
 
 /* Check if the hwcap auxv entry indicates that isa205 is supported.  */
-bool ppc_linux_has_isa205 (unsigned long hwcap);
+bool ppc_linux_has_isa205 (CORE_ADDR hwcap);
 
 /* Features used to determine the target description.  */
 struct ppc_linux_features
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index 0f7dd4c8e2..eb21f91c13 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -1165,15 +1165,15 @@ store_ppc_registers (const struct regcache *regcache, int tid)
 }
 
 /* Fetch the AT_HWCAP entry from the aux vector.  */
-static unsigned long
+static CORE_ADDR
 ppc_linux_get_hwcap (void)
 {
   CORE_ADDR field;
 
-  if (target_auxv_search (target_stack, AT_HWCAP, &field))
-    return (unsigned long) field;
+  if (target_auxv_search (target_stack, AT_HWCAP, &field) != 1)
+    return 0;
 
-  return 0;
+  return field;
 }
 
 /* The cached DABR value, to install in new threads.
@@ -2236,7 +2236,7 @@ ppc_linux_nat_target::read_description ()
 
   features.wordsize = ppc_linux_target_wordsize (tid);
 
-  unsigned long hwcap = ppc_linux_get_hwcap ();
+  CORE_ADDR hwcap = ppc_linux_get_hwcap ();
 
   if (have_ptrace_getsetvsxregs
       && (hwcap & PPC_FEATURE_HAS_VSX))
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 293353a878..5716f82810 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -1058,6 +1058,13 @@ ppc_linux_core_read_description (struct gdbarch *gdbarch,
   if (vsx)
     features.vsx = true;
 
+  CORE_ADDR hwcap;
+
+  if (target_auxv_search (target, AT_HWCAP, &hwcap) != 1)
+    hwcap = 0;
+
+  features.isa205 = ppc_linux_has_isa205 (hwcap);
+
   return ppc_linux_match_description (features);
 }
 
diff --git a/gdb/testsuite/gdb.arch/powerpc-fpscr-gcore.exp b/gdb/testsuite/gdb.arch/powerpc-fpscr-gcore.exp
new file mode 100644
index 0000000000..d5db5320b6
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/powerpc-fpscr-gcore.exp
@@ -0,0 +1,93 @@
+# Copyright (C) 2018 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the gdb testsuite.
+
+# This tests checks that generating and loading a core file preserves
+# the correct FPSCR size.
+
+if {![istarget "powerpc*-*-linux*"]} then {
+    verbose "Skipping PowerPC test for corefiles with FPSCR."
+    return
+}
+
+standard_testfile .c
+
+set gen_src [standard_output_file $srcfile]
+
+gdb_produce_source $gen_src {
+	int main() {
+	    return 0;
+	}
+}
+
+if {[build_executable "compile" $binfile $gen_src] == -1} {
+    return -1
+}
+
+clean_restart $binfile
+
+if ![runto_main] then {
+    fail "could not run to main"
+    return -1
+}
+
+# Check if our target has FPSCR
+proc check_fpscr_access {} {
+    global gdb_prompt
+
+    set test "fpscr register access"
+    gdb_test_multiple "info reg fpscr" "$test" {
+	-re "Invalid register.*\r\n$gdb_prompt $" {
+	    unsupported "$test"
+	    return 0
+	}
+	-re "\r\nfpscr.*\r\n$gdb_prompt $" {
+	    pass "$test"
+	    return 1
+	}
+    }
+    return 0
+}
+
+if { ![check_fpscr_access] } {
+    return -1
+}
+
+set fpscr_size_process [get_integer_valueof "sizeof(\$fpscr)" -1]
+
+set core_filename [standard_output_file "$testfile.core"]
+set core_generated [gdb_gcore_cmd "$core_filename" "generate core file"]
+
+if { !$core_generated } {
+    return -1
+}
+
+clean_restart
+
+set core_loaded [gdb_core_cmd "$core_filename" "load core file"]
+
+if { $core_loaded != 1 } {
+    return -1
+}
+
+set fpscr_size_corefile [get_integer_valueof "sizeof(\$fpscr)" -2]
+
+set test "fpscr size matches"
+if {$fpscr_size_process == $fpscr_size_corefile} {
+    pass $test
+} else {
+    fail $test
+}
-- 
2.13.6

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

* [PATCH v2 7/8] [PowerPC] Fix inclusion of dfp pseudoregs in tdep
  2018-05-21 20:46 ` [PATCH v2 1/8] [PowerPC] Consolidate linux target description selection Pedro Franco de Carvalho
                     ` (4 preceding siblings ...)
  2018-05-21 23:55   ` [PATCH v2 8/8] [PowerPC] Recognize isa205 in linux core files Pedro Franco de Carvalho
@ 2018-05-21 23:56   ` Pedro Franco de Carvalho
  2018-05-22 12:56     ` Ulrich Weigand
  2018-05-22  0:54   ` [PATCH v2 6/8] [PowerPC] Fix VSX registers in linux core files Pedro Franco de Carvalho
  2018-05-22 12:48   ` [PATCH v2 1/8] [PowerPC] Consolidate linux target description selection Ulrich Weigand
  7 siblings, 1 reply; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-21 23:56 UTC (permalink / raw)
  To: gdb-patches; +Cc: uweigand

Previously, decimal floating point pseudoregisters were always included
in the target if it had a floating point unit.

This patch changes this to only include them if the target description
indicates that they are present, i.e. if the FPSCR register has more
than 32 bits.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* rs6000-tdep.c (rs6000_gdbarch_init): Assign 1 to have_dfp only
	if the size of fpscr is larger than 32 bits.
---
 gdb/rs6000-tdep.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index 0a56c7890a..ff4699c191 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -5981,14 +5981,16 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 	      return NULL;
 	    }
 	  have_fpu = 1;
+
+	  /* The fpscr register was expanded in isa 2.05 to 64 bits
+	     along with the addition of the decimal floating point
+	     facility.  */
+	  if (tdesc_register_size (feature, "fpscr") > 32)
+	    have_dfp = 1;
 	}
       else
 	have_fpu = 0;
 
-      /* The DFP pseudo-registers will be available when there are floating
-         point registers.  */
-      have_dfp = have_fpu;
-
       feature = tdesc_find_feature (tdesc,
 				    "org.gnu.gdb.power.altivec");
       if (feature != NULL)
-- 
2.13.6

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

* [PATCH v2 6/8] [PowerPC] Fix VSX registers in linux core files
  2018-05-21 20:46 ` [PATCH v2 1/8] [PowerPC] Consolidate linux target description selection Pedro Franco de Carvalho
                     ` (5 preceding siblings ...)
  2018-05-21 23:56   ` [PATCH v2 7/8] [PowerPC] Fix inclusion of dfp pseudoregs in tdep Pedro Franco de Carvalho
@ 2018-05-22  0:54   ` Pedro Franco de Carvalho
  2018-05-22 13:46     ` Ulrich Weigand
  2018-05-22 12:48   ` [PATCH v2 1/8] [PowerPC] Consolidate linux target description selection Ulrich Weigand
  7 siblings, 1 reply; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-22  0:54 UTC (permalink / raw)
  To: gdb-patches; +Cc: uweigand

The functions used by the VSX regset to collect and supply registers
from core files where incorrect. This patch changes the regset to use
the standard regset collect/supply functions to fix this. The native
target is also changed to use the same regset.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* ppc-linux-tdep.c (ppc_linux_vsxregset): New function.
	(ppc32_linux_vsxregmap): New global.
	(ppc32_linux_vsxregset): Initialize with ppc32_linux_vsxregmap,
	regcache_supply_regset, and regcache_collect_regset.
	* ppc-linux-tdep.h (ppc_linux_vsxregset): Declare.
	* ppc-linux-nat.c (supply_vsxregset, fill_vsxregset): Remove.
	(fetch_vsx_register, store_vsx_register): Remove.
	(fetch_vsx_registers): Add regno parameter. Get regset using
	ppc_linux_vsxregset. Use regset to supply registers.
	(store_vsx_registers): Add regno parameter. Get regset using
	ppc_linux_vsxregset. Use regset to collect registers.
	(fetch_register): Call fetch_vsx_registers instead of
	fetch_vsx_register.
	(store_register): Call store_vsx_registers instead of
	store_vsx_register.
	(fetch_ppc_registers): Call fetch_vsx_registers with -1 for the
	new regno parameter.
	(store_ppc_registers): Call store_vsx_registers with -1 for the
	new regno parameter.
	* rs6000-tdep.c (ppc_vsx_support_p, ppc_supply_vsxreget)
	(ppc_collect_vsxregset): Remove.

gdb/testsuite/ChangeLog:
yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>

	* gdb.arch/powerpc-vsx-gcore.exp: New file.
---
 gdb/ppc-linux-nat.c                          | 106 ++++-----------------------
 gdb/ppc-linux-tdep.c                         |  18 ++++-
 gdb/ppc-linux-tdep.h                         |   1 +
 gdb/rs6000-tdep.c                            |  74 -------------------
 gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp |  90 +++++++++++++++++++++++
 5 files changed, 121 insertions(+), 168 deletions(-)
 create mode 100644 gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp

diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index e00831a248..0f7dd4c8e2 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -409,13 +409,11 @@ ppc_register_u_addr (struct gdbarch *gdbarch, int regno)
    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)
+fetch_vsx_registers (struct regcache *regcache, int tid, int regno)
 {
   int ret;
   gdb_vsxregset_t regs;
-  struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum);
+  const struct regset *vsxregset = ppc_linux_vsxregset ();
 
   ret = ptrace (PTRACE_GETVSXREGS, tid, 0, &regs);
   if (ret < 0)
@@ -425,12 +423,11 @@ fetch_vsx_register (struct regcache *regcache, int tid, int regno)
 	  have_ptrace_getsetvsxregs = 0;
 	  return;
 	}
-      perror_with_name (_("Unable to fetch VSX register"));
+      perror_with_name (_("Unable to fetch VSX registers"));
     }
 
-  regcache_raw_supply (regcache, regno,
-		       regs + (regno - tdep->ppc_vsr0_upper_regnum)
-		       * vsxregsize);
+  vsxregset->supply_regset (vsxregset, regcache, regno, &regs,
+			    PPC_LINUX_SIZEOF_VSXREGSET);
 }
 
 /* The Linux kernel ptrace interface for AltiVec registers uses the
@@ -563,7 +560,7 @@ fetch_register (struct regcache *regcache, int tid, int regno)
     {
       if (have_ptrace_getsetvsxregs)
 	{
-	  fetch_vsx_register (regcache, tid, regno);
+	  fetch_vsx_registers (regcache, tid, regno);
 	  return;
 	}
     }
@@ -624,40 +621,6 @@ fetch_register (struct regcache *regcache, int tid, int regno)
                     gdbarch_byte_order (gdbarch));
 }
 
-static void
-supply_vsxregset (struct regcache *regcache, gdb_vsxregset_t *vsxregsetp)
-{
-  int i;
-  struct gdbarch *gdbarch = regcache->arch ();
-  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
-fetch_vsx_registers (struct regcache *regcache, int tid)
-{
-  int ret;
-  gdb_vsxregset_t regs;
-
-  ret = ptrace (PTRACE_GETVSXREGS, tid, 0, &regs);
-  if (ret < 0)
-    {
-      if (errno == EIO)
-	{
-	  have_ptrace_getsetvsxregs = 0;
-	  return;
-	}
-      perror_with_name (_("Unable to fetch VSX registers"));
-    }
-  supply_vsxregset (regcache, &regs);
-}
-
 /* This function actually issues the request to ptrace, telling
    it to get all general-purpose registers and put them into the
    specified regset.
@@ -799,7 +762,7 @@ fetch_ppc_registers (struct regcache *regcache, int tid)
       fetch_altivec_registers (regcache, tid, -1);
   if (have_ptrace_getsetvsxregs)
     if (tdep->ppc_vsr0_upper_regnum != -1)
-      fetch_vsx_registers (regcache, tid);
+      fetch_vsx_registers (regcache, tid, -1);
   if (tdep->ppc_ev0_upper_regnum >= 0)
     fetch_spe_register (regcache, tid, -1);
 }
@@ -818,15 +781,12 @@ ppc_linux_nat_target::fetch_registers (struct regcache *regcache, int regno)
     fetch_register (regcache, tid, regno);
 }
 
-/* Store one VSX register.  */
 static void
-store_vsx_register (const struct regcache *regcache, int tid, int regno)
+store_vsx_registers (const struct regcache *regcache, int tid, int regno)
 {
   int ret;
   gdb_vsxregset_t regs;
-  struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum);
+  const struct regset *vsxregset = ppc_linux_vsxregset ();
 
   ret = ptrace (PTRACE_GETVSXREGS, tid, 0, &regs);
   if (ret < 0)
@@ -836,15 +796,15 @@ store_vsx_register (const struct regcache *regcache, int tid, int regno)
 	  have_ptrace_getsetvsxregs = 0;
 	  return;
 	}
-      perror_with_name (_("Unable to fetch VSX register"));
+      perror_with_name (_("Unable to fetch VSX registers"));
     }
 
-  regcache_raw_collect (regcache, regno, regs +
-			(regno - tdep->ppc_vsr0_upper_regnum) * vsxregsize);
+  vsxregset->collect_regset (vsxregset, regcache, regno, &regs,
+			     PPC_LINUX_SIZEOF_VSXREGSET);
 
   ret = ptrace (PTRACE_SETVSXREGS, tid, 0, &regs);
   if (ret < 0)
-    perror_with_name (_("Unable to store VSX register"));
+    perror_with_name (_("Unable to store VSX registers"));
 }
 
 static void
@@ -980,7 +940,7 @@ store_register (const struct regcache *regcache, int tid, int regno)
     }
   if (vsx_register_p (gdbarch, regno))
     {
-      store_vsx_register (regcache, tid, regno);
+      store_vsx_registers (regcache, tid, regno);
       return;
     }
   else if (spe_register_p (gdbarch, regno))
@@ -1038,42 +998,6 @@ store_register (const struct regcache *regcache, int tid, int regno)
     }
 }
 
-static void
-fill_vsxregset (const struct regcache *regcache, gdb_vsxregset_t *vsxregsetp)
-{
-  int i;
-  struct gdbarch *gdbarch = regcache->arch ();
-  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
-store_vsx_registers (const struct regcache *regcache, int tid)
-{
-  int ret;
-  gdb_vsxregset_t regs;
-
-  ret = ptrace (PTRACE_GETVSXREGS, tid, 0, &regs);
-  if (ret < 0)
-    {
-      if (errno == EIO)
-	{
-	  have_ptrace_getsetvsxregs = 0;
-	  return;
-	}
-      perror_with_name (_("Couldn't get VSX registers"));
-    }
-
-  fill_vsxregset (regcache, &regs);
-
-  if (ptrace (PTRACE_SETVSXREGS, tid, 0, &regs) < 0)
-    perror_with_name (_("Couldn't write VSX registers"));
-}
-
 /* This function actually issues the request to ptrace, telling
    it to store all general-purpose registers present in the specified
    regset.
@@ -1235,7 +1159,7 @@ store_ppc_registers (const struct regcache *regcache, int tid)
       store_altivec_registers (regcache, tid, -1);
   if (have_ptrace_getsetvsxregs)
     if (tdep->ppc_vsr0_upper_regnum != -1)
-      store_vsx_registers (regcache, tid);
+      store_vsx_registers (regcache, tid, -1);
   if (tdep->ppc_ev0_upper_regnum >= 0)
     store_spe_register (regcache, tid, -1);
 }
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 7362c4bbe1..293353a878 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -553,10 +553,16 @@ static const struct regset ppc32_be_linux_vrregset = {
   ppc_linux_collect_vrregset
 };
 
+static const struct regcache_map_entry ppc32_linux_vsxregmap[] =
+  {
+      { 32, PPC_VSR0_UPPER_REGNUM, 8 },
+      { 0 }
+  };
+
 static const struct regset ppc32_linux_vsxregset = {
-  &ppc32_linux_reg_offsets,
-  ppc_supply_vsxregset,
-  ppc_collect_vsxregset
+  ppc32_linux_vsxregmap,
+  regcache_supply_regset,
+  regcache_collect_regset
 };
 
 const struct regset *
@@ -580,6 +586,12 @@ ppc_linux_vrregset (struct gdbarch *gdbarch)
     return &ppc32_le_linux_vrregset;
 }
 
+const struct regset *
+ppc_linux_vsxregset (void)
+{
+  return &ppc32_linux_vsxregset;
+}
+
 /* Iterate over supported core file register note sections. */
 
 static void
diff --git a/gdb/ppc-linux-tdep.h b/gdb/ppc-linux-tdep.h
index a8715bd418..51f4b506a1 100644
--- a/gdb/ppc-linux-tdep.h
+++ b/gdb/ppc-linux-tdep.h
@@ -30,6 +30,7 @@ const struct regset *ppc_linux_fpregset (void);
 
 /* Get the vector regset that matches the target byte order.  */
 const struct regset *ppc_linux_vrregset (struct gdbarch *gdbarch);
+const struct regset *ppc_linux_vsxregset (void);
 
 /* Extra register number constants.  The Linux kernel stores a
    "trap" code and the original value of r3 into special "registers";
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index 4ef6f9e980..0a56c7890a 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -224,16 +224,6 @@ ppc_floating_point_unit_p (struct gdbarch *gdbarch)
 }
 
 /* Return non-zero if the architecture described by GDBARCH has
-   VSX registers (vsr0 --- vsr63).  */
-static int
-ppc_vsx_support_p (struct gdbarch *gdbarch)
-{
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-
-  return tdep->ppc_vsr0_regnum >= 0;
-}
-
-/* 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)
@@ -573,37 +563,6 @@ ppc_supply_fpregset (const struct regset *regset, struct regcache *regcache,
 		  regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8);
 }
 
-/* Supply register REGNUM in the VSX register set REGSET
-   from the buffer specified by VSXREGS and LEN to register cache
-   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
-
-void
-ppc_supply_vsxregset (const struct regset *regset, struct regcache *regcache,
-		     int regnum, const void *vsxregs, size_t len)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep;
-
-  if (!ppc_vsx_support_p (gdbarch))
-    return;
-
-  tdep = gdbarch_tdep (gdbarch);
-
-  if (regnum == -1)
-    {
-      int i;
-
-      for (i = tdep->ppc_vsr0_upper_regnum;
-	   i < tdep->ppc_vsr0_upper_regnum + 32;
-	   i++)
-	ppc_supply_reg (regcache, i, (const gdb_byte *) vsxregs, 0, 8);
-
-      return;
-    }
-  else
-    ppc_supply_reg (regcache, regnum, (const gdb_byte *) vsxregs, 0, 8);
-}
-
 /* 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
@@ -695,39 +654,6 @@ ppc_collect_fpregset (const struct regset *regset,
 		   regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8);
 }
 
-/* Collect register REGNUM in the VSX register set
-   REGSET from register cache REGCACHE into the buffer specified by
-   VSXREGS and LEN.  If REGNUM is -1, do this for all registers in
-   REGSET.  */
-
-void
-ppc_collect_vsxregset (const struct regset *regset,
-		      const struct regcache *regcache,
-		      int regnum, void *vsxregs, size_t len)
-{
-  struct gdbarch *gdbarch = regcache->arch ();
-  struct gdbarch_tdep *tdep;
-
-  if (!ppc_vsx_support_p (gdbarch))
-    return;
-
-  tdep = gdbarch_tdep (gdbarch);
-
-  if (regnum == -1)
-    {
-      int i;
-
-      for (i = tdep->ppc_vsr0_upper_regnum;
-	   i < tdep->ppc_vsr0_upper_regnum + 32;
-	   i++)
-	ppc_collect_reg (regcache, i, (gdb_byte *) vsxregs, 0, 8);
-
-      return;
-    }
-  else
-    ppc_collect_reg (regcache, regnum, (gdb_byte *) vsxregs, 0, 8);
-}
-
 static int
 insn_changes_sp_or_jumps (unsigned long insn)
 {
diff --git a/gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp b/gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp
new file mode 100644
index 0000000000..e9bdfcdd44
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp
@@ -0,0 +1,90 @@
+# Copyright (C) 2018 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the gdb testsuite.
+
+# This test checks that generating and loading a core file preserves
+# the correct VSX register state.
+
+if {![istarget "powerpc*-*-linux*"] || [skip_vsx_tests]} then {
+    verbose "Skipping PowerPC test for corefiles with VSX registers."
+    return
+}
+
+standard_testfile .c
+
+set gen_src [standard_output_file $srcfile]
+
+gdb_produce_source $gen_src {
+	int main() {
+	    return 0;
+	}
+}
+
+if {[build_executable "compile" $binfile $gen_src] == -1} {
+    return -1
+}
+
+clean_restart $binfile
+
+if ![runto_main] then {
+    fail "could not run to main"
+    return -1
+}
+
+# Check if VSX register access through gdb is supported
+proc check_vsx_access {} {
+    global gdb_prompt
+
+    set test "vsx register access"
+    gdb_test_multiple "info reg vs0" "$test" {
+	-re "Invalid register.*\r\n$gdb_prompt $" {
+	    unsupported "$test"
+	    return 0
+	}
+	-re "\r\nvs0.*\r\n$gdb_prompt $" {
+	    pass "$test"
+	    return 1
+	}
+    }
+    return 0
+}
+
+if { ![check_vsx_access] } {
+    return -1
+}
+
+for {set i 0} {$i < 64} {incr i 1} {
+    gdb_test_no_output "set \$vs$i.uint128 = $i"
+}
+
+set core_filename [standard_output_file "$testfile.core"]
+set core_generated [gdb_gcore_cmd "$core_filename" "generate core file"]
+
+if { !$core_generated } {
+    return -1
+}
+
+clean_restart
+
+set core_loaded [gdb_core_cmd "$core_filename" "load core file"]
+
+if { $core_loaded != 1 } {
+    return -1
+}
+
+for {set i 0} {$i < 64} {incr i 1} {
+    gdb_test "print \$vs$i.uint128" ".* = $i" "print vs$i"
+}
-- 
2.13.6

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

* Re: [PATCH v2 3/8] [PowerPC] Disable regsets using zero sizes in gdbserver
  2018-05-21 20:46   ` [PATCH v2 3/8] [PowerPC] Disable regsets using zero sizes in gdbserver Pedro Franco de Carvalho
@ 2018-05-22 12:48     ` Ulrich Weigand
  0 siblings, 0 replies; 44+ messages in thread
From: Ulrich Weigand @ 2018-05-22 12:48 UTC (permalink / raw)
  To: Pedro Franco de Carvalho; +Cc: gdb-patches

Pedro Franco de Carvalho wrote:

> gdb/gdbserver/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* linux-ppc-low.c (ppc_fill_vsxregset): Remove ppc_hwcap check.
> 	(ppc_store_vsxregset): Likewise.
> 	(ppc_fill_vrregset): Likewise.
> 	(ppc_store_vrregset): Likewise.
> 	(ppc_fill_evrregset): Likewise.
> 	(ppc_store_evrregset): Likewise.
> 	(ppc_regsets): Set VSX/VR/EVR regset sizes to 0.
> 	(ppc_arch_setup): Iterate through ppc_regsets and set sizes when
> 	needed.

This is OK.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH v2 4/8] [PowerPC] Consolidate linux vector regset sizes
  2018-05-21 20:46   ` [PATCH v2 4/8] [PowerPC] Consolidate linux vector regset sizes Pedro Franco de Carvalho
@ 2018-05-22 12:48     ` Ulrich Weigand
  0 siblings, 0 replies; 44+ messages in thread
From: Ulrich Weigand @ 2018-05-22 12:48 UTC (permalink / raw)
  To: Pedro Franco de Carvalho; +Cc: gdb-patches

Pedro Franco de Carvalho wrote:

> gdb/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* arch/ppc-linux-common.h (PPC_LINUX_SIZEOF_VRREGSET)
> 	(PPC_LINUX_SIZEOF_VSXREGSET): Define.
> 	* ppc-linux-nat.c (SIZEOF_VSXREGS, SIZEOF_VRREGS): Remove.
> 	(gdb_vrregset_t): Change array type size to
> 	PPC_LINUX_SIZEOF_VRREGSET.
> 	(gdb_vsxregset_t): Change array type size to
> 	PPC_LINUX_SIZEOF_VSXREGSET.
> 	* ppc-linux-tdep.c (ppc_linux_iterate_over_regset_sections):
> 	Change integer literals to PPC_LINUX_SIZEOF_VRREGSET and
> 	PPC_LINUX_SIZEOF_VSXREGSET.
> 
> gdb/gdbserver/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* linux-ppc-low.c (SIZEOF_VSXREGS, SIZEOF_VRREGS): Remove.
> 	(ppc_arch_setup): Change SIZEOF_VRREGS and SIZEOF_VSXREGS to
> 	PPC_LINUX_SIZEOF_VRREGSET and PPC_LINUX_SIZEOF_VSXREGSET.

This is OK.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH v2 1/8] [PowerPC] Consolidate linux target description selection
  2018-05-21 20:46 ` [PATCH v2 1/8] [PowerPC] Consolidate linux target description selection Pedro Franco de Carvalho
                     ` (6 preceding siblings ...)
  2018-05-22  0:54   ` [PATCH v2 6/8] [PowerPC] Fix VSX registers in linux core files Pedro Franco de Carvalho
@ 2018-05-22 12:48   ` Ulrich Weigand
  7 siblings, 0 replies; 44+ messages in thread
From: Ulrich Weigand @ 2018-05-22 12:48 UTC (permalink / raw)
  To: Pedro Franco de Carvalho; +Cc: gdb-patches

Pedro Franco de Carvalho wrote:

> gdb/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* arch/ppc-linux-common.c: New file.
> 	* arch/ppc-linux-common.h: New file.
> 	* arch/ppc-linux-tdesc.h: New file.
> 	* configure.tgt (powerpc*-*-linux*): Add arch/ppc-linux-common.o.
> 	* Makefile.in (ALL_TARGET_OBS): Add arch/ppc-linux-common.o.
> 	(HFILES_NO_SRCDIR): Add arch/ppc-linux-common.h and
> 	arch/ppc-linux-tdesc.h.
> 	* ppc-linux-nat.c: Include arch/ppc-linux-common.h and
> 	arch/ppc-linux-tdesc.h.
> 	(ppc_linux_nat_target::read_description): Remove target
> 	description matching code. Fill a ppc_linux_features struct and
> 	call ppc_linux_match_description with it. Move comment about ISA
> 	2.05 to ppc-linux-common.c.
> 	* ppc-linux-tdep.c: Include arch/ppc-linux-common.h and
> 	arch/ppc-linux-tdesc.h.
> 	(ppc_linux_core_read_description): Remove target description
> 	matching code. Fill a ppc_linux_features struct and call
> 	ppc_linux_match_description with it.
> 	* ppc-linux-tdep.h (tdesc_powerpc_32l, tdesc_powerpc_64l)
> 	(tdesc_powerpc_altivec32l, tdesc_powerpc_altivec64l)
> 	(tdesc_powerpc_cell32l, tdesc_powerpc_cell64l)
> 	(tdesc_powerpc_vsx32l, tdesc_powerpc_vsx64l)
> 	(tdesc_powerpc_isa205_32l, tdesc_powerpc_isa205_64l)
> 	(tdesc_powerpc_isa205_altivec32l, tdesc_powerpc_isa205_altivec64l)
> 	(tdesc_powerpc_isa205_vsx32l, tdesc_powerpc_isa205_vsx64l)
> 	(tdesc_powerpc_e500l): Remove.
> 
> gdb/gdbserver/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* configure.srv (srv_tgtobj): Add arch/ppc-linux-common.o.
> 	* Makefile.in (SFILES): Add arch/ppc-linux-common.c.
> 	* linux-ppc-tdesc.h: Rename to linux-ppc-tdesc-init.h.
> 	* linux-ppc-tdesc-init.h (tdesc_powerpc_32l, tdesc_powerpc_64l)
> 	(tdesc_powerpc_altivec32l, tdesc_powerpc_altivec64l)
> 	(tdesc_powerpc_cell32l, tdesc_powerpc_cell64l)
> 	(tdesc_powerpc_vsx32l, tdesc_powerpc_vsx64l)
> 	(tdesc_powerpc_isa205_32l, tdesc_powerpc_isa205_64l)
> 	(tdesc_powerpc_isa205_altivec32l, tdesc_powerpc_isa205_altivec64l)
> 	(tdesc_powerpc_isa205_vsx32l, tdesc_powerpc_isa205_vsx64l)
> 	(tdesc_powerpc_e500l): Remove.
> 	* linux-ppc-ipa.c: Include arch/ppc-linux-tdesc.h and
> 	linux-ppc-tdesc-init.h. Don't include linux-ppc-tdesc.h.
> 	* linux-ppc-low.c: Include arch/ppc-linux-common.h,
> 	arch/ppc-linux-tdesc.h, and linux-ppc-tdesc-init.h. Don't include
> 	linux-ppc-tdesc.h.
> 	(ppc_arch_setup): Remove target description matching code. Fill a
> 	ppc_linux_features struct and call ppc_linux_match_description
> 	with it.

This is OK.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH 8/8] [PowerPC] Recognize isa205 in linux core files
  2018-05-21 20:46         ` Pedro Franco de Carvalho
@ 2018-05-22 12:48           ` Ulrich Weigand
  2018-05-22 14:33             ` Pedro Franco de Carvalho
  0 siblings, 1 reply; 44+ messages in thread
From: Ulrich Weigand @ 2018-05-22 12:48 UTC (permalink / raw)
  To: Pedro Franco de Carvalho; +Cc: gdb-patches

Pedro Franco de Carvalho wrote:

> Now I'm confused as to which target should be passed to
> target_auxv_search. It uses the target parameter for reading the auxv
> data but then it calls target_auxv_parse through the global
> target_stack.

Right, this is all a bit confused right now and really ought
to be cleaned up ...  That's something for the future, though.

> Should ppc-linux-tdep also also pass target_stack in
> core_read_description, for consistency?
> 
> Or should ppc-linux-nat be changed to pass "this"? I can do this either
> by moving ppc_linux_get_hwcap to ppc-linux-tdep.c and adding a target
> parameter, and then change all the call sites in ppc-linux-nat.c, or I
> can make ppc_linux_get_hwcap a private method of ppc_linux_nat_target
> and pass "this" inside it (which wouldn't require changing the call
> sites), and leave the bare call to target_auxv_search in
> ppc-linux-tdep.c.

The latter makes more sense to me.  Sooner or later, we want to
eliminate most uses of target_stack anyway, so if we are already
within target code, that target should be passed to subroutine
calls wherever appropriate.

> I haven't changed this in v2 yet. I did change how an error is checked
> and handled to make it more explicit.

Yes, that looks fine for now.

> And it turns out that target_auxv_search already caches the whole auxv
> for each inferior. This part could still be improved because
> ppc_linux_nat_target::auxv_parse calls ppc_linux_target_wordsize (which
> issues a ptrace call) a second time, and at the point were it is
> called the wordsize is already known, but it's not clear how to pass the
> wordsize to auxv_parse in read_description.

Probably the best solution longer term would be to cache the parameters
describing the auxv vector (size of the key, size of the data, byte order)
in struct auxv_data, have them determined once per inferior and then
re-used.  This would also allow removing most of the near-duplicate
auxv_parse overloads ...

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH v2 2/8] [PowerPC] Consolidate wordsize getter between native and gdbserver
  2018-05-21 20:46   ` [PATCH v2 2/8] [PowerPC] Consolidate wordsize getter between native and gdbserver Pedro Franco de Carvalho
@ 2018-05-22 12:56     ` Ulrich Weigand
  0 siblings, 0 replies; 44+ messages in thread
From: Ulrich Weigand @ 2018-05-22 12:56 UTC (permalink / raw)
  To: Pedro Franco de Carvalho; +Cc: gdb-patches

Pedro Franco de Carvalho wrote:

> gdb/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* configure.nat <linux powerpc>: Add ppc-linux.o to NATDEPFILES.
> 	* ppc-linux-nat.c (ppc_linux_target_wordsize): Move to
> 	nat/ppc-linux.c.
> 	(ppc_linux_nat_target::auxv_parse): Get thread id tid. Call
> 	ppc_linux_target_wordsize with tid.
> 	(ppc_linux_nat_target::read_description): Call ppc_linux_target
> 	wordsize with tid.
> 	* nat/ppc-linux.c: Include nat/gdb_ptrace.h.
> 	(ppc64_64bit_inferior_p): Add static and inline specifiers.
> 	(ppc_linux_target_wordsize): Move here from ppc-linux-nat.c. Add
> 	tid parameter. Remove static specifier.
> 	* nat/ppc-linux.h (ppc64_64bit_inferior_p): Remove declaration.
> 	(ppc_linux_target_wordsize): New declaration.
> 
> gdb/gdbserver/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* linux-ppc-low.c (ppc_arch_setup): Remove code for getting the
> 	wordsize of the inferior. Call ppc_linux_target_wordsize.

This is OK.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH v2 7/8] [PowerPC] Fix inclusion of dfp pseudoregs in tdep
  2018-05-21 23:56   ` [PATCH v2 7/8] [PowerPC] Fix inclusion of dfp pseudoregs in tdep Pedro Franco de Carvalho
@ 2018-05-22 12:56     ` Ulrich Weigand
  0 siblings, 0 replies; 44+ messages in thread
From: Ulrich Weigand @ 2018-05-22 12:56 UTC (permalink / raw)
  To: Pedro Franco de Carvalho; +Cc: gdb-patches

Pedro Franco de Carvalho wrote:

> gdb/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* rs6000-tdep.c (rs6000_gdbarch_init): Assign 1 to have_dfp only
> 	if the size of fpscr is larger than 32 bits.

This is OK.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH 5/8] [PowerPC] Fix access to VSCR in linux targets
  2018-05-21 20:46     ` Pedro Franco de Carvalho
@ 2018-05-22 12:56       ` Ulrich Weigand
  0 siblings, 0 replies; 44+ messages in thread
From: Ulrich Weigand @ 2018-05-22 12:56 UTC (permalink / raw)
  To: Pedro Franco de Carvalho; +Cc: gdb-patches

Pedro Franco de Carvalho wrote:
> Ulrich Weigand <uweigand@de.ibm.com> writes:
> 
> > This removes all users of ppc_supply_vrregset / ppc_collect_vrregset,
> > right?  Then those functions should go away as well, together with
> > all their associates data, in particular the v*_offset fields in
> > struct ppc_reg_offsets ...
> 
> In v2 I removed these. I did have to alter the ppc bsd and aix targets,
> but I did not test these. The .tdep files were compiled (with
> --enable-targets=all), but there is one native openbsd file that was
> also altered.

This looks good to me.  Thanks for the rework!

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH v2 5/8] [PowerPC] Fix access to VSCR in linux targets
  2018-05-21 23:45   ` [PATCH v2 5/8] [PowerPC] Fix access to VSCR in linux targets Pedro Franco de Carvalho
@ 2018-05-22 12:56     ` Ulrich Weigand
  0 siblings, 0 replies; 44+ messages in thread
From: Ulrich Weigand @ 2018-05-22 12:56 UTC (permalink / raw)
  To: Pedro Franco de Carvalho; +Cc: gdb-patches

Pedro Franco de Carvalho wrote:

> gdb/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* ppc-tdep.h (struct ppc_reg_offsets): Remove vector register
> 	offset fields.
> 	* ppc-fbsd-tdep.c (ppc32_fbsd_reg_offsets): Remove initializers
> 	for vector register offset fields.
> 	(ppc64_fbsd_reg_offsets): Likewise.
> 	* ppc-nbsd-tdep.c (_initialize_ppcnbsd_tdep): Remove assignment
> 	to vector register offset fields.
> 	* ppc-obsd-tdep.c (_initialize_ppcnbsd_tdep): Remove assignment
> 	to vector register offset fields.
> 	* ppc-obsd-nat.c (_initialize_ppcobsd_nat): Remove assignment to
> 	vector register offset fields.
> 	* rs6000-aix-tdep.c (rs6000_aix32_reg_offsets): Remove
> 	initializers for vector register offset fields.
> 	(rs6000_aix64_reg_offsets): Likewise.
> 	* rs6000-tdep.c (ppc_vrreg_offset): Remove.
> 	(ppc_supply_vrregset): Remove.
> 	(ppc_collect_vrregset): Remove.
> 	* ppc-linux-tdep.c (ppc_linux_collect_vrregset): New function.
> 	(ppc_linux_vrregset) : New function.
> 	(ppc32_le_linux_vrregmap, ppc32_be_linux_vrregmap)
> 	(ppc32_le_linux_vrregset, ppc32_be_linux_vrregset): New globals.
> 	(ppc32_linux_vrregset): Remove.
> 	(ppc_linux_iterate_over_regset_sections): Call ppc_linux_vrregset
> 	and use result instead of ppc32_linux_vrregset.
> 	(ppc32_linux_reg_offsets): Remove initializers for vector register
> 	offset fields.
> 	(ppc64_linux_reg_offsets): Likewise.
> 	* ppc-linux-tdep.h (ppc_linux_vrregset): New declaration.
> 	* ppc-linux-nat.c: Include regset.h.
> 	(gdb_vrregset_t): Adjust comment to account for little-endian
> 	mode.
> 	(supply_vrregset, fill_vrregset): Remove.
> 	(fetch_altivec_register, store_altivec_register): Remove.
> 	(fetch_altivec_registers): Add regno parameter. Get regset using
> 	ppc_linux_vrregset. Use regset to supply registers.
> 	(store_altivec_registers): Add regno parameter. Get regset using
> 	ppc_linux_vrregset. Use regset to collect registers.
> 	(fetch_register): Call fetch_altivec_registers instead of
> 	fetch_altivec_register.
> 	(store_register): Call store_altivec_registers instead of
> 	store_altivec_register.
> 	(fetch_ppc_registers): Call fetch_altivec_registers with -1 for
> 	the new regno parameter.
> 	(store_ppc_registers): Call store_altivec_registers with -1 for
> 	the new regno parameter.
> 
> gdb/gdbserver/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* linux-ppc-low.c (ppc_fill_vrregset): Add vscr_offset variable.
> 	Set vscr_offset to 0 in little-endian mode and 12 in big-endian
> 	mode. Call collect_register_by_name with vscr using
> 	vscr_offset. Zero-pad vscr and vrsave fields in collector buffer.
> 	(ppc_store_vrregset): Add and set vscr_offset variable as in
> 	ppc_fill_vrregset. Call supply_register_by_name with vscr using
> 	vscr_offset.

This is OK.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH v2 8/8] [PowerPC] Recognize isa205 in linux core files
  2018-05-21 23:55   ` [PATCH v2 8/8] [PowerPC] Recognize isa205 in linux core files Pedro Franco de Carvalho
@ 2018-05-22 13:34     ` Ulrich Weigand
  0 siblings, 0 replies; 44+ messages in thread
From: Ulrich Weigand @ 2018-05-22 13:34 UTC (permalink / raw)
  To: Pedro Franco de Carvalho; +Cc: gdb-patches

Pedro Franco de Carvalho wrote:

> gdb/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* arch/ppc-linux-common.c (ppc_linux_has_isa205): Change the
> 	parameter type to CORE_ADDR.
> 	* arch/ppc-linux-common.h (ppc_linux_has_isa205): Change the
> 	parameter type in declaration to CORE_ADDR.
> 	* ppc-linux-tdep.c (ppc_linux_core_read_description): Call
> 	target_auxv_search to get AT_HWCAP and use the result to get the
> 	target description.
> 	* ppc-linux-nat.c (ppc_linux_get_hwcap): Change the return type
> 	to CORE_ADDR. Remove the cast of the return value to unsigned
> 	long. Fix error predicate of target_auxv_search.
> 	(ppc_linux_nat_target::read_description): Change the type of the
> 	hwcap variable to CORE_ADDR.
> 
> gdb/testsuite/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* gdb.arch/powerpc-fpscr-gcore.exp: New file.

This is OK.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH v2 6/8] [PowerPC] Fix VSX registers in linux core files
  2018-05-22  0:54   ` [PATCH v2 6/8] [PowerPC] Fix VSX registers in linux core files Pedro Franco de Carvalho
@ 2018-05-22 13:46     ` Ulrich Weigand
  0 siblings, 0 replies; 44+ messages in thread
From: Ulrich Weigand @ 2018-05-22 13:46 UTC (permalink / raw)
  To: Pedro Franco de Carvalho; +Cc: gdb-patches

Pedro Franco de Carvalho wrote:

> gdb/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* ppc-linux-tdep.c (ppc_linux_vsxregset): New function.
> 	(ppc32_linux_vsxregmap): New global.
> 	(ppc32_linux_vsxregset): Initialize with ppc32_linux_vsxregmap,
> 	regcache_supply_regset, and regcache_collect_regset.
> 	* ppc-linux-tdep.h (ppc_linux_vsxregset): Declare.
> 	* ppc-linux-nat.c (supply_vsxregset, fill_vsxregset): Remove.
> 	(fetch_vsx_register, store_vsx_register): Remove.
> 	(fetch_vsx_registers): Add regno parameter. Get regset using
> 	ppc_linux_vsxregset. Use regset to supply registers.
> 	(store_vsx_registers): Add regno parameter. Get regset using
> 	ppc_linux_vsxregset. Use regset to collect registers.
> 	(fetch_register): Call fetch_vsx_registers instead of
> 	fetch_vsx_register.
> 	(store_register): Call store_vsx_registers instead of
> 	store_vsx_register.
> 	(fetch_ppc_registers): Call fetch_vsx_registers with -1 for the
> 	new regno parameter.
> 	(store_ppc_registers): Call store_vsx_registers with -1 for the
> 	new regno parameter.
> 	* rs6000-tdep.c (ppc_vsx_support_p, ppc_supply_vsxreget)
> 	(ppc_collect_vsxregset): Remove.
> 
> gdb/testsuite/ChangeLog:
> yyyy-mm-dd  Pedro Franco de Carvalho  <pedromfc@linux.vnet.ibm.com>
> 
> 	* gdb.arch/powerpc-vsx-gcore.exp: New file.

This is OK.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

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

* Re: [PATCH 8/8] [PowerPC] Recognize isa205 in linux core files
  2018-05-22 12:48           ` Ulrich Weigand
@ 2018-05-22 14:33             ` Pedro Franco de Carvalho
  0 siblings, 0 replies; 44+ messages in thread
From: Pedro Franco de Carvalho @ 2018-05-22 14:33 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gdb-patches

Ulrich Weigand <uweigand@de.ibm.com> writes:

>> I haven't changed this in v2 yet. I did change how an error is checked
>> and handled to make it more explicit.
>
> Yes, that looks fine for now.

Ok, I'll commit the patch as it is now (with target_stack used by
ppc_linux_nat) and leave the auxv changes for the future.

Thank you for the reviews!

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

end of thread, other threads:[~2018-05-22 13:58 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-10 19:59 [PATCH 0/8] [PowerPC] Miscellaneous fixes for register access Pedro Franco de Carvalho
2018-05-10 19:59 ` [PATCH 4/8] [PowerPC] Consolidate linux vector regset sizes Pedro Franco de Carvalho
2018-05-16 16:35   ` Ulrich Weigand
2018-05-10 19:59 ` [PATCH 3/8] [PowerPC] Disable regsets using zero sizes in gdbserver Pedro Franco de Carvalho
2018-05-16 16:17   ` Ulrich Weigand
2018-05-10 19:59 ` [PATCH 1/8] [PowerPC] Consolidate linux target description selection Pedro Franco de Carvalho
2018-05-16 14:05   ` Ulrich Weigand
2018-05-16 22:50     ` Pedro Franco de Carvalho
2018-05-17  8:28       ` Ulrich Weigand
2018-05-10 20:00 ` [PATCH 8/8] [PowerPC] Recognize isa205 in linux core files Pedro Franco de Carvalho
2018-05-16 15:53   ` Ulrich Weigand
2018-05-16 23:32     ` Pedro Franco de Carvalho
2018-05-17 10:22       ` Ulrich Weigand
2018-05-21 20:46         ` Pedro Franco de Carvalho
2018-05-22 12:48           ` Ulrich Weigand
2018-05-22 14:33             ` Pedro Franco de Carvalho
2018-05-10 20:33 ` [PATCH 6/8] [PowerPC] Fix VSX registers " Pedro Franco de Carvalho
2018-05-16 14:18   ` Ulrich Weigand
2018-05-10 20:33 ` [PATCH 2/8] [PowerPC] Consolidate wordsize getter between native and gdbserver Pedro Franco de Carvalho
2018-05-16 15:54   ` Ulrich Weigand
2018-05-10 21:46 ` [PATCH 5/8] [PowerPC] Fix access to VSCR in linux targets Pedro Franco de Carvalho
2018-05-16 14:06   ` Ulrich Weigand
2018-05-17 21:25     ` Pedro Franco de Carvalho
2018-05-18 15:37       ` Ulrich Weigand
2018-05-21 20:46     ` Pedro Franco de Carvalho
2018-05-22 12:56       ` Ulrich Weigand
2018-05-10 22:25 ` [PATCH 7/8] [PowerPC] Fix inclusion of dfp pseudoregs in tdep Pedro Franco de Carvalho
2018-05-16 14:18   ` Ulrich Weigand
2018-05-21 20:46 ` [PATCH v2 1/8] [PowerPC] Consolidate linux target description selection Pedro Franco de Carvalho
2018-05-21 20:46   ` [PATCH v2 3/8] [PowerPC] Disable regsets using zero sizes in gdbserver Pedro Franco de Carvalho
2018-05-22 12:48     ` Ulrich Weigand
2018-05-21 20:46   ` [PATCH v2 4/8] [PowerPC] Consolidate linux vector regset sizes Pedro Franco de Carvalho
2018-05-22 12:48     ` Ulrich Weigand
2018-05-21 20:46   ` [PATCH v2 2/8] [PowerPC] Consolidate wordsize getter between native and gdbserver Pedro Franco de Carvalho
2018-05-22 12:56     ` Ulrich Weigand
2018-05-21 23:45   ` [PATCH v2 5/8] [PowerPC] Fix access to VSCR in linux targets Pedro Franco de Carvalho
2018-05-22 12:56     ` Ulrich Weigand
2018-05-21 23:55   ` [PATCH v2 8/8] [PowerPC] Recognize isa205 in linux core files Pedro Franco de Carvalho
2018-05-22 13:34     ` Ulrich Weigand
2018-05-21 23:56   ` [PATCH v2 7/8] [PowerPC] Fix inclusion of dfp pseudoregs in tdep Pedro Franco de Carvalho
2018-05-22 12:56     ` Ulrich Weigand
2018-05-22  0:54   ` [PATCH v2 6/8] [PowerPC] Fix VSX registers in linux core files Pedro Franco de Carvalho
2018-05-22 13:46     ` Ulrich Weigand
2018-05-22 12:48   ` [PATCH v2 1/8] [PowerPC] Consolidate linux target description selection Ulrich Weigand

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).