public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 08/12] NIOS2 Linux: Fill 'collect_regset' in regset structure.
  2014-05-26 16:37 [PATCH 00/12] Regset rework preparations part 2 Andreas Arnez
                   ` (3 preceding siblings ...)
  2014-05-26 16:37 ` [PATCH 06/12] HPPA " Andreas Arnez
@ 2014-05-26 16:37 ` Andreas Arnez
  2014-05-27  2:15   ` Yao Qi
  2014-05-26 16:37 ` [PATCH 01/12] regcache: Add functions suitable for regset_supply/collect Andreas Arnez
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 25+ messages in thread
From: Andreas Arnez @ 2014-05-26 16:37 UTC (permalink / raw)
  To: gdb-patches; +Cc: Yao Qi

gdb/
	* nios2-linux-tdep.c (NIOS2_GREGS_SIZE): New macro.
	(nios2_collect_gregset): New function.
	(nios2_core_regset): Add collect method.
---
 gdb/nios2-linux-tdep.c | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/gdb/nios2-linux-tdep.c b/gdb/nios2-linux-tdep.c
index 84ab576..f4cacf6 100644
--- a/gdb/nios2-linux-tdep.c
+++ b/gdb/nios2-linux-tdep.c
@@ -51,6 +51,8 @@ static const int reg_offsets[NIOS2_NUM_REGS] =
   -1, -1, -1, -1, -1, -1, -1, -1
 };
 
+#define NIOS2_GREGS_SIZE (4 * 31)
+
 /* Implement the supply_regset hook for core files.  */
 
 static void
@@ -73,11 +75,26 @@ nios2_supply_gregset (const struct regset *regset,
       }
 }
 
+static void
+nios2_collect_gregset (const struct regset *regset,
+		       const struct regcache *regcache,
+		       int regnum, void *gregs_buf, size_t len)
+{
+  gdb_byte *gregs = gregs_buf;
+  int regno;
+
+  for (regno = NIOS2_Z_REGNUM; regno <= NIOS2_MPUACC_REGNUM; regno++)
+    if (regnum == -1 || regnum == regno)
+      {
+	if (reg_offsets[regno] != -1)
+	  regcache_raw_collect (regcache, regno,
+				gregs + 4 * reg_offsets[regno]);
+      }
+}
+
 static const struct regset nios2_core_regset =
 {
-  NULL,
-  nios2_supply_gregset,
-  NULL,
+  NULL, nios2_supply_gregset, nios2_collect_gregset
 };
 
 /* Implement the regset_from_core_section gdbarch method.  */
-- 
1.8.4.2

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

* [PATCH 00/12] Regset rework preparations part 2
@ 2014-05-26 16:37 Andreas Arnez
  2014-05-26 16:37 ` [PATCH 10/12] TILEGX Linux: Fill 'collect_regset' in regset structure Andreas Arnez
                   ` (12 more replies)
  0 siblings, 13 replies; 25+ messages in thread
From: Andreas Arnez @ 2014-05-26 16:37 UTC (permalink / raw)
  To: gdb-patches; +Cc: Mark Kettenis

Now that part 1 of the regset rework preparations has been integrated
(https://sourceware.org/ml/gdb-patches/2014-05/msg00239.html), I'd
like to continue with part 2.

This part adds a collect_regset method to all Linux regsets where it
had been missing.  This is necessary, but not sufficient, to make the
"gcore" command multi-arch capable for the affected targets.  When
this part is approved, I can provide a follow-on patch set that fills
the remaining gaps to multi-arch capable core file handling for all
Linux targets.

Another goal is to make regset handling more similar across
architectures.  Therefore the first patch in this series introduces
generic regset_supply/collect functions, and several of the following
patches exploit them.  Last time I posted this, Mark Kettenis
indicated a need for discussing these functions' interfaces, and I
tried to explain my reasons for the suggested choice:
https://sourceware.org/ml/gdb-patches/2014-05/msg00043.html.

Andreas Arnez (12):
  regcache: Add functions suitable for regset_supply/collect.
  S390: Migrate to regcache_supply/collect_regset.
  AARCH64 Linux: Fill 'collect_regset' in regset structures.
  ALPHA Linux: Fill 'collect_regset' in regset structures.
  FRV Linux: Fill 'collect_regset' in regset structures.
  HPPA Linux: Fill 'collect_regset' in regset structures.
  M32R Linux: Fill 'collect_regset' in regset structure.
  NIOS2 Linux: Fill 'collect_regset' in regset structure.
  SCORE: Fill 'collect_regset' in regset structure.
  TILEGX Linux: Fill 'collect_regset' in regset structure.
  M68K Linux: Define regset structures.
  IA64 Linux: Define regset structures.

 gdb/aarch64-linux-nat.c  |  38 ++-----
 gdb/aarch64-linux-tdep.c |  90 ++++-----------
 gdb/aarch64-linux-tdep.h |  18 ++-
 gdb/alpha-linux-tdep.c   |  56 ++++++----
 gdb/frv-linux-tdep.c     | 141 +++++++++---------------
 gdb/hppa-linux-tdep.c    | 101 ++++++-----------
 gdb/ia64-linux-tdep.c    |  87 +++++++++++++++
 gdb/m32r-linux-tdep.c    |  81 +++++++++++---
 gdb/m68klinux-tdep.c     |  65 +++++++++++
 gdb/nios2-linux-tdep.c   |  23 +++-
 gdb/regcache.c           |  66 +++++++++++
 gdb/regcache.h           |  38 +++++++
 gdb/s390-linux-nat.c     | 177 +++++++++++++-----------------
 gdb/s390-linux-tdep.c    | 278 ++++++++++-------------------------------------
 gdb/s390-linux-tdep.h    |  13 +--
 gdb/score-tdep.c         |  72 ++++--------
 gdb/score-tdep.h         |  34 +-----
 gdb/tilegx-linux-tdep.c  |  37 +++----
 18 files changed, 690 insertions(+), 725 deletions(-)

-- 
1.8.4.2

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

* [PATCH 07/12] M32R Linux: Fill 'collect_regset' in regset structure.
  2014-05-26 16:37 [PATCH 00/12] Regset rework preparations part 2 Andreas Arnez
                   ` (10 preceding siblings ...)
  2014-05-26 16:37 ` [PATCH 12/12] IA64 Linux: Define " Andreas Arnez
@ 2014-05-26 16:37 ` Andreas Arnez
  2014-05-27  2:56 ` [PATCH 00/12] Regset rework preparations part 2 Yao Qi
  12 siblings, 0 replies; 25+ messages in thread
From: Andreas Arnez @ 2014-05-26 16:37 UTC (permalink / raw)
  To: gdb-patches

gdb/
	* m32r-linux-tdep.c (M32R_LINUX_GREGS_SIZE): New macro.
	(m32r_linux_supply_gregset): Make platform-independent and don't
	write to read-only input buffer.
	(m32r_linux_collect_gregset): New function.
	(m32r_linux_gregset): Add collect method.
---
 gdb/m32r-linux-tdep.c | 81 +++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 63 insertions(+), 18 deletions(-)

diff --git a/gdb/m32r-linux-tdep.c b/gdb/m32r-linux-tdep.c
index bf1ffff..5eaca6e 100644
--- a/gdb/m32r-linux-tdep.c
+++ b/gdb/m32r-linux-tdep.c
@@ -346,19 +346,26 @@ static int m32r_pt_regs_offset[] = {
 #define SPU_OFFSET (4 * 23)
 #define SPI_OFFSET (4 * 26)
 
+#define M32R_LINUX_GREGS_SIZE (4 * 27)
+
 static void
 m32r_linux_supply_gregset (const struct regset *regset,
 			   struct regcache *regcache, int regnum,
 			   const void *gregs, size_t size)
 {
-  const char *regs = gregs;
-  unsigned long psw, bbpsw;
+  const gdb_byte *regs = gregs;
+  enum bfd_endian byte_order =
+    gdbarch_byte_order (get_regcache_arch (regcache));
+  ULONGEST psw, bbpsw;
+  gdb_byte buf[4];
+  const gdb_byte *p;
   int i;
 
-  psw = *((unsigned long *) (regs + PSW_OFFSET));
-  bbpsw = *((unsigned long *) (regs + BBPSW_OFFSET));
+  psw = extract_unsigned_integer (regs + PSW_OFFSET, 4, byte_order);
+  bbpsw = extract_unsigned_integer (regs + BBPSW_OFFSET, 4, byte_order);
+  psw = ((0x00c1 & bbpsw) << 8) | ((0xc100 & psw) >> 8);
 
-  for (i = 0; i < sizeof (m32r_pt_regs_offset) / 4; i++)
+  for (i = 0; i < ARRAY_SIZE (m32r_pt_regs_offset); i++)
     {
       if (regnum != -1 && regnum != i)
 	continue;
@@ -366,30 +373,68 @@ m32r_linux_supply_gregset (const struct regset *regset,
       switch (i)
 	{
 	case PSW_REGNUM:
-	  *((unsigned long *) (regs + m32r_pt_regs_offset[i])) =
-	    ((0x00c1 & bbpsw) << 8) | ((0xc100 & psw) >> 8);
+	  store_unsigned_integer (buf, 4, byte_order, psw);
+	  p = buf;
 	  break;
 	case CBR_REGNUM:
-	  *((unsigned long *) (regs + m32r_pt_regs_offset[i])) =
-	    ((psw >> 8) & 1);
+	  store_unsigned_integer (buf, 4, byte_order, psw & 1);
+	  p = buf;
 	  break;
 	case M32R_SP_REGNUM:
-	  if (psw & 0x8000)
-	    *((unsigned long *) (regs + m32r_pt_regs_offset[i])) =
-	      *((unsigned long *) (regs + SPU_OFFSET));
-	  else
-	    *((unsigned long *) (regs + m32r_pt_regs_offset[i])) =
-	      *((unsigned long *) (regs + SPI_OFFSET));
+	  p = regs + ((psw & 0x80) ? SPU_OFFSET : SPI_OFFSET);
 	  break;
+	default:
+	  p = regs + m32r_pt_regs_offset[i];
 	}
 
-      regcache_raw_supply (regcache, i,
-			   regs + m32r_pt_regs_offset[i]);
+      regcache_raw_supply (regcache, i, p);
+    }
+}
+
+static void
+m32r_linux_collect_gregset (const struct regset *regset,
+			    const struct regcache *regcache,
+			    int regnum, void *gregs, size_t size)
+{
+  gdb_byte *regs = gregs;
+  int i;
+  enum bfd_endian byte_order =
+    gdbarch_byte_order (get_regcache_arch (regcache));
+  ULONGEST psw;
+  gdb_byte buf[4];
+
+  regcache_raw_collect (regcache, PSW_REGNUM, buf);
+  psw = extract_unsigned_integer (buf, 4, byte_order);
+
+  for (i = 0; i < ARRAY_SIZE (m32r_pt_regs_offset); i++)
+    {
+      if (regnum != -1 && regnum != i)
+	continue;
+
+      switch (i)
+	{
+	case PSW_REGNUM:
+	  store_unsigned_integer (regs + PSW_OFFSET, 4, byte_order,
+				  (psw & 0xc1) << 8);
+	  store_unsigned_integer (regs + BBPSW_OFFSET, 4, byte_order,
+				  (psw >> 8) & 0xc1);
+	  break;
+	case CBR_REGNUM:
+	  break;
+	case M32R_SP_REGNUM:
+	  regcache_raw_collect (regcache, i, regs
+				+ ((psw & 0x80) ? SPU_OFFSET : SPI_OFFSET));
+	  break;
+	default:
+	  regcache_raw_collect (regcache, i,
+				regs + m32r_pt_regs_offset[i]);
+	}
     }
 }
 
 static const struct regset m32r_linux_gregset = {
-  NULL, m32r_linux_supply_gregset
+  NULL,
+  m32r_linux_supply_gregset, m32r_linux_collect_gregset
 };
 
 static const struct regset *
-- 
1.8.4.2

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

* [PATCH 06/12] HPPA Linux: Fill 'collect_regset' in regset structures.
  2014-05-26 16:37 [PATCH 00/12] Regset rework preparations part 2 Andreas Arnez
                   ` (2 preceding siblings ...)
  2014-05-26 16:37 ` [PATCH 05/12] FRV Linux: Fill 'collect_regset' in regset structures Andreas Arnez
@ 2014-05-26 16:37 ` Andreas Arnez
  2014-05-26 16:37 ` [PATCH 08/12] NIOS2 Linux: Fill 'collect_regset' in regset structure Andreas Arnez
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Andreas Arnez @ 2014-05-26 16:37 UTC (permalink / raw)
  To: gdb-patches; +Cc: Randolph Chung

gdb/
	* hppa-linux-tdep.c (greg_map): Rename to...
	(hppa_linux_gregmap): ... this.  Also convert to
	regcache_map_entry format.
	(hppa_linux_supply_regset): Delete function.
	(hppa_linux_supply_fpregset): Delete function.  Move logic to...
	(hppa_linux_fpregmap): ... this new register map.
	(hppa_linux_regset, hppa_linux_fpregset): Refer to appropriate
	register map, replace supply method by regcache_supply_regset, and
	add collect method regcache_collect_regset.
---
 gdb/hppa-linux-tdep.c | 101 +++++++++++++++++---------------------------------
 1 file changed, 34 insertions(+), 67 deletions(-)

diff --git a/gdb/hppa-linux-tdep.c b/gdb/hppa-linux-tdep.c
index 7a765a2..af57e6c 100644
--- a/gdb/hppa-linux-tdep.c
+++ b/gdb/hppa-linux-tdep.c
@@ -423,84 +423,51 @@ hppa_linux_find_global_pointer (struct gdbarch *gdbarch,
  * cr10, cr15
  */
 
-#define GR_REGNUM(_n)	(HPPA_R0_REGNUM+_n)
-#define TR_REGNUM(_n)	(HPPA_TR0_REGNUM+_n)
-static const int greg_map[] =
+static const struct regcache_map_entry hppa_linux_gregmap[] =
   {
-    GR_REGNUM(0), GR_REGNUM(1), GR_REGNUM(2), GR_REGNUM(3),
-    GR_REGNUM(4), GR_REGNUM(5), GR_REGNUM(6), GR_REGNUM(7),
-    GR_REGNUM(8), GR_REGNUM(9), GR_REGNUM(10), GR_REGNUM(11),
-    GR_REGNUM(12), GR_REGNUM(13), GR_REGNUM(14), GR_REGNUM(15),
-    GR_REGNUM(16), GR_REGNUM(17), GR_REGNUM(18), GR_REGNUM(19),
-    GR_REGNUM(20), GR_REGNUM(21), GR_REGNUM(22), GR_REGNUM(23),
-    GR_REGNUM(24), GR_REGNUM(25), GR_REGNUM(26), GR_REGNUM(27),
-    GR_REGNUM(28), GR_REGNUM(29), GR_REGNUM(30), GR_REGNUM(31),
-
-    HPPA_SR4_REGNUM+1, HPPA_SR4_REGNUM+2, HPPA_SR4_REGNUM+3, HPPA_SR4_REGNUM+4,
-    HPPA_SR4_REGNUM, HPPA_SR4_REGNUM+5, HPPA_SR4_REGNUM+6, HPPA_SR4_REGNUM+7,
-
-    HPPA_PCOQ_HEAD_REGNUM, HPPA_PCOQ_TAIL_REGNUM,
-    HPPA_PCSQ_HEAD_REGNUM, HPPA_PCSQ_TAIL_REGNUM,
-
-    HPPA_SAR_REGNUM, HPPA_IIR_REGNUM, HPPA_ISR_REGNUM, HPPA_IOR_REGNUM,
-    HPPA_IPSW_REGNUM, HPPA_RCR_REGNUM,
-
-    TR_REGNUM(0), TR_REGNUM(1), TR_REGNUM(2), TR_REGNUM(3),
-    TR_REGNUM(4), TR_REGNUM(5), TR_REGNUM(6), TR_REGNUM(7),
-
-    HPPA_PID0_REGNUM, HPPA_PID1_REGNUM, HPPA_PID2_REGNUM, HPPA_PID3_REGNUM,
-    HPPA_CCR_REGNUM, HPPA_EIEM_REGNUM,
+    { 32, HPPA_R0_REGNUM },
+    { 1, HPPA_SR4_REGNUM+1 },
+    { 1, HPPA_SR4_REGNUM+2 },
+    { 1, HPPA_SR4_REGNUM+3 },
+    { 1, HPPA_SR4_REGNUM+4 },
+    { 1, HPPA_SR4_REGNUM },
+    { 1, HPPA_SR4_REGNUM+5 },
+    { 1, HPPA_SR4_REGNUM+6 },
+    { 1, HPPA_SR4_REGNUM+7 },
+    { 1, HPPA_PCOQ_HEAD_REGNUM },
+    { 1, HPPA_PCOQ_TAIL_REGNUM },
+    { 1, HPPA_PCSQ_HEAD_REGNUM },
+    { 1, HPPA_PCSQ_TAIL_REGNUM },
+    { 1, HPPA_SAR_REGNUM },
+    { 1, HPPA_IIR_REGNUM },
+    { 1, HPPA_ISR_REGNUM },
+    { 1, HPPA_IOR_REGNUM },
+    { 1, HPPA_IPSW_REGNUM },
+    { 1, HPPA_RCR_REGNUM },
+    { 8, HPPA_TR0_REGNUM },
+    { 4, HPPA_PID0_REGNUM },
+    { 1, HPPA_CCR_REGNUM },
+    { 1, HPPA_EIEM_REGNUM },
+    { 0 }
   };
 
-static void
-hppa_linux_supply_regset (const struct regset *regset,
-			  struct regcache *regcache,
-			  int regnum, const void *regs, size_t len)
-{
-  struct gdbarch *arch = get_regcache_arch (regcache);
-  struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
-  const char *buf = regs;
-  int i, offset;
-
-  offset = 0;
-  for (i = 0; i < ARRAY_SIZE (greg_map); i++)
-    {
-      if (regnum == greg_map[i] || regnum == -1)
-        regcache_raw_supply (regcache, greg_map[i], buf + offset);
-
-      offset += tdep->bytes_per_address;
-    }
-}
-
-static void
-hppa_linux_supply_fpregset (const struct regset *regset,
-			    struct regcache *regcache,
-			    int regnum, const void *regs, size_t len)
-{
-  const char *buf = regs;
-  int i, offset;
-
-  offset = 0;
-  for (i = 0; i < 64; i++)
-    {
-      if (regnum == HPPA_FP0_REGNUM + i || regnum == -1)
-        regcache_raw_supply (regcache, HPPA_FP0_REGNUM + i, 
-			     buf + offset);
-      offset += 4;
-    }
-}
+static const struct regcache_map_entry hppa_linux_fpregmap[] =
+  {
+    { 64, HPPA_FP0_REGNUM },
+    { 0 }
+  };
 
 /* HPPA Linux kernel register set.  */
 static const struct regset hppa_linux_regset =
 {
-  NULL,
-  hppa_linux_supply_regset
+  hppa_linux_gregmap,
+  regcache_supply_regset, regcache_collect_regset
 };
 
 static const struct regset hppa_linux_fpregset =
 {
-  NULL,
-  hppa_linux_supply_fpregset
+  hppa_linux_fpregmap,
+  regcache_supply_regset, regcache_collect_regset
 };
 
 static const struct regset *
-- 
1.8.4.2

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

* [PATCH 01/12] regcache: Add functions suitable for regset_supply/collect.
  2014-05-26 16:37 [PATCH 00/12] Regset rework preparations part 2 Andreas Arnez
                   ` (4 preceding siblings ...)
  2014-05-26 16:37 ` [PATCH 08/12] NIOS2 Linux: Fill 'collect_regset' in regset structure Andreas Arnez
@ 2014-05-26 16:37 ` Andreas Arnez
  2014-05-27  2:49   ` Yao Qi
  2014-05-26 16:37 ` [PATCH 02/12] S390: Migrate to regcache_supply/collect_regset Andreas Arnez
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 25+ messages in thread
From: Andreas Arnez @ 2014-05-26 16:37 UTC (permalink / raw)
  To: gdb-patches

These functions are intended to suit all targets that don't require too
special logic in their regset supply/collect methods.  Having such
generic functions helps reducing target-specific complexity.

gdb/
	* regcache.c: Include "regset.h".
	(regcache_supply_regset, regcache_collect_regset): New functions.
	* regcache.h (struct regcache_map_entry): New structure.
	(REGCACHE_MAP_SKIP_BYTES): New enum value.
	(regcache_supply_regset, regcache_collect_regset): New prototypes.
---
 gdb/regcache.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/regcache.h | 38 +++++++++++++++++++++++++++++++++
 2 files changed, 104 insertions(+)

diff --git a/gdb/regcache.c b/gdb/regcache.c
index 8b588c6..b38031e 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -30,6 +30,7 @@
 #include "exceptions.h"
 #include "remote.h"
 #include "valprint.h"
+#include "regset.h"
 
 /*
  * DATA STRUCTURE
@@ -1031,6 +1032,71 @@ regcache_raw_collect (const struct regcache *regcache, int regnum, void *buf)
   memcpy (buf, regbuf, size);
 }
 
+/* Supply register REGNUM from BUF to REGCACHE, using the register map
+   in REGSET.  If REGNUM is -1, do this for all registers in
+   REGSET.  */
+
+void
+regcache_supply_regset (const struct regset *regset,
+			struct regcache *regcache,
+			int regnum, const void *buf, size_t size)
+{
+  const struct regcache_map_entry *map = regset->descr;
+  int offs = 0;
+  int i, count;
+
+  for (i = 0; (count = map[i].count) != 0; i++)
+    {
+      int regno = map[i].regno;
+
+      if (regno == REGCACHE_MAP_SKIP_BYTES)
+	offs += count;
+      else
+	for (; count--; regno++)
+	  {
+	    int new_offs = offs + regcache->descr->sizeof_register[regno];
+
+	    if (new_offs <= size && (regnum == -1 || regnum == regno))
+	      regcache_raw_supply (regcache, regno,
+				   buf ? (const gdb_byte *) buf + offs
+				   : NULL);
+	    offs = new_offs;
+	  }
+    }
+}
+
+/* Collect register REGNUM from REGCACHE to BUF, using the register
+   map in REGSET.  If REGNUM is -1, do this for all registers in
+   REGSET.  */
+
+void
+regcache_collect_regset (const struct regset *regset,
+			 const struct regcache *regcache,
+			 int regnum, void *buf, size_t size)
+{
+  const struct regcache_map_entry *map = regset->descr;
+  int offs = 0;
+  int i, count;
+
+  for (i = 0; (count = map[i].count) != 0; i++)
+    {
+      int regno = map[i].regno;
+
+      if (regno == REGCACHE_MAP_SKIP_BYTES)
+	offs += count;
+      else
+	for (; count--; regno++)
+	  {
+	    int new_offs = offs + regcache->descr->sizeof_register[regno];
+
+	    if (new_offs <= size && (regnum == -1 || regnum == regno))
+	      regcache_raw_collect (regcache, regno,
+				    (gdb_byte *) buf + offs);
+	    offs = new_offs;
+	  }
+    }
+}
+
 
 /* Special handling for register PC.  */
 
diff --git a/gdb/regcache.h b/gdb/regcache.h
index 8423f57..cc2bda8 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -147,6 +147,44 @@ extern void regcache_raw_supply (struct regcache *regcache,
 extern void regcache_raw_collect (const struct regcache *regcache,
 				  int regnum, void *buf);
 
+/* Mapping between register numbers and offsets in a buffer, for use
+   in the '*regset' functions below.  The first entry in a map refers
+   to offset 0, and each entry increases the offset by its size.
+   Specifying count=N and regno=R is equivalent to N consecutive
+   entries with count=1 and with regno ranging from R to R+N-1.  The
+   end of the map is marked with a dummy entry having count=0.  */
+
+struct regcache_map_entry
+{
+  int count;
+  int regno;
+};
+
+/* Special value for the 'regno' field in the struct above.  */
+
+enum
+  {
+    REGCACHE_MAP_SKIP_BYTES = -1,
+  };
+
+/* Transfer a set of registers (as described by REGSET) between
+   REGCACHE and BUF.  If REGNUM == -1, transfer all registers
+   belonging to the regset, otherwise just the register numbered
+   REGNUM.  The REGSET's 'descr' field must point to an array of
+   'struct regcache_map_entry'.
+
+   These functions are suitable for the 'regset_supply' and
+   'regset_collect' fields in a regset structure.
+  */
+
+extern void regcache_supply_regset (const struct regset *regset,
+				    struct regcache *regcache,
+				    int regnum, const void *buf,
+				    size_t size);
+extern void regcache_collect_regset (const struct regset *regset,
+				     const struct regcache *regcache,
+				     int regnum, void *buf, size_t size);
+
 
 /* The type of a register.  This function is slightly more efficient
    then its gdbarch vector counterpart since it returns a precomputed
-- 
1.8.4.2

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

* [PATCH 12/12] IA64 Linux: Define regset structures.
  2014-05-26 16:37 [PATCH 00/12] Regset rework preparations part 2 Andreas Arnez
                   ` (9 preceding siblings ...)
  2014-05-26 16:37 ` [PATCH 04/12] ALPHA " Andreas Arnez
@ 2014-05-26 16:37 ` Andreas Arnez
  2014-05-26 16:37 ` [PATCH 07/12] M32R Linux: Fill 'collect_regset' in regset structure Andreas Arnez
  2014-05-27  2:56 ` [PATCH 00/12] Regset rework preparations part 2 Yao Qi
  12 siblings, 0 replies; 25+ messages in thread
From: Andreas Arnez @ 2014-05-26 16:37 UTC (permalink / raw)
  To: gdb-patches; +Cc: Jeff Johnston

gdb/
	* ia64-linux-tdep.c: Include "regset.h".
	(ia64_linux_gregmap, ia64_linux_fpregmap): New register maps.
	(IA64_LINUX_GREGS_SIZE, IA64_LINUX_FPREGS_SIZE): New macros.
	(ia64_linux_supply_fpregset): New function.
	(ia64_linux_gregset, ia64_linux_fpregset): New regsets.
	(ia64_linux_regset_from_core_section): New function.
	(ia64_linux_init_abi): Set regset_from_core_section gdbarch
	method.
---
 gdb/ia64-linux-tdep.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 87 insertions(+)

diff --git a/gdb/ia64-linux-tdep.c b/gdb/ia64-linux-tdep.c
index 128924e..9989602 100644
--- a/gdb/ia64-linux-tdep.c
+++ b/gdb/ia64-linux-tdep.c
@@ -26,6 +26,7 @@
 #include "solib-svr4.h"
 #include "symtab.h"
 #include "linux-tdep.h"
+#include "regset.h"
 
 #include <ctype.h>
 
@@ -131,6 +132,88 @@ ia64_linux_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
 	  || isdigit (*s));  /* Literal number.  */
 }
 
+/* Core file support. */
+
+static const struct regcache_map_entry ia64_linux_gregmap[] =
+  {
+    { 32, IA64_GR0_REGNUM },	/* r0 ... r31 */
+    { 8, REGCACHE_MAP_SKIP_BYTES }, /* FIXME: NAT collection bits? */
+    { 1, IA64_PR_REGNUM },
+    { 8, IA64_BR0_REGNUM },	/* b0 ... b7 */
+    { 1, IA64_IP_REGNUM },
+    { 1, IA64_CFM_REGNUM },
+    { 1, IA64_PSR_REGNUM },
+    { 1, IA64_RSC_REGNUM },
+    { 1, IA64_BSP_REGNUM },
+    { 1, IA64_BSPSTORE_REGNUM },
+    { 1, IA64_RNAT_REGNUM },
+    { 1, IA64_CCV_REGNUM },
+    { 1, IA64_UNAT_REGNUM },
+    { 1, IA64_FPSR_REGNUM },
+    { 1, IA64_PFS_REGNUM },
+    { 1, IA64_LC_REGNUM },
+    { 1, IA64_EC_REGNUM },
+    { 0 }
+  };
+
+#define IA64_LINUX_GREGS_SIZE (55 * 8)
+
+static const struct regcache_map_entry ia64_linux_fpregmap[] =
+  {
+    { 128, IA64_FR0_REGNUM },	/* f0 ... f127 */
+    { 0 }
+  };
+
+#define IA64_LINUX_FPREGS_SIZE (128 * 8)
+
+static void
+ia64_linux_supply_fpregset (const struct regset *regset,
+			    struct regcache *regcache,
+			    int regnum, const void *regs, size_t len)
+{
+  const gdb_byte f_zero[16] = { 0 };
+  const gdb_byte f_one[16] =
+    { 0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0 };
+
+  regcache_supply_regset (regset, regcache, regnum, regs, len);
+
+  /* Kernel generated cores have fr1==0 instead of 1.0.  Older GDBs
+     did the same.  So ignore whatever might be recorded in fpregset_t
+     for fr0/fr1 and always supply their expected values.  */
+  if (regnum == -1 || regnum == IA64_FR0_REGNUM)
+    regcache_raw_supply (regcache, IA64_FR0_REGNUM, f_zero);
+  if (regnum == -1 || regnum == IA64_FR1_REGNUM)
+    regcache_raw_supply (regcache, IA64_FR1_REGNUM, f_one);
+}
+
+static const struct regset ia64_linux_gregset =
+  {
+    ia64_linux_gregmap,
+    regcache_supply_regset, regcache_collect_regset
+  };
+
+static const struct regset ia64_linux_fpregset =
+  {
+    ia64_linux_fpregmap,
+    ia64_linux_supply_fpregset, regcache_collect_regset
+  };
+
+static const struct regset *
+ia64_linux_regset_from_core_section (struct gdbarch *gdbarch,
+				     const char *sect_name,
+				     size_t sect_size)
+{
+  if (strcmp (sect_name, ".reg") == 0
+      && sect_size >= IA64_LINUX_GREGS_SIZE)
+    return &ia64_linux_gregset;
+
+  if (strcmp (sect_name, ".reg2") == 0
+      && sect_size >= IA64_LINUX_FPREGS_SIZE)
+    return &ia64_linux_fpregset;
+
+  return NULL;
+}
+
 static void
 ia64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
@@ -161,6 +244,10 @@ ia64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);
 
+  /* Core file support. */
+  set_gdbarch_regset_from_core_section (gdbarch,
+					ia64_linux_regset_from_core_section);
+
   /* SystemTap related.  */
   set_gdbarch_stap_register_prefixes (gdbarch, stap_register_prefixes);
   set_gdbarch_stap_register_indirection_prefixes (gdbarch,
-- 
1.8.4.2

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

* [PATCH 04/12] ALPHA Linux: Fill 'collect_regset' in regset structures.
  2014-05-26 16:37 [PATCH 00/12] Regset rework preparations part 2 Andreas Arnez
                   ` (8 preceding siblings ...)
  2014-05-26 16:37 ` [PATCH 03/12] AARCH64 Linux: Fill 'collect_regset' in " Andreas Arnez
@ 2014-05-26 16:37 ` Andreas Arnez
  2014-05-26 16:37 ` [PATCH 12/12] IA64 Linux: Define " Andreas Arnez
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Andreas Arnez @ 2014-05-26 16:37 UTC (permalink / raw)
  To: gdb-patches; +Cc: Richard Henderson

gdb/
	* alpha-linux-tdep.c (alpha_linux_supply_gregset): Replace logic
	by call to alpha_supply_int_regs.
	(alpha_linux_collect_gregset): New function.
	(alpha_linux_supply_fpregset): Replace logic by call to
	alpha_supply_fp_regs.
	(alpha_linux_collect_fpregset): New function.
	(alpha_linux_gregset, alpha_linux_fpregset): Add collect method.
---
 gdb/alpha-linux-tdep.c | 56 +++++++++++++++++++++++++++++++-------------------
 1 file changed, 35 insertions(+), 21 deletions(-)

diff --git a/gdb/alpha-linux-tdep.c b/gdb/alpha-linux-tdep.c
index 52f19d0..51bce4f 100644
--- a/gdb/alpha-linux-tdep.c
+++ b/gdb/alpha-linux-tdep.c
@@ -166,21 +166,27 @@ alpha_linux_supply_gregset (const struct regset *regset,
 			    int regnum, const void *gregs, size_t len)
 {
   const gdb_byte *regs = gregs;
-  int i;
+
   gdb_assert (len >= 32 * 8);
+  alpha_supply_int_regs (regcache, regnum, regs, regs + 31 * 8,
+			 len >= 33 * 8 ? regs + 32 * 8 : NULL);
+}
 
-  for (i = 0; i < ALPHA_ZERO_REGNUM; i++)
-    {
-      if (regnum == i || regnum == -1)
-	regcache_raw_supply (regcache, i, regs + i * 8);
-    }
+/* Collect register REGNUM from the register cache REGCACHE and store
+   it in the buffer specified by GREGS and LEN as described by the
+   general-purpose register set REGSET.  If REGNUM is -1, do this for
+   all registers in REGSET.  */
 
-  if (regnum == ALPHA_PC_REGNUM || regnum == -1)
-    regcache_raw_supply (regcache, ALPHA_PC_REGNUM, regs + 31 * 8);
+static void
+alpha_linux_collect_gregset (const struct regset *regset,
+			     const struct regcache *regcache,
+			     int regnum, void *gregs, size_t len)
+{
+  gdb_byte *regs = gregs;
 
-  if (regnum == ALPHA_UNIQUE_REGNUM || regnum == -1)
-    regcache_raw_supply (regcache, ALPHA_UNIQUE_REGNUM,
-			 len >= 33 * 8 ? regs + 32 * 8 : NULL);
+  gdb_assert (len >= 32 * 8);
+  alpha_fill_int_regs (regcache, regnum, regs, regs + 31 * 8,
+		       len >= 33 * 8 ? regs + 32 * 8 : NULL);
 }
 
 /* Supply register REGNUM from the buffer specified by FPREGS and LEN
@@ -193,29 +199,37 @@ alpha_linux_supply_fpregset (const struct regset *regset,
 			     int regnum, const void *fpregs, size_t len)
 {
   const gdb_byte *regs = fpregs;
-  int i;
+
   gdb_assert (len >= 32 * 8);
+  alpha_supply_fp_regs (regcache, regnum, regs, regs + 31 * 8);
+}
 
-  for (i = ALPHA_FP0_REGNUM; i < ALPHA_FP0_REGNUM + 31; i++)
-    {
-      if (regnum == i || regnum == -1)
-	regcache_raw_supply (regcache, i, regs + (i - ALPHA_FP0_REGNUM) * 8);
-    }
+/* Collect register REGNUM from the register cache REGCACHE and store
+   it in the buffer specified by FPREGS and LEN as described by the
+   general-purpose register set REGSET.  If REGNUM is -1, do this for
+   all registers in REGSET.  */
 
-  if (regnum == ALPHA_FPCR_REGNUM || regnum == -1)
-    regcache_raw_supply (regcache, ALPHA_FPCR_REGNUM, regs + 31 * 8);
+static void
+alpha_linux_collect_fpregset (const struct regset *regset,
+			      const struct regcache *regcache,
+			      int regnum, void *fpregs, size_t len)
+{
+  gdb_byte *regs = fpregs;
+
+  gdb_assert (len >= 32 * 8);
+  alpha_fill_fp_regs (regcache, regnum, regs, regs + 31 * 8);
 }
 
 static const struct regset alpha_linux_gregset =
 {
   NULL,
-  alpha_linux_supply_gregset
+  alpha_linux_supply_gregset, alpha_linux_collect_gregset
 };
 
 static const struct regset alpha_linux_fpregset =
 {
   NULL,
-  alpha_linux_supply_fpregset
+  alpha_linux_supply_fpregset, alpha_linux_collect_fpregset
 };
 
 /* Return the appropriate register set for the core section identified
-- 
1.8.4.2

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

* [PATCH 09/12] SCORE: Fill 'collect_regset' in regset structure.
  2014-05-26 16:37 [PATCH 00/12] Regset rework preparations part 2 Andreas Arnez
  2014-05-26 16:37 ` [PATCH 10/12] TILEGX Linux: Fill 'collect_regset' in regset structure Andreas Arnez
@ 2014-05-26 16:37 ` Andreas Arnez
  2014-05-26 16:37 ` [PATCH 05/12] FRV Linux: Fill 'collect_regset' in regset structures Andreas Arnez
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Andreas Arnez @ 2014-05-26 16:37 UTC (permalink / raw)
  To: gdb-patches; +Cc: Qinwei

gdb/
	* score-tdep.c (score7_linux_supply_gregset): Delete function.
	Move logic to...
	(score7_linux_gregmap): ... this new register map.
	(SCORE7_LINUX_SIZEOF_GREGSET): New macro.
	(score7_linux_gregset): Refer to register map, replace supply
	method by regcache_supply_regset, and add collect method.
	(score7_linux_regset_from_core_section): Replace
	sizeof(elf_gregset_t) by SCORE7_LINUX_SIZEOF_GREGSET.
	* score-tdep.h (SCORE_EPC_REGNUM): New enum value.
	(struct pt_regs): Delete structure definition.
	(elf_gregset_t): Delete typedef.
---
 gdb/score-tdep.c | 72 +++++++++++++++++++-------------------------------------
 gdb/score-tdep.h | 34 +-------------------------
 2 files changed, 25 insertions(+), 81 deletions(-)

diff --git a/gdb/score-tdep.c b/gdb/score-tdep.c
index c224189..90afdf3 100644
--- a/gdb/score-tdep.c
+++ b/gdb/score-tdep.c
@@ -1398,59 +1398,34 @@ score_prologue_frame_base_sniffer (struct frame_info *this_frame)
   return &score_prologue_frame_base;
 }
 
-/* Core file support (dirty hack)
-  
-   The core file MUST be generated by GNU/Linux on S+core.  */
-
-static void
-score7_linux_supply_gregset(const struct regset *regset,
-                struct regcache *regcache,
-                int regnum, const void *gregs_buf, size_t len)
-{
-  int regno;
-  elf_gregset_t *gregs;
-
-  gdb_assert (regset != NULL);
-  gdb_assert ((regcache != NULL) && (gregs_buf != NULL));
-
-  gregs = (elf_gregset_t *) gregs_buf;
-
-  for (regno = 0; regno < 32; regno++)
-    if (regnum == -1 || regnum == regno)
-      regcache_raw_supply (regcache, regno, gregs->regs + regno);
+/* Core file support.  */
 
+static const struct regcache_map_entry score7_linux_gregmap[] =
   {
-    struct sreg {
-      int regnum;
-      void *buf;
-    } sregs [] = {
-      { 55, &(gregs->cel) },  /* CEL */
-      { 54, &(gregs->ceh) },  /* CEH */
-      { 53, &(gregs->sr0) },  /* sr0, i.e. cnt or COUNTER */
-      { 52, &(gregs->sr1) },  /* sr1, i.e. lcr or LDCR */
-      { 51, &(gregs->sr1) },  /* sr2, i.e. scr or STCR */
-
-      /* Exception occured at this address, exactly the PC we want */
-      { 49, &(gregs->cp0_epc) }, /* PC */
-
-      { 38, &(gregs->cp0_ema) }, /* EMA */
-      { 37, &(gregs->cp0_epc) }, /* EPC */
-      { 34, &(gregs->cp0_ecr) }, /* ECR */
-      { 33, &(gregs->cp0_condition) }, /* COND */
-      { 32, &(gregs->cp0_psr) }, /* PSR */
-    };
+    { 7 * 4, REGCACHE_MAP_SKIP_BYTES },
+    { 32, 0 },			/* r0 ... r31 */
+    { 1, 55 },			/* CEL */
+    { 1, 54 },			/* CEH */
+    { 1, 53 },			/* sr0, i.e. cnt or COUNTER */
+    { 1, 52 },			/* sr1, i.e. lcr or LDCR */
+    { 1, 51 },			/* sr2, i.e. scr or STCR */
+    /* EPC and PC are stored in the same slot.  */
+    { 1, 37 },			/* EPC */
+    { -4, REGCACHE_MAP_SKIP_BYTES },
+    { 1, 49 },			/* PC */
+    { 1, 38 },			/* EMA */
+    { 1, 32 },			/* PSR */
+    { 1, 34 },			/* ECR */
+    { 1, 33 },			/* COND */
+    { 0 }
+  };
 
-    for (regno = 0; regno < sizeof(sregs)/sizeof(sregs[0]); regno++)
-      if (regnum == -1 || regnum == sregs[regno].regnum)
-	regcache_raw_supply (regcache,
-			     sregs[regno].regnum, sregs[regno].buf);
-  }
-}
+#define SCORE7_LINUX_SIZEOF_GREGSET 196
 
 static const struct regset score7_linux_gregset =
   {
-    NULL,
-    score7_linux_supply_gregset, NULL
+    score7_linux_gregmap,
+    regcache_supply_regset, regcache_collect_regset
   };
 
 /* Return the appropriate register set from the core section identified
@@ -1463,7 +1438,8 @@ score7_linux_regset_from_core_section(struct gdbarch *gdbarch,
   gdb_assert (gdbarch != NULL);
   gdb_assert (sect_name != NULL);
 
-  if (strcmp(sect_name, ".reg") == 0 && sect_size == sizeof(elf_gregset_t))
+  if (strcmp(sect_name, ".reg") == 0
+      && sect_size == SCORE7_LINUX_SIZEOF_GREGSET)
     return &score7_linux_gregset;
 
   return NULL;
diff --git a/gdb/score-tdep.h b/gdb/score-tdep.h
index 02a334e..cef0e6a 100644
--- a/gdb/score-tdep.h
+++ b/gdb/score-tdep.h
@@ -32,6 +32,7 @@ enum gdb_regnum
   SCORE_RA_REGNUM = 3,
   SCORE_A0_REGNUM = 4,
   SCORE_AL_REGNUM = 7,
+  SCORE_EPC_REGNUM = 37,
   SCORE_PC_REGNUM = 49,
 };
 
@@ -46,37 +47,4 @@ enum gdb_regnum
 #define SCORE_INSTLEN          4
 #define SCORE16_INSTLEN        2
 
-/* Forward declarations.  */
-struct regset;
-
-/* Linux Core file support (dirty hack)
-  
-   S+core Linux register set definition, copy from S+core Linux.  */
-struct pt_regs {
-    /* Pad bytes for argument save space on the stack.  */
-    unsigned long pad0[6]; /* may be 4, MIPS accept 6var, SCore
-			      accepts 4 Var--yuchen */
-
-    /* Saved main processor registers.  */
-    unsigned long orig_r4;
-    unsigned long regs[32];
-
-    /* Other saved registers.  */
-    unsigned long cel;
-    unsigned long ceh;
-
-    unsigned long sr0;  /*cnt*/
-    unsigned long sr1;  /*lcr*/
-    unsigned long sr2;  /*scr*/
-
-    /* saved cp0 registers */
-    unsigned long cp0_epc;
-    unsigned long cp0_ema;
-    unsigned long cp0_psr;
-    unsigned long cp0_ecr;
-    unsigned long cp0_condition;
-};
-
-typedef struct pt_regs elf_gregset_t;
-
 #endif /* SCORE_TDEP_H */
-- 
1.8.4.2

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

* [PATCH 10/12] TILEGX Linux: Fill 'collect_regset' in regset structure.
  2014-05-26 16:37 [PATCH 00/12] Regset rework preparations part 2 Andreas Arnez
@ 2014-05-26 16:37 ` Andreas Arnez
  2014-05-26 16:37 ` [PATCH 09/12] SCORE: " Andreas Arnez
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Andreas Arnez @ 2014-05-26 16:37 UTC (permalink / raw)
  To: gdb-patches; +Cc: Jiong Wang

gdb/
	* tilegx-linux-tdep.c (tilegx_linux_supply_regset): Delete
	function.  Move logic to...
	(tilegx_linux_regmap): ... this new register map.
	(TILEGX_GREGS_SIZE): New enum value.
	(tilegx_linux_regset): Refer to register map, replace supply
	method by regcache_supply_regset, and add collect method.
---
 gdb/tilegx-linux-tdep.c | 37 +++++++++++++++----------------------
 1 file changed, 15 insertions(+), 22 deletions(-)

diff --git a/gdb/tilegx-linux-tdep.c b/gdb/tilegx-linux-tdep.c
index 98b03db..4169433 100644
--- a/gdb/tilegx-linux-tdep.c
+++ b/gdb/tilegx-linux-tdep.c
@@ -73,34 +73,27 @@ static const struct tramp_frame tilegx_linux_rt_sigframe =
   tilegx_linux_sigframe_init
 };
 
-/* Supply raw registers from REGCACHE to REGS.  */
+/* Register map; must match struct pt_regs in "ptrace.h".  */
 
-static void
-tilegx_linux_supply_regset (const struct regset *regset,
-			    struct regcache *regcache,
-			    int regnum, const void *regs, size_t len)
-{
-  struct gdbarch *arch = get_regcache_arch (regcache);
-  const char *ptr = regs;
-  int i;
-
-  /* This logic must match that of struct pt_regs in "ptrace.h".  */
-  for (i = 0; i < TILEGX_NUM_EASY_REGS + 2; i++, ptr += tilegx_reg_size)
-    {
-      int gri = (i < TILEGX_NUM_EASY_REGS)
-                 ? i : (i == TILEGX_NUM_EASY_REGS)
-                        ? TILEGX_PC_REGNUM : TILEGX_FAULTNUM_REGNUM;
+static const struct regcache_map_entry tilegx_linux_regmap[] =
+  {
+    { TILEGX_NUM_EASY_REGS, 0 },
+    { 1, TILEGX_PC_REGNUM },
+    { 1, TILEGX_FAULTNUM_REGNUM },
+    { 0 }
+  };
 
-      if (regnum == gri || regnum == -1)
-	regcache_raw_supply (regcache, gri, ptr);
-    }
-}
+enum
+{
+  TILEGX_GREGS_SIZE = (TILEGX_NUM_EASY_REGS + 2) * tilegx_reg_size
+};
 
 /* TILE-Gx Linux kernel register set.  */
+
 static const struct regset tilegx_linux_regset =
 {
-  NULL,
-  tilegx_linux_supply_regset
+  tilegx_linux_regmap,
+  regcache_supply_regset, regcache_collect_regset
 };
 
 static const struct regset *
-- 
1.8.4.2

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

* [PATCH 03/12] AARCH64 Linux: Fill 'collect_regset' in regset structures.
  2014-05-26 16:37 [PATCH 00/12] Regset rework preparations part 2 Andreas Arnez
                   ` (7 preceding siblings ...)
  2014-05-26 16:37 ` [PATCH 11/12] M68K Linux: Define regset structures Andreas Arnez
@ 2014-05-26 16:37 ` Andreas Arnez
  2014-05-27 21:36   ` Yufeng Zhang
  2014-05-26 16:37 ` [PATCH 04/12] ALPHA " Andreas Arnez
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 25+ messages in thread
From: Andreas Arnez @ 2014-05-26 16:37 UTC (permalink / raw)
  To: gdb-patches; +Cc: Richard Earnshaw

In order to provide 'collect_regset' support, the generic function
regcache_collect_regset is exploited.  Since this requires writing
appropriate register maps, these can be used for supply_regset as
well.

gdb/
	* aarch64-linux-nat.c (fill_gregset, fill_fpregset): Replace logic
	by call to regcache_collect_regset.
	(supply_gregset, supply_fpregset): Call regcache_supply_regset
	instead of aarch64_linux_supply_gregset/_fpregset.
	* aarch64-linux-tdep.c (AARCH64_LINUX_SIZEOF_GREGSET)
	(AARCH64_LINUX_SIZEOF_FPREGSET): Delete macros here, move to
	header file instead.
	(aarch64_linux_supply_gregset, supply_gregset_from_core)
	(aarch64_linux_suply_fpregset, supply_fpregset_from_core): Delete
	functions.  Move logic to ...
	(aarch64_linux_gregmap, aarch64_linux_fpregmap): ... these new
	register maps.
	(aarch64_linux_gregset, aarch64_linux_fpregset): Make global,
	refer to new register maps, replace *_regset_from_core by
	regcache_supply_regset, and also use regcache_collect_regset.
	* aarch64-linux-tdep.h: Include "regset.h".
	(aarch64_linux_supply_gregset, aarch64_linux_supply_fpregset):
	Delete prototypes.
	(AARCH64_LINUX_SIZEOF_GREGSET, AARCH64_LINUX_SIZEOF_FPREGSET): New
	macros, moved from C source file.
	(aarch64_linux_gregset, aarch64_linux_fpregset): New global
	variable declarations.
---
 gdb/aarch64-linux-nat.c  | 38 +++++++-------------
 gdb/aarch64-linux-tdep.c | 90 +++++++++++++-----------------------------------
 gdb/aarch64-linux-tdep.h | 18 +++++++---
 3 files changed, 48 insertions(+), 98 deletions(-)

diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index 877e702..4ae789b 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -616,14 +616,9 @@ void
 fill_gregset (const struct regcache *regcache,
 	      gdb_gregset_t *gregsetp, int regno)
 {
-  gdb_byte *gregs_buf = (gdb_byte *) gregsetp;
-  int i;
-
-  for (i = AARCH64_X0_REGNUM; i <= AARCH64_CPSR_REGNUM; i++)
-    if (regno == -1 || regno == i)
-      regcache_raw_collect (regcache, i,
-			    gregs_buf + X_REGISTER_SIZE
-			    * (i - AARCH64_X0_REGNUM));
+  regcache_collect_regset (&aarch64_linux_gregset, regcache,
+			   regno, (gdb_byte *) gregsetp,
+			   AARCH64_LINUX_SIZEOF_GREGSET);
 }
 
 /* Fill GDB's register array with the general-purpose register values
@@ -632,7 +627,9 @@ fill_gregset (const struct regcache *regcache,
 void
 supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
 {
-  aarch64_linux_supply_gregset (regcache, (const gdb_byte *) gregsetp);
+  regcache_supply_regset (&aarch64_linux_gregset, regcache, -1,
+			  (const gdb_byte *) gregsetp,
+			  AARCH64_LINUX_SIZEOF_GREGSET);
 }
 
 /* Fill register REGNO (if it is a floating-point register) in
@@ -643,22 +640,9 @@ void
 fill_fpregset (const struct regcache *regcache,
 	       gdb_fpregset_t *fpregsetp, int regno)
 {
-  gdb_byte *fpregs_buf = (gdb_byte *) fpregsetp;
-  int i;
-
-  for (i = AARCH64_V0_REGNUM; i <= AARCH64_V31_REGNUM; i++)
-    if (regno == -1 || regno == i)
-      regcache_raw_collect (regcache, i,
-			    fpregs_buf + V_REGISTER_SIZE
-			    * (i - AARCH64_V0_REGNUM));
-
-  if (regno == -1 || regno == AARCH64_FPSR_REGNUM)
-    regcache_raw_collect (regcache, AARCH64_FPSR_REGNUM,
-			  fpregs_buf + V_REGISTER_SIZE * 32);
-
-  if (regno == -1 || regno == AARCH64_FPCR_REGNUM)
-    regcache_raw_collect (regcache, AARCH64_FPCR_REGNUM,
-			  fpregs_buf + V_REGISTER_SIZE * 32 + 4);
+  regcache_collect_regset (&aarch64_linux_fpregset, regcache,
+			   regno, (gdb_byte *) fpregsetp,
+			   AARCH64_LINUX_SIZEOF_FPREGSET);
 }
 
 /* Fill GDB's register array with the floating-point register values
@@ -667,7 +651,9 @@ fill_fpregset (const struct regcache *regcache,
 void
 supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
 {
-  aarch64_linux_supply_fpregset (regcache, (const gdb_byte *) fpregsetp);
+  regcache_supply_regset (&aarch64_linux_fpregset, regcache, -1,
+			  (const gdb_byte *) fpregsetp,
+			  AARCH64_LINUX_SIZEOF_FPREGSET);
 }
 
 /* Called when resuming a thread.
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 30ed73f..b3eaa95 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -41,16 +41,6 @@
 #include "user-regs.h"
 #include <ctype.h>
 
-/* The general-purpose regset consists of 31 X registers, plus SP, PC,
-   and PSTATE registers, as defined in the AArch64 port of the Linux
-   kernel.  */
-#define AARCH64_LINUX_SIZEOF_GREGSET  (34 * X_REGISTER_SIZE)
-
-/* The fp regset consists of 32 V registers, plus FPCR and FPSR which
-   are 4 bytes wide each, and the whole structure is padded to 128 bit
-   alignment.  */
-#define AARCH64_LINUX_SIZEOF_FPREGSET (33 * V_REGISTER_SIZE)
-
 /* Signal frame handling.
 
       +------------+  ^
@@ -190,71 +180,37 @@ static const struct tramp_frame aarch64_linux_rt_sigframe =
   aarch64_linux_sigframe_init
 };
 
-/* Fill GDB's register array with the general-purpose register values
-   in the buffer pointed by GREGS_BUF.  */
-
-void
-aarch64_linux_supply_gregset (struct regcache *regcache,
-			      const gdb_byte *gregs_buf)
-{
-  int regno;
-
-  for (regno = AARCH64_X0_REGNUM; regno <= AARCH64_CPSR_REGNUM; regno++)
-    regcache_raw_supply (regcache, regno,
-			 gregs_buf + X_REGISTER_SIZE
-			 * (regno - AARCH64_X0_REGNUM));
-}
-
-/* The "supply_regset" function for the general-purpose register set.  */
-
-static void
-supply_gregset_from_core (const struct regset *regset,
-			  struct regcache *regcache,
-			  int regnum, const void *regbuf, size_t len)
-{
-  aarch64_linux_supply_gregset (regcache, (const gdb_byte *) regbuf);
-}
-
-/* Fill GDB's register array with the floating-point register values
-   in the buffer pointed by FPREGS_BUF.  */
+/* Register maps.  */
 
-void
-aarch64_linux_supply_fpregset (struct regcache *regcache,
-			       const gdb_byte *fpregs_buf)
-{
-  int regno;
-
-  for (regno = AARCH64_V0_REGNUM; regno <= AARCH64_V31_REGNUM; regno++)
-    regcache_raw_supply (regcache, regno,
-			 fpregs_buf + V_REGISTER_SIZE
-			 * (regno - AARCH64_V0_REGNUM));
-
-  regcache_raw_supply (regcache, AARCH64_FPSR_REGNUM,
-		       fpregs_buf + V_REGISTER_SIZE * 32);
-  regcache_raw_supply (regcache, AARCH64_FPCR_REGNUM,
-		       fpregs_buf + V_REGISTER_SIZE * 32 + 4);
-}
-
-/* The "supply_regset" function for the floating-point register set.  */
+static const struct regcache_map_entry aarch64_linux_gregmap[] =
+  {
+    { 31, AARCH64_X0_REGNUM },	/* x0 ... x30 */
+    { 1, AARCH64_SP_REGNUM },
+    { 1, AARCH64_PC_REGNUM },
+    { 1, AARCH64_CPSR_REGNUM },
+    { 0 }
+  };
 
-static void
-supply_fpregset_from_core (const struct regset *regset,
-			   struct regcache *regcache,
-			   int regnum, const void *regbuf, size_t len)
-{
-  aarch64_linux_supply_fpregset (regcache, (const gdb_byte *) regbuf);
-}
+static const struct regcache_map_entry aarch64_linux_fpregmap[] =
+  {
+    { 32, AARCH64_V0_REGNUM },	/* v0 ... v31 */
+    { 1, AARCH64_FPSR_REGNUM },
+    { 1, AARCH64_FPCR_REGNUM },
+    { 0 }
+  };
 
-/* Register set definitions. */
+/* Register set definitions.  */
 
-static const struct regset aarch64_linux_gregset =
+const struct regset aarch64_linux_gregset =
   {
-    NULL, supply_gregset_from_core, NULL
+    aarch64_linux_gregmap,
+    regcache_supply_regset, regcache_collect_regset
   };
 
-static const struct regset aarch64_linux_fpregset =
+const struct regset aarch64_linux_fpregset =
   {
-    NULL, supply_fpregset_from_core, NULL
+    aarch64_linux_fpregmap,
+    regcache_supply_regset, regcache_collect_regset
   };
 
 /* Implement the "regset_from_core_section" gdbarch method.  */
diff --git a/gdb/aarch64-linux-tdep.h b/gdb/aarch64-linux-tdep.h
index 48c7092..2e1de60 100644
--- a/gdb/aarch64-linux-tdep.h
+++ b/gdb/aarch64-linux-tdep.h
@@ -18,9 +18,17 @@
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-struct regcache;
+#include "regset.h"
 
-extern void aarch64_linux_supply_gregset (struct regcache *regcache,
-					  const gdb_byte *gregs_buf);
-extern void aarch64_linux_supply_fpregset (struct regcache *regcache,
-					   const gdb_byte *fpregs_buf);
+/* The general-purpose regset consists of 31 X registers, plus SP, PC,
+   and PSTATE registers, as defined in the AArch64 port of the Linux
+   kernel.  */
+#define AARCH64_LINUX_SIZEOF_GREGSET  (34 * X_REGISTER_SIZE)
+
+/* The fp regset consists of 32 V registers, plus FPCR and FPSR which
+   are 4 bytes wide each, and the whole structure is padded to 128 bit
+   alignment.  */
+#define AARCH64_LINUX_SIZEOF_FPREGSET (33 * V_REGISTER_SIZE)
+
+extern const struct regset aarch64_linux_gregset;
+extern const struct regset aarch64_linux_fpregset;
-- 
1.8.4.2

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

* [PATCH 05/12] FRV Linux: Fill 'collect_regset' in regset structures.
  2014-05-26 16:37 [PATCH 00/12] Regset rework preparations part 2 Andreas Arnez
  2014-05-26 16:37 ` [PATCH 10/12] TILEGX Linux: Fill 'collect_regset' in regset structure Andreas Arnez
  2014-05-26 16:37 ` [PATCH 09/12] SCORE: " Andreas Arnez
@ 2014-05-26 16:37 ` Andreas Arnez
  2014-05-26 16:37 ` [PATCH 06/12] HPPA " Andreas Arnez
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Andreas Arnez @ 2014-05-26 16:37 UTC (permalink / raw)
  To: gdb-patches

gdb/
	* frv-linux-tdep.c (FRV_PT_PSR, FRV_PT_ISR, FRV_PT_CCR)
	(FRV_PT_CCCR, FRV_PT_LR, FRV_PT_LCR, FRV_PT_PC, FRV_PT_GNER0)
	(FRV_PT_GNER1, FRV_PT_IACC0H, FRV_PT_IACC0L, FRV_PT_GR)
	(FRV_PT_TBR, FRV_PT_GR, FRV_PT_EXEC_FDPIC_LOADMAP)
	(FRV_PT_INTERP_FDPIC_LOADMAP): Delete macros.
	(frv_linux_gregmap, frv_linux_fpregmap): New register maps.
	(frv_linux_supply_gregset): Replace main logic by call to
	regcache_supply_regset, but keep clearing gr32-gr63.
	(frv_linux_supply_fpregset): Delete function.
	(frv_linux_gregset): Refer to appropriate register map and add
	regcache_collect_regset as the collect method.
	(frv_linux_fpregset): Likewise.  Also exchange the supply method
	by regcache_supply_regset.
---
 gdb/frv-linux-tdep.c | 141 ++++++++++++++++++++-------------------------------
 1 file changed, 54 insertions(+), 87 deletions(-)

diff --git a/gdb/frv-linux-tdep.c b/gdb/frv-linux-tdep.c
index fb163a8..104e6c1 100644
--- a/gdb/frv-linux-tdep.c
+++ b/gdb/frv-linux-tdep.c
@@ -360,37 +360,52 @@ typedef struct
   frv_elf_fpreg_t fsr[1];
 } frv_elf_fpregset_t;
 
-/* Constants for accessing elements of frv_elf_gregset_t.  */
-
-#define FRV_PT_PSR 0
-#define	FRV_PT_ISR 1
-#define FRV_PT_CCR 2
-#define FRV_PT_CCCR 3
-#define FRV_PT_LR 4
-#define FRV_PT_LCR 5
-#define FRV_PT_PC 6
-#define FRV_PT_GNER0 10
-#define FRV_PT_GNER1 11
-#define FRV_PT_IACC0H 12
-#define FRV_PT_IACC0L 13
-
-/* Note: Only 32 of the GRs will be found in the corefile.  */
-#define FRV_PT_GR(j)	( 14 + (j))	/* GRj for 0<=j<=63.  */
-
-#define FRV_PT_TBR FRV_PT_GR(0)		/* gr0 is always 0, so TBR is stuffed
-					   there.  */
-
-/* Technically, the loadmap addresses are not part of `pr_reg' as
-   found in the elf_prstatus struct.  The fields which communicate the
-   loadmap address appear (by design) immediately after `pr_reg'
-   though, and the BFD function elf32_frv_grok_prstatus() has been
-   implemented to include these fields in the register section that it
-   extracts from the core file.  So, for our purposes, they may be
-   viewed as registers.  */
-
-#define FRV_PT_EXEC_FDPIC_LOADMAP 46
-#define FRV_PT_INTERP_FDPIC_LOADMAP 47
-
+/* Register maps.  */
+
+static const struct regcache_map_entry frv_linux_gregmap[] =
+  {
+    { 1, psr_regnum },
+    { 4, REGCACHE_MAP_SKIP_BYTES }, /* isr */
+    { 1, ccr_regnum },
+    { 1, cccr_regnum },
+    { 1, lr_regnum },
+    { 1, lcr_regnum },
+    { 1, pc_regnum },
+    { 4, REGCACHE_MAP_SKIP_BYTES }, /* __status */
+    { 4, REGCACHE_MAP_SKIP_BYTES }, /* syscallno */
+    { 4, REGCACHE_MAP_SKIP_BYTES }, /* orig_gr8 */
+    { 1, gner0_regnum },
+    { 1, gner1_regnum },
+    { 8, REGCACHE_MAP_SKIP_BYTES }, /* iacc0 */
+    { 1, tbr_regnum },
+    { 31, first_gpr_regnum + 1 }, /* gr1 ... gr31 */
+
+    /* Technically, the loadmap addresses are not part of `pr_reg' as
+       found in the elf_prstatus struct.  The fields which communicate
+       the loadmap address appear (by design) immediately after
+       `pr_reg' though, and the BFD function elf32_frv_grok_prstatus()
+       has been implemented to include these fields in the register
+       section that it extracts from the core file.  So, for our
+       purposes, they may be viewed as registers.  */
+
+    { 1, fdpic_loadmap_exec_regnum },
+    { 1, fdpic_loadmap_interp_regnum },
+    { 0 }
+  };
+
+static const struct regcache_map_entry frv_linux_fpregmap[] =
+  {
+    { 64, first_fpr_regnum },	/* fr0 ... fr63 */
+    { 1, fner0_regnum },
+    { 1, fner1_regnum },
+    { 1, msr0_regnum },
+    { 1, msr1_regnum },
+    { 8, acc0_regnum },		/* acc0 ... acc7 */
+    { 1, accg0123_regnum },
+    { 1, accg4567_regnum },
+    { 1, fsr0_regnum },
+    { 0 }
+  };
 
 /* Unpack an frv_elf_gregset_t into GDB's register cache.  */
 
@@ -401,7 +416,6 @@ frv_linux_supply_gregset (const struct regset *regset,
 {
   int regi;
   char zerobuf[MAX_REGISTER_SIZE];
-  const frv_elf_gregset_t *gregsetp = gregs;
 
   memset (zerobuf, 0, MAX_REGISTER_SIZE);
 
@@ -409,72 +423,25 @@ frv_linux_supply_gregset (const struct regset *regset,
      this slot.  */
   regcache_raw_supply (regcache, first_gpr_regnum, zerobuf);
 
-  for (regi = first_gpr_regnum + 1; regi <= last_gpr_regnum; regi++)
-    {
-      if (regi >= first_gpr_regnum + 32)
-	regcache_raw_supply (regcache, regi, zerobuf);
-      else
-	regcache_raw_supply (regcache, regi,
-			     gregsetp->reg[FRV_PT_GR (regi
-						      - first_gpr_regnum)]);
-    }
-
-  regcache_raw_supply (regcache, pc_regnum, gregsetp->reg[FRV_PT_PC]);
-  regcache_raw_supply (regcache, psr_regnum, gregsetp->reg[FRV_PT_PSR]);
-  regcache_raw_supply (regcache, ccr_regnum, gregsetp->reg[FRV_PT_CCR]);
-  regcache_raw_supply (regcache, cccr_regnum, gregsetp->reg[FRV_PT_CCCR]);
-  regcache_raw_supply (regcache, lr_regnum, gregsetp->reg[FRV_PT_LR]);
-  regcache_raw_supply (regcache, lcr_regnum, gregsetp->reg[FRV_PT_LCR]);
-  regcache_raw_supply (regcache, gner0_regnum, gregsetp->reg[FRV_PT_GNER0]);
-  regcache_raw_supply (regcache, gner1_regnum, gregsetp->reg[FRV_PT_GNER1]);
-  regcache_raw_supply (regcache, tbr_regnum, gregsetp->reg[FRV_PT_TBR]);
-  regcache_raw_supply (regcache, fdpic_loadmap_exec_regnum,
-                       gregsetp->reg[FRV_PT_EXEC_FDPIC_LOADMAP]);
-  regcache_raw_supply (regcache, fdpic_loadmap_interp_regnum,
-                       gregsetp->reg[FRV_PT_INTERP_FDPIC_LOADMAP]);
-}
-
-/* Unpack an frv_elf_fpregset_t into GDB's register cache.  */
-
-static void
-frv_linux_supply_fpregset (const struct regset *regset,
-                           struct regcache *regcache,
-			   int regnum, const void *gregs, size_t len)
-{
-  int regi;
-  const frv_elf_fpregset_t *fpregsetp = gregs;
-
-  for (regi = first_fpr_regnum; regi <= last_fpr_regnum; regi++)
-    regcache_raw_supply (regcache, regi,
-			 fpregsetp->fr[regi - first_fpr_regnum]);
-
-  regcache_raw_supply (regcache, fner0_regnum, fpregsetp->fner[0]);
-  regcache_raw_supply (regcache, fner1_regnum, fpregsetp->fner[1]);
-
-  regcache_raw_supply (regcache, msr0_regnum, fpregsetp->msr[0]);
-  regcache_raw_supply (regcache, msr1_regnum, fpregsetp->msr[1]);
+  /* Fill gr32, ..., gr63 with zeros. */
+  for (regi = first_gpr_regnum + 32; regi <= last_gpr_regnum; regi++)
+    regcache_raw_supply (regcache, regi, zerobuf);
 
-  for (regi = acc0_regnum; regi <= acc7_regnum; regi++)
-    regcache_raw_supply (regcache, regi, fpregsetp->acc[regi - acc0_regnum]);
-
-  regcache_raw_supply (regcache, accg0123_regnum, fpregsetp->accg);
-  regcache_raw_supply (regcache, accg4567_regnum, fpregsetp->accg + 4);
-
-  regcache_raw_supply (regcache, fsr0_regnum, fpregsetp->fsr[0]);
+  regcache_supply_regset (regset, regcache, regnum, gregs, len);
 }
 
 /* FRV Linux kernel register sets.  */
 
 static const struct regset frv_linux_gregset =
 {
-  NULL,
-  frv_linux_supply_gregset
+  frv_linux_gregmap,
+  frv_linux_supply_gregset, regcache_collect_regset
 };
 
 static const struct regset frv_linux_fpregset =
 {
-  NULL,
-  frv_linux_supply_fpregset
+  frv_linux_fpregmap,
+  regcache_supply_regset, regcache_collect_regset
 };
 
 static const struct regset *
-- 
1.8.4.2

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

* [PATCH 02/12] S390: Migrate to regcache_supply/collect_regset.
  2014-05-26 16:37 [PATCH 00/12] Regset rework preparations part 2 Andreas Arnez
                   ` (5 preceding siblings ...)
  2014-05-26 16:37 ` [PATCH 01/12] regcache: Add functions suitable for regset_supply/collect Andreas Arnez
@ 2014-05-26 16:37 ` Andreas Arnez
  2014-05-26 16:37 ` [PATCH 11/12] M68K Linux: Define regset structures Andreas Arnez
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Andreas Arnez @ 2014-05-26 16:37 UTC (permalink / raw)
  To: gdb-patches; +Cc: Ulrich Weigand

Rather than supplying own supply/collect functions, use the generic
functions regcache_supply_regset and regcache_collect_regset instead.
The register maps are rewritten accordingly and become much shorter
(and better readable) than before.

gdb/
	* s390-linux-nat.c: Include "regset.h".
	(regmap_gregset): Delete macro.
	(s390_64_regmap_gregset): New register map for
	regcache_supply/_collect_regset.
	(s390_64_gregset): New regset.
	(S390_PSWM_OFFSET, S390_PSWA_OFFSET): New macros.
	(regmap_fpregset): Delete macro.
	(s390_native_supply, s390_native_collect): Delete functions.
	(supply_gregset, fill_gregset): Replace s390-specific regmap
	handling by a call to regcache_supply/_collect_regset.
	(supply_fpregset, fill_fpregset): Call regcache_supply/
	_collect_regset instead of s390_native_supply/_collect.
	(fetch_regset, store_regset): Likewise.  Also change the last
	parameter to a regset instead of a regmap.
	(s390_linux_fetch_inferior_registers)
	(390_linux_store_inferior_registers): Adjust last parameter in
	calls to fetch_regset and store_regset.
	* s390-linux-tdep.c (s390_regmap_gregset): Rename to...
	(s390_gregmap): ... this.  Also make static const and convert to
	regcache_map_entry format.
	(s390x_regmap_gregset): Delete.
	(s390_regmap_fpregset): Rename to...
	(s390_fpregmap): ... this.  Make static const and convert to
	regcache_map_entry format.
	(s390_regmap_upper, s390_regmap_last_break)
	(s390x_regmap_last_break, s390_regmap_system_call)
	(s390_regmap_tdb): Likewise.
	(s390_supply_regset, s390_collect_regset): Remove functions.
	(s390_supply_tdb_regset): Call regcache_supply_regset instead of
	s390_supply_regset.
	(s390_gregset, s390_fpregset, s390_upper_regset)
	(s390_last_break_regset, s390x_last_break_regset)
	(s390_system_call_regset, s390_tdb_regset): Make global and
	replace s390_supply/_collect_regset by regcache_supply/
	_collect_regset.
	(s390x_gregset): Delete.
	(s390_gdbarch_init): Replace s390x_gregset by s390_gregset.
	* s390-linux-tdep.h (s390_regmap_gregset, s390x_regmap_gregset)
	(s390_regmap_fpregset, s390_regmap_last_break)
	(s390x_regmap_last_break, s390_regmap_system_call)
	(s390_regmap_tdb): Delete global variable declarations.
	(s390_gregset, s390_fpregset, s390_last_break_regset)
	(s390x_last_break_regset, s390_system_call_regset)
	(s390_tdb_regset): New global variable declarations.
---
 gdb/s390-linux-nat.c  | 177 ++++++++++++++------------------
 gdb/s390-linux-tdep.c | 278 +++++++++++---------------------------------------
 gdb/s390-linux-tdep.h |  13 ++-
 3 files changed, 140 insertions(+), 328 deletions(-)

diff --git a/gdb/s390-linux-nat.c b/gdb/s390-linux-nat.c
index 45db7c9..8d8cf59 100644
--- a/gdb/s390-linux-nat.c
+++ b/gdb/s390-linux-nat.c
@@ -26,6 +26,7 @@
 #include "linux-nat.h"
 #include "auxv.h"
 #include "gregset.h"
+#include "regset.h"
 
 #include "s390-linux-tdep.h"
 #include "elf/common.h"
@@ -49,42 +50,46 @@ static int have_regset_last_break = 0;
 static int have_regset_system_call = 0;
 static int have_regset_tdb = 0;
 
-/* Map registers to gregset/ptrace offsets.
-   These arrays are defined in s390-tdep.c.  */
+/* Register map for 32-bit executables running under a 64-bit
+   kernel.  */
 
 #ifdef __s390x__
-#define regmap_gregset s390x_regmap_gregset
-#else
-#define regmap_gregset s390_regmap_gregset
+static const struct regcache_map_entry s390_64_regmap_gregset[] =
+  {
+    /* Skip PSWM and PSWA, since they must be handled specially.  */
+    { 16, REGCACHE_MAP_SKIP_BYTES },
+    { 1, S390_R0_UPPER_REGNUM }, { 1, S390_R0_REGNUM },
+    { 1, S390_R1_UPPER_REGNUM }, { 1, S390_R1_REGNUM },
+    { 1, S390_R2_UPPER_REGNUM }, { 1, S390_R2_REGNUM },
+    { 1, S390_R3_UPPER_REGNUM }, { 1, S390_R3_REGNUM },
+    { 1, S390_R4_UPPER_REGNUM }, { 1, S390_R4_REGNUM },
+    { 1, S390_R5_UPPER_REGNUM }, { 1, S390_R5_REGNUM },
+    { 1, S390_R6_UPPER_REGNUM }, { 1, S390_R6_REGNUM },
+    { 1, S390_R7_UPPER_REGNUM }, { 1, S390_R7_REGNUM },
+    { 1, S390_R8_UPPER_REGNUM }, { 1, S390_R8_REGNUM },
+    { 1, S390_R9_UPPER_REGNUM }, { 1, S390_R9_REGNUM },
+    { 1, S390_R10_UPPER_REGNUM }, { 1, S390_R10_REGNUM },
+    { 1, S390_R11_UPPER_REGNUM }, { 1, S390_R11_REGNUM },
+    { 1, S390_R12_UPPER_REGNUM }, { 1, S390_R12_REGNUM },
+    { 1, S390_R13_UPPER_REGNUM }, { 1, S390_R13_REGNUM },
+    { 1, S390_R14_UPPER_REGNUM }, { 1, S390_R14_REGNUM },
+    { 1, S390_R15_UPPER_REGNUM }, { 1, S390_R15_REGNUM },
+    { 16, S390_A0_REGNUM },
+    { 4, REGCACHE_MAP_SKIP_BYTES }, { 1, S390_ORIG_R2_REGNUM },
+    { 0 }
+  };
+
+static const struct regset s390_64_gregset =
+  {
+    s390_64_regmap_gregset,
+    regcache_supply_regset,
+    regcache_collect_regset
+  };
+
+#define S390_PSWM_OFFSET 0
+#define S390_PSWA_OFFSET 8
 #endif
 
-#define regmap_fpregset s390_regmap_fpregset
-
-/* Fill the regset described by MAP into REGCACHE, using the values
-   from REGP.  The MAP array represents each register as a pair
-   (offset, regno) of short integers and is terminated with -1. */
-
-static void
-s390_native_supply (struct regcache *regcache, const short *map,
-		    const gdb_byte *regp)
-{
-  for (; map[0] >= 0; map += 2)
-    regcache_raw_supply (regcache, map[1], regp ? regp + map[0] : NULL);
-}
-
-/* Collect the register REGNO out of the regset described by MAP from
-   REGCACHE into REGP.  If REGNO == -1, do this for all registers in
-   this regset. */
-
-static void
-s390_native_collect (const struct regcache *regcache, const short *map,
-		     int regno, gdb_byte *regp)
-{
-  for (; map[0] >= 0; map += 2)
-    if (regno == -1 || regno == map[1])
-      regcache_raw_collect (regcache, map[1], regp + map[0]);
-}
-
 /* Fill GDB's register array with the general-purpose register values
    in *REGP.
 
@@ -100,28 +105,15 @@ supply_gregset (struct regcache *regcache, const gregset_t *regp)
   if (gdbarch_ptr_bit (gdbarch) == 32)
     {
       enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-      ULONGEST pswm = 0, pswa = 0;
+      ULONGEST pswm, pswa;
       gdb_byte buf[4];
-      const short *map;
-
-      for (map = regmap_gregset; map[0] >= 0; map += 2)
-	{
-	  const gdb_byte *p = (const gdb_byte *) regp + map[0];
-	  int regno = map[1];
-
-	  if (regno == S390_PSWM_REGNUM)
-	    pswm = extract_unsigned_integer (p, 8, byte_order);
-	  else if (regno == S390_PSWA_REGNUM)
-	    pswa = extract_unsigned_integer (p, 8, byte_order);
-	  else
-	    {
-	      if ((regno >= S390_R0_REGNUM && regno <= S390_R15_REGNUM)
-		  || regno == S390_ORIG_R2_REGNUM)
-		p += 4;
-	      regcache_raw_supply (regcache, regno, p);
-	    }
-	}
 
+      regcache_supply_regset (&s390_64_gregset, regcache, -1,
+			      regp, sizeof (gregset_t));
+      pswm = extract_unsigned_integer ((const gdb_byte *) regp
+				       + S390_PSWM_OFFSET, 8, byte_order);
+      pswa = extract_unsigned_integer ((const gdb_byte *) regp
+				       + S390_PSWA_OFFSET, 8, byte_order);
       store_unsigned_integer (buf, 4, byte_order, (pswm >> 32) | 0x80000);
       regcache_raw_supply (regcache, S390_PSWM_REGNUM, buf);
       store_unsigned_integer (buf, 4, byte_order,
@@ -131,7 +123,8 @@ supply_gregset (struct regcache *regcache, const gregset_t *regp)
     }
 #endif
 
-  s390_native_supply (regcache, regmap_gregset, (const gdb_byte *) regp);
+  regcache_supply_regset (&s390_gregset, regcache, -1, regp,
+			  sizeof (gregset_t));
 }
 
 /* Fill register REGNO (if it is a general-purpose register) in
@@ -145,28 +138,8 @@ fill_gregset (const struct regcache *regcache, gregset_t *regp, int regno)
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   if (gdbarch_ptr_bit (gdbarch) == 32)
     {
-      gdb_byte *psw_p[2];
-      const short *map;
-
-      for (map = regmap_gregset; map[0] >= 0; map += 2)
-	{
-	  gdb_byte *p = (gdb_byte *) regp + map[0];
-	  int reg = map[1];
-
-	  if (reg >= S390_PSWM_REGNUM && reg <= S390_PSWA_REGNUM)
-	    psw_p[reg - S390_PSWM_REGNUM] = p;
-
-	  else if (regno == -1 || regno == reg)
-	    {
-	      if ((reg >= S390_R0_REGNUM && reg <= S390_R15_REGNUM)
-		  || reg == S390_ORIG_R2_REGNUM)
-		{
-		  memset (p, 0, 4);
-		  p += 4;
-		}
-	      regcache_raw_collect (regcache, reg, p);
-	    }
-	}
+      regcache_collect_regset (&s390_64_gregset, regcache, regno,
+			       regp, sizeof (gregset_t));
 
       if (regno == -1
 	  || regno == S390_PSWM_REGNUM || regno == S390_PSWA_REGNUM)
@@ -181,18 +154,19 @@ fill_gregset (const struct regcache *regcache, gregset_t *regp, int regno)
 	  pswa = extract_unsigned_integer (buf, 4, byte_order);
 
 	  if (regno == -1 || regno == S390_PSWM_REGNUM)
-	    store_unsigned_integer (psw_p[0], 8, byte_order,
-				    ((pswm & 0xfff7ffff) << 32) |
+	    store_unsigned_integer ((gdb_byte *) regp + S390_PSWM_OFFSET, 8,
+				    byte_order, ((pswm & 0xfff7ffff) << 32) |
 				    (pswa & 0x80000000));
 	  if (regno == -1 || regno == S390_PSWA_REGNUM)
-	    store_unsigned_integer (psw_p[1], 8, byte_order,
-				    pswa & 0x7fffffff);
+	    store_unsigned_integer ((gdb_byte *) regp + S390_PSWA_OFFSET, 8,
+				    byte_order, pswa & 0x7fffffff);
 	}
       return;
     }
 #endif
 
-  s390_native_collect (regcache, regmap_gregset, regno, (gdb_byte *) regp);
+  regcache_collect_regset (&s390_gregset, regcache, regno, regp,
+			   sizeof (gregset_t));
 }
 
 /* Fill GDB's register array with the floating-point register values
@@ -200,7 +174,8 @@ fill_gregset (const struct regcache *regcache, gregset_t *regp, int regno)
 void
 supply_fpregset (struct regcache *regcache, const fpregset_t *regp)
 {
-  s390_native_supply (regcache, regmap_fpregset, (const gdb_byte *) regp);
+  regcache_supply_regset (&s390_fpregset, regcache, -1, regp,
+			  sizeof (fpregset_t));
 }
 
 /* Fill register REGNO (if it is a general-purpose register) in
@@ -209,7 +184,8 @@ supply_fpregset (struct regcache *regcache, const fpregset_t *regp)
 void
 fill_fpregset (const struct regcache *regcache, fpregset_t *regp, int regno)
 {
-  s390_native_collect (regcache, regmap_fpregset, regno, (gdb_byte *) regp);
+  regcache_collect_regset (&s390_fpregset, regcache, regno, regp,
+			   sizeof (fpregset_t));
 }
 
 /* Find the TID for the current inferior thread to use with ptrace.  */
@@ -298,12 +274,13 @@ store_fpregs (const struct regcache *regcache, int tid, int regnum)
     perror_with_name (_("Couldn't write floating point status"));
 }
 
-/* Fetch all registers in the kernel's register set whose number is REGSET,
-   whose size is REGSIZE, and whose layout is described by REGMAP, from
-   process/thread TID and store their values in GDB's register cache.  */
+/* Fetch all registers in the kernel's register set whose number is
+   REGSET_ID, whose size is REGSIZE, and whose layout is described by
+   REGSET, from process/thread TID and store their values in GDB's
+   register cache.  */
 static void
 fetch_regset (struct regcache *regcache, int tid,
-	      int regset, int regsize, const short *regmap)
+	      int regset_id, int regsize, const struct regset *regset)
 {
   gdb_byte *buf = alloca (regsize);
   struct iovec iov;
@@ -311,23 +288,23 @@ fetch_regset (struct regcache *regcache, int tid,
   iov.iov_base = buf;
   iov.iov_len = regsize;
 
-  if (ptrace (PTRACE_GETREGSET, tid, (long) regset, (long) &iov) < 0)
+  if (ptrace (PTRACE_GETREGSET, tid, (long) regset_id, (long) &iov) < 0)
     {
       if (errno == ENODATA)
-	s390_native_supply (regcache, regmap, NULL);
+	regcache_supply_regset (regset, regcache, -1, NULL, regsize);
       else
 	perror_with_name (_("Couldn't get register set"));
     }
   else
-    s390_native_supply (regcache, regmap, buf);
+    regcache_supply_regset (regset, regcache, -1, buf, regsize);
 }
 
-/* Store all registers in the kernel's register set whose number is REGSET,
-   whose size is REGSIZE, and whose layout is described by REGMAP, from
-   GDB's register cache back to process/thread TID.  */
+/* Store all registers in the kernel's register set whose number is
+   REGSET_ID, whose size is REGSIZE, and whose layout is described by
+   REGSET, from GDB's register cache back to process/thread TID.  */
 static void
 store_regset (struct regcache *regcache, int tid,
-	      int regset, int regsize, const short *regmap)
+	      int regset_id, int regsize, const struct regset *regset)
 {
   gdb_byte *buf = alloca (regsize);
   struct iovec iov;
@@ -335,12 +312,12 @@ store_regset (struct regcache *regcache, int tid,
   iov.iov_base = buf;
   iov.iov_len = regsize;
 
-  if (ptrace (PTRACE_GETREGSET, tid, (long) regset, (long) &iov) < 0)
+  if (ptrace (PTRACE_GETREGSET, tid, (long) regset_id, (long) &iov) < 0)
     perror_with_name (_("Couldn't get register set"));
 
-  s390_native_collect (regcache, regmap, -1, buf);
+  regcache_collect_regset (regset, regcache, -1, buf, regsize);
 
-  if (ptrace (PTRACE_SETREGSET, tid, (long) regset, (long) &iov) < 0)
+  if (ptrace (PTRACE_SETREGSET, tid, (long) regset_id, (long) &iov) < 0)
     perror_with_name (_("Couldn't set register set"));
 }
 
@@ -379,17 +356,17 @@ s390_linux_fetch_inferior_registers (struct target_ops *ops,
     if (regnum == -1 || regnum == S390_LAST_BREAK_REGNUM)
       fetch_regset (regcache, tid, NT_S390_LAST_BREAK, 8,
 		    (gdbarch_ptr_bit (get_regcache_arch (regcache)) == 32
-		     ? s390_regmap_last_break : s390x_regmap_last_break));
+		     ? &s390_last_break_regset : &s390x_last_break_regset));
 
   if (have_regset_system_call)
     if (regnum == -1 || regnum == S390_SYSTEM_CALL_REGNUM)
       fetch_regset (regcache, tid, NT_S390_SYSTEM_CALL, 4,
-		    s390_regmap_system_call);
+		    &s390_system_call_regset);
 
   if (have_regset_tdb)
     if (regnum == -1 || S390_IS_TDBREGSET_REGNUM (regnum))
       fetch_regset (regcache, tid, NT_S390_TDB, s390_sizeof_tdbregset,
-		    s390_regmap_tdb);
+		    &s390_tdb_regset);
 }
 
 /* Store register REGNUM back into the child process.  If REGNUM is
@@ -411,7 +388,7 @@ s390_linux_store_inferior_registers (struct target_ops *ops,
   if (have_regset_system_call)
     if (regnum == -1 || regnum == S390_SYSTEM_CALL_REGNUM)
       store_regset (regcache, tid, NT_S390_SYSTEM_CALL, 4,
-		    s390_regmap_system_call);
+		    &s390_system_call_regset);
 }
 
 
diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index ea743b5..f67ba9c 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -420,204 +420,61 @@ s390_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
 
 /* Maps for register sets.  */
 
-const short s390_regmap_gregset[] =
+static const struct regcache_map_entry s390_gregmap[] =
   {
-    0x00, S390_PSWM_REGNUM,
-    0x04, S390_PSWA_REGNUM,
-    0x08, S390_R0_REGNUM,
-    0x0c, S390_R1_REGNUM,
-    0x10, S390_R2_REGNUM,
-    0x14, S390_R3_REGNUM,
-    0x18, S390_R4_REGNUM,
-    0x1c, S390_R5_REGNUM,
-    0x20, S390_R6_REGNUM,
-    0x24, S390_R7_REGNUM,
-    0x28, S390_R8_REGNUM,
-    0x2c, S390_R9_REGNUM,
-    0x30, S390_R10_REGNUM,
-    0x34, S390_R11_REGNUM,
-    0x38, S390_R12_REGNUM,
-    0x3c, S390_R13_REGNUM,
-    0x40, S390_R14_REGNUM,
-    0x44, S390_R15_REGNUM,
-    0x48, S390_A0_REGNUM,
-    0x4c, S390_A1_REGNUM,
-    0x50, S390_A2_REGNUM,
-    0x54, S390_A3_REGNUM,
-    0x58, S390_A4_REGNUM,
-    0x5c, S390_A5_REGNUM,
-    0x60, S390_A6_REGNUM,
-    0x64, S390_A7_REGNUM,
-    0x68, S390_A8_REGNUM,
-    0x6c, S390_A9_REGNUM,
-    0x70, S390_A10_REGNUM,
-    0x74, S390_A11_REGNUM,
-    0x78, S390_A12_REGNUM,
-    0x7c, S390_A13_REGNUM,
-    0x80, S390_A14_REGNUM,
-    0x84, S390_A15_REGNUM,
-    0x88, S390_ORIG_R2_REGNUM,
-    -1, -1
+    { 1, S390_PSWM_REGNUM },
+    { 1, S390_PSWA_REGNUM },
+    { 16, S390_R0_REGNUM },
+    { 16, S390_A0_REGNUM },
+    { 1, S390_ORIG_R2_REGNUM },
+    { 0 }
   };
 
-const short s390x_regmap_gregset[] =
+static const struct regcache_map_entry s390_fpregmap[] =
   {
-    0x00, S390_PSWM_REGNUM,
-    0x08, S390_PSWA_REGNUM,
-    0x10, S390_R0_REGNUM,
-    0x18, S390_R1_REGNUM,
-    0x20, S390_R2_REGNUM,
-    0x28, S390_R3_REGNUM,
-    0x30, S390_R4_REGNUM,
-    0x38, S390_R5_REGNUM,
-    0x40, S390_R6_REGNUM,
-    0x48, S390_R7_REGNUM,
-    0x50, S390_R8_REGNUM,
-    0x58, S390_R9_REGNUM,
-    0x60, S390_R10_REGNUM,
-    0x68, S390_R11_REGNUM,
-    0x70, S390_R12_REGNUM,
-    0x78, S390_R13_REGNUM,
-    0x80, S390_R14_REGNUM,
-    0x88, S390_R15_REGNUM,
-    0x90, S390_A0_REGNUM,
-    0x94, S390_A1_REGNUM,
-    0x98, S390_A2_REGNUM,
-    0x9c, S390_A3_REGNUM,
-    0xa0, S390_A4_REGNUM,
-    0xa4, S390_A5_REGNUM,
-    0xa8, S390_A6_REGNUM,
-    0xac, S390_A7_REGNUM,
-    0xb0, S390_A8_REGNUM,
-    0xb4, S390_A9_REGNUM,
-    0xb8, S390_A10_REGNUM,
-    0xbc, S390_A11_REGNUM,
-    0xc0, S390_A12_REGNUM,
-    0xc4, S390_A13_REGNUM,
-    0xc8, S390_A14_REGNUM,
-    0xcc, S390_A15_REGNUM,
-    0x10, S390_R0_UPPER_REGNUM,
-    0x18, S390_R1_UPPER_REGNUM,
-    0x20, S390_R2_UPPER_REGNUM,
-    0x28, S390_R3_UPPER_REGNUM,
-    0x30, S390_R4_UPPER_REGNUM,
-    0x38, S390_R5_UPPER_REGNUM,
-    0x40, S390_R6_UPPER_REGNUM,
-    0x48, S390_R7_UPPER_REGNUM,
-    0x50, S390_R8_UPPER_REGNUM,
-    0x58, S390_R9_UPPER_REGNUM,
-    0x60, S390_R10_UPPER_REGNUM,
-    0x68, S390_R11_UPPER_REGNUM,
-    0x70, S390_R12_UPPER_REGNUM,
-    0x78, S390_R13_UPPER_REGNUM,
-    0x80, S390_R14_UPPER_REGNUM,
-    0x88, S390_R15_UPPER_REGNUM,
-    0xd0, S390_ORIG_R2_REGNUM,
-    -1, -1
+    { 1, S390_FPC_REGNUM }, { 4, REGCACHE_MAP_SKIP_BYTES },
+    { 16, S390_F0_REGNUM },
+    { 0 }
   };
 
-const short s390_regmap_fpregset[] =
+static const struct regcache_map_entry s390_regmap_upper[] =
   {
-    0x00, S390_FPC_REGNUM,
-    0x08, S390_F0_REGNUM,
-    0x10, S390_F1_REGNUM,
-    0x18, S390_F2_REGNUM,
-    0x20, S390_F3_REGNUM,
-    0x28, S390_F4_REGNUM,
-    0x30, S390_F5_REGNUM,
-    0x38, S390_F6_REGNUM,
-    0x40, S390_F7_REGNUM,
-    0x48, S390_F8_REGNUM,
-    0x50, S390_F9_REGNUM,
-    0x58, S390_F10_REGNUM,
-    0x60, S390_F11_REGNUM,
-    0x68, S390_F12_REGNUM,
-    0x70, S390_F13_REGNUM,
-    0x78, S390_F14_REGNUM,
-    0x80, S390_F15_REGNUM,
-    -1, -1
+    { 16, S390_R0_UPPER_REGNUM },
+    { 0 }
   };
 
-const short s390_regmap_upper[] =
+static const struct regcache_map_entry s390_regmap_last_break[] =
   {
-    0x00, S390_R0_UPPER_REGNUM,
-    0x04, S390_R1_UPPER_REGNUM,
-    0x08, S390_R2_UPPER_REGNUM,
-    0x0c, S390_R3_UPPER_REGNUM,
-    0x10, S390_R4_UPPER_REGNUM,
-    0x14, S390_R5_UPPER_REGNUM,
-    0x18, S390_R6_UPPER_REGNUM,
-    0x1c, S390_R7_UPPER_REGNUM,
-    0x20, S390_R8_UPPER_REGNUM,
-    0x24, S390_R9_UPPER_REGNUM,
-    0x28, S390_R10_UPPER_REGNUM,
-    0x2c, S390_R11_UPPER_REGNUM,
-    0x30, S390_R12_UPPER_REGNUM,
-    0x34, S390_R13_UPPER_REGNUM,
-    0x38, S390_R14_UPPER_REGNUM,
-    0x3c, S390_R15_UPPER_REGNUM,
-    -1, -1
+    { 1, S390_LAST_BREAK_REGNUM },
+    { 0 }
   };
 
-const short s390_regmap_last_break[] =
+static const struct regcache_map_entry s390x_regmap_last_break[] =
   {
-    0x04, S390_LAST_BREAK_REGNUM,
-    -1, -1
+    { 1, S390_LAST_BREAK_REGNUM },
+    { 0 }
   };
 
-const short s390x_regmap_last_break[] =
+static const struct regcache_map_entry s390_regmap_system_call[] =
   {
-    0x00, S390_LAST_BREAK_REGNUM,
-    -1, -1
+    { 1, S390_SYSTEM_CALL_REGNUM },
+    { 0 }
   };
 
-const short s390_regmap_system_call[] =
+static const struct regcache_map_entry s390_regmap_tdb[] =
   {
-    0x00, S390_SYSTEM_CALL_REGNUM,
-    -1, -1
+    { 1, S390_TDB_DWORD0_REGNUM },
+    { 1, S390_TDB_ABORT_CODE_REGNUM },
+    { 1, S390_TDB_CONFLICT_TOKEN_REGNUM },
+    { 1, S390_TDB_ATIA_REGNUM },
+    { 96, REGCACHE_MAP_SKIP_BYTES },
+    { 16, S390_TDB_R0_REGNUM },
+    { 0 }
   };
 
-const short s390_regmap_tdb[] =
-  {
-    0x00, S390_TDB_DWORD0_REGNUM,
-    0x08, S390_TDB_ABORT_CODE_REGNUM,
-    0x10, S390_TDB_CONFLICT_TOKEN_REGNUM,
-    0x18, S390_TDB_ATIA_REGNUM,
-    0x80, S390_TDB_R0_REGNUM,
-    0x88, S390_TDB_R1_REGNUM,
-    0x90, S390_TDB_R2_REGNUM,
-    0x98, S390_TDB_R3_REGNUM,
-    0xa0, S390_TDB_R4_REGNUM,
-    0xa8, S390_TDB_R5_REGNUM,
-    0xb0, S390_TDB_R6_REGNUM,
-    0xb8, S390_TDB_R7_REGNUM,
-    0xc0, S390_TDB_R8_REGNUM,
-    0xc8, S390_TDB_R9_REGNUM,
-    0xd0, S390_TDB_R10_REGNUM,
-    0xd8, S390_TDB_R11_REGNUM,
-    0xe0, S390_TDB_R12_REGNUM,
-    0xe8, S390_TDB_R13_REGNUM,
-    0xf0, S390_TDB_R14_REGNUM,
-    0xf8, S390_TDB_R15_REGNUM,
-    -1, -1
-  };
-
-
-/* Supply register REGNUM from the register set REGSET to register cache
-   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
-static void
-s390_supply_regset (const struct regset *regset, struct regcache *regcache,
-		    int regnum, const void *regs, size_t len)
-{
-  const short *map;
-  for (map = regset->descr; map[0] >= 0; map += 2)
-    if (regnum == -1 || regnum == map[1])
-      regcache_raw_supply (regcache, map[1],
-			   regs ? (const char *)regs + map[0] : NULL);
-}
 
-/* Supply the TDB regset.  Like s390_supply_regset, but invalidate the
-   TDB registers unless the TDB format field is valid.  */
+/* Supply the TDB regset.  Like regcache_supply_regset, but invalidate
+   the TDB registers unless the TDB format field is valid.  */
 
 static void
 s390_supply_tdb_regset (const struct regset *regset, struct regcache *regcache,
@@ -627,73 +484,52 @@ s390_supply_tdb_regset (const struct regset *regset, struct regcache *regcache,
   enum register_status ret;
   int i;
 
-  s390_supply_regset (regset, regcache, regnum, regs, len);
+  regcache_supply_regset (regset, regcache, regnum, regs, len);
   ret = regcache_cooked_read_unsigned (regcache, S390_TDB_DWORD0_REGNUM, &tdw);
   if (ret != REG_VALID || (tdw >> 56) != 1)
-    s390_supply_regset (regset, regcache, regnum, NULL, len);
+    regcache_supply_regset (regset, regcache, regnum, NULL, len);
 }
 
-/* Collect register REGNUM from the register cache REGCACHE and store
-   it in the buffer specified by REGS and LEN as described by the
-   general-purpose register set REGSET.  If REGNUM is -1, do this for
-   all registers in REGSET.  */
-static void
-s390_collect_regset (const struct regset *regset,
-		     const struct regcache *regcache,
-		     int regnum, void *regs, size_t len)
-{
-  const short *map;
-  for (map = regset->descr; map[0] >= 0; map += 2)
-    if (regnum == -1 || regnum == map[1])
-      regcache_raw_collect (regcache, map[1], (char *)regs + map[0]);
-}
-
-static const struct regset s390_gregset = {
-  s390_regmap_gregset,
-  s390_supply_regset,
-  s390_collect_regset
+const struct regset s390_gregset = {
+  s390_gregmap,
+  regcache_supply_regset,
+  regcache_collect_regset
 };
 
-static const struct regset s390x_gregset = {
-  s390x_regmap_gregset,
-  s390_supply_regset,
-  s390_collect_regset
-};
-
-static const struct regset s390_fpregset = {
-  s390_regmap_fpregset,
-  s390_supply_regset,
-  s390_collect_regset
+const struct regset s390_fpregset = {
+  s390_fpregmap,
+  regcache_supply_regset,
+  regcache_collect_regset
 };
 
 static const struct regset s390_upper_regset = {
   s390_regmap_upper,
-  s390_supply_regset,
-  s390_collect_regset
+  regcache_supply_regset,
+  regcache_collect_regset
 };
 
-static const struct regset s390_last_break_regset = {
+const struct regset s390_last_break_regset = {
   s390_regmap_last_break,
-  s390_supply_regset,
-  s390_collect_regset
+  regcache_supply_regset,
+  regcache_collect_regset
 };
 
-static const struct regset s390x_last_break_regset = {
+const struct regset s390x_last_break_regset = {
   s390x_regmap_last_break,
-  s390_supply_regset,
-  s390_collect_regset
+  regcache_supply_regset,
+  regcache_collect_regset
 };
 
-static const struct regset s390_system_call_regset = {
+const struct regset s390_system_call_regset = {
   s390_regmap_system_call,
-  s390_supply_regset,
-  s390_collect_regset
+  regcache_supply_regset,
+  regcache_collect_regset
 };
 
-static const struct regset s390_tdb_regset = {
+const struct regset s390_tdb_regset = {
   s390_regmap_tdb,
   s390_supply_tdb_regset,
-  s390_collect_regset
+  regcache_collect_regset
 };
 
 static struct core_regset_section s390_linux32_regset_sections[] =
@@ -3371,7 +3207,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       break;
 
     case ABI_LINUX_ZSERIES:
-      tdep->gregset = &s390x_gregset;
+      tdep->gregset = &s390_gregset;
       tdep->sizeof_gregset = s390x_sizeof_gregset;
       tdep->fpregset = &s390_fpregset;
       tdep->sizeof_fpregset = s390_sizeof_fpregset;
diff --git a/gdb/s390-linux-tdep.h b/gdb/s390-linux-tdep.h
index 52bed9d..1e12000 100644
--- a/gdb/s390-linux-tdep.h
+++ b/gdb/s390-linux-tdep.h
@@ -150,15 +150,14 @@
 
 /* Core file register sets, defined in s390-tdep.c.  */
 #define s390_sizeof_gregset 0x90
-extern const short s390_regmap_gregset[];
 #define s390x_sizeof_gregset 0xd8
-extern const short s390x_regmap_gregset[];
+extern const struct regset s390_gregset;
 #define s390_sizeof_fpregset 0x88
-extern const short s390_regmap_fpregset[];
-extern const short s390_regmap_last_break[];
-extern const short s390x_regmap_last_break[];
-extern const short s390_regmap_system_call[];
-extern const short s390_regmap_tdb[];
+extern const struct regset s390_fpregset;
+extern const struct regset s390_last_break_regset;
+extern const struct regset s390x_last_break_regset;
+extern const struct regset s390_system_call_regset;
+extern const struct regset s390_tdb_regset;
 #define s390_sizeof_tdbregset 0x100
 
 /* GNU/Linux target descriptions.  */
-- 
1.8.4.2

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

* [PATCH 11/12] M68K Linux: Define regset structures.
  2014-05-26 16:37 [PATCH 00/12] Regset rework preparations part 2 Andreas Arnez
                   ` (6 preceding siblings ...)
  2014-05-26 16:37 ` [PATCH 02/12] S390: Migrate to regcache_supply/collect_regset Andreas Arnez
@ 2014-05-26 16:37 ` Andreas Arnez
  2014-05-27  1:37   ` Yao Qi
  2014-05-26 16:37 ` [PATCH 03/12] AARCH64 Linux: Fill 'collect_regset' in " Andreas Arnez
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 25+ messages in thread
From: Andreas Arnez @ 2014-05-26 16:37 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andreas Schwab

gdb/
	* m68klinux-tdep.c: Include "regset.h".
	(m68k_linux_gregmap, m68k_linux_fpregmap): New register maps.
	(M68K_LINUX_GREGS_SIZE, M68K_LINUX_FPREGS_SIZE): New macros.
	(m68k_linux_gregset, m68k_linux_fpregset): New regsets.
	(m68k_linux_regset_from_core_section): New function.
	(m68k_linux_init_abi): Set regset_from_core_section gdbarch
	method.
---
 gdb/m68klinux-tdep.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/gdb/m68klinux-tdep.c b/gdb/m68klinux-tdep.c
index f6fed38..8967d28 100644
--- a/gdb/m68klinux-tdep.c
+++ b/gdb/m68klinux-tdep.c
@@ -38,6 +38,7 @@
 #include "observer.h"
 #include "elf/common.h"
 #include "linux-tdep.h"
+#include "regset.h"
 \f
 /* Offsets (in target ints) into jmp_buf.  */
 
@@ -327,6 +328,66 @@ static const struct frame_unwind m68k_linux_sigtramp_frame_unwind =
   m68k_linux_sigtramp_frame_sniffer
 };
 
+/* Register maps for supply/collect regset functions.  */
+
+static const struct regcache_map_entry m68k_linux_gregmap[] =
+  {
+    { 7, M68K_D1_REGNUM },	/* d1 ... d7 */
+    { 7, M68K_A0_REGNUM },	/* a0 ... a6 */
+    { 1, M68K_D0_REGNUM },
+    { 1, M68K_SP_REGNUM },
+    { 4, REGCACHE_MAP_SKIP_BYTES }, /* orig_d0 (skip) */
+    { 1, M68K_PS_REGNUM },
+    { 1, M68K_PC_REGNUM },
+    { 0 }
+  };
+
+#define M68K_LINUX_GREGS_SIZE (19 * 4)
+
+static const struct regcache_map_entry m68k_linux_fpregmap[] =
+  {
+    { 8, M68K_FP0_REGNUM },	/* fp0 ... fp7 */
+    { 1, M68K_FPC_REGNUM },
+    { 1, M68K_FPS_REGNUM },
+    { 1, M68K_FPI_REGNUM },
+    { 0 }
+  };
+
+#define M68K_LINUX_FPREGS_SIZE (27 * 4)
+
+/* Register sets. */
+
+static const struct regset m68k_linux_gregset =
+  {
+    m68k_linux_gregmap,
+    regcache_supply_regset, regcache_collect_regset
+  };
+
+static const struct regset m68k_linux_fpregset =
+  {
+    m68k_linux_fpregmap,
+    regcache_supply_regset, regcache_collect_regset
+  };
+
+/* Return the appropriate register set for the core section identified
+   by SECT_NAME and SECT_SIZE.  */
+
+static const struct regset *
+m68k_linux_regset_from_core_section (struct gdbarch *gdbarch,
+				     const char *sect_name,
+				     size_t sect_size)
+{
+  if (strcmp (sect_name, ".reg") == 0
+      && sect_size >= M68K_LINUX_GREGS_SIZE)
+    return &m68k_linux_gregset;
+
+  if (strcmp (sect_name, ".reg2") == 0
+      && sect_size >= M68K_LINUX_FPREGS_SIZE)
+    return &m68k_linux_fpregset;
+
+  return NULL;
+}
+
 static void
 m68k_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
@@ -361,6 +422,10 @@ m68k_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 
   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
 
+  /* Core file support. */
+  set_gdbarch_regset_from_core_section
+    (gdbarch, m68k_linux_regset_from_core_section);
+
   /* Enable TLS support.  */
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);
-- 
1.8.4.2

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

* Re: [PATCH 11/12] M68K Linux: Define regset structures.
  2014-05-26 16:37 ` [PATCH 11/12] M68K Linux: Define regset structures Andreas Arnez
@ 2014-05-27  1:37   ` Yao Qi
  2014-05-27  8:51     ` Andreas Arnez
  0 siblings, 1 reply; 25+ messages in thread
From: Yao Qi @ 2014-05-27  1:37 UTC (permalink / raw)
  To: Andreas Arnez, gdb-patches; +Cc: Andreas Schwab

On 05/27/2014 12:36 AM, Andreas Arnez wrote:
> +/* Return the appropriate register set for the core section identified
> +   by SECT_NAME and SECT_SIZE.  */
> +
> +static const struct regset *
> +m68k_linux_regset_from_core_section (struct gdbarch *gdbarch,
> +				     const char *sect_name,
> +				     size_t sect_size)
> +{
> +  if (strcmp (sect_name, ".reg") == 0
> +      && sect_size >= M68K_LINUX_GREGS_SIZE)
> +    return &m68k_linux_gregset;
> +
> +  if (strcmp (sect_name, ".reg2") == 0
> +      && sect_size >= M68K_LINUX_FPREGS_SIZE)
> +    return &m68k_linux_fpregset;
> +
> +  return NULL;
> +}
> +
>  static void
>  m68k_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>  {
> @@ -361,6 +422,10 @@ m68k_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>  
>    set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
>  
> +  /* Core file support. */
> +  set_gdbarch_regset_from_core_section
> +    (gdbarch, m68k_linux_regset_from_core_section);
> +

Is it intended to include this change in this patch? or it should go
to the next patch series?

-- 
Yao (齐尧)

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

* Re: [PATCH 08/12] NIOS2 Linux: Fill 'collect_regset' in regset structure.
  2014-05-26 16:37 ` [PATCH 08/12] NIOS2 Linux: Fill 'collect_regset' in regset structure Andreas Arnez
@ 2014-05-27  2:15   ` Yao Qi
  2014-06-02  9:09     ` Andreas Arnez
  0 siblings, 1 reply; 25+ messages in thread
From: Yao Qi @ 2014-05-27  2:15 UTC (permalink / raw)
  To: Andreas Arnez, gdb-patches

On 05/27/2014 12:36 AM, Andreas Arnez wrote:
> +#define NIOS2_GREGS_SIZE (4 * 31)
> +

Is it used?

>  /* Implement the supply_regset hook for core files.  */
>  
>  static void
> @@ -73,11 +75,26 @@ nios2_supply_gregset (const struct regset *regset,
>        }
>  }
>  
> +static void
> +nios2_collect_gregset (const struct regset *regset,
> +		       const struct regcache *regcache,
> +		       int regnum, void *gregs_buf, size_t len)

The comment to this function is needed, like the comment to
nios2_supply_gregset.

> +{
> +  gdb_byte *gregs = gregs_buf;
> +  int regno;
> +
> +  for (regno = NIOS2_Z_REGNUM; regno <= NIOS2_MPUACC_REGNUM; regno++)
> +    if (regnum == -1 || regnum == regno)
> +      {
> +	if (reg_offsets[regno] != -1)
> +	  regcache_raw_collect (regcache, regno,
> +				gregs + 4 * reg_offsets[regno]);
> +      }
> +}
> +
>  static const struct regset nios2_core_regset =
>  {
> -  NULL,
> -  nios2_supply_gregset,
> -  NULL,
> +  NULL, nios2_supply_gregset, nios2_collect_gregset
>  };

I'd like to put each field in one line.  Otherwise, it is OK.

-- 
Yao (齐尧)

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

* Re: [PATCH 01/12] regcache: Add functions suitable for regset_supply/collect.
  2014-05-26 16:37 ` [PATCH 01/12] regcache: Add functions suitable for regset_supply/collect Andreas Arnez
@ 2014-05-27  2:49   ` Yao Qi
  2014-05-27 11:54     ` Andreas Arnez
  0 siblings, 1 reply; 25+ messages in thread
From: Yao Qi @ 2014-05-27  2:49 UTC (permalink / raw)
  To: Andreas Arnez, gdb-patches

On 05/27/2014 12:36 AM, Andreas Arnez wrote:
> +/* Mapping between register numbers and offsets in a buffer, for use
> +   in the '*regset' functions below.  The first entry in a map refers
> +   to offset 0, and each entry increases the offset by its size.

Except that 'regno' is REGCACHE_MAP_SKIP_BYTES.  When 'regno' is
REGCACHE_MAP_SKIP_BYTES, 'count' is the increased offset by bytes, IIUC.

> +/* Transfer a set of registers (as described by REGSET) between
> +   REGCACHE and BUF.  If REGNUM == -1, transfer all registers
> +   belonging to the regset, otherwise just the register numbered
> +   REGNUM.  The REGSET's 'descr' field must point to an array of
> +   'struct regcache_map_entry'.

IWBN to update the comments to 'descr' field, and go a step further,
rename field 'descr'.

> +
> +   These functions are suitable for the 'regset_supply' and
> +   'regset_collect' fields in a regset structure.
> +  */

"*/" should go to the previous line.

-- 
Yao (齐尧)

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

* Re: [PATCH 00/12] Regset rework preparations part 2
  2014-05-26 16:37 [PATCH 00/12] Regset rework preparations part 2 Andreas Arnez
                   ` (11 preceding siblings ...)
  2014-05-26 16:37 ` [PATCH 07/12] M32R Linux: Fill 'collect_regset' in regset structure Andreas Arnez
@ 2014-05-27  2:56 ` Yao Qi
  2014-05-28 17:36   ` Andreas Arnez
  12 siblings, 1 reply; 25+ messages in thread
From: Yao Qi @ 2014-05-27  2:56 UTC (permalink / raw)
  To: Andreas Arnez, gdb-patches; +Cc: Mark Kettenis

On 05/27/2014 12:36 AM, Andreas Arnez wrote:
> This part adds a collect_regset method to all Linux regsets where it
> had been missing.  This is necessary, but not sufficient, to make the
> "gcore" command multi-arch capable for the affected targets.  When
> this part is approved, I can provide a follow-on patch set that fills
> the remaining gaps to multi-arch capable core file handling for all
> Linux targets.

Your multi-arch core file handling patches can justify the changes in
this series.  You don't have to post them, but descriptions on how
multi-arch core file handling needs such regset interface are useful.

-- 
Yao (齐尧)

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

* Re: [PATCH 11/12] M68K Linux: Define regset structures.
  2014-05-27  1:37   ` Yao Qi
@ 2014-05-27  8:51     ` Andreas Arnez
  2014-05-27 12:48       ` Yao Qi
  0 siblings, 1 reply; 25+ messages in thread
From: Andreas Arnez @ 2014-05-27  8:51 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches, Andreas Schwab

On Tue, May 27 2014, Yao Qi wrote:

> On 05/27/2014 12:36 AM, Andreas Arnez wrote:
>> +/* Return the appropriate register set for the core section identified
>> +   by SECT_NAME and SECT_SIZE.  */
>> +
>> +static const struct regset *
>> +m68k_linux_regset_from_core_section (struct gdbarch *gdbarch,
>> +				     const char *sect_name,
>> +				     size_t sect_size)
>> +{
>> +  if (strcmp (sect_name, ".reg") == 0
>> +      && sect_size >= M68K_LINUX_GREGS_SIZE)
>> +    return &m68k_linux_gregset;
>> +
>> +  if (strcmp (sect_name, ".reg2") == 0
>> +      && sect_size >= M68K_LINUX_FPREGS_SIZE)
>> +    return &m68k_linux_fpregset;
>> +
>> +  return NULL;
>> +}
>> +
>>  static void
>>  m68k_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>>  {
>> @@ -361,6 +422,10 @@ m68k_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>>  
>>    set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
>>  
>> +  /* Core file support. */
>> +  set_gdbarch_regset_from_core_section
>> +    (gdbarch, m68k_linux_regset_from_core_section);
>> +
>
> Is it intended to include this change in this patch? or it should go
> to the next patch series?

It is intended here, such that the register sets are actually used by
linux_nat_collect_thread_registers and get_core_register_section.

If I didn't miss anything, M68K and IA64 were the only Linux targets
without regset_from_core_section gdbarch methods before.  After the
patch series all Linux targets should have them, and all their regsets
should have supply- *and* collect methods.

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

* Re: [PATCH 01/12] regcache: Add functions suitable for regset_supply/collect.
  2014-05-27  2:49   ` Yao Qi
@ 2014-05-27 11:54     ` Andreas Arnez
  2014-05-27 12:22       ` Yao Qi
  0 siblings, 1 reply; 25+ messages in thread
From: Andreas Arnez @ 2014-05-27 11:54 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On Tue, May 27 2014, Yao Qi wrote:

> On 05/27/2014 12:36 AM, Andreas Arnez wrote:
>> +/* Mapping between register numbers and offsets in a buffer, for use
>> +   in the '*regset' functions below.  The first entry in a map refers
>> +   to offset 0, and each entry increases the offset by its size.
>
> Except that 'regno' is REGCACHE_MAP_SKIP_BYTES.  When 'regno' is
> REGCACHE_MAP_SKIP_BYTES, 'count' is the increased offset by bytes, IIUC.

Correct.  Maybe it's better to rephrase the whole comment like this:

/* Mapping between register numbers and offsets in a buffer, for use
   in the '*regset' functions below.  In an array of
   'regcache_map_entry' each element is interpreted like follows:

   - If 'regno' is a register number: Map register 'regno' to the
     current offset (starting with 0) and increase the current offset
     by the register's size.  Repeat this with consecutive register
     numbers up to 'regno+count-1'.

   - If 'regno' has the special value REGCACHE_MAP_SKIP_BYTES: Add
     'count' to the current offset.

   - If count=0: End of the map.  */

>
>> +/* Transfer a set of registers (as described by REGSET) between
>> +   REGCACHE and BUF.  If REGNUM == -1, transfer all registers
>> +   belonging to the regset, otherwise just the register numbered
>> +   REGNUM.  The REGSET's 'descr' field must point to an array of
>> +   'struct regcache_map_entry'.
>
> IWBN to update the comments to 'descr' field, and go a step further,
> rename field 'descr'.

With the new name being something like 'map' or 'regmap', I guess?  If
that's what you mean, I tend to agree, and I could provide a separate
patch for that.

>> +
>> +   These functions are suitable for the 'regset_supply' and
>> +   'regset_collect' fields in a regset structure.
>> +  */
>
> "*/" should go to the previous line.

Done.

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

* Re: [PATCH 01/12] regcache: Add functions suitable for regset_supply/collect.
  2014-05-27 11:54     ` Andreas Arnez
@ 2014-05-27 12:22       ` Yao Qi
  2014-05-27 14:21         ` Andreas Arnez
  0 siblings, 1 reply; 25+ messages in thread
From: Yao Qi @ 2014-05-27 12:22 UTC (permalink / raw)
  To: Andreas Arnez; +Cc: gdb-patches

On 05/27/2014 07:53 PM, Andreas Arnez wrote:
> Correct.  Maybe it's better to rephrase the whole comment like this:
> 

Yes, that is much better.

> /* Mapping between register numbers and offsets in a buffer, for use
>    in the '*regset' functions below.  In an array of
>    'regcache_map_entry' each element is interpreted like follows:
> 
>    - If 'regno' is a register number: Map register 'regno' to the
>      current offset (starting with 0) and increase the current offset
>      by the register's size.  Repeat this with consecutive register
>      numbers up to 'regno+count-1'.
> 
>    - If 'regno' has the special value REGCACHE_MAP_SKIP_BYTES: Add
>      'count' to the current offset.

Nit: I'd say "If 'regno' is REGCACHE_MAP_SKIP_BYTES, 'count' is the
increased offset".  This is just my suggestion, which may be worse
than yours.

> 
>    - If count=0: End of the map.  */
> 
>> >
>>> >> +/* Transfer a set of registers (as described by REGSET) between
>>> >> +   REGCACHE and BUF.  If REGNUM == -1, transfer all registers
>>> >> +   belonging to the regset, otherwise just the register numbered
>>> >> +   REGNUM.  The REGSET's 'descr' field must point to an array of
>>> >> +   'struct regcache_map_entry'.
>> >
>> > IWBN to update the comments to 'descr' field, and go a step further,
>> > rename field 'descr'.
> With the new name being something like 'map' or 'regmap', I guess?  If
> that's what you mean, I tend to agree, and I could provide a separate
> patch for that.
> 

'regmap' sounds good to me.  I don't have other comments.

-- 
Yao (齐尧)

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

* Re: [PATCH 11/12] M68K Linux: Define regset structures.
  2014-05-27  8:51     ` Andreas Arnez
@ 2014-05-27 12:48       ` Yao Qi
  0 siblings, 0 replies; 25+ messages in thread
From: Yao Qi @ 2014-05-27 12:48 UTC (permalink / raw)
  To: Andreas Arnez; +Cc: gdb-patches, Andreas Schwab

On 05/27/2014 04:51 PM, Andreas Arnez wrote:
> It is intended here, such that the register sets are actually used by
> linux_nat_collect_thread_registers and get_core_register_section.
> 
> If I didn't miss anything, M68K and IA64 were the only Linux targets
> without regset_from_core_section gdbarch methods before.  After the
> patch series all Linux targets should have them, and all their regsets
> should have supply- *and* collect methods.

I have no comments then.

-- 
Yao (齐尧)

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

* Re: [PATCH 01/12] regcache: Add functions suitable for regset_supply/collect.
  2014-05-27 12:22       ` Yao Qi
@ 2014-05-27 14:21         ` Andreas Arnez
  0 siblings, 0 replies; 25+ messages in thread
From: Andreas Arnez @ 2014-05-27 14:21 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On Tue, May 27 2014, Yao Qi wrote:

> On 05/27/2014 07:53 PM, Andreas Arnez wrote:
>> Correct.  Maybe it's better to rephrase the whole comment like this:
>> 
>
> Yes, that is much better.

Good -- thanks for pointing this out.

>
>> /* Mapping between register numbers and offsets in a buffer, for use
>>    in the '*regset' functions below.  In an array of
>>    'regcache_map_entry' each element is interpreted like follows:
>> 
>>    - If 'regno' is a register number: Map register 'regno' to the
>>      current offset (starting with 0) and increase the current offset
>>      by the register's size.  Repeat this with consecutive register
>>      numbers up to 'regno+count-1'.
>> 
>>    - If 'regno' has the special value REGCACHE_MAP_SKIP_BYTES: Add
>>      'count' to the current offset.
>
> Nit: I'd say "If 'regno' is REGCACHE_MAP_SKIP_BYTES, 'count' is the
> increased offset".  This is just my suggestion, which may be worse
> than yours.

I agree with simplifying the phrase "has the special value" to "is".
For consistency I'd like to stick to the term "current offset" from the
previous bullet.  Also, I intentionally avoid saying "increase", because
the current implementation allows 'count' to be negative.  So I'll just
shorten to:

  If 'regno' is REGCACHE_MAP_SKIP_BYTES: Add 'count' to the current
  offset.

>
>> 
>>    - If count=0: End of the map.  */
>> 
>>> >
>>>> >> +/* Transfer a set of registers (as described by REGSET) between
>>>> >> +   REGCACHE and BUF.  If REGNUM == -1, transfer all registers
>>>> >> +   belonging to the regset, otherwise just the register numbered
>>>> >> +   REGNUM.  The REGSET's 'descr' field must point to an array of
>>>> >> +   'struct regcache_map_entry'.
>>> >
>>> > IWBN to update the comments to 'descr' field, and go a step further,
>>> > rename field 'descr'.
>> With the new name being something like 'map' or 'regmap', I guess?  If
>> that's what you mean, I tend to agree, and I could provide a separate
>> patch for that.
>> 
>
> 'regmap' sounds good to me.  I don't have other comments.

OK, I'll post a separate patch for that.

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

* Re: [PATCH 03/12] AARCH64 Linux: Fill 'collect_regset' in regset structures.
  2014-05-26 16:37 ` [PATCH 03/12] AARCH64 Linux: Fill 'collect_regset' in " Andreas Arnez
@ 2014-05-27 21:36   ` Yufeng Zhang
  0 siblings, 0 replies; 25+ messages in thread
From: Yufeng Zhang @ 2014-05-27 21:36 UTC (permalink / raw)
  To: Andreas Arnez; +Cc: gdb-patches, Richard Earnshaw

It looks good to me, but I cannot approve it.  Thanks for the refactoring.

Yufeng

On 05/26/14 17:36, Andreas Arnez wrote:
> In order to provide 'collect_regset' support, the generic function
> regcache_collect_regset is exploited.  Since this requires writing
> appropriate register maps, these can be used for supply_regset as
> well.
>
> gdb/
>          * aarch64-linux-nat.c (fill_gregset, fill_fpregset): Replace logic
>          by call to regcache_collect_regset.
>          (supply_gregset, supply_fpregset): Call regcache_supply_regset
>          instead of aarch64_linux_supply_gregset/_fpregset.
>          * aarch64-linux-tdep.c (AARCH64_LINUX_SIZEOF_GREGSET)
>          (AARCH64_LINUX_SIZEOF_FPREGSET): Delete macros here, move to
>          header file instead.
>          (aarch64_linux_supply_gregset, supply_gregset_from_core)
>          (aarch64_linux_suply_fpregset, supply_fpregset_from_core): Delete
>          functions.  Move logic to ...
>          (aarch64_linux_gregmap, aarch64_linux_fpregmap): ... these new
>          register maps.
>          (aarch64_linux_gregset, aarch64_linux_fpregset): Make global,
>          refer to new register maps, replace *_regset_from_core by
>          regcache_supply_regset, and also use regcache_collect_regset.
>          * aarch64-linux-tdep.h: Include "regset.h".
>          (aarch64_linux_supply_gregset, aarch64_linux_supply_fpregset):
>          Delete prototypes.
>          (AARCH64_LINUX_SIZEOF_GREGSET, AARCH64_LINUX_SIZEOF_FPREGSET): New
>          macros, moved from C source file.
>          (aarch64_linux_gregset, aarch64_linux_fpregset): New global
>          variable declarations.
> ---
>   gdb/aarch64-linux-nat.c  | 38 +++++++-------------
>   gdb/aarch64-linux-tdep.c | 90 +++++++++++++-----------------------------------
>   gdb/aarch64-linux-tdep.h | 18 +++++++---
>   3 files changed, 48 insertions(+), 98 deletions(-)
>
> diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
> index 877e702..4ae789b 100644
> --- a/gdb/aarch64-linux-nat.c
> +++ b/gdb/aarch64-linux-nat.c
> @@ -616,14 +616,9 @@ void
>   fill_gregset (const struct regcache *regcache,
>                gdb_gregset_t *gregsetp, int regno)
>   {
> -  gdb_byte *gregs_buf = (gdb_byte *) gregsetp;
> -  int i;
> -
> -  for (i = AARCH64_X0_REGNUM; i<= AARCH64_CPSR_REGNUM; i++)
> -    if (regno == -1 || regno == i)
> -      regcache_raw_collect (regcache, i,
> -                           gregs_buf + X_REGISTER_SIZE
> -                           * (i - AARCH64_X0_REGNUM));
> +  regcache_collect_regset (&aarch64_linux_gregset, regcache,
> +                          regno, (gdb_byte *) gregsetp,
> +                          AARCH64_LINUX_SIZEOF_GREGSET);
>   }
>
>   /* Fill GDB's register array with the general-purpose register values
> @@ -632,7 +627,9 @@ fill_gregset (const struct regcache *regcache,
>   void
>   supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
>   {
> -  aarch64_linux_supply_gregset (regcache, (const gdb_byte *) gregsetp);
> +  regcache_supply_regset (&aarch64_linux_gregset, regcache, -1,
> +                         (const gdb_byte *) gregsetp,
> +                         AARCH64_LINUX_SIZEOF_GREGSET);
>   }
>
>   /* Fill register REGNO (if it is a floating-point register) in
> @@ -643,22 +640,9 @@ void
>   fill_fpregset (const struct regcache *regcache,
>                 gdb_fpregset_t *fpregsetp, int regno)
>   {
> -  gdb_byte *fpregs_buf = (gdb_byte *) fpregsetp;
> -  int i;
> -
> -  for (i = AARCH64_V0_REGNUM; i<= AARCH64_V31_REGNUM; i++)
> -    if (regno == -1 || regno == i)
> -      regcache_raw_collect (regcache, i,
> -                           fpregs_buf + V_REGISTER_SIZE
> -                           * (i - AARCH64_V0_REGNUM));
> -
> -  if (regno == -1 || regno == AARCH64_FPSR_REGNUM)
> -    regcache_raw_collect (regcache, AARCH64_FPSR_REGNUM,
> -                         fpregs_buf + V_REGISTER_SIZE * 32);
> -
> -  if (regno == -1 || regno == AARCH64_FPCR_REGNUM)
> -    regcache_raw_collect (regcache, AARCH64_FPCR_REGNUM,
> -                         fpregs_buf + V_REGISTER_SIZE * 32 + 4);
> +  regcache_collect_regset (&aarch64_linux_fpregset, regcache,
> +                          regno, (gdb_byte *) fpregsetp,
> +                          AARCH64_LINUX_SIZEOF_FPREGSET);
>   }
>
>   /* Fill GDB's register array with the floating-point register values
> @@ -667,7 +651,9 @@ fill_fpregset (const struct regcache *regcache,
>   void
>   supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
>   {
> -  aarch64_linux_supply_fpregset (regcache, (const gdb_byte *) fpregsetp);
> +  regcache_supply_regset (&aarch64_linux_fpregset, regcache, -1,
> +                         (const gdb_byte *) fpregsetp,
> +                         AARCH64_LINUX_SIZEOF_FPREGSET);
>   }
>
>   /* Called when resuming a thread.
> diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
> index 30ed73f..b3eaa95 100644
> --- a/gdb/aarch64-linux-tdep.c
> +++ b/gdb/aarch64-linux-tdep.c
> @@ -41,16 +41,6 @@
>   #include "user-regs.h"
>   #include<ctype.h>
>
> -/* The general-purpose regset consists of 31 X registers, plus SP, PC,
> -   and PSTATE registers, as defined in the AArch64 port of the Linux
> -   kernel.  */
> -#define AARCH64_LINUX_SIZEOF_GREGSET  (34 * X_REGISTER_SIZE)
> -
> -/* The fp regset consists of 32 V registers, plus FPCR and FPSR which
> -   are 4 bytes wide each, and the whole structure is padded to 128 bit
> -   alignment.  */
> -#define AARCH64_LINUX_SIZEOF_FPREGSET (33 * V_REGISTER_SIZE)
> -
>   /* Signal frame handling.
>
>         +------------+  ^
> @@ -190,71 +180,37 @@ static const struct tramp_frame aarch64_linux_rt_sigframe =
>     aarch64_linux_sigframe_init
>   };
>
> -/* Fill GDB's register array with the general-purpose register values
> -   in the buffer pointed by GREGS_BUF.  */
> -
> -void
> -aarch64_linux_supply_gregset (struct regcache *regcache,
> -                             const gdb_byte *gregs_buf)
> -{
> -  int regno;
> -
> -  for (regno = AARCH64_X0_REGNUM; regno<= AARCH64_CPSR_REGNUM; regno++)
> -    regcache_raw_supply (regcache, regno,
> -                        gregs_buf + X_REGISTER_SIZE
> -                        * (regno - AARCH64_X0_REGNUM));
> -}
> -
> -/* The "supply_regset" function for the general-purpose register set.  */
> -
> -static void
> -supply_gregset_from_core (const struct regset *regset,
> -                         struct regcache *regcache,
> -                         int regnum, const void *regbuf, size_t len)
> -{
> -  aarch64_linux_supply_gregset (regcache, (const gdb_byte *) regbuf);
> -}
> -
> -/* Fill GDB's register array with the floating-point register values
> -   in the buffer pointed by FPREGS_BUF.  */
> +/* Register maps.  */
>
> -void
> -aarch64_linux_supply_fpregset (struct regcache *regcache,
> -                              const gdb_byte *fpregs_buf)
> -{
> -  int regno;
> -
> -  for (regno = AARCH64_V0_REGNUM; regno<= AARCH64_V31_REGNUM; regno++)
> -    regcache_raw_supply (regcache, regno,
> -                        fpregs_buf + V_REGISTER_SIZE
> -                        * (regno - AARCH64_V0_REGNUM));
> -
> -  regcache_raw_supply (regcache, AARCH64_FPSR_REGNUM,
> -                      fpregs_buf + V_REGISTER_SIZE * 32);
> -  regcache_raw_supply (regcache, AARCH64_FPCR_REGNUM,
> -                      fpregs_buf + V_REGISTER_SIZE * 32 + 4);
> -}
> -
> -/* The "supply_regset" function for the floating-point register set.  */
> +static const struct regcache_map_entry aarch64_linux_gregmap[] =
> +  {
> +    { 31, AARCH64_X0_REGNUM }, /* x0 ... x30 */
> +    { 1, AARCH64_SP_REGNUM },
> +    { 1, AARCH64_PC_REGNUM },
> +    { 1, AARCH64_CPSR_REGNUM },
> +    { 0 }
> +  };
>
> -static void
> -supply_fpregset_from_core (const struct regset *regset,
> -                          struct regcache *regcache,
> -                          int regnum, const void *regbuf, size_t len)
> -{
> -  aarch64_linux_supply_fpregset (regcache, (const gdb_byte *) regbuf);
> -}
> +static const struct regcache_map_entry aarch64_linux_fpregmap[] =
> +  {
> +    { 32, AARCH64_V0_REGNUM }, /* v0 ... v31 */
> +    { 1, AARCH64_FPSR_REGNUM },
> +    { 1, AARCH64_FPCR_REGNUM },
> +    { 0 }
> +  };
>
> -/* Register set definitions. */
> +/* Register set definitions.  */
>
> -static const struct regset aarch64_linux_gregset =
> +const struct regset aarch64_linux_gregset =
>     {
> -    NULL, supply_gregset_from_core, NULL
> +    aarch64_linux_gregmap,
> +    regcache_supply_regset, regcache_collect_regset
>     };
>
> -static const struct regset aarch64_linux_fpregset =
> +const struct regset aarch64_linux_fpregset =
>     {
> -    NULL, supply_fpregset_from_core, NULL
> +    aarch64_linux_fpregmap,
> +    regcache_supply_regset, regcache_collect_regset
>     };
>
>   /* Implement the "regset_from_core_section" gdbarch method.  */
> diff --git a/gdb/aarch64-linux-tdep.h b/gdb/aarch64-linux-tdep.h
> index 48c7092..2e1de60 100644
> --- a/gdb/aarch64-linux-tdep.h
> +++ b/gdb/aarch64-linux-tdep.h
> @@ -18,9 +18,17 @@
>      You should have received a copy of the GNU General Public License
>      along with this program.  If not, see<http://www.gnu.org/licenses/>.  */
>
> -struct regcache;
> +#include "regset.h"
>
> -extern void aarch64_linux_supply_gregset (struct regcache *regcache,
> -                                         const gdb_byte *gregs_buf);
> -extern void aarch64_linux_supply_fpregset (struct regcache *regcache,
> -                                          const gdb_byte *fpregs_buf);
> +/* The general-purpose regset consists of 31 X registers, plus SP, PC,
> +   and PSTATE registers, as defined in the AArch64 port of the Linux
> +   kernel.  */
> +#define AARCH64_LINUX_SIZEOF_GREGSET  (34 * X_REGISTER_SIZE)
> +
> +/* The fp regset consists of 32 V registers, plus FPCR and FPSR which
> +   are 4 bytes wide each, and the whole structure is padded to 128 bit
> +   alignment.  */
> +#define AARCH64_LINUX_SIZEOF_FPREGSET (33 * V_REGISTER_SIZE)
> +
> +extern const struct regset aarch64_linux_gregset;
> +extern const struct regset aarch64_linux_fpregset;
> --
> 1.8.4.2
>
>


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

* Re: [PATCH 00/12] Regset rework preparations part 2
  2014-05-27  2:56 ` [PATCH 00/12] Regset rework preparations part 2 Yao Qi
@ 2014-05-28 17:36   ` Andreas Arnez
  0 siblings, 0 replies; 25+ messages in thread
From: Andreas Arnez @ 2014-05-28 17:36 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches, Mark Kettenis

On Tue, May 27 2014, Yao Qi wrote:

> On 05/27/2014 12:36 AM, Andreas Arnez wrote:
>> This part adds a collect_regset method to all Linux regsets where it
>> had been missing.  This is necessary, but not sufficient, to make the
>> "gcore" command multi-arch capable for the affected targets.  When
>> this part is approved, I can provide a follow-on patch set that fills
>> the remaining gaps to multi-arch capable core file handling for all
>> Linux targets.
>
> Your multi-arch core file handling patches can justify the changes in
> this series.  You don't have to post them, but descriptions on how
> multi-arch core file handling needs such regset interface are useful.

OK, let's try.  The following description applies to GNU/Linux targets:

1. What's needed for multi-arch capable "gcore" functionality?

With the current implementation (see linux_make_corefile_notes_1()), the
gdbarch field 'core_regset_sections' must be set; it specifies the names
and sizes of the corefile register note sections to be written.  In
addition, the gdbarch method 'regset_from_core_section' must assign a
regset structure to each of the 'core_regset_sections'.  And all the
returned regsets must contain platform-independent 'collect_regset'
methods.

  1a. What if a target does not fulfil these requirements?

  If 'core_regset_sections' is missing, the current implementation falls
  back to the (deprecated) target method 'make_corefile_notes',
  implemented for generic GNU/Linux targets by
  linux_nat_make_corefile_notes().  This invokes the native-dependent
  fill_gregset() and fill_fpregset() global functions, or (if available)
  uses the 'collect_regset' methods for each of the regsets associated
  with ".reg" and ".reg2".  In the latter case the sizes of the register
  note sections are derived from the type definitions 'gregset_t' and
  'fpregset_t' in the native-dependent system header files.

2. What's needed for multi-arch capable core file reading?

As above, the gdbarch method 'regset_from_core_section' must be set.
The 'core_regset_sections' list is optional, and if not set, is assumed
to consist of ".reg" and ".reg2".  The register note sizes are retrieved
from the core file.  Each of the regsets returned by
'regset_from_core_section' must have a platform-independent
'supply_regset' method.

  2a. What if a target does not fulfil these requirements?

  If 'regset_from_core_section' is missing, the current code falls back
  to the 'core_read_registers' method from the core_fns object that has
  been registered by deprecated_add_core_fns().  This
  'core_read_register' method then calls one of the native-dependent
  global functions supply_gregset() or supply_fpregset(), as
  appropriate.

(4) What does the series at hand provide, and how about the follow-on
    series?

This series defines 'collect_regset' methods and, where missing, also
the 'supply_regset' methods and 'regset_from_core_section'.  Since it
does not set 'core_regset_sections', "gcore" still falls back to the
native-dependent approach, but should at least use the new
'collect_regset' methods.  Core file *reading* should be made multi-arch
capable with this series already.

My follow-on series merges 'core_regset_sections' with
'regset_from_core_section' and defines the merged method for all
GNU/Linux targets.

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

* Re: [PATCH 08/12] NIOS2 Linux: Fill 'collect_regset' in regset structure.
  2014-05-27  2:15   ` Yao Qi
@ 2014-06-02  9:09     ` Andreas Arnez
  0 siblings, 0 replies; 25+ messages in thread
From: Andreas Arnez @ 2014-06-02  9:09 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On Tue, May 27 2014, Yao Qi wrote:

> On 05/27/2014 12:36 AM, Andreas Arnez wrote:
>> +#define NIOS2_GREGS_SIZE (4 * 31)
>> +
>
> Is it used?

No, this is needed in the follow-on patch series, but not here.
Removed.

>>  /* Implement the supply_regset hook for core files.  */
>>  
>>  static void
>> @@ -73,11 +75,26 @@ nios2_supply_gregset (const struct regset *regset,
>>        }
>>  }
>>  
>> +static void
>> +nios2_collect_gregset (const struct regset *regset,
>> +		       const struct regcache *regcache,
>> +		       int regnum, void *gregs_buf, size_t len)
>
> The comment to this function is needed, like the comment to
> nios2_supply_gregset.

Done.

>>  static const struct regset nios2_core_regset =
>>  {
>> -  NULL,
>> -  nios2_supply_gregset,
>> -  NULL,
>> +  NULL, nios2_supply_gregset, nios2_collect_gregset
>>  };
>
> I'd like to put each field in one line.  Otherwise, it is OK.

Done.

See the updated patch below.

BTW, I was wondering why nios2_supply_gregset initializes the
unavailable registers with zero instead of just leaving them
<unavailable>.  This special treatment is the main reason against using
the new generic supply/collect functions from regcache.c, because those
currently do not support initializing registers with zero.

--

diff --git a/gdb/nios2-linux-tdep.c b/gdb/nios2-linux-tdep.c
index 84ab576..0f53477 100644
--- a/gdb/nios2-linux-tdep.c
+++ b/gdb/nios2-linux-tdep.c
@@ -73,11 +73,30 @@ nios2_supply_gregset (const struct regset *regset,
       }
 }
 
+/* Implement the collect_regset hook for core files.  */
+
+static void
+nios2_collect_gregset (const struct regset *regset,
+		       const struct regcache *regcache,
+		       int regnum, void *gregs_buf, size_t len)
+{
+  gdb_byte *gregs = gregs_buf;
+  int regno;
+
+  for (regno = NIOS2_Z_REGNUM; regno <= NIOS2_MPUACC_REGNUM; regno++)
+    if (regnum == -1 || regnum == regno)
+      {
+	if (reg_offsets[regno] != -1)
+	  regcache_raw_collect (regcache, regno,
+				gregs + 4 * reg_offsets[regno]);
+      }
+}
+
 static const struct regset nios2_core_regset =
 {
   NULL,
   nios2_supply_gregset,
-  NULL,
+  nios2_collect_gregset
 };
 
 /* Implement the regset_from_core_section gdbarch method.  */

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

end of thread, other threads:[~2014-06-02  9:09 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-26 16:37 [PATCH 00/12] Regset rework preparations part 2 Andreas Arnez
2014-05-26 16:37 ` [PATCH 10/12] TILEGX Linux: Fill 'collect_regset' in regset structure Andreas Arnez
2014-05-26 16:37 ` [PATCH 09/12] SCORE: " Andreas Arnez
2014-05-26 16:37 ` [PATCH 05/12] FRV Linux: Fill 'collect_regset' in regset structures Andreas Arnez
2014-05-26 16:37 ` [PATCH 06/12] HPPA " Andreas Arnez
2014-05-26 16:37 ` [PATCH 08/12] NIOS2 Linux: Fill 'collect_regset' in regset structure Andreas Arnez
2014-05-27  2:15   ` Yao Qi
2014-06-02  9:09     ` Andreas Arnez
2014-05-26 16:37 ` [PATCH 01/12] regcache: Add functions suitable for regset_supply/collect Andreas Arnez
2014-05-27  2:49   ` Yao Qi
2014-05-27 11:54     ` Andreas Arnez
2014-05-27 12:22       ` Yao Qi
2014-05-27 14:21         ` Andreas Arnez
2014-05-26 16:37 ` [PATCH 02/12] S390: Migrate to regcache_supply/collect_regset Andreas Arnez
2014-05-26 16:37 ` [PATCH 11/12] M68K Linux: Define regset structures Andreas Arnez
2014-05-27  1:37   ` Yao Qi
2014-05-27  8:51     ` Andreas Arnez
2014-05-27 12:48       ` Yao Qi
2014-05-26 16:37 ` [PATCH 03/12] AARCH64 Linux: Fill 'collect_regset' in " Andreas Arnez
2014-05-27 21:36   ` Yufeng Zhang
2014-05-26 16:37 ` [PATCH 04/12] ALPHA " Andreas Arnez
2014-05-26 16:37 ` [PATCH 12/12] IA64 Linux: Define " Andreas Arnez
2014-05-26 16:37 ` [PATCH 07/12] M32R Linux: Fill 'collect_regset' in regset structure Andreas Arnez
2014-05-27  2:56 ` [PATCH 00/12] Regset rework preparations part 2 Yao Qi
2014-05-28 17:36   ` Andreas Arnez

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).