public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 13/15] No longer create readonly regcache
  2017-12-01 10:48 [RFC 00/15] Remove regcache::m_readonly_p Yao Qi
                   ` (4 preceding siblings ...)
  2017-12-01 10:48 ` [PATCH 08/15] class regcache_read and Pass regcache_read to gdbarch methods Yao Qi
@ 2017-12-01 10:48 ` Yao Qi
  2017-12-01 10:48 ` [PATCH 05/15] regcache_cooked_read -> regcache->cooked_read Yao Qi
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 32+ messages in thread
From: Yao Qi @ 2017-12-01 10:48 UTC (permalink / raw)
  To: gdb-patches

Nowadays, we create a readonly regcache in get_return_value, and pass it
to gdbarch_return_value to get the return value.  In theory, we can pass a
regcache_readonly instance and get the return value, because we don't need
to modify the regcache.  Unfortunately, gdbarch_return_value is designed
to multiplex regcache, according to READBUF and WRITEBUF.

 # If READBUF is not NULL, extract the return value and save it in this
 # buffer.
 #
 # If WRITEBUF is not NULL, it contains a return value which will be
 # stored into the appropriate register.

In fact, gdbarch_return_value should be split to three functions, 1) only
return return_value_convention, 2) pass regcache_readonly and readbuf, 3)
pass regcache and writebuf.  These changes are out of the scope of this
patch series, so I pass regcache to gdbarch_return_value even for read,
and trust each gdbarch backend doesn't modify regcache.

gdb:

2017-11-02  Yao Qi  <yao.qi@linaro.org>

	* infcmd.c (get_return_value): Let stop_regs point to
	get_current_regcache.
	* regcache.c (regcache::regcache): Remove.
	(register_dump_reg_buffer): New class.
	(regcache_print): Adjust.
	* regcache.h (regcache): Remove constructors.
---
 gdb/infcmd.c   |  6 ++---
 gdb/regcache.c | 71 +++++++++++++++++++++++++++++++++++++++++++++-------------
 gdb/regcache.h | 10 ---------
 3 files changed, 58 insertions(+), 29 deletions(-)

diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 9cee174..ee60ce9 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1627,8 +1627,8 @@ advance_command (const char *arg, int from_tty)
 struct value *
 get_return_value (struct value *function, struct type *value_type)
 {
-  regcache stop_regs (regcache::readonly, *get_current_regcache ());
-  struct gdbarch *gdbarch = stop_regs.arch ();
+  regcache *stop_regs = get_current_regcache ();
+  struct gdbarch *gdbarch = stop_regs->arch ();
   struct value *value;
 
   value_type = check_typedef (value_type);
@@ -1648,7 +1648,7 @@ get_return_value (struct value *function, struct type *value_type)
     case RETURN_VALUE_ABI_RETURNS_ADDRESS:
     case RETURN_VALUE_ABI_PRESERVES_ADDRESS:
       value = allocate_value (value_type);
-      gdbarch_return_value (gdbarch, function, value_type, &stop_regs,
+      gdbarch_return_value (gdbarch, function, value_type, stop_regs,
 			    value_contents_raw (value), NULL);
       break;
     case RETURN_VALUE_STRUCT_CONVENTION:
diff --git a/gdb/regcache.c b/gdb/regcache.c
index 9195bff..4286f36 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -219,13 +219,6 @@ do_cooked_read (void *src, int regnum, gdb_byte *buf)
   return regcache_cooked_read (regcache, regnum, buf);
 }
 
-regcache::regcache (readonly_t, const regcache &src)
-  : regcache (src.arch (), nullptr, true)
-{
-  gdb_assert (!src.m_readonly_p);
-  save (do_cooked_read, (void *) &src);
-}
-
 regcache_readonly::regcache_readonly (const regcache &src)
   : regcache_readonly (src.arch (), do_cooked_read, (void *) &src)
 {
@@ -1512,6 +1505,55 @@ private:
   const bool m_dump_pseudo;
 };
 
+/* Dump from reg_buffer, used when there is no thread or
+   registers.  */
+
+class register_dump_reg_buffer : public register_dump, reg_buffer
+{
+public:
+  register_dump_reg_buffer (gdbarch *gdbarch, bool dump_pseudo)
+    : register_dump (gdbarch), reg_buffer (gdbarch, dump_pseudo)
+  {
+  }
+
+protected:
+  void dump_reg (ui_file *file, int regnum) override
+  {
+    if (regnum < 0)
+      {
+	if (m_has_pseudo)
+	  fprintf_unfiltered (file, "Cooked value");
+	else
+	  fprintf_unfiltered (file, "Raw value");
+      }
+    else
+      {
+	if (regnum < gdbarch_num_regs (m_gdbarch) || m_has_pseudo)
+	  {
+	    auto size = register_size (m_gdbarch, regnum);
+
+	    if (size == 0)
+	      return;
+
+	    auto status = get_register_status (regnum);
+
+	    gdb_assert (status != REG_VALID);
+
+	    if (status == REG_UNKNOWN)
+	      fprintf_unfiltered (file, "<invalid>");
+	    else
+	      fprintf_unfiltered (file, "<unavailable>");
+	  }
+	else
+	  {
+	    /* Just print "<cooked>" for pseudo register when
+	       regcache_dump_raw.  */
+	    fprintf_unfiltered (file, "<cooked>");
+	  }
+      }
+  }
+};
+
 /* For "maint print registers".  */
 
 class register_dump_none : public register_dump
@@ -1633,22 +1675,19 @@ regcache_print (const char *args, enum regcache_dump_what what_to_dump)
     case regcache_dump_raw:
     case regcache_dump_cooked:
       {
-	regcache *reg;
+	auto dump_pseudo = (what_to_dump == regcache_dump_cooked);
 
 	if (target_has_registers)
-	  reg = get_current_regcache ();
+	  dump.reset (new register_dump_regcache (get_current_regcache (),
+						  dump_pseudo));
 	else
 	  {
 	    /* For the benefit of "maint print registers" & co when
 	       debugging an executable, allow dumping a regcache even when
 	       there is no thread selected / no registers.  */
-	    reg = new regcache (target_gdbarch ());
-	    regs.reset (reg);
+	    dump.reset (new register_dump_reg_buffer (target_gdbarch (),
+						      dump_pseudo));
 	  }
-
-	auto dump_pseudo = (what_to_dump == regcache_dump_cooked);
-
-	dump.reset (new register_dump_regcache (reg, dump_pseudo));
       }
       break;
     }
@@ -1937,7 +1976,7 @@ cooked_read_test (struct gdbarch *gdbarch)
       mock_target.reset ();
     }
 
-  regcache readonly (regcache::readonly, readwrite);
+  regcache_readonly readonly (readwrite);
 
   /* GDB may go to target layer to fetch all registers and memory for
      readonly regcache.  */
diff --git a/gdb/regcache.h b/gdb/regcache.h
index 5c0850d..fc645c4 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -305,16 +305,6 @@ class regcache_readonly;
 class regcache : public reg_buffer_rw
 {
 public:
-  regcache (gdbarch *gdbarch)
-    : regcache (gdbarch, nullptr, true)
-  {}
-
-  struct readonly_t {};
-  static constexpr readonly_t readonly {};
-
-  /* Create a readonly regcache from a non-readonly regcache.  */
-  regcache (readonly_t, const regcache &src);
-
   DISABLE_COPY_AND_ASSIGN (regcache);
 
   /* Return REGCACHE's address space.  */
-- 
1.9.1

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

* [RFC 00/15] Remove regcache::m_readonly_p
@ 2017-12-01 10:48 Yao Qi
  2017-12-01 10:48 ` [PATCH 09/15] Remove regcache_save and regcache_cpy Yao Qi
                   ` (15 more replies)
  0 siblings, 16 replies; 32+ messages in thread
From: Yao Qi @ 2017-12-01 10:48 UTC (permalink / raw)
  To: gdb-patches

regcache is used in many places in gdb in different ways, so regcache
becomes a flat and fat object.  That exposes some unnecessary APIs to
different part, and some APIs are misused or abused:

 1) gdbarch methods pseudo_register_read and pseudo_register_read_value
 have a parameter 'regcache *', but these two gdbarch methods only need
 raw_read* and cooked_read* methods.  So it is better to pass a class
 which only has raw_read* and cooked_read* methods, and other regcache
 methods are invisible to each gdbarch implementation.

 2) target_ops methods to_fetch_registers and to_store_registers have a
 parameter 'regcache *', but these two target_ops methods only need
 raw_supply and raw_collect methods, because raw registers are from target
 layer, pseudo registers are "composed" or "created" by gdbarch.

 3) jit.c uses regcache in an odd way, and record-full.c should use
 a simple version regcache instead of an array (see patch 11)

Beside these api issues, one issue in regcache is that there is no
type or class for readonly regcache.  We use a flag field m_readonly_p
to indicate the regcache is readonly or not, so some regcache apis have
assert that this regcache is or is not readonly.  The better way to do
this is to create a new class for readonly regcache which doesn't have
write methods at all.

This patch series fixes all of the problems above except 2) (I had a
patch to fix 2 in my tree, but still need more time to polish it.) by
designing a class hierarchy about regcache, like this,

                      reg_buffer
                         ^
                         |
                   ------+-----
                   ^
                   |
            regcache_read
                 ^
                 |
           ------+------
           ^           ^
           |           |
    reg_buffer_rw regcache_readonly
          ^
          |
      regcache

Class reg_buffer is a simple class, having register contents and status
(in patch 7).  regcache_read is an abstract class only having raw_read*
and cooked_read* methods (in patch 8).  reg_buffer_rw is a class which
has read and write methods, but it disconnects from target, IOW, the
write doesn't go through.  Class regcache_readonly is the readonly
regcache, created from regcache::save method.

This patch series is tested on {x86_64, aarch64, ppc64}-linux.  It is
an RFC, want to get comments.  I write them in at least seven different
ways, and this one is satisfying.  I don't push them in until 8.1 is
branched.

*** BLURB HERE ***

Yao Qi (15):
  Call cooked_read in ppu2spu_prev_register
  Don't call gdbarch_pseudo_register_read_value in jit.c
  Remove mt port
  Replace regcache_raw_read with regcache->raw_read
  regcache_cooked_read -> regcache->cooked_read
  regcache::cooked_write test
  Class reg_buffer
  class regcache_read and Pass regcache_read to gdbarch methods
  Remove regcache_save and regcache_cpy
  Class regcache_readonly
  Class reg_buffer_rw
  Replace regcache::dump with class register_dump
  No longer create readonly regcache
  Remove regcache::m_readonly_p
  Move register_dump to regcache-dump.c

 gdb/Makefile.in       |    3 +-
 gdb/aarch64-tdep.c    |   12 +-
 gdb/amd64-tdep.c      |   11 +-
 gdb/arm-tdep.c        |   12 +-
 gdb/avr-tdep.c        |    4 +-
 gdb/bfin-tdep.c       |    4 +-
 gdb/configure.tgt     |    6 +-
 gdb/dummy-frame.c     |    6 +-
 gdb/frame.c           |   15 +-
 gdb/frame.h           |    3 +-
 gdb/frv-tdep.c        |    8 +-
 gdb/gdbarch.c         |    4 +-
 gdb/gdbarch.h         |    8 +-
 gdb/gdbarch.sh        |    4 +-
 gdb/h8300-tdep.c      |    8 +-
 gdb/hppa-tdep.c       |    4 +-
 gdb/i386-tdep.c       |   72 ++-
 gdb/i386-tdep.h       |    2 +-
 gdb/ia64-tdep.c       |   32 +-
 gdb/infcmd.c          |    6 +-
 gdb/inferior.h        |    2 +-
 gdb/infrun.c          |    8 +-
 gdb/jit.c             |   26 +-
 gdb/linux-fork.c      |   20 +-
 gdb/m32c-tdep.c       |   54 +--
 gdb/m68hc11-tdep.c    |    6 +-
 gdb/mep-tdep.c        |   12 +-
 gdb/mi/mi-main.c      |   12 +-
 gdb/mips-tdep.c       |    8 +-
 gdb/msp430-tdep.c     |    4 +-
 gdb/mt-tdep.c         | 1218 -------------------------------------------------
 gdb/nds32-tdep.c      |    4 +-
 gdb/ppc-linux-tdep.c  |   15 +-
 gdb/record-full.c     |   21 +-
 gdb/regcache-dump.c   |  335 ++++++++++++++
 gdb/regcache.c        |  586 ++++++++++--------------
 gdb/regcache.h        |  242 ++++++----
 gdb/rl78-tdep.c       |   29 +-
 gdb/rs6000-tdep.c     |   88 ++--
 gdb/s390-linux-tdep.c |   17 +-
 gdb/sh-tdep.c         |    8 +-
 gdb/sh64-tdep.c       |   12 +-
 gdb/sparc-tdep.c      |    6 +-
 gdb/sparc64-tdep.c    |   22 +-
 gdb/spu-tdep.c        |   16 +-
 gdb/xtensa-tdep.c     |   15 +-
 46 files changed, 1024 insertions(+), 1986 deletions(-)
 delete mode 100644 gdb/mt-tdep.c
 create mode 100644 gdb/regcache-dump.c

-- 
1.9.1

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

* [PATCH 08/15] class regcache_read and Pass regcache_read to gdbarch methods
  2017-12-01 10:48 [RFC 00/15] Remove regcache::m_readonly_p Yao Qi
                   ` (3 preceding siblings ...)
  2017-12-01 10:48 ` [PATCH 15/15] Move register_dump to regcache-dump.c Yao Qi
@ 2017-12-01 10:48 ` Yao Qi
  2018-01-23 21:51   ` Simon Marchi
  2017-12-01 10:48 ` [PATCH 13/15] No longer create readonly regcache Yao Qi
                   ` (10 subsequent siblings)
  15 siblings, 1 reply; 32+ messages in thread
From: Yao Qi @ 2017-12-01 10:48 UTC (permalink / raw)
  To: gdb-patches

pseudo registers are either from raw registers or memory, so
gdbarch methods pseudo_register_read and pseudo_register_read_value
should have regcache object which only have read methods.  In other
words, we should disallow writing to regcache in these two gdbarch
methods.  In order to apply this restriction, this patch adds a new
class regcache_read, derived from reg_buffer, and it only has
raw_read and cooked_read methods.  regcache is derived from
regcache_read.  This patch also passes regcache_read instead of
regcache to gdbarch methods pseudo_register_read and
pseudo_register_read_value.

This patch moves raw_read* and cooked_read* methods to regcache_read,
which is straightforward.  One thing not straightforward is that I split
regcache::xfer_part to regcache_read::read_part and regcache::write_part,
because regcache_read can only have methods to read.

regcache_read is an abstract base class, and it has a pure virtual
function raw_update, because I don't want regcache_read know where these
raw registers are from.  They can be from either the target (readwrite
regcache) or the regcache itself (readonly regcache).

gdb:

2017-11-29  Yao Qi  <yao.qi@linaro.org>

	* aarch64-tdep.c (aarch64_pseudo_register_read_value): Change
	parameter type to 'regcache_read *'.
	* amd64-tdep.c (amd64_pseudo_register_read_value): Likewise.
	* arm-tdep.c (arm_neon_quad_read): Likewise.
	(arm_pseudo_read): Likewise.
	* avr-tdep.c (avr_pseudo_register_read): Likewise.
	* bfin-tdep.c (bfin_pseudo_register_read): Likewise.
	* frv-tdep.c (frv_pseudo_register_read): Likewise.
	* gdbarch.c: Re-generated.
	* gdbarch.h: Re-generated.
	* gdbarch.sh (pseudo_register_read): Change parameter type to
	'regcache_read *'.
	(pseudo_register_read_value): Likewise.
	* h8300-tdep.c (pseudo_from_raw_register): Likewise.
	(h8300_pseudo_register_read): Likewise.
	* hppa-tdep.c (hppa_pseudo_register_read): Likewise.
	* i386-tdep.c (i386_mmx_regnum_to_fp_regnum): Likewise.
	(i386_pseudo_register_read_into_value): Likewise.
	(i386_pseudo_register_read_value): Likewise.
	* i386-tdep.h (i386_pseudo_register_read_into_value): Update
	declaration.
	* ia64-tdep.c (ia64_pseudo_register_read): Likewise.
	* m32c-tdep.c (m32c_raw_read): Likewise.
	(m32c_read_flg): Likewise.
	(m32c_banked_register): Likewise.
	(m32c_banked_read): Likewise.
	(m32c_sb_read): Likewise.
	(m32c_part_read): Likewise.
	(m32c_cat_read): Likewise.
	(m32c_r3r2r1r0_read): Likewise.
	(m32c_pseudo_register_read): Likewise.
	* m68hc11-tdep.c (m68hc11_pseudo_register_read): Likewise.
	* mep-tdep.c (mep_pseudo_cr32_read): Likewise.
	(mep_pseudo_cr64_read): Likewise.
	(mep_pseudo_register_read): Likewise.
	* mips-tdep.c (mips_pseudo_register_read): Likewise.
	* msp430-tdep.c (msp430_pseudo_register_read): Likewise.
	* nds32-tdep.c (nds32_pseudo_register_read): Likewise.
	* regcache.c (regcache::raw_read): Move it to regcache_read.
	(regcache::cooked_read): Likewise.
	(regcache::cooked_read_value): Likewise.
	(regcache_cooked_read_signed):
	(regcache::cooked_read): Likewise.
	* regcache.h (regcache_read): New class.
	(regcache): Inherit regcache_read.  Move some methods to
	regcache_read.
	* rl78-tdep.c (rl78_pseudo_register_read): Change
	parameter type to 'regcache_read *'.
	* rs6000-tdep.c (do_regcache_raw_read): Remove.
	(e500_pseudo_register_read): Change parameter type to
	'regcache_read *'.
	(dfp_pseudo_register_read): Likewise.
	(vsx_pseudo_register_read): Likewise.
	(efpr_pseudo_register_read): Likewise.
	* s390-linux-tdep.c (s390_pseudo_register_read): Likewise.
	* sh-tdep.c (sh_pseudo_register_read): Likewise.
	* sh64-tdep.c (pseudo_register_read_portions): Likewise.
	(sh64_pseudo_register_read): Likewise.
	* sparc-tdep.c (sparc32_pseudo_register_read): Likewise.
	* sparc64-tdep.c (sparc64_pseudo_register_read): Likewise.
	* spu-tdep.c (spu_pseudo_register_read_spu): Likewise.
	(spu_pseudo_register_read): Likewise.
	* xtensa-tdep.c	(xtensa_register_read_masked): Likewise.
	(xtensa_pseudo_register_read): Likewise.
---
 gdb/aarch64-tdep.c    |  2 +-
 gdb/amd64-tdep.c      |  2 +-
 gdb/arm-tdep.c        |  6 ++--
 gdb/avr-tdep.c        |  2 +-
 gdb/bfin-tdep.c       |  2 +-
 gdb/frv-tdep.c        |  2 +-
 gdb/gdbarch.c         |  4 +--
 gdb/gdbarch.h         |  8 ++---
 gdb/gdbarch.sh        |  4 +--
 gdb/h8300-tdep.c      |  4 +--
 gdb/hppa-tdep.c       |  2 +-
 gdb/i386-tdep.c       |  6 ++--
 gdb/i386-tdep.h       |  2 +-
 gdb/ia64-tdep.c       |  2 +-
 gdb/m32c-tdep.c       | 20 ++++++------
 gdb/m68hc11-tdep.c    |  2 +-
 gdb/mep-tdep.c        |  6 ++--
 gdb/mips-tdep.c       |  2 +-
 gdb/msp430-tdep.c     |  2 +-
 gdb/nds32-tdep.c      |  2 +-
 gdb/regcache.c        | 84 ++++++++++++++++++++++++++++++++-------------------
 gdb/regcache.h        | 58 +++++++++++++++++++++--------------
 gdb/rl78-tdep.c       |  2 +-
 gdb/rs6000-tdep.c     | 52 +++++++++++++++++++++----------
 gdb/s390-linux-tdep.c |  2 +-
 gdb/sh-tdep.c         |  4 +--
 gdb/sh64-tdep.c       |  4 +--
 gdb/sparc-tdep.c      |  2 +-
 gdb/sparc64-tdep.c    |  2 +-
 gdb/spu-tdep.c        |  4 +--
 gdb/xtensa-tdep.c     |  4 +--
 31 files changed, 178 insertions(+), 122 deletions(-)

diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 0947100..58ab741 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -2225,7 +2225,7 @@ aarch64_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
 
 static struct value *
 aarch64_pseudo_read_value (struct gdbarch *gdbarch,
-			   struct regcache *regcache,
+			   regcache_read *regcache,
 			   int regnum)
 {
   gdb_byte reg_buf[V_REGISTER_SIZE];
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index 57dc979..a8c43b2 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -347,7 +347,7 @@ amd64_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
 
 static struct value *
 amd64_pseudo_register_read_value (struct gdbarch *gdbarch,
-				  struct regcache *regcache,
+				  regcache_read *regcache,
 				  int regnum)
 {
   gdb_byte *raw_buf = (gdb_byte *) alloca (register_size (gdbarch, regnum));
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 20da423..bde199a 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -227,7 +227,7 @@ static void show_disassembly_style_sfunc (struct ui_file *, int,
 					  const char *);
 
 static enum register_status arm_neon_quad_read (struct gdbarch *gdbarch,
-						struct regcache *regcache,
+						regcache_read *regcache,
 						int regnum, gdb_byte *buf);
 static void arm_neon_quad_write (struct gdbarch *gdbarch,
 				 struct regcache *regcache,
@@ -8678,7 +8678,7 @@ arm_write_pc (struct regcache *regcache, CORE_ADDR pc)
    the quad register, in [0, 15].  */
 
 static enum register_status
-arm_neon_quad_read (struct gdbarch *gdbarch, struct regcache *regcache,
+arm_neon_quad_read (struct gdbarch *gdbarch, regcache_read *regcache,
 		    int regnum, gdb_byte *buf)
 {
   char name_buf[4];
@@ -8711,7 +8711,7 @@ arm_neon_quad_read (struct gdbarch *gdbarch, struct regcache *regcache,
 }
 
 static enum register_status
-arm_pseudo_read (struct gdbarch *gdbarch, struct regcache *regcache,
+arm_pseudo_read (struct gdbarch *gdbarch, regcache_read *regcache,
 		 int regnum, gdb_byte *buf)
 {
   const int num_regs = gdbarch_num_regs (gdbarch);
diff --git a/gdb/avr-tdep.c b/gdb/avr-tdep.c
index bcf844a..40cb724 100644
--- a/gdb/avr-tdep.c
+++ b/gdb/avr-tdep.c
@@ -382,7 +382,7 @@ avr_write_pc (struct regcache *regcache, CORE_ADDR val)
 }
 
 static enum register_status
-avr_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+avr_pseudo_register_read (struct gdbarch *gdbarch, regcache_read *regcache,
                           int regnum, gdb_byte *buf)
 {
   ULONGEST val;
diff --git a/gdb/bfin-tdep.c b/gdb/bfin-tdep.c
index 9e37898..fc4d246 100644
--- a/gdb/bfin-tdep.c
+++ b/gdb/bfin-tdep.c
@@ -688,7 +688,7 @@ bfin_register_name (struct gdbarch *gdbarch, int i)
 }
 
 static enum register_status
-bfin_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+bfin_pseudo_register_read (struct gdbarch *gdbarch, regcache_read *regcache,
 			   int regnum, gdb_byte *buffer)
 {
   gdb_byte buf[BFIN_MAX_REGISTER_SIZE];
diff --git a/gdb/frv-tdep.c b/gdb/frv-tdep.c
index 9e552eb..1b7b1f8 100644
--- a/gdb/frv-tdep.c
+++ b/gdb/frv-tdep.c
@@ -295,7 +295,7 @@ frv_register_type (struct gdbarch *gdbarch, int reg)
 }
 
 static enum register_status
-frv_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+frv_pseudo_register_read (struct gdbarch *gdbarch, regcache_read *regcache,
                           int reg, gdb_byte *buffer)
 {
   enum register_status status;
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 007392c..525e8bd 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -1965,7 +1965,7 @@ gdbarch_pseudo_register_read_p (struct gdbarch *gdbarch)
 }
 
 enum register_status
-gdbarch_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, gdb_byte *buf)
+gdbarch_pseudo_register_read (struct gdbarch *gdbarch, regcache_read *regcache, int cookednum, gdb_byte *buf)
 {
   gdb_assert (gdbarch != NULL);
   gdb_assert (gdbarch->pseudo_register_read != NULL);
@@ -1989,7 +1989,7 @@ gdbarch_pseudo_register_read_value_p (struct gdbarch *gdbarch)
 }
 
 struct value *
-gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum)
+gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, regcache_read *regcache, int cookednum)
 {
   gdb_assert (gdbarch != NULL);
   gdb_assert (gdbarch->pseudo_register_read_value != NULL);
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index d2e6b6f..7499917 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -265,8 +265,8 @@ extern void set_gdbarch_virtual_frame_pointer (struct gdbarch *gdbarch, gdbarch_
 
 extern int gdbarch_pseudo_register_read_p (struct gdbarch *gdbarch);
 
-typedef enum register_status (gdbarch_pseudo_register_read_ftype) (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, gdb_byte *buf);
-extern enum register_status gdbarch_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, gdb_byte *buf);
+typedef enum register_status (gdbarch_pseudo_register_read_ftype) (struct gdbarch *gdbarch, regcache_read *regcache, int cookednum, gdb_byte *buf);
+extern enum register_status gdbarch_pseudo_register_read (struct gdbarch *gdbarch, regcache_read *regcache, int cookednum, gdb_byte *buf);
 extern void set_gdbarch_pseudo_register_read (struct gdbarch *gdbarch, gdbarch_pseudo_register_read_ftype *pseudo_register_read);
 
 /* Read a register into a new struct value.  If the register is wholly
@@ -276,8 +276,8 @@ extern void set_gdbarch_pseudo_register_read (struct gdbarch *gdbarch, gdbarch_p
 
 extern int gdbarch_pseudo_register_read_value_p (struct gdbarch *gdbarch);
 
-typedef struct value * (gdbarch_pseudo_register_read_value_ftype) (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum);
-extern struct value * gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum);
+typedef struct value * (gdbarch_pseudo_register_read_value_ftype) (struct gdbarch *gdbarch, regcache_read *regcache, int cookednum);
+extern struct value * gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, regcache_read *regcache, int cookednum);
 extern void set_gdbarch_pseudo_register_read_value (struct gdbarch *gdbarch, gdbarch_pseudo_register_read_value_ftype *pseudo_register_read_value);
 
 extern int gdbarch_pseudo_register_write_p (struct gdbarch *gdbarch);
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 6459b12..9da7328 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -429,12 +429,12 @@ F;void;write_pc;struct regcache *regcache, CORE_ADDR val;regcache, val
 # serious shakedown.
 m;void;virtual_frame_pointer;CORE_ADDR pc, int *frame_regnum, LONGEST *frame_offset;pc, frame_regnum, frame_offset;0;legacy_virtual_frame_pointer;;0
 #
-M;enum register_status;pseudo_register_read;struct regcache *regcache, int cookednum, gdb_byte *buf;regcache, cookednum, buf
+M;enum register_status;pseudo_register_read;regcache_read *regcache, int cookednum, gdb_byte *buf;regcache, cookednum, buf
 # Read a register into a new struct value.  If the register is wholly
 # or partly unavailable, this should call mark_value_bytes_unavailable
 # as appropriate.  If this is defined, then pseudo_register_read will
 # never be called.
-M;struct value *;pseudo_register_read_value;struct regcache *regcache, int cookednum;regcache, cookednum
+M;struct value *;pseudo_register_read_value;regcache_read *regcache, int cookednum;regcache, cookednum
 M;void;pseudo_register_write;struct regcache *regcache, int cookednum, const gdb_byte *buf;regcache, cookednum, buf
 #
 v;int;num_regs;;;0;-1
diff --git a/gdb/h8300-tdep.c b/gdb/h8300-tdep.c
index fc8c72f..15ee458 100644
--- a/gdb/h8300-tdep.c
+++ b/gdb/h8300-tdep.c
@@ -1160,7 +1160,7 @@ h8300_register_type (struct gdbarch *gdbarch, int regno)
    raw registers.  These helpers extend/narrow the values.  */
 
 static enum register_status
-pseudo_from_raw_register (struct gdbarch *gdbarch, struct regcache *regcache,
+pseudo_from_raw_register (struct gdbarch *gdbarch, regcache_read *regcache,
 			  gdb_byte *buf, int pseudo_regno, int raw_regno)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
@@ -1191,7 +1191,7 @@ raw_from_pseudo_register (struct gdbarch *gdbarch, struct regcache *regcache,
 
 static enum register_status
 h8300_pseudo_register_read (struct gdbarch *gdbarch,
-			    struct regcache *regcache, int regno,
+			    regcache_read *regcache, int regno,
 			    gdb_byte *buf)
 {
   if (regno == E_PSEUDO_CCR_REGNUM (gdbarch))
diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c
index 1e007d9..f6a2f50 100644
--- a/gdb/hppa-tdep.c
+++ b/gdb/hppa-tdep.c
@@ -2747,7 +2747,7 @@ hppa_fetch_pointer_argument (struct frame_info *frame, int argi,
 }
 
 static enum register_status
-hppa_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+hppa_pseudo_register_read (struct gdbarch *gdbarch, regcache_read *regcache,
 			   int regnum, gdb_byte *buf)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 2a9e4a7..913bdc8 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -3248,7 +3248,7 @@ i386_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
    the MMX registers need to be mapped onto floating point registers.  */
 
 static int
-i386_mmx_regnum_to_fp_regnum (struct regcache *regcache, int regnum)
+i386_mmx_regnum_to_fp_regnum (regcache_read *regcache, int regnum)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ());
   int mmxreg, fpreg;
@@ -3269,7 +3269,7 @@ i386_mmx_regnum_to_fp_regnum (struct regcache *regcache, int regnum)
 
 void
 i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
-				      struct regcache *regcache,
+				      regcache_read *regcache,
 				      int regnum,
 				      struct value *result_value)
 {
@@ -3448,7 +3448,7 @@ i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
 
 static struct value *
 i386_pseudo_register_read_value (struct gdbarch *gdbarch,
-				 struct regcache *regcache,
+				 regcache_read *regcache,
 				 int regnum)
 {
   struct value *result;
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index f190bb3..f5c2194 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -364,7 +364,7 @@ extern struct type *i386_pseudo_register_type (struct gdbarch *gdbarch,
 					       int regnum);
 
 extern void i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
-						  struct regcache *regcache,
+						  regcache_read *regcache,
 						  int regnum,
 						  struct value *result);
 
diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c
index 5bce751..acd0909 100644
--- a/gdb/ia64-tdep.c
+++ b/gdb/ia64-tdep.c
@@ -927,7 +927,7 @@ rse_address_add(CORE_ADDR addr, int nslots)
 }
 
 static enum register_status
-ia64_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+ia64_pseudo_register_read (struct gdbarch *gdbarch, regcache_read *regcache,
                            int regnum, gdb_byte *buf)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
diff --git a/gdb/m32c-tdep.c b/gdb/m32c-tdep.c
index e04fdfd..8efc142 100644
--- a/gdb/m32c-tdep.c
+++ b/gdb/m32c-tdep.c
@@ -51,7 +51,7 @@ typedef enum register_status (m32c_write_reg_t) (struct m32c_reg *reg,
 						 const gdb_byte *buf);
 
 typedef enum register_status (m32c_read_reg_t) (struct m32c_reg *reg,
-						struct regcache *cache,
+						regcache_read *cache,
 						gdb_byte *buf);
 
 struct m32c_reg
@@ -310,7 +310,7 @@ static m32c_write_reg_t m32c_r3r2r1r0_write;
 
 /* Copy the value of the raw register REG from CACHE to BUF.  */
 static enum register_status
-m32c_raw_read (struct m32c_reg *reg, struct regcache *cache, gdb_byte *buf)
+m32c_raw_read (struct m32c_reg *reg, regcache_read *cache, gdb_byte *buf)
 {
   return cache->raw_read (reg->num, buf);
 }
@@ -329,7 +329,7 @@ m32c_raw_write (struct m32c_reg *reg, struct regcache *cache,
 
 /* Return the value of the 'flg' register in CACHE.  */
 static int
-m32c_read_flg (struct regcache *cache)
+m32c_read_flg (regcache_read *cache)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (cache->arch ());
   ULONGEST flg;
@@ -341,7 +341,7 @@ m32c_read_flg (struct regcache *cache)
 
 /* Evaluate the real register number of a banked register.  */
 static struct m32c_reg *
-m32c_banked_register (struct m32c_reg *reg, struct regcache *cache)
+m32c_banked_register (struct m32c_reg *reg, regcache_read *cache)
 {
   return ((m32c_read_flg (cache) & reg->n) ? reg->ry : reg->rx);
 }
@@ -352,7 +352,7 @@ m32c_banked_register (struct m32c_reg *reg, struct regcache *cache)
    masked in REG->n set, then read REG->ry.  Otherwise, read
    REG->rx.  */
 static enum register_status
-m32c_banked_read (struct m32c_reg *reg, struct regcache *cache, gdb_byte *buf)
+m32c_banked_read (struct m32c_reg *reg, regcache_read *cache, gdb_byte *buf)
 {
   struct m32c_reg *bank_reg = m32c_banked_register (reg, cache);
   return cache->raw_read (bank_reg->num, buf);
@@ -377,7 +377,7 @@ m32c_banked_write (struct m32c_reg *reg, struct regcache *cache,
 /* Move the value of SB from CACHE to BUF.  On bfd_mach_m32c, SB is a
    banked register; on bfd_mach_m16c, it's not.  */
 static enum register_status
-m32c_sb_read (struct m32c_reg *reg, struct regcache *cache, gdb_byte *buf)
+m32c_sb_read (struct m32c_reg *reg, regcache_read *cache, gdb_byte *buf)
 {
   if (gdbarch_bfd_arch_info (reg->arch)->mach == bfd_mach_m16c)
     return m32c_raw_read (reg->rx, cache, buf);
@@ -442,7 +442,7 @@ m32c_find_part (struct m32c_reg *reg, int *offset_p, int *len_p)
    REG->type values, where higher indices refer to more significant
    bits, read the value of the REG->n'th element.  */
 static enum register_status
-m32c_part_read (struct m32c_reg *reg, struct regcache *cache, gdb_byte *buf)
+m32c_part_read (struct m32c_reg *reg, regcache_read *cache, gdb_byte *buf)
 {
   int offset, len;
 
@@ -473,7 +473,7 @@ m32c_part_write (struct m32c_reg *reg, struct regcache *cache,
    concatenation of the values of the registers REG->rx and REG->ry,
    with REG->rx contributing the more significant bits.  */
 static enum register_status
-m32c_cat_read (struct m32c_reg *reg, struct regcache *cache, gdb_byte *buf)
+m32c_cat_read (struct m32c_reg *reg, regcache_read *cache, gdb_byte *buf)
 {
   int high_bytes = TYPE_LENGTH (reg->rx->type);
   int low_bytes  = TYPE_LENGTH (reg->ry->type);
@@ -528,7 +528,7 @@ m32c_cat_write (struct m32c_reg *reg, struct regcache *cache,
    the concatenation (from most significant to least) of r3, r2, r1,
    and r0.  */
 static enum register_status
-m32c_r3r2r1r0_read (struct m32c_reg *reg, struct regcache *cache, gdb_byte *buf)
+m32c_r3r2r1r0_read (struct m32c_reg *reg, regcache_read *cache, gdb_byte *buf)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (reg->arch);
   int len = TYPE_LENGTH (tdep->r0->type);
@@ -590,7 +590,7 @@ m32c_r3r2r1r0_write (struct m32c_reg *reg, struct regcache *cache,
 
 static enum register_status
 m32c_pseudo_register_read (struct gdbarch *arch,
-			   struct regcache *cache,
+			   regcache_read *cache,
 			   int cookednum,
 			   gdb_byte *buf)
 {
diff --git a/gdb/m68hc11-tdep.c b/gdb/m68hc11-tdep.c
index 3ef1fbf..878b1a9 100644
--- a/gdb/m68hc11-tdep.c
+++ b/gdb/m68hc11-tdep.c
@@ -279,7 +279,7 @@ m68hc11_which_soft_register (CORE_ADDR addr)
    fetch into a memory read.  */
 static enum register_status
 m68hc11_pseudo_register_read (struct gdbarch *gdbarch,
-			      struct regcache *regcache,
+			      regcache_read *regcache,
 			      int regno, gdb_byte *buf)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
diff --git a/gdb/mep-tdep.c b/gdb/mep-tdep.c
index 4069d59..3c5f258 100644
--- a/gdb/mep-tdep.c
+++ b/gdb/mep-tdep.c
@@ -1125,7 +1125,7 @@ mep_read_pc (struct regcache *regcache)
 
 static enum register_status
 mep_pseudo_cr32_read (struct gdbarch *gdbarch,
-                      struct regcache *regcache,
+		      regcache_read *regcache,
                       int cookednum,
                       gdb_byte *buf)
 {
@@ -1151,7 +1151,7 @@ mep_pseudo_cr32_read (struct gdbarch *gdbarch,
 
 static enum register_status
 mep_pseudo_cr64_read (struct gdbarch *gdbarch,
-                      struct regcache *regcache,
+                      regcache_read *regcache,
                       int cookednum,
                       gdb_byte *buf)
 {
@@ -1161,7 +1161,7 @@ mep_pseudo_cr64_read (struct gdbarch *gdbarch,
 
 static enum register_status
 mep_pseudo_register_read (struct gdbarch *gdbarch,
-                          struct regcache *regcache,
+			  regcache_read *regcache,
                           int cookednum,
                           gdb_byte *buf)
 {
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 1e7cb4a..35e0132 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -737,7 +737,7 @@ mips_tdesc_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
    registers.  Take care of alignment and size problems.  */
 
 static enum register_status
-mips_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+mips_pseudo_register_read (struct gdbarch *gdbarch, regcache_read *regcache,
 			   int cookednum, gdb_byte *buf)
 {
   int rawnum = cookednum % gdbarch_num_regs (gdbarch);
diff --git a/gdb/msp430-tdep.c b/gdb/msp430-tdep.c
index 834f4e6..eebe7da 100644
--- a/gdb/msp430-tdep.c
+++ b/gdb/msp430-tdep.c
@@ -218,7 +218,7 @@ msp430_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
 
 static enum register_status
 msp430_pseudo_register_read (struct gdbarch *gdbarch,
-			     struct regcache *regcache,
+			     regcache_read *regcache,
 			     int regnum, gdb_byte *buffer)
 {
   if (MSP430_NUM_REGS <= regnum && regnum < MSP430_NUM_TOTAL_REGS)
diff --git a/gdb/nds32-tdep.c b/gdb/nds32-tdep.c
index f4037b2..001db1f 100644
--- a/gdb/nds32-tdep.c
+++ b/gdb/nds32-tdep.c
@@ -437,7 +437,7 @@ nds32_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
 
 static enum register_status
 nds32_pseudo_register_read (struct gdbarch *gdbarch,
-			    struct regcache *regcache, int regnum,
+			    regcache_read *regcache, int regnum,
 			    gdb_byte *buf)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
diff --git a/gdb/regcache.c b/gdb/regcache.c
index 8cc9c98..5ce6064 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -205,7 +205,7 @@ regcache::regcache (gdbarch *gdbarch, const address_space *aspace_,
 /* The register buffers.  A read-only register cache can hold the
    full [0 .. gdbarch_num_regs + gdbarch_num_pseudo_regs) while a
    read/write register cache can only hold [0 .. gdbarch_num_regs).  */
-  : reg_buffer (gdbarch, readonly_p_),
+  : regcache_read (gdbarch, readonly_p_),
     m_aspace (aspace_), m_readonly_p (readonly_p_)
 {
   m_ptid = minus_one_ptid;
@@ -581,7 +581,7 @@ regcache_raw_read (struct regcache *regcache, int regnum, gdb_byte *buf)
 }
 
 enum register_status
-regcache::raw_read (int regnum, gdb_byte *buf)
+regcache_read::raw_read (int regnum, gdb_byte *buf)
 {
   gdb_assert (buf != NULL);
   raw_update (regnum);
@@ -604,7 +604,7 @@ regcache_raw_read_signed (struct regcache *regcache, int regnum, LONGEST *val)
 
 template<typename T, typename>
 enum register_status
-regcache::raw_read (int regnum, T *val)
+regcache_read::raw_read (int regnum, T *val)
 {
   gdb_byte *buf;
   enum register_status status;
@@ -677,17 +677,15 @@ regcache_cooked_read (struct regcache *regcache, int regnum, gdb_byte *buf)
 }
 
 enum register_status
-regcache::cooked_read (int regnum, gdb_byte *buf)
+regcache_read::cooked_read (int regnum, gdb_byte *buf)
 {
   gdb_assert (regnum >= 0);
   gdb_assert (regnum < m_descr->nr_cooked_registers);
   if (regnum < num_raw_registers ())
     return raw_read (regnum, buf);
-  else if (m_readonly_p
+  else if (m_has_pseudo
 	   && m_register_status[regnum] != REG_UNKNOWN)
     {
-      /* Read-only register cache, perhaps the cooked value was
-	 cached?  */
       if (m_register_status[regnum] == REG_VALID)
 	memcpy (buf, register_buffer (regnum),
 		m_descr->sizeof_register[regnum]);
@@ -730,13 +728,13 @@ regcache_cooked_read_value (struct regcache *regcache, int regnum)
 }
 
 struct value *
-regcache::cooked_read_value (int regnum)
+regcache_read::cooked_read_value (int regnum)
 {
   gdb_assert (regnum >= 0);
   gdb_assert (regnum < m_descr->nr_cooked_registers);
 
   if (regnum < num_raw_registers ()
-      || (m_readonly_p && m_register_status[regnum] != REG_UNKNOWN)
+      || (m_has_pseudo && m_register_status[regnum] != REG_UNKNOWN)
       || !gdbarch_pseudo_register_read_value_p (m_descr->gdbarch))
     {
       struct value *result;
@@ -770,7 +768,7 @@ regcache_cooked_read_signed (struct regcache *regcache, int regnum,
 
 template<typename T, typename>
 enum register_status
-regcache::cooked_read (int regnum, T *val)
+regcache_read::cooked_read (int regnum, T *val)
 {
   enum register_status status;
   gdb_byte *buf;
@@ -910,20 +908,49 @@ typedef void (regcache_write_ftype) (struct regcache *regcache, int regnum,
 				     const void *buf);
 
 enum register_status
-regcache::xfer_part (int regnum, int offset, int len, void *in,
+regcache_read::read_part (int regnum, int offset, int len, void *in,
+			  bool is_raw)
+{
+  struct gdbarch *gdbarch = arch ();
+  gdb_byte *reg = (gdb_byte *) alloca (register_size (gdbarch, regnum));
+
+  gdb_assert (in != NULL);
+  gdb_assert (offset >= 0 && offset <= m_descr->sizeof_register[regnum]);
+  gdb_assert (len >= 0 && offset + len <= m_descr->sizeof_register[regnum]);
+  /* Something to do?  */
+  if (offset + len == 0)
+    return REG_VALID;
+  /* Read (when needed) ...  */
+  enum register_status status;
+
+  if (is_raw)
+    status = raw_read (regnum, reg);
+  else
+    status = cooked_read (regnum, reg);
+  if (status != REG_VALID)
+    return status;
+
+  /* ... modify ...  */
+  memcpy (in, reg + offset, len);
+
+  return REG_VALID;
+}
+
+enum register_status
+regcache::write_part (int regnum, int offset, int len,
 		     const void *out, bool is_raw)
 {
   struct gdbarch *gdbarch = arch ();
   gdb_byte *reg = (gdb_byte *) alloca (register_size (gdbarch, regnum));
 
+  gdb_assert (out != NULL);
   gdb_assert (offset >= 0 && offset <= m_descr->sizeof_register[regnum]);
   gdb_assert (len >= 0 && offset + len <= m_descr->sizeof_register[regnum]);
   /* Something to do?  */
   if (offset + len == 0)
     return REG_VALID;
   /* Read (when needed) ...  */
-  if (in != NULL
-      || offset > 0
+  if (offset > 0
       || offset + len < m_descr->sizeof_register[regnum])
     {
       enum register_status status;
@@ -935,19 +962,13 @@ regcache::xfer_part (int regnum, int offset, int len, void *in,
       if (status != REG_VALID)
 	return status;
     }
-  /* ... modify ...  */
-  if (in != NULL)
-    memcpy (in, reg + offset, len);
-  if (out != NULL)
-    memcpy (reg + offset, out, len);
+
+  memcpy (reg + offset, out, len);
   /* ... write (when needed).  */
-  if (out != NULL)
-    {
-      if (is_raw)
-	raw_write (regnum, reg);
-      else
-	cooked_write (regnum, reg);
-    }
+  if (is_raw)
+    raw_write (regnum, reg);
+  else
+    cooked_write (regnum, reg);
 
   return REG_VALID;
 }
@@ -960,10 +981,10 @@ regcache_raw_read_part (struct regcache *regcache, int regnum,
 }
 
 enum register_status
-regcache::raw_read_part (int regnum, int offset, int len, gdb_byte *buf)
+regcache_read::raw_read_part (int regnum, int offset, int len, gdb_byte *buf)
 {
   assert_regnum (regnum);
-  return xfer_part (regnum, offset, len, buf, NULL, true);
+  return read_part (regnum, offset, len, buf, true);
 }
 
 void
@@ -978,7 +999,7 @@ regcache::raw_write_part (int regnum, int offset, int len,
 			  const gdb_byte *buf)
 {
   assert_regnum (regnum);
-  xfer_part (regnum, offset, len, NULL, buf, true);
+  write_part (regnum, offset, len, buf, true);
 }
 
 enum register_status
@@ -990,10 +1011,11 @@ regcache_cooked_read_part (struct regcache *regcache, int regnum,
 
 
 enum register_status
-regcache::cooked_read_part (int regnum, int offset, int len, gdb_byte *buf)
+regcache_read::cooked_read_part (int regnum, int offset, int len,
+				 gdb_byte *buf)
 {
   gdb_assert (regnum >= 0 && regnum < m_descr->nr_cooked_registers);
-  return xfer_part (regnum, offset, len, buf, NULL, false);
+  return read_part (regnum, offset, len, buf, false);
 }
 
 void
@@ -1008,7 +1030,7 @@ regcache::cooked_write_part (int regnum, int offset, int len,
 			     const gdb_byte *buf)
 {
   gdb_assert (regnum >= 0 && regnum < m_descr->nr_cooked_registers);
-  xfer_part (regnum, offset, len, NULL, buf, false);
+  write_part (regnum, offset, len, buf, false);
 }
 
 /* Supply register REGNUM, whose contents are stored in BUF, to REGCACHE.  */
diff --git a/gdb/regcache.h b/gdb/regcache.h
index a133de1..b107bbd 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -262,9 +262,39 @@ protected:
   signed char *m_register_status;
 };
 
+class regcache_read : public reg_buffer
+{
+public:
+  regcache_read (gdbarch *gdbarch, bool has_pseudo)
+    : reg_buffer (gdbarch, has_pseudo)
+  {}
+
+  enum register_status raw_read (int regnum, gdb_byte *buf);
+  template<typename T, typename = RequireLongest<T>>
+  enum register_status raw_read (int regnum, T *val);
+
+  enum register_status raw_read_part (int regnum, int offset, int len,
+				      gdb_byte *buf);
+
+  virtual void raw_update (int regnum) = 0;
+
+  enum register_status cooked_read (int regnum, gdb_byte *buf);
+  template<typename T, typename = RequireLongest<T>>
+  enum register_status cooked_read (int regnum, T *val);
+
+  enum register_status cooked_read_part (int regnum, int offset, int len,
+					 gdb_byte *buf);
+
+  struct value *cooked_read_value (int regnum);
+
+protected:
+  enum register_status read_part (int regnum, int offset, int len, void *in,
+				  bool is_raw);
+};
+
 /* The register cache for storing raw register values.  */
 
-class regcache : public reg_buffer
+class regcache : public regcache_read
 {
 public:
   regcache (gdbarch *gdbarch)
@@ -287,28 +317,17 @@ public:
 
   void save (regcache_cooked_read_ftype *cooked_read, void *src);
 
-  enum register_status cooked_read (int regnum, gdb_byte *buf);
   void cooked_write (int regnum, const gdb_byte *buf);
 
-  enum register_status raw_read (int regnum, gdb_byte *buf);
-
   void raw_write (int regnum, const gdb_byte *buf);
 
   template<typename T, typename = RequireLongest<T>>
-  enum register_status raw_read (int regnum, T *val);
-
-  template<typename T, typename = RequireLongest<T>>
   void raw_write (int regnum, T val);
 
-  struct value *cooked_read_value (int regnum);
-
-  template<typename T, typename = RequireLongest<T>>
-  enum register_status cooked_read (int regnum, T *val);
-
   template<typename T, typename = RequireLongest<T>>
   void cooked_write (int regnum, T val);
 
-  void raw_update (int regnum);
+  void raw_update (int regnum) override;
 
   void raw_collect (int regnum, void *buf) const;
 
@@ -328,14 +347,8 @@ public:
 
   void invalidate (int regnum);
 
-  enum register_status raw_read_part (int regnum, int offset, int len,
-				      gdb_byte *buf);
-
   void raw_write_part (int regnum, int offset, int len, const gdb_byte *buf);
 
-  enum register_status cooked_read_part (int regnum, int offset, int len,
-					 gdb_byte *buf);
-
   void cooked_write_part (int regnum, int offset, int len,
 			  const gdb_byte *buf);
 
@@ -370,14 +383,15 @@ protected:
 private:
   void restore (struct regcache *src);
 
-  enum register_status xfer_part (int regnum, int offset, int len, void *in,
-				  const void *out, bool is_raw);
-
   void transfer_regset (const struct regset *regset,
 			struct regcache *out_regcache,
 			int regnum, const void *in_buf,
 			void *out_buf, size_t size) const;
 
+  enum register_status write_part (int regnum, int offset, int len,
+				   const void *out, bool is_raw);
+
+
   /* The address space of this register cache (for registers where it
      makes sense, like PC or SP).  */
   const address_space * const m_aspace;
diff --git a/gdb/rl78-tdep.c b/gdb/rl78-tdep.c
index 76630af..4c116be 100644
--- a/gdb/rl78-tdep.c
+++ b/gdb/rl78-tdep.c
@@ -640,7 +640,7 @@ rl78_make_data_address (CORE_ADDR addr)
 
 static enum register_status
 rl78_pseudo_register_read (struct gdbarch *gdbarch,
-                           struct regcache *regcache,
+			   regcache_read *regcache,
                            int reg, gdb_byte *buffer)
 {
   enum register_status status;
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index c902daf..427e6d2 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -2707,12 +2707,6 @@ e500_move_ev_register (move_ev_register_func move,
 }
 
 static enum register_status
-do_regcache_raw_read (struct regcache *regcache, int regnum, void *buffer)
-{
-  return regcache_raw_read (regcache, regnum, (gdb_byte *) buffer);
-}
-
-static enum register_status
 do_regcache_raw_write (struct regcache *regcache, int regnum, void *buffer)
 {
   regcache_raw_write (regcache, regnum, (const gdb_byte *) buffer);
@@ -2721,10 +2715,36 @@ do_regcache_raw_write (struct regcache *regcache, int regnum, void *buffer)
 }
 
 static enum register_status
-e500_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
-			   int reg_nr, gdb_byte *buffer)
+e500_pseudo_register_read (struct gdbarch *gdbarch, regcache_read *regcache,
+			   int ev_reg, gdb_byte *buffer)
 {
-  return e500_move_ev_register (do_regcache_raw_read, regcache, reg_nr, buffer);
+  struct gdbarch *arch = regcache->arch ();
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
+  int reg_index;
+  enum register_status status;
+
+  gdb_assert (IS_SPE_PSEUDOREG (tdep, ev_reg));
+
+  reg_index = ev_reg - tdep->ppc_ev0_regnum;
+
+  if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG)
+    {
+      status = regcache->raw_read (tdep->ppc_ev0_upper_regnum + reg_index,
+				   buffer);
+      if (status == REG_VALID)
+	status = regcache->raw_read (tdep->ppc_gp0_regnum + reg_index,
+				     buffer + 4);
+    }
+  else
+    {
+      status = regcache->raw_read (tdep->ppc_gp0_regnum + reg_index, buffer);
+      if (status == REG_VALID)
+	status = regcache->raw_read (tdep->ppc_ev0_upper_regnum + reg_index,
+				     buffer + 4);
+    }
+
+  return status;
+
 }
 
 static void
@@ -2737,7 +2757,7 @@ e500_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
 
 /* Read method for DFP pseudo-registers.  */
 static enum register_status
-dfp_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+dfp_pseudo_register_read (struct gdbarch *gdbarch, regcache_read *regcache,
 			   int reg_nr, gdb_byte *buffer)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
@@ -2793,7 +2813,7 @@ dfp_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
 
 /* Read method for POWER7 VSX pseudo-registers.  */
 static enum register_status
-vsx_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+vsx_pseudo_register_read (struct gdbarch *gdbarch, regcache_read *regcache,
 			   int reg_nr, gdb_byte *buffer)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
@@ -2858,7 +2878,7 @@ vsx_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
 
 /* Read method for POWER7 Extended FP pseudo-registers.  */
 static enum register_status
-efpr_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+efpr_pseudo_register_read (struct gdbarch *gdbarch, regcache_read *regcache,
 			   int reg_nr, gdb_byte *buffer)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
@@ -2866,9 +2886,9 @@ efpr_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
   int offset = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8;
 
   /* Read the portion that overlaps the VMX register.  */
-  return regcache_raw_read_part (regcache, tdep->ppc_vr0_regnum + reg_index,
-				 offset, register_size (gdbarch, reg_nr),
-				 buffer);
+  return regcache->raw_read_part (tdep->ppc_vr0_regnum + reg_index,
+				  offset, register_size (gdbarch, reg_nr),
+				  buffer);
 }
 
 /* Write method for POWER7 Extended FP pseudo-registers.  */
@@ -2888,7 +2908,7 @@ efpr_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
 
 static enum register_status
 rs6000_pseudo_register_read (struct gdbarch *gdbarch,
-			     struct regcache *regcache,
+			     regcache_read *regcache,
 			     int reg_nr, gdb_byte *buffer)
 {
   struct gdbarch *regcache_arch = regcache->arch ();
diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index a016864..efc74d1 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -387,7 +387,7 @@ s390_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
 }
 
 static enum register_status
-s390_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+s390_pseudo_register_read (struct gdbarch *gdbarch, regcache_read *regcache,
 			   int regnum, gdb_byte *buf)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c
index 6c4e5bb..2da727b 100644
--- a/gdb/sh-tdep.c
+++ b/gdb/sh-tdep.c
@@ -1628,7 +1628,7 @@ dr_reg_base_num (struct gdbarch *gdbarch, int dr_regnum)
 
 static enum register_status
 pseudo_register_read_portions (struct gdbarch *gdbarch,
-			       struct regcache *regcache,
+			       regcache_read *regcache,
 			       int portions,
 			       int base_regnum, gdb_byte *buffer)
 {
@@ -1649,7 +1649,7 @@ pseudo_register_read_portions (struct gdbarch *gdbarch,
 }
 
 static enum register_status
-sh_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+sh_pseudo_register_read (struct gdbarch *gdbarch, regcache_read *regcache,
 			 int reg_nr, gdb_byte *buffer)
 {
   int base_regnum;
diff --git a/gdb/sh64-tdep.c b/gdb/sh64-tdep.c
index ec87902..a900dce 100644
--- a/gdb/sh64-tdep.c
+++ b/gdb/sh64-tdep.c
@@ -1504,7 +1504,7 @@ sh64_register_convert_to_raw (struct gdbarch *gdbarch, struct type *type,
 
 static enum register_status
 pseudo_register_read_portions (struct gdbarch *gdbarch,
-			       struct regcache *regcache,
+			       regcache_read *regcache,
 			       int portions,
 			       int base_regnum, gdb_byte *buffer)
 {
@@ -1525,7 +1525,7 @@ pseudo_register_read_portions (struct gdbarch *gdbarch,
 }
 
 static enum register_status
-sh64_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+sh64_pseudo_register_read (struct gdbarch *gdbarch, regcache_read *regcache,
 			   int reg_nr, gdb_byte *buffer)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c
index 0fb3481..90bee1a 100644
--- a/gdb/sparc-tdep.c
+++ b/gdb/sparc-tdep.c
@@ -503,7 +503,7 @@ sparc32_register_type (struct gdbarch *gdbarch, int regnum)
 
 static enum register_status
 sparc32_pseudo_register_read (struct gdbarch *gdbarch,
-			      struct regcache *regcache,
+			      regcache_read *regcache,
 			      int regnum, gdb_byte *buf)
 {
   enum register_status status;
diff --git a/gdb/sparc64-tdep.c b/gdb/sparc64-tdep.c
index 54af887..60dd644 100644
--- a/gdb/sparc64-tdep.c
+++ b/gdb/sparc64-tdep.c
@@ -899,7 +899,7 @@ sparc64_register_type (struct gdbarch *gdbarch, int regnum)
 
 static enum register_status
 sparc64_pseudo_register_read (struct gdbarch *gdbarch,
-			      struct regcache *regcache,
+			      regcache_read *regcache,
 			      int regnum, gdb_byte *buf)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
diff --git a/gdb/spu-tdep.c b/gdb/spu-tdep.c
index bc7ac77..fb7b089 100644
--- a/gdb/spu-tdep.c
+++ b/gdb/spu-tdep.c
@@ -182,7 +182,7 @@ spu_register_type (struct gdbarch *gdbarch, int reg_nr)
 /* Pseudo registers for preferred slots - stack pointer.  */
 
 static enum register_status
-spu_pseudo_register_read_spu (struct regcache *regcache, const char *regname,
+spu_pseudo_register_read_spu (regcache_read *regcache, const char *regname,
 			      gdb_byte *buf)
 {
   struct gdbarch *gdbarch = regcache->arch ();
@@ -207,7 +207,7 @@ spu_pseudo_register_read_spu (struct regcache *regcache, const char *regname,
 }
 
 static enum register_status
-spu_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+spu_pseudo_register_read (struct gdbarch *gdbarch, regcache_read *regcache,
                           int regnum, gdb_byte *buf)
 {
   gdb_byte reg[16];
diff --git a/gdb/xtensa-tdep.c b/gdb/xtensa-tdep.c
index f582708..892873b 100644
--- a/gdb/xtensa-tdep.c
+++ b/gdb/xtensa-tdep.c
@@ -453,7 +453,7 @@ xtensa_register_write_masked (struct regcache *regcache,
    of the registers and assemble them into a single value.  */
 
 static enum register_status
-xtensa_register_read_masked (struct regcache *regcache,
+xtensa_register_read_masked (regcache_read *regcache,
 			     xtensa_register_t *reg, gdb_byte *buffer)
 {
   unsigned int value[(XTENSA_MAX_REGISTER_SIZE + 3) / 4];
@@ -547,7 +547,7 @@ xtensa_register_read_masked (struct regcache *regcache,
 
 static enum register_status
 xtensa_pseudo_register_read (struct gdbarch *gdbarch,
-			     struct regcache *regcache,
+			     regcache_read *regcache,
 			     int regnum,
 			     gdb_byte *buffer)
 {
-- 
1.9.1

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

* [PATCH 07/15] Class reg_buffer
  2017-12-01 10:48 [RFC 00/15] Remove regcache::m_readonly_p Yao Qi
                   ` (12 preceding siblings ...)
  2017-12-01 10:48 ` [PATCH 12/15] Replace regcache::dump with class register_dump Yao Qi
@ 2017-12-01 10:48 ` Yao Qi
  2017-12-01 10:48 ` [PATCH 10/15] Class regcache_readonly Yao Qi
  2018-01-16 16:18 ` [RFC 00/15] Remove regcache::m_readonly_p Yao Qi
  15 siblings, 0 replies; 32+ messages in thread
From: Yao Qi @ 2017-12-01 10:48 UTC (permalink / raw)
  To: gdb-patches

This patch adds a new class reg_buffer, and regcache inherits it.  Class
reg_buffer is a very simple class, which has the buffer for register
contents and status only.  It doesn't have any methods to set contents and
status, and it is expected that its children classes can inherit it and
add different access methods.

Another reason I keep class reg_buffer so simple is that I think
reg_buffer can be even reused in other classes which need to record the
registers contents and status, like frame cache for example.

gdb:

2017-11-27  Yao Qi  <yao.qi@linaro.org>

	* regcache.c (regcache::regcache): Call reg_buffer ctor.
	(regcache::arch): Move it to reg_buffer::arch.
	(regcache::register_buffer): Likewise.
	(regcache::assert_regnum): Likewise.
	(regcache::num_raw_registers): Likewise.
	* regcache.h (reg_buffer): New class.
	(regcache): Inherit reg_buffer.
---
 gdb/regcache.c | 31 ++++++++++++++++++++---------
 gdb/regcache.h | 62 ++++++++++++++++++++++++++++++++++------------------------
 2 files changed, 58 insertions(+), 35 deletions(-)

diff --git a/gdb/regcache.c b/gdb/regcache.c
index 4577913..8cc9c98 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -181,14 +181,13 @@ regcache_register_size (const struct regcache *regcache, int n)
   return register_size (regcache->arch (), n);
 }
 
-regcache::regcache (gdbarch *gdbarch, const address_space *aspace_,
-		    bool readonly_p_)
-  : m_aspace (aspace_), m_readonly_p (readonly_p_)
+reg_buffer::reg_buffer (gdbarch *gdbarch, bool has_pseudo)
+  : m_has_pseudo (has_pseudo)
 {
   gdb_assert (gdbarch != NULL);
   m_descr = regcache_descr (gdbarch);
 
-  if (m_readonly_p)
+  if (has_pseudo)
     {
       m_registers = XCNEWVEC (gdb_byte, m_descr->sizeof_cooked_registers);
       m_register_status = XCNEWVEC (signed char,
@@ -199,6 +198,16 @@ regcache::regcache (gdbarch *gdbarch, const address_space *aspace_,
       m_registers = XCNEWVEC (gdb_byte, m_descr->sizeof_raw_registers);
       m_register_status = XCNEWVEC (signed char, gdbarch_num_regs (gdbarch));
     }
+}
+
+regcache::regcache (gdbarch *gdbarch, const address_space *aspace_,
+		    bool readonly_p_)
+/* The register buffers.  A read-only register cache can hold the
+   full [0 .. gdbarch_num_regs + gdbarch_num_pseudo_regs) while a
+   read/write register cache can only hold [0 .. gdbarch_num_regs).  */
+  : reg_buffer (gdbarch, readonly_p_),
+    m_aspace (aspace_), m_readonly_p (readonly_p_)
+{
   m_ptid = minus_one_ptid;
 }
 
@@ -218,7 +227,7 @@ regcache::regcache (readonly_t, const regcache &src)
 }
 
 gdbarch *
-regcache::arch () const
+reg_buffer::arch () const
 {
   return m_descr->gdbarch;
 }
@@ -267,7 +276,7 @@ private:
 /* Return  a pointer to register REGNUM's buffer cache.  */
 
 gdb_byte *
-regcache::register_buffer (int regnum) const
+reg_buffer::register_buffer (int regnum) const
 {
   return m_registers + m_descr->register_offset[regnum];
 }
@@ -390,9 +399,13 @@ regcache::invalidate (int regnum)
 }
 
 void
-regcache::assert_regnum (int regnum) const
+reg_buffer::assert_regnum (int regnum) const
 {
-  gdb_assert (regnum >= 0 && regnum < gdbarch_num_regs (arch ()));
+  gdb_assert (regnum >= 0);
+  if (m_has_pseudo)
+    gdb_assert (regnum < m_descr->nr_cooked_registers);
+  else
+    gdb_assert (regnum < gdbarch_num_regs (arch ()));
 }
 
 /* Global structure containing the current regcache.  */
@@ -1272,7 +1285,7 @@ regcache_write_pc (struct regcache *regcache, CORE_ADDR pc)
 }
 
 int
-regcache::num_raw_registers () const
+reg_buffer::num_raw_registers () const
 {
   return gdbarch_num_regs (arch ());
 }
diff --git a/gdb/regcache.h b/gdb/regcache.h
index c5ef41b..a133de1 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -227,9 +227,44 @@ typedef struct cached_reg
   gdb_byte *data;
 } cached_reg_t;
 
+/* Buffer of registers.  */
+
+class reg_buffer
+{
+public:
+  reg_buffer (gdbarch *gdbarch, bool has_pseudo);
+
+  DISABLE_COPY_AND_ASSIGN (reg_buffer);
+
+  /* Return regcache's architecture.  */
+  gdbarch *arch () const;
+
+  virtual ~reg_buffer ()
+  {
+    xfree (m_registers);
+    xfree (m_register_status);
+  }
+
+protected:
+  /* Assert on the range of REGNUM.  */
+  void assert_regnum (int regnum) const;
+
+  int num_raw_registers () const;
+
+  gdb_byte *register_buffer (int regnum) const;
+
+  struct regcache_descr *m_descr;
+
+  bool m_has_pseudo;
+  /* The register buffers.  */
+  gdb_byte *m_registers;
+  /* Register cache status.  */
+  signed char *m_register_status;
+};
+
 /* The register cache for storing raw register values.  */
 
-class regcache
+class regcache : public reg_buffer
 {
 public:
   regcache (gdbarch *gdbarch)
@@ -244,15 +279,6 @@ public:
 
   DISABLE_COPY_AND_ASSIGN (regcache);
 
-  ~regcache ()
-  {
-    xfree (m_registers);
-    xfree (m_register_status);
-  }
-
-  /* Return regcache's architecture.  */
-  gdbarch *arch () const;
-
   /* Return REGCACHE's address space.  */
   const address_space *aspace () const
   {
@@ -339,14 +365,9 @@ public:
   static void regcache_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid);
 protected:
   regcache (gdbarch *gdbarch, const address_space *aspace_, bool readonly_p_);
-
-  int num_raw_registers () const;
-
   static std::forward_list<regcache *> current_regcache;
 
 private:
-  gdb_byte *register_buffer (int regnum) const;
-
   void restore (struct regcache *src);
 
   enum register_status xfer_part (int regnum, int offset, int len, void *in,
@@ -357,21 +378,10 @@ private:
 			int regnum, const void *in_buf,
 			void *out_buf, size_t size) const;
 
-  /* Assert on the range of REGNUM.  */
-  void assert_regnum (int regnum) const;
-
-  struct regcache_descr *m_descr;
-
   /* The address space of this register cache (for registers where it
      makes sense, like PC or SP).  */
   const address_space * const m_aspace;
 
-  /* The register buffers.  A read-only register cache can hold the
-     full [0 .. gdbarch_num_regs + gdbarch_num_pseudo_regs) while a read/write
-     register cache can only hold [0 .. gdbarch_num_regs).  */
-  gdb_byte *m_registers;
-  /* Register cache status.  */
-  signed char *m_register_status;
   /* Is this a read-only cache?  A read-only cache is used for saving
      the target's register state (e.g, across an inferior function
      call or just before forcing a function return).  A read-only
-- 
1.9.1

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

* [PATCH 05/15] regcache_cooked_read -> regcache->cooked_read
  2017-12-01 10:48 [RFC 00/15] Remove regcache::m_readonly_p Yao Qi
                   ` (5 preceding siblings ...)
  2017-12-01 10:48 ` [PATCH 13/15] No longer create readonly regcache Yao Qi
@ 2017-12-01 10:48 ` Yao Qi
  2017-12-01 10:48 ` [PATCH 03/15] Remove mt port Yao Qi
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 32+ messages in thread
From: Yao Qi @ 2017-12-01 10:48 UTC (permalink / raw)
  To: gdb-patches

Similarly, this patch replaces regcache_cooked_read with
regcache->cooked_read.

gdb:

2017-11-29  Yao Qi  <yao.qi@linaro.org>

	* ia64-tdep.c (ia64_pseudo_register_read): Call
	regcache->cooked_read instead of regcache_cooked_read_unsigned.
	* m32c-tdep.c (m32c_cat_read): Likewise.
	(m32c_r3r2r1r0_read): Likewise.
	* m68hc11-tdep.c (m68hc11_pseudo_register_read): Likewise.
	* xtensa-tdep.c (xtensa_register_read_masked): Likewise.
---
 gdb/ia64-tdep.c    | 30 ++++++++++++++++--------------
 gdb/m32c-tdep.c    | 25 ++++++++++++-------------
 gdb/m68hc11-tdep.c |  4 ++--
 gdb/xtensa-tdep.c  |  2 +-
 4 files changed, 31 insertions(+), 30 deletions(-)

diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c
index e1d8075..5bce751 100644
--- a/gdb/ia64-tdep.c
+++ b/gdb/ia64-tdep.c
@@ -951,13 +951,11 @@ ia64_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 	  ULONGEST bsp;
 	  CORE_ADDR reg;
 
-	  status = regcache_cooked_read_unsigned (regcache,
-						  IA64_BSP_REGNUM, &bsp);
+	  status = regcache->cooked_read (IA64_BSP_REGNUM, &bsp);
 	  if (status != REG_VALID)
 	    return status;
 
-	  status = regcache_cooked_read_unsigned (regcache,
-						  IA64_CFM_REGNUM, &cfm);
+	  status = regcache->cooked_read (IA64_CFM_REGNUM, &cfm);
 	  if (status != REG_VALID)
 	    return status;
 
@@ -982,7 +980,8 @@ ia64_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
     {
       ULONGEST unatN_val;
       ULONGEST unat;
-      status = regcache_cooked_read_unsigned (regcache, IA64_UNAT_REGNUM, &unat);
+
+      status = regcache->cooked_read (IA64_UNAT_REGNUM, &unat);
       if (status != REG_VALID)
 	return status;
       unatN_val = (unat & (1LL << (regnum - IA64_NAT0_REGNUM))) != 0;
@@ -995,10 +994,12 @@ ia64_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
       ULONGEST bsp;
       ULONGEST cfm;
       CORE_ADDR gr_addr = 0;
-      status = regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp);
+
+      status = regcache->cooked_read (IA64_BSP_REGNUM, &bsp);
       if (status != REG_VALID)
 	return status;
-      status = regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm);
+
+      status = regcache->cooked_read (IA64_CFM_REGNUM, &cfm);
       if (status != REG_VALID)
 	return status;
 
@@ -1013,14 +1014,13 @@ ia64_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 	{
 	  /* Compute address of nat collection bits.  */
 	  CORE_ADDR nat_addr = gr_addr | 0x1f8;
-	  CORE_ADDR nat_collection;
+	  ULONGEST nat_collection;
 	  int nat_bit;
 	  /* If our nat collection address is bigger than bsp, we have to get
 	     the nat collection from rnat.  Otherwise, we fetch the nat
 	     collection from the computed address.  */
 	  if (nat_addr >= bsp)
-	    regcache_cooked_read_unsigned (regcache, IA64_RNAT_REGNUM,
-					   &nat_collection);
+	    regcache->cooked_read (IA64_RNAT_REGNUM, &nat_collection);
 	  else
 	    nat_collection = read_memory_integer (nat_addr, 8, byte_order);
 	  nat_bit = (gr_addr >> 3) & 0x3f;
@@ -1036,10 +1036,11 @@ ia64_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
          It can be calculated as the bsp - sof (sizeof frame).  */
       ULONGEST bsp, vbsp;
       ULONGEST cfm;
-      status = regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp);
+
+      status = regcache->cooked_read (IA64_BSP_REGNUM, &bsp);
       if (status != REG_VALID)
 	return status;
-      status = regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm);
+      status = regcache->cooked_read (IA64_CFM_REGNUM, &cfm);
       if (status != REG_VALID)
 	return status;
 
@@ -1054,10 +1055,11 @@ ia64_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
       ULONGEST pr;
       ULONGEST cfm;
       ULONGEST prN_val;
-      status = regcache_cooked_read_unsigned (regcache, IA64_PR_REGNUM, &pr);
+
+      status = regcache->cooked_read (IA64_PR_REGNUM, &pr);
       if (status != REG_VALID)
 	return status;
-      status = regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm);
+      status = regcache->cooked_read (IA64_CFM_REGNUM, &cfm);
       if (status != REG_VALID)
 	return status;
 
diff --git a/gdb/m32c-tdep.c b/gdb/m32c-tdep.c
index 67b8a11..e04fdfd 100644
--- a/gdb/m32c-tdep.c
+++ b/gdb/m32c-tdep.c
@@ -483,17 +483,16 @@ m32c_cat_read (struct m32c_reg *reg, struct regcache *cache, gdb_byte *buf)
 
   if (gdbarch_byte_order (reg->arch) == BFD_ENDIAN_BIG)
     {
-      status = regcache_cooked_read (cache, reg->rx->num, buf);
+      status = cache->cooked_read (reg->rx->num, buf);
       if (status == REG_VALID)
-	status = regcache_cooked_read (cache, reg->ry->num, buf + high_bytes);
+	status = cache->cooked_read (reg->ry->num, buf + high_bytes);
     }
   else
     {
-      status = regcache_cooked_read (cache, reg->rx->num, buf + low_bytes);
+      status = cache->cooked_read (reg->rx->num, buf + low_bytes);
       if (status == REG_VALID)
-	status = regcache_cooked_read (cache, reg->ry->num, buf);
+	status = cache->cooked_read (reg->ry->num, buf);
     }
-
   return status;
 }
 
@@ -537,23 +536,23 @@ m32c_r3r2r1r0_read (struct m32c_reg *reg, struct regcache *cache, gdb_byte *buf)
 
   if (gdbarch_byte_order (reg->arch) == BFD_ENDIAN_BIG)
     {
-      status = regcache_cooked_read (cache, tdep->r0->num, buf + len * 3);
+      status = cache->cooked_read (tdep->r0->num, buf + len * 3);
       if (status == REG_VALID)
-	status = regcache_cooked_read (cache, tdep->r1->num, buf + len * 2);
+	status = cache->cooked_read (tdep->r1->num, buf + len * 2);
       if (status == REG_VALID)
-	status = regcache_cooked_read (cache, tdep->r2->num, buf + len * 1);
+	status = cache->cooked_read (tdep->r2->num, buf + len * 1);
       if (status == REG_VALID)
-	status = regcache_cooked_read (cache, tdep->r3->num, buf);
+	status = cache->cooked_read (tdep->r3->num, buf);
     }
   else
     {
-      status = regcache_cooked_read (cache, tdep->r0->num, buf);
+      status = cache->cooked_read (tdep->r0->num, buf);
       if (status == REG_VALID)
-	status = regcache_cooked_read (cache, tdep->r1->num, buf + len * 1);
+	status = cache->cooked_read (tdep->r1->num, buf + len * 1);
       if (status == REG_VALID)
-	status = regcache_cooked_read (cache, tdep->r2->num, buf + len * 2);
+	status = cache->cooked_read (tdep->r2->num, buf + len * 2);
       if (status == REG_VALID)
-	status = regcache_cooked_read (cache, tdep->r3->num, buf + len * 3);
+	status = cache->cooked_read (tdep->r3->num, buf + len * 3);
     }
 
   return status;
diff --git a/gdb/m68hc11-tdep.c b/gdb/m68hc11-tdep.c
index 9c2ecb0..3ef1fbf 100644
--- a/gdb/m68hc11-tdep.c
+++ b/gdb/m68hc11-tdep.c
@@ -292,14 +292,14 @@ m68hc11_pseudo_register_read (struct gdbarch *gdbarch,
       const int regsize = 4;
       enum register_status status;
 
-      status = regcache_cooked_read_unsigned (regcache, HARD_PC_REGNUM, &pc);
+      status = regcache->cooked_read (HARD_PC_REGNUM, &pc);
       if (status != REG_VALID)
 	return status;
       if (pc >= 0x8000 && pc < 0xc000)
         {
           ULONGEST page;
 
-          regcache_cooked_read_unsigned (regcache, HARD_PAGE_REGNUM, &page);
+	  regcache->cooked_read (HARD_PAGE_REGNUM, &page);
           pc -= 0x8000;
           pc += (page << 14);
           pc += 0x1000000;
diff --git a/gdb/xtensa-tdep.c b/gdb/xtensa-tdep.c
index 9779c3a..f582708 100644
--- a/gdb/xtensa-tdep.c
+++ b/gdb/xtensa-tdep.c
@@ -481,7 +481,7 @@ xtensa_register_read_masked (struct regcache *regcache,
 	  enum register_status status;
 	  ULONGEST val;
 
-	  status = regcache_cooked_read_unsigned (regcache, r, &val);
+	  status = regcache->cooked_read (r, &val);
 	  if (status != REG_VALID)
 	    return status;
 	  regval = (unsigned int) val;
-- 
1.9.1

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

* [PATCH 02/15] Don't call gdbarch_pseudo_register_read_value in jit.c
  2017-12-01 10:48 [RFC 00/15] Remove regcache::m_readonly_p Yao Qi
                   ` (7 preceding siblings ...)
  2017-12-01 10:48 ` [PATCH 03/15] Remove mt port Yao Qi
@ 2017-12-01 10:48 ` Yao Qi
  2017-12-01 10:48 ` [PATCH 14/15] Remove regcache::m_readonly_p Yao Qi
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 32+ messages in thread
From: Yao Qi @ 2017-12-01 10:48 UTC (permalink / raw)
  To: gdb-patches

gdbarch_pseudo_register_read_value is not implemented in every gdbarch, so
the predicate gdbarch_pseudo_register_read_value_p is needed before
calling it.  However, there is no such guard in jit_frame_prev_register, I
am wondering how does jit work on the arch without having gdbarch method
pseudo_register_read_value.

The proper way to get register value is to call cooked_read, and then
create the value object from the buffer.

gdb:

2017-11-01  Yao Qi  <yao.qi@linaro.org>

	* jit.c (jit_frame_prev_register): Call regcache::cooked_read
	instead of gdbarch_pseudo_register_read_value.
---
 gdb/jit.c | 16 +++++-----------
 1 file changed, 5 insertions(+), 11 deletions(-)

diff --git a/gdb/jit.c b/gdb/jit.c
index 98afdf2..36aaefc 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -1271,19 +1271,13 @@ jit_frame_prev_register (struct frame_info *this_frame, void **cache, int reg)
     return frame_unwind_got_optimized (this_frame, reg);
 
   gdbarch = priv->regcache->arch ();
-  if (reg < gdbarch_num_regs (gdbarch))
-    {
-      gdb_byte *buf = (gdb_byte *) alloca (register_size (gdbarch, reg));
-      enum register_status status;
+  gdb_byte *buf = (gdb_byte *) alloca (register_size (gdbarch, reg));
+  enum register_status status = priv->regcache->cooked_read (reg, buf);
 
-      status = regcache_raw_read (priv->regcache, reg, buf);
-      if (status == REG_VALID)
-	return frame_unwind_got_bytes (this_frame, reg, buf);
-      else
-	return frame_unwind_got_optimized (this_frame, reg);
-    }
+  if (status == REG_VALID)
+    return frame_unwind_got_bytes (this_frame, reg, buf);
   else
-    return gdbarch_pseudo_register_read_value (gdbarch, priv->regcache, reg);
+    return frame_unwind_got_optimized (this_frame, reg);
 }
 
 /* Relay everything back to the unwinder registered by the JIT debug
-- 
1.9.1

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

* [PATCH 10/15] Class regcache_readonly
  2017-12-01 10:48 [RFC 00/15] Remove regcache::m_readonly_p Yao Qi
                   ` (13 preceding siblings ...)
  2017-12-01 10:48 ` [PATCH 07/15] Class reg_buffer Yao Qi
@ 2017-12-01 10:48 ` Yao Qi
  2018-01-24  3:05   ` Simon Marchi
  2018-01-16 16:18 ` [RFC 00/15] Remove regcache::m_readonly_p Yao Qi
  15 siblings, 1 reply; 32+ messages in thread
From: Yao Qi @ 2017-12-01 10:48 UTC (permalink / raw)
  To: gdb-patches

This patch adds a new class (type) for readonly regcache, which is
created via regcache::save.  regcache_readonly inherts from
regcache_read.

gdb:

2017-11-28  Yao Qi  <yao.qi@linaro.org>

	* dummy-frame.c (dummy_frame_cache) <prev_regcache>: Use
	regcache_readonly.
	(dummy_frame_prev_register): Use regcache->cooked_read.
	* frame.c (frame_save_as_regcache): Change return type.
	(frame_pop): Update.
	* frame.h (frame_save_as_regcache): Update declaration.
	* inferior.h (get_infcall_suspend_state_regcache): Update
	declaration.
	* infrun.c (infcall_suspend_state) <registers>: use
	regcache_readonly.
	(save_infcall_suspend_state): Don't use regcache_dup.
	(get_infcall_suspend_state_regcache): Change return type.
	* linux-fork.c (struct fork_info) <savedregs>: Change to
	regcache_readonly.
	<pc>: New field.
	(fork_save_infrun_state): Don't use regcache_dup.
	(info_checkpoints_command): Adjust.
	* mi/mi-main.c (register_changed_p): Update declaration.
	(mi_cmd_data_list_changed_registers): Use regcache_readonly.
	(register_changed_p): Change parameter type to regcache_readonly.
	* ppc-linux-tdep.c (ppu2spu_cache) <regcache>: Use
	regcache_readonly.
	(ppu2spu_sniffer): Construct a new regcache_readonly.
	* regcache.c (regcache_readonly::regcache_readonly): New.
	(regcache::save): Move it to reg_buffer.
	(regcache::restore): Change parameter type.
	(regcache_dup): Remove.
	* regcache.h (reg_buffer) <save>: New method.
	(regcache_readonly): New class.
	* spu-tdep.c (spu2ppu_cache) <regcache>: Use regcache_readonly.
	(spu2ppu_sniffer): Construct a new regcache_readonly.
---
 gdb/dummy-frame.c    |  6 +++---
 gdb/frame.c          | 10 +++++-----
 gdb/frame.h          |  3 ++-
 gdb/inferior.h       |  2 +-
 gdb/infrun.c         |  6 +++---
 gdb/linux-fork.c     | 18 ++++++++----------
 gdb/mi/mi-main.c     | 12 ++++++------
 gdb/ppc-linux-tdep.c |  9 ++++-----
 gdb/regcache.c       | 27 +++++++++++----------------
 gdb/regcache.h       | 43 +++++++++++++++++++++++++++++++++----------
 gdb/spu-tdep.c       |  6 +++---
 11 files changed, 79 insertions(+), 63 deletions(-)

diff --git a/gdb/dummy-frame.c b/gdb/dummy-frame.c
index a08031c..5133e4a 100644
--- a/gdb/dummy-frame.c
+++ b/gdb/dummy-frame.c
@@ -282,7 +282,7 @@ cleanup_dummy_frames (struct target_ops *target, int from_tty)
 struct dummy_frame_cache
 {
   struct frame_id this_id;
-  struct regcache *prev_regcache;
+  regcache_readonly *prev_regcache;
 };
 
 static int
@@ -352,8 +352,8 @@ dummy_frame_prev_register (struct frame_info *this_frame,
   /* Use the regcache_cooked_read() method so that it, on the fly,
      constructs either a raw or pseudo register from the raw
      register cache.  */
-  regcache_cooked_read (cache->prev_regcache, regnum,
-			value_contents_writeable (reg_val));
+  cache->prev_regcache->cooked_read (regnum,
+				     value_contents_writeable (reg_val));
   return reg_val;
 }
 
diff --git a/gdb/frame.c b/gdb/frame.c
index 4659cf5..25b8c20 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -1017,13 +1017,13 @@ do_frame_register_read (void *src, int regnum, gdb_byte *buf)
     return REG_VALID;
 }
 
-std::unique_ptr<struct regcache>
+std::unique_ptr<regcache_readonly>
 frame_save_as_regcache (struct frame_info *this_frame)
 {
-  std::unique_ptr<struct regcache> regcache
-    (new struct regcache (get_frame_arch (this_frame)));
+  std::unique_ptr<regcache_readonly> regcache
+    (new regcache_readonly (get_frame_arch (this_frame),
+			    do_frame_register_read, this_frame));
 
-  regcache->save (do_frame_register_read, this_frame);
   return regcache;
 }
 
@@ -1057,7 +1057,7 @@ frame_pop (struct frame_info *this_frame)
      Save them in a scratch buffer so that there isn't a race between
      trying to extract the old values from the current regcache while
      at the same time writing new values into that same cache.  */
-  std::unique_ptr<struct regcache> scratch
+  std::unique_ptr<regcache_readonly> scratch
     = frame_save_as_regcache (prev_frame);
 
   /* FIXME: cagney/2003-03-16: It should be possible to tell the
diff --git a/gdb/frame.h b/gdb/frame.h
index 0ed7a14..044a073 100644
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -680,8 +680,9 @@ extern void *frame_obstack_zalloc (unsigned long size);
 #define FRAME_OBSTACK_CALLOC(NUMBER,TYPE) \
   ((TYPE *) frame_obstack_zalloc ((NUMBER) * sizeof (TYPE)))
 
+class regcache_readonly;
 /* Create a regcache, and copy the frame's registers into it.  */
-std::unique_ptr<struct regcache> frame_save_as_regcache
+std::unique_ptr<regcache_readonly> frame_save_as_regcache
     (struct frame_info *this_frame);
 
 extern const struct block *get_frame_block (struct frame_info *,
diff --git a/gdb/inferior.h b/gdb/inferior.h
index 37252a6..5460021 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -70,7 +70,7 @@ extern struct cleanup *make_cleanup_restore_infcall_control_state
 extern void discard_infcall_suspend_state (struct infcall_suspend_state *);
 extern void discard_infcall_control_state (struct infcall_control_state *);
 
-extern struct regcache *
+extern regcache_readonly *
   get_infcall_suspend_state_regcache (struct infcall_suspend_state *);
 
 extern void set_sigint_trap (void);
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 5c128b5..b96b99d 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -8780,7 +8780,7 @@ struct infcall_suspend_state
 
   /* Other fields:  */
   CORE_ADDR stop_pc;
-  struct regcache *registers;
+  regcache_readonly *registers;
 
   /* Format of SIGINFO_DATA or NULL if it is not present.  */
   struct gdbarch *siginfo_gdbarch;
@@ -8836,7 +8836,7 @@ save_infcall_suspend_state (void)
 
   inf_state->stop_pc = stop_pc;
 
-  inf_state->registers = regcache_dup (regcache);
+  inf_state->registers = new regcache_readonly (*regcache);
 
   return inf_state;
 }
@@ -8893,7 +8893,7 @@ discard_infcall_suspend_state (struct infcall_suspend_state *inf_state)
   xfree (inf_state);
 }
 
-struct regcache *
+regcache_readonly *
 get_infcall_suspend_state_regcache (struct infcall_suspend_state *inf_state)
 {
   return inf_state->registers;
diff --git a/gdb/linux-fork.c b/gdb/linux-fork.c
index 5d05cb3..02b0e68 100644
--- a/gdb/linux-fork.c
+++ b/gdb/linux-fork.c
@@ -45,8 +45,9 @@ struct fork_info
   ptid_t ptid;
   ptid_t parent_ptid;
   int num;			/* Convenient handle (GDB fork id).  */
-  struct regcache *savedregs;	/* Convenient for info fork, saves
+  regcache_readonly *savedregs;	/* Convenient for info fork, saves
 				   having to actually switch contexts.  */
+  CORE_ADDR pc;
   int clobber_regs;		/* True if we should restore saved regs.  */
   off_t *filepos;		/* Set of open file descriptors' offsets.  */
   int maxfd;
@@ -294,7 +295,8 @@ fork_save_infrun_state (struct fork_info *fp, int clobber_regs)
   if (fp->savedregs)
     delete fp->savedregs;
 
-  fp->savedregs = regcache_dup (get_current_regcache ());
+  fp->savedregs = new regcache_readonly (*get_current_regcache ());
+  fp->pc = regcache_read_pc (get_current_regcache ());
   fp->clobber_regs = clobber_regs;
 
   if (clobber_regs)
@@ -590,15 +592,11 @@ info_checkpoints_command (const char *arg, int from_tty)
 
       printed = fp;
       if (ptid_equal (fp->ptid, inferior_ptid))
-	{
-	  printf_filtered ("* ");
-	  pc = regcache_read_pc (get_current_regcache ());
-	}
+	printf_filtered ("* ");
       else
-	{
-	  printf_filtered ("  ");
-	  pc = regcache_read_pc (fp->savedregs);
-	}
+	printf_filtered ("  ");
+
+      pc = fp->pc;
       printf_filtered ("%d %s", fp->num, target_pid_to_str (fp->ptid));
       if (fp->num == 0)
 	printf_filtered (_(" (main process)"));
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 3261488..74d3e1c 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -96,8 +96,8 @@ static void mi_execute_cli_command (const char *cmd, int args_p,
 				    const char *args);
 static void mi_execute_async_cli_command (const char *cli_command,
 					  char **argv, int argc);
-static bool register_changed_p (int regnum, regcache *,
-				regcache *);
+static bool register_changed_p (int regnum, regcache_readonly *,
+			       regcache_readonly *);
 static void output_register (struct frame_info *, int regnum, int format,
 			     int skip_unavailable);
 
@@ -931,9 +931,9 @@ mi_cmd_data_list_register_names (const char *command, char **argv, int argc)
 void
 mi_cmd_data_list_changed_registers (const char *command, char **argv, int argc)
 {
-  static std::unique_ptr<struct regcache> this_regs;
+  static std::unique_ptr<regcache_readonly> this_regs;
   struct ui_out *uiout = current_uiout;
-  std::unique_ptr<struct regcache> prev_regs;
+  std::unique_ptr<regcache_readonly> prev_regs;
   struct gdbarch *gdbarch;
   int regnum, numregs;
   int i;
@@ -995,8 +995,8 @@ mi_cmd_data_list_changed_registers (const char *command, char **argv, int argc)
 }
 
 static bool
-register_changed_p (int regnum, struct regcache *prev_regs,
-		    struct regcache *this_regs)
+register_changed_p (int regnum, regcache_readonly *prev_regs,
+		    regcache_readonly *this_regs)
 {
   struct gdbarch *gdbarch = this_regs->arch ();
   struct value *prev_value, *this_value;
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 398ac24..8d62b81 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -1241,7 +1241,7 @@ ppc_linux_spe_context (int wordsize, enum bfd_endian byte_order,
 struct ppu2spu_cache
 {
   struct frame_id frame_id;
-  struct regcache *regcache;
+  regcache_readonly *regcache;
 };
 
 static struct gdbarch *
@@ -1348,10 +1348,9 @@ ppu2spu_sniffer (const struct frame_unwind *self,
 	{
 	  struct ppu2spu_cache *cache
 	    = FRAME_OBSTACK_CALLOC (1, struct ppu2spu_cache);
-	  std::unique_ptr<struct regcache> regcache
-	    (new struct regcache (data.gdbarch));
-
-	  regcache->save (ppu2spu_unwind_register, &data);
+	  std::unique_ptr<regcache_readonly> regcache
+	    (new regcache_readonly (data.gdbarch, ppu2spu_unwind_register,
+				    &data));
 
 	  cache->frame_id = frame_id_build (base, func);
 	  cache->regcache = regcache.release ();
diff --git a/gdb/regcache.c b/gdb/regcache.c
index f4ef933..4174a8c 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -226,6 +226,11 @@ regcache::regcache (readonly_t, const regcache &src)
   save (do_cooked_read, (void *) &src);
 }
 
+regcache_readonly::regcache_readonly (const regcache &src)
+  : regcache_readonly (src.arch (), do_cooked_read, (void *) &src)
+{
+}
+
 gdbarch *
 reg_buffer::arch () const
 {
@@ -282,16 +287,14 @@ reg_buffer::register_buffer (int regnum) const
 }
 
 void
-regcache::save (regcache_cooked_read_ftype *cooked_read,
-		void *src)
+reg_buffer::save (regcache_cooked_read_ftype *cooked_read,
+		  void *src)
 {
   struct gdbarch *gdbarch = m_descr->gdbarch;
   int regnum;
 
-  /* The DST should be `read-only', if it wasn't then the save would
-     end up trying to write the register values back out to the
-     target.  */
-  gdb_assert (m_readonly_p);
+  /* It should have pseudo registers.  */
+  gdb_assert (m_has_pseudo);
   /* Clear the dest.  */
   memset (m_registers, 0, m_descr->sizeof_cooked_registers);
   memset (m_register_status, 0, m_descr->nr_cooked_registers);
@@ -317,16 +320,14 @@ regcache::save (regcache_cooked_read_ftype *cooked_read,
 }
 
 void
-regcache::restore (struct regcache *src)
+regcache::restore (regcache_readonly *src)
 {
   struct gdbarch *gdbarch = m_descr->gdbarch;
   int regnum;
 
   gdb_assert (src != NULL);
-  /* The dst had better not be read-only.  If it is, the `restore'
-     doesn't make much sense.  */
   gdb_assert (!m_readonly_p);
-  gdb_assert (src->m_readonly_p);
+  gdb_assert (src->m_has_pseudo);
 
   gdb_assert (gdbarch == src->arch ());
 
@@ -344,12 +345,6 @@ regcache::restore (struct regcache *src)
     }
 }
 
-struct regcache *
-regcache_dup (struct regcache *src)
-{
-  return new regcache (regcache::readonly, *src);
-}
-
 enum register_status
 regcache_register_status (const struct regcache *regcache, int regnum)
 {
diff --git a/gdb/regcache.h b/gdb/regcache.h
index d8054b2..bd91bc6 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -243,6 +243,11 @@ protected:
 
   gdb_byte *register_buffer (int regnum) const;
 
+  /* Save a register cache.  The set of registers saved into the
+     regcache determined by the save_reggroup.  COOKED_READ returns
+     zero iff the register's value can't be returned.  */
+  void save (regcache_cooked_read_ftype *cooked_read, void *src);
+
   struct regcache_descr *m_descr;
 
   bool m_has_pseudo;
@@ -250,6 +255,8 @@ protected:
   gdb_byte *m_registers;
   /* Register cache status.  */
   signed char *m_register_status;
+
+  friend class regcache;
 };
 
 class regcache_read : public reg_buffer
@@ -282,6 +289,8 @@ protected:
 				  bool is_raw);
 };
 
+class regcache_readonly;
+
 /* The register cache for storing raw register values.  */
 
 class regcache : public regcache_read
@@ -305,14 +314,11 @@ public:
     return m_aspace;
   }
 
-/* Save/restore a register cache.  The set of registers saved /
-   restored into the regcache determined by the save_reggroup /
-   restore_reggroup respectively.  COOKED_READ returns zero iff the
-   register's value can't be returned.  */
-  void save (regcache_cooked_read_ftype *cooked_read, void *src);
-  /* Writes to regcache will go through to the target.  SRC is a
+  /* Restore a register cache.  The set of registers restored into
+     the regcache determined by the restore_reggroup.
+     Writes to regcache will go through to the target.  SRC is a
      read-only register cache.  */
-  void restore (struct regcache *src);
+  void restore (regcache_readonly *src);
 
   void cooked_write (int regnum, const gdb_byte *buf);
 
@@ -410,9 +416,26 @@ private:
   registers_changed_ptid (ptid_t ptid);
 };
 
-/* Duplicate the contents of a register cache to a read-only register
-   cache.  The operation is pass-through.  */
-extern struct regcache *regcache_dup (struct regcache *regcache);
+class regcache_readonly : public regcache_read
+{
+public:
+  regcache_readonly (const regcache &src);
+
+  /* Create a readonly regcache by getting contents from COOKED_READ.  */
+
+  regcache_readonly (gdbarch *gdbarch,
+		     regcache_cooked_read_ftype *cooked_read,
+		     void *src)
+    : regcache_read (gdbarch, true)
+  {
+    save (cooked_read, src);
+  }
+
+  DISABLE_COPY_AND_ASSIGN (regcache_readonly);
+
+  void raw_update (int regnum) override
+  {}
+};
 
 extern void registers_changed (void);
 extern void registers_changed_ptid (ptid_t);
diff --git a/gdb/spu-tdep.c b/gdb/spu-tdep.c
index fb7b089..73c905f 100644
--- a/gdb/spu-tdep.c
+++ b/gdb/spu-tdep.c
@@ -1202,7 +1202,7 @@ spu_write_pc (struct regcache *regcache, CORE_ADDR pc)
 struct spu2ppu_cache
 {
   struct frame_id frame_id;
-  struct regcache *regcache;
+  regcache_readonly *regcache;
 };
 
 static struct gdbarch *
@@ -1229,7 +1229,7 @@ spu2ppu_prev_register (struct frame_info *this_frame,
   gdb_byte *buf;
 
   buf = (gdb_byte *) alloca (register_size (gdbarch, regnum));
-  regcache_cooked_read (cache->regcache, regnum, buf);
+  cache->regcache->cooked_read (regnum, buf);
   return frame_unwind_got_bytes (this_frame, regnum, buf);
 }
 
@@ -1274,7 +1274,7 @@ spu2ppu_sniffer (const struct frame_unwind *self,
 	{
 	  struct regcache *regcache;
 	  regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ());
-	  cache->regcache = regcache_dup (regcache);
+	  cache->regcache = new regcache_readonly (*regcache);
 	  *this_prologue_cache = cache;
 	  return 1;
 	}
-- 
1.9.1

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

* [PATCH 09/15] Remove regcache_save and regcache_cpy
  2017-12-01 10:48 [RFC 00/15] Remove regcache::m_readonly_p Yao Qi
@ 2017-12-01 10:48 ` Yao Qi
  2017-12-01 10:48 ` [PATCH 01/15] Call cooked_read in ppu2spu_prev_register Yao Qi
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 32+ messages in thread
From: Yao Qi @ 2017-12-01 10:48 UTC (permalink / raw)
  To: gdb-patches

... instead we start to use regcache methods save and restore.  It is
quite straightforward to replace regcache_save with regcache->save.

regcache_cpy has some asserts, some of them not necessary, like

 gdb_assert (src != dst);

because we already assert !m_readonly_p and src->m_readonly_p, so
src isn't dst.  Some of the asserts are moved to ::restore.

gdb:

2017-10-30  Yao Qi  <yao.qi@linaro.org>

	* frame.c (frame_save_as_regcache): Use regcache method save.
	(frame_pop): Use regcache method restore.
	* infrun.c (restore_infcall_suspend_state): Likewise.
	* linux-fork.c (fork_load_infrun_state): Likewise.
	* ppc-linux-tdep.c (ppu2spu_sniffer): User regcache method
	save.
	* regcache.c (regcache_save): Remove.
	(regcache::restore): More asserts.
	(regcache_cpy): Remove.
	* regcache.h (regcache_save): Remove the declaration.
	(regcache::restore): Move from private to public.
	Remove the friend declaration of regcache_cpy.
	(regcache_cpy): Remove declaration.
---
 gdb/frame.c          |  7 +++----
 gdb/infrun.c         |  2 +-
 gdb/linux-fork.c     |  2 +-
 gdb/ppc-linux-tdep.c |  2 +-
 gdb/regcache.c       | 22 ++++------------------
 gdb/regcache.h       | 30 +++++++++---------------------
 6 files changed, 19 insertions(+), 46 deletions(-)

diff --git a/gdb/frame.c b/gdb/frame.c
index e643823..4659cf5 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -1023,7 +1023,7 @@ frame_save_as_regcache (struct frame_info *this_frame)
   std::unique_ptr<struct regcache> regcache
     (new struct regcache (get_frame_arch (this_frame)));
 
-  regcache_save (regcache.get (), do_frame_register_read, this_frame);
+  regcache->save (do_frame_register_read, this_frame);
   return regcache;
 }
 
@@ -1068,9 +1068,8 @@ frame_pop (struct frame_info *this_frame)
      Unfortunately, they don't implement it.  Their lack of a formal
      definition can lead to targets writing back bogus values
      (arguably a bug in the target code mind).  */
-  /* Now copy those saved registers into the current regcache.
-     Here, regcache_cpy() calls regcache_restore().  */
-  regcache_cpy (get_current_regcache (), scratch.get ());
+  /* Now copy those saved registers into the current regcache.  */
+  get_current_regcache ()->restore (scratch.get ());
 
   /* We've made right mess of GDB's local state, just discard
      everything.  */
diff --git a/gdb/infrun.c b/gdb/infrun.c
index d7df3c7..5c128b5 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -8867,7 +8867,7 @@ restore_infcall_suspend_state (struct infcall_suspend_state *inf_state)
      (and perhaps other times).  */
   if (target_has_execution)
     /* NB: The register write goes through to the target.  */
-    regcache_cpy (regcache, inf_state->registers);
+    regcache->restore (inf_state->registers);
 
   discard_infcall_suspend_state (inf_state);
 }
diff --git a/gdb/linux-fork.c b/gdb/linux-fork.c
index f55f743..5d05cb3 100644
--- a/gdb/linux-fork.c
+++ b/gdb/linux-fork.c
@@ -261,7 +261,7 @@ fork_load_infrun_state (struct fork_info *fp)
   linux_nat_switch_fork (fp->ptid);
 
   if (fp->savedregs && fp->clobber_regs)
-    regcache_cpy (get_current_regcache (), fp->savedregs);
+    get_current_regcache ()->restore (fp->savedregs);
 
   registers_changed ();
   reinit_frame_cache ();
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 70e5b95..398ac24 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -1351,7 +1351,7 @@ ppu2spu_sniffer (const struct frame_unwind *self,
 	  std::unique_ptr<struct regcache> regcache
 	    (new struct regcache (data.gdbarch));
 
-	  regcache_save (regcache.get (), ppu2spu_unwind_register, &data);
+	  regcache->save (ppu2spu_unwind_register, &data);
 
 	  cache->frame_id = frame_id_build (base, func);
 	  cache->regcache = regcache.release ();
diff --git a/gdb/regcache.c b/gdb/regcache.c
index 5ce6064..f4ef933 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -282,13 +282,6 @@ reg_buffer::register_buffer (int regnum) const
 }
 
 void
-regcache_save (struct regcache *regcache,
-	       regcache_cooked_read_ftype *cooked_read, void *src)
-{
-  regcache->save (cooked_read, src);
-}
-
-void
 regcache::save (regcache_cooked_read_ftype *cooked_read,
 		void *src)
 {
@@ -329,10 +322,14 @@ regcache::restore (struct regcache *src)
   struct gdbarch *gdbarch = m_descr->gdbarch;
   int regnum;
 
+  gdb_assert (src != NULL);
   /* The dst had better not be read-only.  If it is, the `restore'
      doesn't make much sense.  */
   gdb_assert (!m_readonly_p);
   gdb_assert (src->m_readonly_p);
+
+  gdb_assert (gdbarch == src->arch ());
+
   /* Copy over any registers, being careful to only restore those that
      were both saved and need to be restored.  The full [0 .. gdbarch_num_regs
      + gdbarch_num_pseudo_regs) range is checked since some architectures need
@@ -347,17 +344,6 @@ regcache::restore (struct regcache *src)
     }
 }
 
-void
-regcache_cpy (struct regcache *dst, struct regcache *src)
-{
-  gdb_assert (src != NULL && dst != NULL);
-  gdb_assert (src->m_descr->gdbarch == dst->m_descr->gdbarch);
-  gdb_assert (src != dst);
-  gdb_assert (src->m_readonly_p && !dst->m_readonly_p);
-
-  dst->restore (src);
-}
-
 struct regcache *
 regcache_dup (struct regcache *src)
 {
diff --git a/gdb/regcache.h b/gdb/regcache.h
index b107bbd..d8054b2 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -198,20 +198,10 @@ extern struct type *register_type (struct gdbarch *gdbarch, int regnum);
    
 extern int register_size (struct gdbarch *gdbarch, int regnum);
 
-
-/* Save/restore a register cache.  The set of registers saved /
-   restored into the DST regcache determined by the save_reggroup /
-   restore_reggroup respectively.  COOKED_READ returns zero iff the
-   register's value can't be returned.  */
-
 typedef enum register_status (regcache_cooked_read_ftype) (void *src,
 							   int regnum,
 							   gdb_byte *buf);
 
-extern void regcache_save (struct regcache *dst,
-			   regcache_cooked_read_ftype *cooked_read,
-			   void *cooked_read_context);
-
 enum regcache_dump_what
 {
   regcache_dump_none, regcache_dump_raw,
@@ -315,7 +305,14 @@ public:
     return m_aspace;
   }
 
+/* Save/restore a register cache.  The set of registers saved /
+   restored into the regcache determined by the save_reggroup /
+   restore_reggroup respectively.  COOKED_READ returns zero iff the
+   register's value can't be returned.  */
   void save (regcache_cooked_read_ftype *cooked_read, void *src);
+  /* Writes to regcache will go through to the target.  SRC is a
+     read-only register cache.  */
+  void restore (struct regcache *src);
 
   void cooked_write (int regnum, const gdb_byte *buf);
 
@@ -381,7 +378,6 @@ protected:
   static std::forward_list<regcache *> current_regcache;
 
 private:
-  void restore (struct regcache *src);
 
   void transfer_regset (const struct regset *regset,
 			struct regcache *out_regcache,
@@ -399,9 +395,8 @@ private:
   /* Is this a read-only cache?  A read-only cache is used for saving
      the target's register state (e.g, across an inferior function
      call or just before forcing a function return).  A read-only
-     cache can only be updated via the methods regcache_dup() and
-     regcache_cpy().  The actual contents are determined by the
-     reggroup_save and reggroup_restore methods.  */
+     cache can only be created via a constructor.  The actual contents
+     are determined by the save and restore methods.  */
   const bool m_readonly_p;
   /* If this is a read-write cache, which thread's registers is
      it connected to?  */
@@ -413,19 +408,12 @@ private:
 
   friend void
   registers_changed_ptid (ptid_t ptid);
-
-  friend void
-  regcache_cpy (struct regcache *dst, struct regcache *src);
 };
 
 /* Duplicate the contents of a register cache to a read-only register
    cache.  The operation is pass-through.  */
 extern struct regcache *regcache_dup (struct regcache *regcache);
 
-/* Writes to DEST will go through to the target.  SRC is a read-only
-   register cache.  */
-extern void regcache_cpy (struct regcache *dest, struct regcache *src);
-
 extern void registers_changed (void);
 extern void registers_changed_ptid (ptid_t);
 
-- 
1.9.1

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

* [PATCH 03/15] Remove mt port
  2017-12-01 10:48 [RFC 00/15] Remove regcache::m_readonly_p Yao Qi
                   ` (6 preceding siblings ...)
  2017-12-01 10:48 ` [PATCH 05/15] regcache_cooked_read -> regcache->cooked_read Yao Qi
@ 2017-12-01 10:48 ` Yao Qi
  2017-12-01 10:48 ` [PATCH 02/15] Don't call gdbarch_pseudo_register_read_value in jit.c Yao Qi
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 32+ messages in thread
From: Yao Qi @ 2017-12-01 10:48 UTC (permalink / raw)
  To: gdb-patches

This patch removes the MT port.  The removal was annoucned
https://sourceware.org/ml/gdb-announce/2017/msg00006.html
I'll remove MT from the top-level configure later.

gdb:

2017-11-27  Yao Qi  <yao.qi@linaro.org>

	* Makefile.in (ALL_TARGET_OBS): Remove mt-tdep.o.
	* configure.tgt: Remove target mt.
	* mt-tdep.c: Remove.
	* regcache.c (cooked_read_test): Remove the check for mt.
---
 gdb/Makefile.in   |    1 -
 gdb/configure.tgt |    6 +-
 gdb/mt-tdep.c     | 1218 -----------------------------------------------------
 gdb/regcache.c    |   17 +-
 4 files changed, 3 insertions(+), 1239 deletions(-)
 delete mode 100644 gdb/mt-tdep.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index ec9900c..3d90fde 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -868,7 +868,6 @@ ALL_TARGET_OBS = \
 	mn10300-tdep.o \
 	moxie-tdep.o \
 	msp430-tdep.o \
-	mt-tdep.o \
 	nbsd-tdep.o \
 	nds32-tdep.o \
 	nios2-linux-tdep.o \
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index daec0a7..4e19e51 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -29,6 +29,7 @@ case $targ in
  hppa*-*-hpux* | \
  ia64-*-hpux* | \
  *-*-vxworks* | \
+ mt-*-* | \
  null)
     echo "*** Configuration $targ is obsolete." >&2
     echo "*** Support has been REMOVED." >&2
@@ -442,11 +443,6 @@ msp430*-*-elf)
 	gdb_sim=../sim/msp430/libsim.a
 	;;
 
-mt-*-*)
-	# Target: Morpho Technologies ms1 processor
-	gdb_target_obs="mt-tdep.o"
-	;;
-
 nds32*-*-elf)
 	# Target: AndesTech NDS32 core
 	gdb_target_obs="nds32-tdep.o"
diff --git a/gdb/mt-tdep.c b/gdb/mt-tdep.c
deleted file mode 100644
index 7992394..0000000
--- a/gdb/mt-tdep.c
+++ /dev/null
@@ -1,1218 +0,0 @@
-/* Target-dependent code for Morpho mt processor, for GDB.
-
-   Copyright (C) 2005-2017 Free Software Foundation, Inc.
-
-   This file is part of GDB.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-/* Contributed by Michael Snyder, msnyder@redhat.com.  */
-
-#include "defs.h"
-#include "frame.h"
-#include "frame-unwind.h"
-#include "frame-base.h"
-#include "symtab.h"
-#include "dis-asm.h"
-#include "arch-utils.h"
-#include "gdbtypes.h"
-#include "regcache.h"
-#include "reggroups.h"
-#include "gdbcore.h"
-#include "trad-frame.h"
-#include "inferior.h"
-#include "dwarf2-frame.h"
-#include "infcall.h"
-#include "language.h"
-#include "valprint.h"
-#include "common/byte-vector.h"
-
-enum mt_arch_constants
-{
-  MT_MAX_STRUCT_SIZE = 16
-};
-
-enum mt_gdb_regnums
-{
-  MT_R0_REGNUM,			/* 32 bit regs.  */
-  MT_R1_REGNUM,
-  MT_1ST_ARGREG = MT_R1_REGNUM,
-  MT_R2_REGNUM,
-  MT_R3_REGNUM,
-  MT_R4_REGNUM,
-  MT_LAST_ARGREG = MT_R4_REGNUM,
-  MT_R5_REGNUM,
-  MT_R6_REGNUM,
-  MT_R7_REGNUM,
-  MT_R8_REGNUM,
-  MT_R9_REGNUM,
-  MT_R10_REGNUM,
-  MT_R11_REGNUM,
-  MT_R12_REGNUM,
-  MT_FP_REGNUM = MT_R12_REGNUM,
-  MT_R13_REGNUM,
-  MT_SP_REGNUM = MT_R13_REGNUM,
-  MT_R14_REGNUM,
-  MT_RA_REGNUM = MT_R14_REGNUM,
-  MT_R15_REGNUM,
-  MT_IRA_REGNUM = MT_R15_REGNUM,
-  MT_PC_REGNUM,
-
-  /* Interrupt Enable pseudo-register, exported by SID.  */
-  MT_INT_ENABLE_REGNUM,
-  /* End of CPU regs.  */
-
-  MT_NUM_CPU_REGS,
-
-  /* Co-processor registers.  */
-  MT_COPRO_REGNUM = MT_NUM_CPU_REGS,	/* 16 bit regs.  */
-  MT_CPR0_REGNUM,
-  MT_CPR1_REGNUM,
-  MT_CPR2_REGNUM,
-  MT_CPR3_REGNUM,
-  MT_CPR4_REGNUM,
-  MT_CPR5_REGNUM,
-  MT_CPR6_REGNUM,
-  MT_CPR7_REGNUM,
-  MT_CPR8_REGNUM,
-  MT_CPR9_REGNUM,
-  MT_CPR10_REGNUM,
-  MT_CPR11_REGNUM,
-  MT_CPR12_REGNUM,
-  MT_CPR13_REGNUM,
-  MT_CPR14_REGNUM,
-  MT_CPR15_REGNUM,
-  MT_BYPA_REGNUM,		/* 32 bit regs.  */
-  MT_BYPB_REGNUM,
-  MT_BYPC_REGNUM,
-  MT_FLAG_REGNUM,
-  MT_CONTEXT_REGNUM,		/* 38 bits (treat as array of
-				   six bytes).  */
-  MT_MAC_REGNUM,			/* 32 bits.  */
-  MT_Z1_REGNUM,			/* 16 bits.  */
-  MT_Z2_REGNUM,			/* 16 bits.  */
-  MT_ICHANNEL_REGNUM,		/* 32 bits.  */
-  MT_ISCRAMB_REGNUM,		/* 32 bits.  */
-  MT_QSCRAMB_REGNUM,		/* 32 bits.  */
-  MT_OUT_REGNUM,			/* 16 bits.  */
-  MT_EXMAC_REGNUM,		/* 32 bits (8 used).  */
-  MT_QCHANNEL_REGNUM,		/* 32 bits.  */
-  MT_ZI2_REGNUM,                /* 16 bits.  */
-  MT_ZQ2_REGNUM,                /* 16 bits.  */
-  MT_CHANNEL2_REGNUM,           /* 32 bits.  */
-  MT_ISCRAMB2_REGNUM,           /* 32 bits.  */
-  MT_QSCRAMB2_REGNUM,           /* 32 bits.  */
-  MT_QCHANNEL2_REGNUM,          /* 32 bits.  */
-
-  /* Number of real registers.  */
-  MT_NUM_REGS,
-
-  /* Pseudo-registers.  */
-  MT_COPRO_PSEUDOREG_REGNUM = MT_NUM_REGS,
-  MT_MAC_PSEUDOREG_REGNUM,
-  MT_COPRO_PSEUDOREG_ARRAY,
-
-  MT_COPRO_PSEUDOREG_DIM_1 = 2,
-  MT_COPRO_PSEUDOREG_DIM_2 = 8,
-  /* The number of pseudo-registers for each coprocessor.  These
-     include the real coprocessor registers, the pseudo-registe for
-     the coprocessor number, and the pseudo-register for the MAC.  */
-  MT_COPRO_PSEUDOREG_REGS = MT_NUM_REGS - MT_NUM_CPU_REGS + 2,
-  /* The register number of the MAC, relative to a given coprocessor.  */
-  MT_COPRO_PSEUDOREG_MAC_REGNUM = MT_COPRO_PSEUDOREG_REGS - 1,
-
-  /* Two pseudo-regs ('coprocessor' and 'mac').  */
-  MT_NUM_PSEUDO_REGS = 2 + (MT_COPRO_PSEUDOREG_REGS
-			    * MT_COPRO_PSEUDOREG_DIM_1
-			    * MT_COPRO_PSEUDOREG_DIM_2)
-};
-
-/* The tdep structure.  */
-struct gdbarch_tdep
-{
-  /* ISA-specific types.  */
-  struct type *copro_type;
-};
-
-
-/* Return name of register number specified by REGNUM.  */
-
-static const char *
-mt_register_name (struct gdbarch *gdbarch, int regnum)
-{
-  static const char *const register_names[] = {
-    /* CPU regs.  */
-    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
-    "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
-    "pc", "IE",
-    /* Co-processor regs.  */
-    "",				/* copro register.  */
-    "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
-    "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15",
-    "bypa", "bypb", "bypc", "flag", "context", "" /* mac.  */ , "z1", "z2",
-    "Ichannel", "Iscramb", "Qscramb", "out", "" /* ex-mac.  */ , "Qchannel",
-    "zi2", "zq2", "Ichannel2", "Iscramb2", "Qscramb2", "Qchannel2",
-    /* Pseudo-registers.  */
-    "coprocessor", "MAC"
-  };
-  static const char *array_names[MT_COPRO_PSEUDOREG_REGS
-				 * MT_COPRO_PSEUDOREG_DIM_1
-				 * MT_COPRO_PSEUDOREG_DIM_2];
-
-  if (regnum < 0)
-    return "";
-  if (regnum < ARRAY_SIZE (register_names))
-    return register_names[regnum];
-  if (array_names[regnum - MT_COPRO_PSEUDOREG_ARRAY])
-    return array_names[regnum - MT_COPRO_PSEUDOREG_ARRAY];
-  
-  {
-    char *name;
-    const char *stub;
-    unsigned dim_1;
-    unsigned dim_2;
-    unsigned index;
-    
-    regnum -= MT_COPRO_PSEUDOREG_ARRAY;
-    index = regnum % MT_COPRO_PSEUDOREG_REGS;
-    dim_2 = (regnum / MT_COPRO_PSEUDOREG_REGS) % MT_COPRO_PSEUDOREG_DIM_2;
-    dim_1 = ((regnum / MT_COPRO_PSEUDOREG_REGS / MT_COPRO_PSEUDOREG_DIM_2)
-	     %  MT_COPRO_PSEUDOREG_DIM_1);
-    
-    if (index == MT_COPRO_PSEUDOREG_MAC_REGNUM)
-      stub = register_names[MT_MAC_PSEUDOREG_REGNUM];
-    else if (index >= MT_NUM_REGS - MT_CPR0_REGNUM)
-      stub = "";
-    else
-      stub = register_names[index + MT_CPR0_REGNUM];
-    if (!*stub)
-      {
-	array_names[regnum] = stub;
-	return stub;
-      }
-    name = (char *) xmalloc (30);
-    sprintf (name, "copro_%d_%d_%s", dim_1, dim_2, stub);
-    array_names[regnum] = name;
-    return name;
-  }
-}
-
-/* Return the type of a coprocessor register.  */
-
-static struct type *
-mt_copro_register_type (struct gdbarch *arch, int regnum)
-{
-  switch (regnum)
-    {
-    case MT_INT_ENABLE_REGNUM:
-    case MT_ICHANNEL_REGNUM:
-    case MT_QCHANNEL_REGNUM:
-    case MT_ISCRAMB_REGNUM:
-    case MT_QSCRAMB_REGNUM:
-      return builtin_type (arch)->builtin_int32;
-    case MT_BYPA_REGNUM:
-    case MT_BYPB_REGNUM:
-    case MT_BYPC_REGNUM:
-    case MT_Z1_REGNUM:
-    case MT_Z2_REGNUM:
-    case MT_OUT_REGNUM:
-    case MT_ZI2_REGNUM:
-    case MT_ZQ2_REGNUM:
-      return builtin_type (arch)->builtin_int16;
-    case MT_EXMAC_REGNUM:
-    case MT_MAC_REGNUM:
-      return builtin_type (arch)->builtin_uint32;
-    case MT_CONTEXT_REGNUM:
-      return builtin_type (arch)->builtin_long_long;
-    case MT_FLAG_REGNUM:
-      return builtin_type (arch)->builtin_unsigned_char;
-    default:
-      if (regnum >= MT_CPR0_REGNUM && regnum <= MT_CPR15_REGNUM)
-	return builtin_type (arch)->builtin_int16;
-      else if (regnum == MT_CPR0_REGNUM + MT_COPRO_PSEUDOREG_MAC_REGNUM)
-	{
-	  if (gdbarch_bfd_arch_info (arch)->mach == bfd_mach_mrisc2
-	      || gdbarch_bfd_arch_info (arch)->mach == bfd_mach_ms2)
-	    return builtin_type (arch)->builtin_uint64;
-	  else
-	    return builtin_type (arch)->builtin_uint32;
-	}
-      else
-	return builtin_type (arch)->builtin_uint32;
-    }
-}
-
-/* Given ARCH and a register number specified by REGNUM, return the
-   type of that register.  */
-
-static struct type *
-mt_register_type (struct gdbarch *arch, int regnum)
-{
-  struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
-
-  if (regnum >= 0 && regnum < MT_NUM_REGS + MT_NUM_PSEUDO_REGS)
-    {
-      switch (regnum)
-	{
-	case MT_PC_REGNUM:
-	case MT_RA_REGNUM:
-	case MT_IRA_REGNUM:
-	  return builtin_type (arch)->builtin_func_ptr;
-	case MT_SP_REGNUM:
-	case MT_FP_REGNUM:
-	  return builtin_type (arch)->builtin_data_ptr;
-	case MT_COPRO_REGNUM:
-	case MT_COPRO_PSEUDOREG_REGNUM:
-	  if (tdep->copro_type == NULL)
-	    {
-	      struct type *elt = builtin_type (arch)->builtin_int16;
-	      tdep->copro_type = lookup_array_range_type (elt, 0, 1);
-	    }
-	  return tdep->copro_type;
-	case MT_MAC_PSEUDOREG_REGNUM:
-	  return mt_copro_register_type (arch,
-					 MT_CPR0_REGNUM
-					 + MT_COPRO_PSEUDOREG_MAC_REGNUM);
-	default:
-	  if (regnum >= MT_R0_REGNUM && regnum <= MT_R15_REGNUM)
-	    return builtin_type (arch)->builtin_int32;
-	  else if (regnum < MT_COPRO_PSEUDOREG_ARRAY)
-	    return mt_copro_register_type (arch, regnum);
-	  else
-	    {
-	      regnum -= MT_COPRO_PSEUDOREG_ARRAY;
-	      regnum %= MT_COPRO_PSEUDOREG_REGS;
-	      regnum += MT_CPR0_REGNUM;
-	      return mt_copro_register_type (arch, regnum);
-	    }
-	}
-    }
-  internal_error (__FILE__, __LINE__,
-		  _("mt_register_type: illegal register number %d"), regnum);
-}
-
-/* Return true if register REGNUM is a member of the register group
-   specified by GROUP.  */
-
-static int
-mt_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
-			 struct reggroup *group)
-{
-  /* Groups of registers that can be displayed via "info reg".  */
-  if (group == all_reggroup)
-    return (regnum >= 0
-	    && regnum < MT_NUM_REGS + MT_NUM_PSEUDO_REGS
-	    && mt_register_name (gdbarch, regnum)[0] != '\0');
-
-  if (group == general_reggroup)
-    return (regnum >= MT_R0_REGNUM && regnum <= MT_R15_REGNUM);
-
-  if (group == float_reggroup)
-    return 0;			/* No float regs.  */
-
-  if (group == vector_reggroup)
-    return 0;			/* No vector regs.  */
-
-  /* For any that are not handled above.  */
-  return default_register_reggroup_p (gdbarch, regnum, group);
-}
-
-/* Return the return value convention used for a given type TYPE.
-   Optionally, fetch or set the return value via READBUF or
-   WRITEBUF respectively using REGCACHE for the register
-   values.  */
-
-static enum return_value_convention
-mt_return_value (struct gdbarch *gdbarch, struct value *function,
-		 struct type *type, struct regcache *regcache,
-		 gdb_byte *readbuf, const gdb_byte *writebuf)
-{
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-
-  if (TYPE_LENGTH (type) > 4)
-    {
-      /* Return values > 4 bytes are returned in memory, 
-         pointed to by R11.  */
-      if (readbuf)
-	{
-	  ULONGEST addr;
-
-	  regcache_cooked_read_unsigned (regcache, MT_R11_REGNUM, &addr);
-	  read_memory (addr, readbuf, TYPE_LENGTH (type));
-	}
-
-      if (writebuf)
-	{
-	  ULONGEST addr;
-
-	  regcache_cooked_read_unsigned (regcache, MT_R11_REGNUM, &addr);
-	  write_memory (addr, writebuf, TYPE_LENGTH (type));
-	}
-
-      return RETURN_VALUE_ABI_RETURNS_ADDRESS;
-    }
-  else
-    {
-      if (readbuf)
-	{
-	  ULONGEST temp;
-
-	  /* Return values of <= 4 bytes are returned in R11.  */
-	  regcache_cooked_read_unsigned (regcache, MT_R11_REGNUM, &temp);
-	  store_unsigned_integer (readbuf, TYPE_LENGTH (type),
-				  byte_order, temp);
-	}
-
-      if (writebuf)
-	{
-	  if (TYPE_LENGTH (type) < 4)
-	    {
-	      gdb_byte buf[4];
-	      /* Add leading zeros to the value.  */
-	      memset (buf, 0, sizeof (buf));
-	      memcpy (buf + sizeof (buf) - TYPE_LENGTH (type),
-		      writebuf, TYPE_LENGTH (type));
-	      regcache_cooked_write (regcache, MT_R11_REGNUM, buf);
-	    }
-	  else			/* (TYPE_LENGTH (type) == 4 */
-	    regcache_cooked_write (regcache, MT_R11_REGNUM, writebuf);
-	}
-
-      return RETURN_VALUE_REGISTER_CONVENTION;
-    }
-}
-
-/* If the input address, PC, is in a function prologue, return the
-   address of the end of the prologue, otherwise return the input
-   address.
-
-   Note:  PC is likely to be the function start, since this function
-   is mainly used for advancing a breakpoint to the first line, or
-   stepping to the first line when we have stepped into a function
-   call.  */
-
-static CORE_ADDR
-mt_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
-{
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  CORE_ADDR func_addr = 0, func_end = 0;
-  const char *func_name;
-  unsigned long instr;
-
-  if (find_pc_partial_function (pc, &func_name, &func_addr, &func_end))
-    {
-      struct symtab_and_line sal;
-      struct symbol *sym;
-
-      /* Found a function.  */
-      sym = lookup_symbol (func_name, NULL, VAR_DOMAIN, NULL).symbol;
-      if (sym && SYMBOL_LANGUAGE (sym) != language_asm)
-	{
-	  /* Don't use this trick for assembly source files.  */
-	  sal = find_pc_line (func_addr, 0);
-
-	  if (sal.end && sal.end < func_end)
-	    {
-	      /* Found a line number, use it as end of prologue.  */
-	      return sal.end;
-	    }
-	}
-    }
-
-  /* No function symbol, or no line symbol.  Use prologue scanning method.  */
-  for (;; pc += 4)
-    {
-      instr = read_memory_unsigned_integer (pc, 4, byte_order);
-      if (instr == 0x12000000)	/* nop */
-	continue;
-      if (instr == 0x12ddc000)	/* copy sp into fp */
-	continue;
-      instr >>= 16;
-      if (instr == 0x05dd)	/* subi sp, sp, imm */
-	continue;
-      if (instr >= 0x43c0 && instr <= 0x43df)	/* push */
-	continue;
-      /* Not an obvious prologue instruction.  */
-      break;
-    }
-
-  return pc;
-}
-
-/* Implement the breakpoint_kind_from_pc gdbarch method.  */
-
-static int
-mt_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
-{
-  return 4;
-}
-
-/* Implement the sw_breakpoint_from_kind gdbarch method.  */
-
-static const gdb_byte *
-mt_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
-{
-  /* The breakpoint instruction must be the same size as the smallest
-     instruction in the instruction set.
-
-     The BP for ms1 is defined as 0x68000000 (BREAK).
-     The BP for ms2 is defined as 0x69000000 (illegal).  */
-  static gdb_byte ms1_breakpoint[] = { 0x68, 0, 0, 0 };
-  static gdb_byte ms2_breakpoint[] = { 0x69, 0, 0, 0 };
-
-  *size = kind;
-
-  if (gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_ms2)
-    return ms2_breakpoint;
-
-  return ms1_breakpoint;
-}
-
-/* Select the correct coprocessor register bank.  Return the pseudo
-   regnum we really want to read.  */
-
-static int
-mt_select_coprocessor (struct gdbarch *gdbarch,
-			struct regcache *regcache, int regno)
-{
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  unsigned index, base;
-  gdb_byte copro[4];
-
-  /* Get the copro pseudo regnum.  */
-  regcache_raw_read (regcache, MT_COPRO_REGNUM, copro);
-  base = ((extract_signed_integer (&copro[0], 2, byte_order)
-	   * MT_COPRO_PSEUDOREG_DIM_2)
-	  + extract_signed_integer (&copro[2], 2, byte_order));
-
-  regno -= MT_COPRO_PSEUDOREG_ARRAY;
-  index = regno % MT_COPRO_PSEUDOREG_REGS;
-  regno /= MT_COPRO_PSEUDOREG_REGS;
-  if (base != regno)
-    {
-      /* Select the correct coprocessor register bank.  Invalidate the
-	 coprocessor register cache.  */
-      unsigned ix;
-
-      store_signed_integer (&copro[0], 2, byte_order,
-			    regno / MT_COPRO_PSEUDOREG_DIM_2);
-      store_signed_integer (&copro[2], 2, byte_order,
-			    regno % MT_COPRO_PSEUDOREG_DIM_2);
-      regcache_raw_write (regcache, MT_COPRO_REGNUM, copro);
-      
-      /* We must flush the cache, as it is now invalid.  */
-      for (ix = MT_NUM_CPU_REGS; ix != MT_NUM_REGS; ix++)
-	regcache_invalidate (regcache, ix);
-    }
-  
-  return index;
-}
-
-/* Fetch the pseudo registers:
-
-   There are two regular pseudo-registers:
-   1) The 'coprocessor' pseudo-register (which mirrors the 
-   "real" coprocessor register sent by the target), and
-   2) The 'MAC' pseudo-register (which represents the union
-   of the original 32 bit target MAC register and the new
-   8-bit extended-MAC register).
-
-   Additionally there is an array of coprocessor registers which track
-   the coprocessor registers for each coprocessor.  */
-
-static enum register_status
-mt_pseudo_register_read (struct gdbarch *gdbarch,
-			 struct regcache *regcache, int regno, gdb_byte *buf)
-{
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-
-  switch (regno)
-    {
-    case MT_COPRO_REGNUM:
-    case MT_COPRO_PSEUDOREG_REGNUM:
-      return regcache_raw_read (regcache, MT_COPRO_REGNUM, buf);
-    case MT_MAC_REGNUM:
-    case MT_MAC_PSEUDOREG_REGNUM:
-      if (gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_mrisc2
-	  || gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_ms2)
-	{
-	  enum register_status status;
-	  ULONGEST oldmac = 0, ext_mac = 0;
-	  ULONGEST newmac;
-
-	  status = regcache_cooked_read_unsigned (regcache, MT_MAC_REGNUM, &oldmac);
-	  if (status != REG_VALID)
-	    return status;
-
-	  regcache_cooked_read_unsigned (regcache, MT_EXMAC_REGNUM, &ext_mac);
-	  if (status != REG_VALID)
-	    return status;
-
-	  newmac =
-	    (oldmac & 0xffffffff) | ((long long) (ext_mac & 0xff) << 32);
-	  store_signed_integer (buf, 8, byte_order, newmac);
-
-	  return REG_VALID;
-	}
-      else
-	return regcache_raw_read (regcache, MT_MAC_REGNUM, buf);
-      break;
-    default:
-      {
-	unsigned index = mt_select_coprocessor (gdbarch, regcache, regno);
-	
-	if (index == MT_COPRO_PSEUDOREG_MAC_REGNUM)
-	  return mt_pseudo_register_read (gdbarch, regcache,
-					  MT_MAC_PSEUDOREG_REGNUM, buf);
-	else if (index < MT_NUM_REGS - MT_CPR0_REGNUM)
-	  return regcache_raw_read (regcache, index + MT_CPR0_REGNUM, buf);
-	else
-	  /* ??? */
-	  return REG_VALID;
-      }
-      break;
-    }
-}
-
-/* Write the pseudo registers:
-
-   Mt pseudo-registers are stored directly to the target.  The
-   'coprocessor' register is special, because when it is modified, all
-   the other coprocessor regs must be flushed from the reg cache.  */
-
-static void
-mt_pseudo_register_write (struct gdbarch *gdbarch,
-			   struct regcache *regcache,
-			   int regno, const gdb_byte *buf)
-{
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  int i;
-
-  switch (regno)
-    {
-    case MT_COPRO_REGNUM:
-    case MT_COPRO_PSEUDOREG_REGNUM:
-      regcache_raw_write (regcache, MT_COPRO_REGNUM, buf);
-      for (i = MT_NUM_CPU_REGS; i < MT_NUM_REGS; i++)
-	regcache_invalidate (regcache, i);
-      break;
-    case MT_MAC_REGNUM:
-    case MT_MAC_PSEUDOREG_REGNUM:
-      if (gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_mrisc2
-	  || gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_ms2)
-	{
-	  /* The 8-byte MAC pseudo-register must be broken down into two
-	     32-byte registers.  */
-	  unsigned int oldmac, ext_mac;
-	  ULONGEST newmac;
-
-	  newmac = extract_unsigned_integer (buf, 8, byte_order);
-	  oldmac = newmac & 0xffffffff;
-	  ext_mac = (newmac >> 32) & 0xff;
-	  regcache_cooked_write_unsigned (regcache, MT_MAC_REGNUM, oldmac);
-	  regcache_cooked_write_unsigned (regcache, MT_EXMAC_REGNUM, ext_mac);
-	}
-      else
-	regcache_raw_write (regcache, MT_MAC_REGNUM, buf);
-      break;
-    default:
-      {
-	unsigned index = mt_select_coprocessor (gdbarch, regcache, regno);
-	
-	if (index == MT_COPRO_PSEUDOREG_MAC_REGNUM)
-	  mt_pseudo_register_write (gdbarch, regcache,
-				    MT_MAC_PSEUDOREG_REGNUM, buf);
-	else if (index < MT_NUM_REGS - MT_CPR0_REGNUM)
-	  regcache_raw_write (regcache, index + MT_CPR0_REGNUM, buf);
-      }
-      break;
-    }
-}
-
-static CORE_ADDR
-mt_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
-{
-  /* Register size is 4 bytes.  */
-  return align_down (sp, 4);
-}
-
-/* Implements the "info registers" command.   When ``all'' is non-zero,
-   the coprocessor registers will be printed in addition to the rest
-   of the registers.  */
-
-static void
-mt_registers_info (struct gdbarch *gdbarch,
-		   struct ui_file *file,
-		   struct frame_info *frame, int regnum, int all)
-{
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-
-  if (regnum == -1)
-    {
-      int lim;
-
-      lim = all ? MT_NUM_REGS : MT_NUM_CPU_REGS;
-
-      for (regnum = 0; regnum < lim; regnum++)
-	{
-	  /* Don't display the Qchannel register since it will be displayed
-	     along with Ichannel.  (See below.)  */
-	  if (regnum == MT_QCHANNEL_REGNUM)
-	    continue;
-
-	  mt_registers_info (gdbarch, file, frame, regnum, all);
-
-	  /* Display the Qchannel register immediately after Ichannel.  */
-	  if (regnum == MT_ICHANNEL_REGNUM)
-	    mt_registers_info (gdbarch, file, frame, MT_QCHANNEL_REGNUM, all);
-	}
-    }
-  else
-    {
-      if (regnum == MT_EXMAC_REGNUM)
-	return;
-      else if (regnum == MT_CONTEXT_REGNUM)
-	{
-	  /* Special output handling for 38-bit context register.  */
-	  unsigned char *buff;
-	  unsigned int i, regsize;
-
-	  regsize = register_size (gdbarch, regnum);
-
-	  buff = (unsigned char *) alloca (regsize);
-
-	  deprecated_frame_register_read (frame, regnum, buff);
-
-	  fputs_filtered (gdbarch_register_name
-			  (gdbarch, regnum), file);
-	  print_spaces_filtered (15 - strlen (gdbarch_register_name
-					        (gdbarch, regnum)),
-				 file);
-	  fputs_filtered ("0x", file);
-
-	  for (i = 0; i < regsize; i++)
-	    fprintf_filtered (file, "%02x", (unsigned int)
-			      extract_unsigned_integer (buff + i, 1, byte_order));
-	  fputs_filtered ("\t", file);
-	  print_longest (file, 'd', 0,
-			 extract_unsigned_integer (buff, regsize, byte_order));
-	  fputs_filtered ("\n", file);
-	}
-      else if (regnum == MT_COPRO_REGNUM
-               || regnum == MT_COPRO_PSEUDOREG_REGNUM)
-	{
-	  /* Special output handling for the 'coprocessor' register.  */
-	  struct value_print_options opts;
-	  struct value *val;
-
-	  val = get_frame_register_value (frame, MT_COPRO_REGNUM);
-	  /* And print.  */
-	  regnum = MT_COPRO_PSEUDOREG_REGNUM;
-	  fputs_filtered (gdbarch_register_name (gdbarch, regnum),
-			  file);
-	  print_spaces_filtered (15 - strlen (gdbarch_register_name
-					        (gdbarch, regnum)),
-				 file);
-	  get_no_prettyformat_print_options (&opts);
-	  opts.deref_ref = 1;
-	  val_print (register_type (gdbarch, regnum),
-		     0, 0, file, 0, val,
-		     &opts, current_language);
-	  fputs_filtered ("\n", file);
-	}
-      else if (regnum == MT_MAC_REGNUM || regnum == MT_MAC_PSEUDOREG_REGNUM)
-	{
-	  ULONGEST oldmac, ext_mac, newmac;
-	  gdb_byte buf[3 * sizeof (LONGEST)];
-
-	  /* Get the two "real" mac registers.  */
-	  deprecated_frame_register_read (frame, MT_MAC_REGNUM, buf);
-	  oldmac = extract_unsigned_integer
-	    (buf, register_size (gdbarch, MT_MAC_REGNUM), byte_order);
-	  if (gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_mrisc2
-	      || gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_ms2)
-	    {
-	      deprecated_frame_register_read (frame, MT_EXMAC_REGNUM, buf);
-	      ext_mac = extract_unsigned_integer
-		(buf, register_size (gdbarch, MT_EXMAC_REGNUM), byte_order);
-	    }
-	  else
-	    ext_mac = 0;
-
-	  /* Add them together.  */
-	  newmac = (oldmac & 0xffffffff) + ((ext_mac & 0xff) << 32);
-
-	  /* And print.  */
-	  regnum = MT_MAC_PSEUDOREG_REGNUM;
-	  fputs_filtered (gdbarch_register_name (gdbarch, regnum),
-			  file);
-	  print_spaces_filtered (15 - strlen (gdbarch_register_name
-					      (gdbarch, regnum)),
-				 file);
-	  fputs_filtered ("0x", file);
-	  print_longest (file, 'x', 0, newmac);
-	  fputs_filtered ("\t", file);
-	  print_longest (file, 'u', 0, newmac);
-	  fputs_filtered ("\n", file);
-	}
-      else
-	default_print_registers_info (gdbarch, file, frame, regnum, all);
-    }
-}
-
-/* Set up the callee's arguments for an inferior function call.  The
-   arguments are pushed on the stack or are placed in registers as
-   appropriate.  It also sets up the return address (which points to
-   the call dummy breakpoint).
-
-   Returns the updated (and aligned) stack pointer.  */
-
-static CORE_ADDR
-mt_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
-		     struct regcache *regcache, CORE_ADDR bp_addr,
-		     int nargs, struct value **args, CORE_ADDR sp,
-		     int struct_return, CORE_ADDR struct_addr)
-{
-#define wordsize 4
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  gdb_byte buf[MT_MAX_STRUCT_SIZE];
-  int argreg = MT_1ST_ARGREG;
-  int split_param_len = 0;
-  int stack_dest = sp;
-  int slacklen;
-  int typelen;
-  int i, j;
-
-  /* First handle however many args we can fit into MT_1ST_ARGREG thru
-     MT_LAST_ARGREG.  */
-  for (i = 0; i < nargs && argreg <= MT_LAST_ARGREG; i++)
-    {
-      const gdb_byte *val;
-      typelen = TYPE_LENGTH (value_type (args[i]));
-      switch (typelen)
-	{
-	case 1:
-	case 2:
-	case 3:
-	case 4:
-	  regcache_cooked_write_unsigned (regcache, argreg++,
-					  extract_unsigned_integer
-					  (value_contents (args[i]),
-					   wordsize, byte_order));
-	  break;
-	case 8:
-	case 12:
-	case 16:
-	  val = value_contents (args[i]);
-	  while (typelen > 0)
-	    {
-	      if (argreg <= MT_LAST_ARGREG)
-		{
-		  /* This word of the argument is passed in a register.  */
-		  regcache_cooked_write_unsigned (regcache, argreg++,
-						  extract_unsigned_integer
-						  (val, wordsize, byte_order));
-		  typelen -= wordsize;
-		  val += wordsize;
-		}
-	      else
-		{
-		  /* Remainder of this arg must be passed on the stack
-		     (deferred to do later).  */
-		  split_param_len = typelen;
-		  memcpy (buf, val, typelen);
-		  break;	/* No more args can be handled in regs.  */
-		}
-	    }
-	  break;
-	default:
-	  /* By reverse engineering of gcc output, args bigger than
-	     16 bytes go on the stack, and their address is passed
-	     in the argreg.  */
-	  stack_dest -= typelen;
-	  write_memory (stack_dest, value_contents (args[i]), typelen);
-	  regcache_cooked_write_unsigned (regcache, argreg++, stack_dest);
-	  break;
-	}
-    }
-
-  /* Next, the rest of the arguments go onto the stack, in reverse order.  */
-  for (j = nargs - 1; j >= i; j--)
-    {
-      const gdb_byte *contents = value_contents (args[j]);
-      
-      /* Right-justify the value in an aligned-length buffer.  */
-      typelen = TYPE_LENGTH (value_type (args[j]));
-      slacklen = (wordsize - (typelen % wordsize)) % wordsize;
-      gdb::byte_vector val (typelen + slacklen);
-      memcpy (val.data (), contents, typelen);
-      memset (val.data () + typelen, 0, slacklen);
-      /* Now write this data to the stack.  */
-      stack_dest -= typelen + slacklen;
-      write_memory (stack_dest, val.data (), typelen + slacklen);
-    }
-
-  /* Finally, if a param needs to be split between registers and stack, 
-     write the second half to the stack now.  */
-  if (split_param_len != 0)
-    {
-      stack_dest -= split_param_len;
-      write_memory (stack_dest, buf, split_param_len);
-    }
-
-  /* Set up return address (provided to us as bp_addr).  */
-  regcache_cooked_write_unsigned (regcache, MT_RA_REGNUM, bp_addr);
-
-  /* Store struct return address, if given.  */
-  if (struct_return && struct_addr != 0)
-    regcache_cooked_write_unsigned (regcache, MT_R11_REGNUM, struct_addr);
-
-  /* Set aside 16 bytes for the callee to save regs 1-4.  */
-  stack_dest -= 16;
-
-  /* Update the stack pointer.  */
-  regcache_cooked_write_unsigned (regcache, MT_SP_REGNUM, stack_dest);
-
-  /* And that should do it.  Return the new stack pointer.  */
-  return stack_dest;
-}
-
-
-/* The 'unwind_cache' data structure.  */
-
-struct mt_unwind_cache
-{
-  /* The previous frame's inner most stack address.
-     Used as this frame ID's stack_addr.  */
-  CORE_ADDR prev_sp;
-  CORE_ADDR frame_base;
-  int framesize;
-  int frameless_p;
-
-  /* Table indicating the location of each and every register.  */
-  struct trad_frame_saved_reg *saved_regs;
-};
-
-/* Initialize an unwind_cache.  Build up the saved_regs table etc. for
-   the frame.  */
-
-static struct mt_unwind_cache *
-mt_frame_unwind_cache (struct frame_info *this_frame,
-			void **this_prologue_cache)
-{
-  struct gdbarch *gdbarch;
-  struct mt_unwind_cache *info;
-  CORE_ADDR next_addr, start_addr, end_addr, prologue_end_addr;
-  unsigned long instr, upper_half, delayed_store = 0;
-  int regnum, offset;
-  ULONGEST sp, fp;
-
-  if ((*this_prologue_cache))
-    return (struct mt_unwind_cache *) (*this_prologue_cache);
-
-  gdbarch = get_frame_arch (this_frame);
-  info = FRAME_OBSTACK_ZALLOC (struct mt_unwind_cache);
-  (*this_prologue_cache) = info;
-
-  info->prev_sp = 0;
-  info->framesize = 0;
-  info->frame_base = 0;
-  info->frameless_p = 1;
-  info->saved_regs = trad_frame_alloc_saved_regs (this_frame);
-
-  /* Grab the frame-relative values of SP and FP, needed below.
-     The frame_saved_register function will find them on the
-     stack or in the registers as appropriate.  */
-  sp = get_frame_register_unsigned (this_frame, MT_SP_REGNUM);
-  fp = get_frame_register_unsigned (this_frame, MT_FP_REGNUM);
-
-  start_addr = get_frame_func (this_frame);
-
-  /* Return early if GDB couldn't find the function.  */
-  if (start_addr == 0)
-    return info;
-
-  end_addr = get_frame_pc (this_frame);
-  prologue_end_addr = skip_prologue_using_sal (gdbarch, start_addr);
-  if (end_addr == 0)
-  for (next_addr = start_addr; next_addr < end_addr; next_addr += 4)
-    {
-      instr = get_frame_memory_unsigned (this_frame, next_addr, 4);
-      if (delayed_store)	/* Previous instr was a push.  */
-	{
-	  upper_half = delayed_store >> 16;
-	  regnum = upper_half & 0xf;
-	  offset = delayed_store & 0xffff;
-	  switch (upper_half & 0xfff0)
-	    {
-	    case 0x43c0:	/* push using frame pointer.  */
-	      info->saved_regs[regnum].addr = offset;
-	      break;
-	    case 0x43d0:	/* push using stack pointer.  */
-	      info->saved_regs[regnum].addr = offset;
-	      break;
-	    default:		/* lint */
-	      break;
-	    }
-	  delayed_store = 0;
-	}
-
-      switch (instr)
-	{
-	case 0x12000000:	/* NO-OP */
-	  continue;
-	case 0x12ddc000:	/* copy sp into fp */
-	  info->frameless_p = 0;	/* Record that the frame
-					   pointer is in use.  */
-	  continue;
-	default:
-	  upper_half = instr >> 16;
-	  if (upper_half == 0x05dd ||	/* subi  sp, sp, imm */
-	      upper_half == 0x07dd)	/* subui sp, sp, imm */
-	    {
-	      /* Record the frame size.  */
-	      info->framesize = instr & 0xffff;
-	      continue;
-	    }
-	  if ((upper_half & 0xfff0) == 0x43c0 ||	/* frame push */
-	      (upper_half & 0xfff0) == 0x43d0)	/* stack push */
-	    {
-	      /* Save this instruction, but don't record the 
-	         pushed register as 'saved' until we see the
-	         next instruction.  That's because of deferred stores
-	         on this target -- GDB won't be able to read the register
-	         from the stack until one instruction later.  */
-	      delayed_store = instr;
-	      continue;
-	    }
-	  /* Not a prologue instruction.  Is this the end of the prologue?
-	     This is the most difficult decision; when to stop scanning. 
-
-	     If we have no line symbol, then the best thing we can do
-	     is to stop scanning when we encounter an instruction that
-	     is not likely to be a part of the prologue. 
-
-	     But if we do have a line symbol, then we should 
-	     keep scanning until we reach it (or we reach end_addr).  */
-
-	  if (prologue_end_addr && (prologue_end_addr > (next_addr + 4)))
-	    continue;	/* Keep scanning, recording saved_regs etc.  */
-	  else
-	    break;	/* Quit scanning: breakpoint can be set here.  */
-	}
-    }
-
-  /* Special handling for the "saved" address of the SP:
-     The SP is of course never saved on the stack at all, so
-     by convention what we put here is simply the previous 
-     _value_ of the SP (as opposed to an address where the
-     previous value would have been pushed).  This will also
-     give us the frame base address.  */
-
-  if (info->frameless_p)
-    {
-      info->frame_base = sp + info->framesize;
-      info->prev_sp = sp + info->framesize;
-    }
-  else
-    {
-      info->frame_base = fp + info->framesize;
-      info->prev_sp = fp + info->framesize;
-    }
-  /* Save prev_sp in saved_regs as a value, not as an address.  */
-  trad_frame_set_value (info->saved_regs, MT_SP_REGNUM, info->prev_sp);
-
-  /* Now convert frame offsets to actual addresses (not offsets).  */
-  for (regnum = 0; regnum < MT_NUM_REGS; regnum++)
-    if (trad_frame_addr_p (info->saved_regs, regnum))
-      info->saved_regs[regnum].addr += info->frame_base - info->framesize;
-
-  /* The call instruction moves the caller's PC in the callee's RA reg.
-     Since this is an unwind, do the reverse.  Copy the location of RA
-     into PC (the address / regnum) so that a request for PC will be
-     converted into a request for the RA.  */
-  info->saved_regs[MT_PC_REGNUM] = info->saved_regs[MT_RA_REGNUM];
-
-  return info;
-}
-
-static CORE_ADDR
-mt_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  ULONGEST pc;
-
-  pc = frame_unwind_register_unsigned (next_frame, MT_PC_REGNUM);
-  return pc;
-}
-
-static CORE_ADDR
-mt_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  ULONGEST sp;
-
-  sp = frame_unwind_register_unsigned (next_frame, MT_SP_REGNUM);
-  return sp;
-}
-
-/* Assuming THIS_FRAME is a dummy, return the frame ID of that dummy
-   frame.  The frame ID's base needs to match the TOS value saved by
-   save_dummy_frame_tos(), and the PC match the dummy frame's breakpoint.  */
-
-static struct frame_id
-mt_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
-{
-  CORE_ADDR sp = get_frame_register_unsigned (this_frame, MT_SP_REGNUM);
-  return frame_id_build (sp, get_frame_pc (this_frame));
-}
-
-/* Given a GDB frame, determine the address of the calling function's
-   frame.  This will be used to create a new GDB frame struct.  */
-
-static void
-mt_frame_this_id (struct frame_info *this_frame,
-		   void **this_prologue_cache, struct frame_id *this_id)
-{
-  struct mt_unwind_cache *info =
-    mt_frame_unwind_cache (this_frame, this_prologue_cache);
-
-  if (!(info == NULL || info->prev_sp == 0))
-    (*this_id) = frame_id_build (info->prev_sp, get_frame_func (this_frame));
-
-  return;
-}
-
-static struct value *
-mt_frame_prev_register (struct frame_info *this_frame,
-			 void **this_prologue_cache, int regnum)
-{
-  struct mt_unwind_cache *info =
-    mt_frame_unwind_cache (this_frame, this_prologue_cache);
-
-  return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
-}
-
-static CORE_ADDR
-mt_frame_base_address (struct frame_info *this_frame,
-			void **this_prologue_cache)
-{
-  struct mt_unwind_cache *info =
-    mt_frame_unwind_cache (this_frame, this_prologue_cache);
-
-  return info->frame_base;
-}
-
-/* This is a shared interface:  the 'frame_unwind' object is what's
-   returned by the 'sniffer' function, and in turn specifies how to
-   get a frame's ID and prev_regs.
-
-   This exports the 'prev_register' and 'this_id' methods.  */
-
-static const struct frame_unwind mt_frame_unwind = {
-  NORMAL_FRAME,
-  default_frame_unwind_stop_reason,
-  mt_frame_this_id,
-  mt_frame_prev_register,
-  NULL,
-  default_frame_sniffer
-};
-
-/* Another shared interface:  the 'frame_base' object specifies how to
-   unwind a frame and secure the base addresses for frame objects
-   (locals, args).  */
-
-static struct frame_base mt_frame_base = {
-  &mt_frame_unwind,
-  mt_frame_base_address,
-  mt_frame_base_address,
-  mt_frame_base_address
-};
-
-static struct gdbarch *
-mt_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
-{
-  struct gdbarch *gdbarch;
-  struct gdbarch_tdep *tdep;
-
-  /* Find a candidate among the list of pre-declared architectures.  */
-  arches = gdbarch_list_lookup_by_info (arches, &info);
-  if (arches != NULL)
-    return arches->gdbarch;
-
-  /* None found, create a new architecture from the information
-     provided.  */
-  tdep = XCNEW (struct gdbarch_tdep);
-  gdbarch = gdbarch_alloc (&info, tdep);
-
-  set_gdbarch_float_format (gdbarch, floatformats_ieee_single);
-  set_gdbarch_double_format (gdbarch, floatformats_ieee_double);
-  set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
-
-  set_gdbarch_register_name (gdbarch, mt_register_name);
-  set_gdbarch_num_regs (gdbarch, MT_NUM_REGS);
-  set_gdbarch_num_pseudo_regs (gdbarch, MT_NUM_PSEUDO_REGS);
-  set_gdbarch_pc_regnum (gdbarch, MT_PC_REGNUM);
-  set_gdbarch_sp_regnum (gdbarch, MT_SP_REGNUM);
-  set_gdbarch_pseudo_register_read (gdbarch, mt_pseudo_register_read);
-  set_gdbarch_pseudo_register_write (gdbarch, mt_pseudo_register_write);
-  set_gdbarch_skip_prologue (gdbarch, mt_skip_prologue);
-  set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
-  set_gdbarch_breakpoint_kind_from_pc (gdbarch, mt_breakpoint_kind_from_pc);
-  set_gdbarch_sw_breakpoint_from_kind (gdbarch, mt_sw_breakpoint_from_kind);
-  set_gdbarch_decr_pc_after_break (gdbarch, 0);
-  set_gdbarch_frame_args_skip (gdbarch, 0);
-  set_gdbarch_register_type (gdbarch, mt_register_type);
-  set_gdbarch_register_reggroup_p (gdbarch, mt_register_reggroup_p);
-
-  set_gdbarch_return_value (gdbarch, mt_return_value);
-  set_gdbarch_sp_regnum (gdbarch, MT_SP_REGNUM);
-
-  set_gdbarch_frame_align (gdbarch, mt_frame_align);
-
-  set_gdbarch_print_registers_info (gdbarch, mt_registers_info);
-
-  set_gdbarch_push_dummy_call (gdbarch, mt_push_dummy_call);
-
-  /* Target builtin data types.  */
-  set_gdbarch_short_bit (gdbarch, 16);
-  set_gdbarch_int_bit (gdbarch, 32);
-  set_gdbarch_long_bit (gdbarch, 32);
-  set_gdbarch_long_long_bit (gdbarch, 64);
-  set_gdbarch_float_bit (gdbarch, 32);
-  set_gdbarch_double_bit (gdbarch, 64);
-  set_gdbarch_long_double_bit (gdbarch, 64);
-  set_gdbarch_ptr_bit (gdbarch, 32);
-
-  /* Register the DWARF 2 sniffer first, and then the traditional prologue
-     based sniffer.  */
-  dwarf2_append_unwinders (gdbarch);
-  frame_unwind_append_unwinder (gdbarch, &mt_frame_unwind);
-  frame_base_set_default (gdbarch, &mt_frame_base);
-
-  /* Register the 'unwind_pc' method.  */
-  set_gdbarch_unwind_pc (gdbarch, mt_unwind_pc);
-  set_gdbarch_unwind_sp (gdbarch, mt_unwind_sp);
-
-  /* Methods for saving / extracting a dummy frame's ID.
-     The ID's stack address must match the SP value returned by
-     PUSH_DUMMY_CALL, and saved by generic_save_dummy_frame_tos.  */
-  set_gdbarch_dummy_id (gdbarch, mt_dummy_id);
-
-  return gdbarch;
-}
-
-void
-_initialize_mt_tdep (void)
-{
-  register_gdbarch_init (bfd_arch_mt, mt_gdbarch_init);
-}
diff --git a/gdb/regcache.c b/gdb/regcache.c
index ac905c6..a7a4683 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -1845,15 +1845,8 @@ cooked_read_test (struct gdbarch *gdbarch)
 
       SELF_CHECK (REG_VALID == readwrite.cooked_read (regnum, buf.data ()));
 
-      if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_mt)
-	{
-	  /* MT pseudo registers are banked, and different banks are
-	     selected by a raw registers, so GDB needs to write to
-	     that raw register to get different banked pseudo registers.
-	     See mt_select_coprocessor.  */
-	  SELF_CHECK (mock_target.fetch_registers_called == 0);
-	  SELF_CHECK (mock_target.store_registers_called == 0);
-	}
+      SELF_CHECK (mock_target.fetch_registers_called == 0);
+      SELF_CHECK (mock_target.store_registers_called == 0);
 
       /* Some SPU pseudo registers are got via TARGET_OBJECT_SPU.  */
       if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_spu)
@@ -1872,12 +1865,6 @@ cooked_read_test (struct gdbarch *gdbarch)
        regnum < gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
        regnum++)
     {
-      if (gdbarch_bfd_arch_info (gdbarch)->arch == bfd_arch_mt)
-	{
-	  /* Trigger an internal error otherwise.  */
-	  continue;
-	}
-
       if (register_size (gdbarch, regnum) == 0)
 	continue;
 
-- 
1.9.1

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

* [PATCH 04/15] Replace regcache_raw_read with regcache->raw_read
  2017-12-01 10:48 [RFC 00/15] Remove regcache::m_readonly_p Yao Qi
  2017-12-01 10:48 ` [PATCH 09/15] Remove regcache_save and regcache_cpy Yao Qi
  2017-12-01 10:48 ` [PATCH 01/15] Call cooked_read in ppu2spu_prev_register Yao Qi
@ 2017-12-01 10:48 ` Yao Qi
  2017-12-01 10:48 ` [PATCH 15/15] Move register_dump to regcache-dump.c Yao Qi
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 32+ messages in thread
From: Yao Qi @ 2017-12-01 10:48 UTC (permalink / raw)
  To: gdb-patches

The patch later in this series will move regcache's raw_read and
cooked_read methods to a new class regcache_read, and regcache is
dervied from it.  Also pass regcache_read instead of regcache to gdbarch
methods pseudo_register_read and pseudo_register_read_value.  In order
to prepare for this change, this patch changes regcache_raw_read to
regcache->raw_read.  On the other hand, since we are in C++, I prefer
using class method (regcache->raw_read).

gdb:

2017-11-14  Yao Qi  <yao.qi@linaro.org>

	* aarch64-tdep.c (aarch64_pseudo_read_value): Call regcache
	method raw_read instead of regcache_raw_read.
	* amd64-tdep.c (amd64_pseudo_register_read_value): Likewise.
	* arm-tdep.c (arm_neon_quad_read): Likewise.
	* avr-tdep.c (avr_pseudo_register_read): Likewise.
	* bfin-tdep.c (bfin_pseudo_register_read): Likewise.
	* frv-tdep.c (frv_pseudo_register_read): Likewise.
	* h8300-tdep.c (h8300_pseudo_register_read): Likewise.
	* i386-tdep.c (i386_mmx_regnum_to_fp_regnum): Likewise.
	(i386_pseudo_register_read_into_value): Likewise.
	* mep-tdep.c (mep_pseudo_cr32_read): Likewise.
	* msp430-tdep.c (msp430_pseudo_register_read): Likewise.
	* nds32-tdep.c (nds32_pseudo_register_read): Likewise.
	* rl78-tdep.c (rl78_pseudo_register_read): Likewise.
	* s390-linux-tdep.c (s390_pseudo_register_read): Likewise.
	* sparc-tdep.c (sparc32_pseudo_register_read):  Likewise.
	* sparc64-tdep.c (sparc64_pseudo_register_read): Likewise.
	* spu-tdep.c (spu_pseudo_register_read_spu):  Likewise.
	* xtensa-tdep.c (xtensa_pseudo_register_read): Likewise.
---
 gdb/aarch64-tdep.c    | 10 ++++----
 gdb/amd64-tdep.c      |  9 ++++---
 gdb/arm-tdep.c        |  6 ++---
 gdb/avr-tdep.c        |  2 +-
 gdb/bfin-tdep.c       |  2 +-
 gdb/frv-tdep.c        |  6 ++---
 gdb/h8300-tdep.c      |  4 ++--
 gdb/hppa-tdep.c       |  2 +-
 gdb/i386-tdep.c       | 66 +++++++++++++++++++++------------------------------
 gdb/m32c-tdep.c       |  9 +++----
 gdb/mep-tdep.c        |  6 ++---
 gdb/mips-tdep.c       |  6 ++---
 gdb/msp430-tdep.c     |  2 +-
 gdb/nds32-tdep.c      |  2 +-
 gdb/rl78-tdep.c       | 27 ++++++++++-----------
 gdb/rs6000-tdep.c     | 36 ++++++++++++++--------------
 gdb/s390-linux-tdep.c | 15 ++++++------
 gdb/sh-tdep.c         |  4 ++--
 gdb/sh64-tdep.c       |  8 +++----
 gdb/sparc-tdep.c      |  4 ++--
 gdb/sparc64-tdep.c    | 20 ++++++++--------
 gdb/spu-tdep.c        |  6 ++---
 gdb/xtensa-tdep.c     |  9 ++++---
 23 files changed, 123 insertions(+), 138 deletions(-)

diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 6a0d4b7..0947100 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -2245,7 +2245,7 @@ aarch64_pseudo_read_value (struct gdbarch *gdbarch,
       unsigned v_regnum;
 
       v_regnum = AARCH64_V0_REGNUM + regnum - AARCH64_Q0_REGNUM;
-      status = regcache_raw_read (regcache, v_regnum, reg_buf);
+      status = regcache->raw_read (v_regnum, reg_buf);
       if (status != REG_VALID)
 	mark_value_bytes_unavailable (result_value, 0,
 				      TYPE_LENGTH (value_type (result_value)));
@@ -2260,7 +2260,7 @@ aarch64_pseudo_read_value (struct gdbarch *gdbarch,
       unsigned v_regnum;
 
       v_regnum = AARCH64_V0_REGNUM + regnum - AARCH64_D0_REGNUM;
-      status = regcache_raw_read (regcache, v_regnum, reg_buf);
+      status = regcache->raw_read (v_regnum, reg_buf);
       if (status != REG_VALID)
 	mark_value_bytes_unavailable (result_value, 0,
 				      TYPE_LENGTH (value_type (result_value)));
@@ -2275,7 +2275,7 @@ aarch64_pseudo_read_value (struct gdbarch *gdbarch,
       unsigned v_regnum;
 
       v_regnum = AARCH64_V0_REGNUM + regnum - AARCH64_S0_REGNUM;
-      status = regcache_raw_read (regcache, v_regnum, reg_buf);
+      status = regcache->raw_read (v_regnum, reg_buf);
       if (status != REG_VALID)
 	mark_value_bytes_unavailable (result_value, 0,
 				      TYPE_LENGTH (value_type (result_value)));
@@ -2290,7 +2290,7 @@ aarch64_pseudo_read_value (struct gdbarch *gdbarch,
       unsigned v_regnum;
 
       v_regnum = AARCH64_V0_REGNUM + regnum - AARCH64_H0_REGNUM;
-      status = regcache_raw_read (regcache, v_regnum, reg_buf);
+      status = regcache->raw_read (v_regnum, reg_buf);
       if (status != REG_VALID)
 	mark_value_bytes_unavailable (result_value, 0,
 				      TYPE_LENGTH (value_type (result_value)));
@@ -2305,7 +2305,7 @@ aarch64_pseudo_read_value (struct gdbarch *gdbarch,
       unsigned v_regnum;
 
       v_regnum = AARCH64_V0_REGNUM + regnum - AARCH64_B0_REGNUM;
-      status = regcache_raw_read (regcache, v_regnum, reg_buf);
+      status = regcache->raw_read (v_regnum, reg_buf);
       if (status != REG_VALID)
 	mark_value_bytes_unavailable (result_value, 0,
 				      TYPE_LENGTH (value_type (result_value)));
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index bcd37ef..57dc979 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -369,9 +369,8 @@ amd64_pseudo_register_read_value (struct gdbarch *gdbarch,
       if (gpnum >= AMD64_NUM_LOWER_BYTE_REGS)
 	{
 	  /* Special handling for AH, BH, CH, DH.  */
-	  status = regcache_raw_read (regcache,
-				      gpnum - AMD64_NUM_LOWER_BYTE_REGS,
-				      raw_buf);
+	  status = regcache->raw_read (gpnum - AMD64_NUM_LOWER_BYTE_REGS,
+				       raw_buf);
 	  if (status == REG_VALID)
 	    memcpy (buf, raw_buf + 1, 1);
 	  else
@@ -380,7 +379,7 @@ amd64_pseudo_register_read_value (struct gdbarch *gdbarch,
 	}
       else
 	{
-	  status = regcache_raw_read (regcache, gpnum, raw_buf);
+	  status = regcache->raw_read (gpnum, raw_buf);
 	  if (status == REG_VALID)
 	    memcpy (buf, raw_buf, 1);
 	  else
@@ -392,7 +391,7 @@ amd64_pseudo_register_read_value (struct gdbarch *gdbarch,
     {
       int gpnum = regnum - tdep->eax_regnum;
       /* Extract (always little endian).  */
-      status = regcache_raw_read (regcache, gpnum, raw_buf);
+      status = regcache->raw_read (gpnum, raw_buf);
       if (status == REG_VALID)
 	memcpy (buf, raw_buf, 4);
       else
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 54c6392..20da423 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -8696,13 +8696,13 @@ arm_neon_quad_read (struct gdbarch *gdbarch, struct regcache *regcache,
   else
     offset = 0;
 
-  status = regcache_raw_read (regcache, double_regnum, reg_buf);
+  status = regcache->raw_read (double_regnum, reg_buf);
   if (status != REG_VALID)
     return status;
   memcpy (buf + offset, reg_buf, 8);
 
   offset = 8 - offset;
-  status = regcache_raw_read (regcache, double_regnum + 1, reg_buf);
+  status = regcache->raw_read (double_regnum + 1, reg_buf);
   if (status != REG_VALID)
     return status;
   memcpy (buf + offset, reg_buf, 8);
@@ -8742,7 +8742,7 @@ arm_pseudo_read (struct gdbarch *gdbarch, struct regcache *regcache,
       double_regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
 						   strlen (name_buf));
 
-      status = regcache_raw_read (regcache, double_regnum, reg_buf);
+      status = regcache->raw_read (double_regnum, reg_buf);
       if (status == REG_VALID)
 	memcpy (buf, reg_buf + offset, 4);
       return status;
diff --git a/gdb/avr-tdep.c b/gdb/avr-tdep.c
index f4ce270..bcf844a 100644
--- a/gdb/avr-tdep.c
+++ b/gdb/avr-tdep.c
@@ -391,7 +391,7 @@ avr_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
   switch (regnum)
     {
     case AVR_PSEUDO_PC_REGNUM:
-      status = regcache_raw_read_unsigned (regcache, AVR_PC_REGNUM, &val);
+      status = regcache->raw_read (AVR_PC_REGNUM, &val);
       if (status != REG_VALID)
 	return status;
       val >>= 1;
diff --git a/gdb/bfin-tdep.c b/gdb/bfin-tdep.c
index f9594d7..9e37898 100644
--- a/gdb/bfin-tdep.c
+++ b/gdb/bfin-tdep.c
@@ -699,7 +699,7 @@ bfin_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 		    _("invalid register number %d"), regnum);
 
   /* Extract the CC bit from the ASTAT register.  */
-  status = regcache_raw_read (regcache, BFIN_ASTAT_REGNUM, buf);
+  status = regcache->raw_read (BFIN_ASTAT_REGNUM, buf);
   if (status == REG_VALID)
     {
       buffer[1] = buffer[2] = buffer[3] = 0;
diff --git a/gdb/frv-tdep.c b/gdb/frv-tdep.c
index bae0e18..9e552eb 100644
--- a/gdb/frv-tdep.c
+++ b/gdb/frv-tdep.c
@@ -302,9 +302,9 @@ frv_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 
   if (reg == iacc0_regnum)
     {
-      status = regcache_raw_read (regcache, iacc0h_regnum, buffer);
+      status = regcache->raw_read (iacc0h_regnum, buffer);
       if (status == REG_VALID)
-	status = regcache_raw_read (regcache, iacc0l_regnum, (bfd_byte *) buffer + 4);
+	status = regcache->raw_read (iacc0l_regnum, (bfd_byte *) buffer + 4);
     }
   else if (accg0_regnum <= reg && reg <= accg7_regnum)
     {
@@ -315,7 +315,7 @@ frv_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
       int byte_num = (reg - accg0_regnum) % 4;
       gdb_byte buf[4];
 
-      status = regcache_raw_read (regcache, raw_regnum, buf);
+      status = regcache->raw_read (raw_regnum, buf);
       if (status == REG_VALID)
 	{
 	  memset (buffer, 0, 4);
diff --git a/gdb/h8300-tdep.c b/gdb/h8300-tdep.c
index acc2da9..fc8c72f 100644
--- a/gdb/h8300-tdep.c
+++ b/gdb/h8300-tdep.c
@@ -1167,7 +1167,7 @@ pseudo_from_raw_register (struct gdbarch *gdbarch, struct regcache *regcache,
   enum register_status status;
   ULONGEST val;
 
-  status = regcache_raw_read_unsigned (regcache, raw_regno, &val);
+  status = regcache->raw_read (raw_regno, &val);
   if (status == REG_VALID)
     store_unsigned_integer (buf,
 			    register_size (gdbarch, pseudo_regno),
@@ -1205,7 +1205,7 @@ h8300_pseudo_register_read (struct gdbarch *gdbarch,
 				       regno, E_EXR_REGNUM);
     }
   else
-    return regcache_raw_read (regcache, regno, buf);
+    return regcache->raw_read (regno, buf);
 }
 
 static void
diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c
index 141399f..1e007d9 100644
--- a/gdb/hppa-tdep.c
+++ b/gdb/hppa-tdep.c
@@ -2754,7 +2754,7 @@ hppa_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
   ULONGEST tmp;
   enum register_status status;
 
-  status = regcache_raw_read_unsigned (regcache, regnum, &tmp);
+  status = regcache->raw_read (regnum, &tmp);
   if (status == REG_VALID)
     {
       if (regnum == HPPA_PCOQ_HEAD_REGNUM || regnum == HPPA_PCOQ_TAIL_REGNUM)
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 8104808..2a9e4a7 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -3256,7 +3256,7 @@ i386_mmx_regnum_to_fp_regnum (struct regcache *regcache, int regnum)
   int tos;
 
   mmxreg = regnum - tdep->mm0_regnum;
-  regcache_raw_read_unsigned (regcache, I387_FSTAT_REGNUM (tdep), &fstat);
+  regcache->raw_read (I387_FSTAT_REGNUM (tdep), &fstat);
   tos = (fstat >> 11) & 0x7;
   fpreg = (mmxreg + tos) % 8;
 
@@ -3282,7 +3282,7 @@ i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
       int fpnum = i386_mmx_regnum_to_fp_regnum (regcache, regnum);
 
       /* Extract (always little endian).  */
-      status = regcache_raw_read (regcache, fpnum, raw_buf);
+      status = regcache->raw_read (fpnum, raw_buf);
       if (status != REG_VALID)
 	mark_value_bytes_unavailable (result_value, 0,
 				      TYPE_LENGTH (value_type (result_value)));
@@ -3297,9 +3297,8 @@ i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
 	  regnum -= tdep->bnd0_regnum;
 
 	  /* Extract (always little endian).  Read lower 128bits.  */
-	  status = regcache_raw_read (regcache,
-				      I387_BND0R_REGNUM (tdep) + regnum,
-				      raw_buf);
+	  status = regcache->raw_read (I387_BND0R_REGNUM (tdep) + regnum,
+				       raw_buf);
 	  if (status != REG_VALID)
 	    mark_value_bytes_unavailable (result_value, 0, 16);
 	  else
@@ -3321,9 +3320,7 @@ i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
 	  regnum -= tdep->k0_regnum;
 
 	  /* Extract (always little endian).  */
-	  status = regcache_raw_read (regcache,
-				      tdep->k0_regnum + regnum,
-				      raw_buf);
+	  status = regcache->raw_read (tdep->k0_regnum + regnum, raw_buf);
 	  if (status != REG_VALID)
 	    mark_value_bytes_unavailable (result_value, 0, 8);
 	  else
@@ -3336,18 +3333,16 @@ i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
 	  if (regnum < num_lower_zmm_regs)
 	    {
 	      /* Extract (always little endian).  Read lower 128bits.  */
-	      status = regcache_raw_read (regcache,
-					  I387_XMM0_REGNUM (tdep) + regnum,
-					  raw_buf);
+	      status = regcache->raw_read (I387_XMM0_REGNUM (tdep) + regnum,
+					   raw_buf);
 	      if (status != REG_VALID)
 		mark_value_bytes_unavailable (result_value, 0, 16);
 	      else
 		memcpy (buf, raw_buf, 16);
 
 	      /* Extract (always little endian).  Read upper 128bits.  */
-	      status = regcache_raw_read (regcache,
-					  tdep->ymm0h_regnum + regnum,
-					  raw_buf);
+	      status = regcache->raw_read (tdep->ymm0h_regnum + regnum,
+					   raw_buf);
 	      if (status != REG_VALID)
 		mark_value_bytes_unavailable (result_value, 16, 16);
 	      else
@@ -3356,20 +3351,18 @@ i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
 	  else
 	    {
 	      /* Extract (always little endian).  Read lower 128bits.  */
-	      status = regcache_raw_read (regcache,
-					  I387_XMM16_REGNUM (tdep) + regnum
-					  - num_lower_zmm_regs,
-					  raw_buf);
+	      status = regcache->raw_read (I387_XMM16_REGNUM (tdep) + regnum
+					   - num_lower_zmm_regs,
+					   raw_buf);
 	      if (status != REG_VALID)
 		mark_value_bytes_unavailable (result_value, 0, 16);
 	      else
 		memcpy (buf, raw_buf, 16);
 
 	      /* Extract (always little endian).  Read upper 128bits.  */
-	      status = regcache_raw_read (regcache,
-					  I387_YMM16H_REGNUM (tdep) + regnum
-					  - num_lower_zmm_regs,
-					  raw_buf);
+	      status = regcache->raw_read (I387_YMM16H_REGNUM (tdep) + regnum
+					   - num_lower_zmm_regs,
+					   raw_buf);
 	      if (status != REG_VALID)
 		mark_value_bytes_unavailable (result_value, 16, 16);
 	      else
@@ -3377,9 +3370,8 @@ i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
 	    }
 
 	  /* Read upper 256bits.  */
-	  status = regcache_raw_read (regcache,
-				      tdep->zmm0h_regnum + regnum,
-				      raw_buf);
+	  status = regcache->raw_read (tdep->zmm0h_regnum + regnum,
+				       raw_buf);
 	  if (status != REG_VALID)
 	    mark_value_bytes_unavailable (result_value, 32, 32);
 	  else
@@ -3390,17 +3382,15 @@ i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
 	  regnum -= tdep->ymm0_regnum;
 
 	  /* Extract (always little endian).  Read lower 128bits.  */
-	  status = regcache_raw_read (regcache,
-				      I387_XMM0_REGNUM (tdep) + regnum,
-				      raw_buf);
+	  status = regcache->raw_read (I387_XMM0_REGNUM (tdep) + regnum,
+				       raw_buf);
 	  if (status != REG_VALID)
 	    mark_value_bytes_unavailable (result_value, 0, 16);
 	  else
 	    memcpy (buf, raw_buf, 16);
 	  /* Read upper 128bits.  */
-	  status = regcache_raw_read (regcache,
-				      tdep->ymm0h_regnum + regnum,
-				      raw_buf);
+	  status = regcache->raw_read (tdep->ymm0h_regnum + regnum,
+				       raw_buf);
 	  if (status != REG_VALID)
 	    mark_value_bytes_unavailable (result_value, 16, 32);
 	  else
@@ -3410,17 +3400,15 @@ i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
 	{
 	  regnum -= tdep->ymm16_regnum;
 	  /* Extract (always little endian).  Read lower 128bits.  */
-	  status = regcache_raw_read (regcache,
-				      I387_XMM16_REGNUM (tdep) + regnum,
-				      raw_buf);
+	  status = regcache->raw_read (I387_XMM16_REGNUM (tdep) + regnum,
+				       raw_buf);
 	  if (status != REG_VALID)
 	    mark_value_bytes_unavailable (result_value, 0, 16);
 	  else
 	    memcpy (buf, raw_buf, 16);
 	  /* Read upper 128bits.  */
-	  status = regcache_raw_read (regcache,
-				      tdep->ymm16h_regnum + regnum,
-				      raw_buf);
+	  status = regcache->raw_read (tdep->ymm16h_regnum + regnum,
+				       raw_buf);
 	  if (status != REG_VALID)
 	    mark_value_bytes_unavailable (result_value, 16, 16);
 	  else
@@ -3431,7 +3419,7 @@ i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
 	  int gpnum = regnum - tdep->ax_regnum;
 
 	  /* Extract (always little endian).  */
-	  status = regcache_raw_read (regcache, gpnum, raw_buf);
+	  status = regcache->raw_read (gpnum, raw_buf);
 	  if (status != REG_VALID)
 	    mark_value_bytes_unavailable (result_value, 0,
 					  TYPE_LENGTH (value_type (result_value)));
@@ -3444,7 +3432,7 @@ i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
 
 	  /* Extract (always little endian).  We read both lower and
 	     upper registers.  */
-	  status = regcache_raw_read (regcache, gpnum % 4, raw_buf);
+	  status = regcache->raw_read (gpnum % 4, raw_buf);
 	  if (status != REG_VALID)
 	    mark_value_bytes_unavailable (result_value, 0,
 					  TYPE_LENGTH (value_type (result_value)));
diff --git a/gdb/m32c-tdep.c b/gdb/m32c-tdep.c
index 8f40777..67b8a11 100644
--- a/gdb/m32c-tdep.c
+++ b/gdb/m32c-tdep.c
@@ -312,7 +312,7 @@ static m32c_write_reg_t m32c_r3r2r1r0_write;
 static enum register_status
 m32c_raw_read (struct m32c_reg *reg, struct regcache *cache, gdb_byte *buf)
 {
-  return regcache_raw_read (cache, reg->num, buf);
+  return cache->raw_read (reg->num, buf);
 }
 
 
@@ -333,7 +333,8 @@ m32c_read_flg (struct regcache *cache)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (cache->arch ());
   ULONGEST flg;
-  regcache_raw_read_unsigned (cache, tdep->flg->num, &flg);
+
+  cache->raw_read (tdep->flg->num, &flg);
   return flg & 0xffff;
 }
 
@@ -354,7 +355,7 @@ static enum register_status
 m32c_banked_read (struct m32c_reg *reg, struct regcache *cache, gdb_byte *buf)
 {
   struct m32c_reg *bank_reg = m32c_banked_register (reg, cache);
-  return regcache_raw_read (cache, bank_reg->num, buf);
+  return cache->raw_read (bank_reg->num, buf);
 }
 
 
@@ -447,7 +448,7 @@ m32c_part_read (struct m32c_reg *reg, struct regcache *cache, gdb_byte *buf)
 
   memset (buf, 0, TYPE_LENGTH (reg->type));
   m32c_find_part (reg, &offset, &len);
-  return regcache_cooked_read_part (cache, reg->rx->num, offset, len, buf);
+  return cache->cooked_read_part (reg->rx->num, offset, len, buf);
 }
 
 
diff --git a/gdb/mep-tdep.c b/gdb/mep-tdep.c
index bf08ca1..4069d59 100644
--- a/gdb/mep-tdep.c
+++ b/gdb/mep-tdep.c
@@ -1138,7 +1138,7 @@ mep_pseudo_cr32_read (struct gdbarch *gdbarch,
 
   gdb_assert (TYPE_LENGTH (register_type (gdbarch, rawnum)) == sizeof (buf64));
   gdb_assert (TYPE_LENGTH (register_type (gdbarch, cookednum)) == 4);
-  status = regcache_raw_read (regcache, rawnum, buf64);
+  status = regcache->raw_read (rawnum, buf64);
   if (status == REG_VALID)
     {
       /* Slow, but legible.  */
@@ -1155,7 +1155,7 @@ mep_pseudo_cr64_read (struct gdbarch *gdbarch,
                       int cookednum,
                       gdb_byte *buf)
 {
-  return regcache_raw_read (regcache, mep_pseudo_to_raw[cookednum], buf);
+  return regcache->raw_read (mep_pseudo_to_raw[cookednum], buf);
 }
 
 
@@ -1167,7 +1167,7 @@ mep_pseudo_register_read (struct gdbarch *gdbarch,
 {
   if (IS_CSR_REGNUM (cookednum)
       || IS_CCR_REGNUM (cookednum))
-    return regcache_raw_read (regcache, mep_pseudo_to_raw[cookednum], buf);
+    return regcache->raw_read (mep_pseudo_to_raw[cookednum], buf);
   else if (IS_CR32_REGNUM (cookednum)
            || IS_FP_CR32_REGNUM (cookednum))
     return mep_pseudo_cr32_read (gdbarch, regcache, cookednum, buf);
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 830535f..1e7cb4a 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -744,19 +744,19 @@ mips_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
   gdb_assert (cookednum >= gdbarch_num_regs (gdbarch)
 	      && cookednum < 2 * gdbarch_num_regs (gdbarch));
   if (register_size (gdbarch, rawnum) == register_size (gdbarch, cookednum))
-    return regcache_raw_read (regcache, rawnum, buf);
+    return regcache->raw_read (rawnum, buf);
   else if (register_size (gdbarch, rawnum) >
 	   register_size (gdbarch, cookednum))
     {
       if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p)
-	return regcache_raw_read_part (regcache, rawnum, 0, 4, buf);
+	return regcache->raw_read_part (rawnum, 0, 4, buf);
       else
 	{
 	  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 	  LONGEST regval;
 	  enum register_status status;
 
-	  status = regcache_raw_read_signed (regcache, rawnum, &regval);
+	  status = regcache->raw_read (rawnum, &regval);
 	  if (status == REG_VALID)
 	    store_signed_integer (buf, 4, byte_order, regval);
 	  return status;
diff --git a/gdb/msp430-tdep.c b/gdb/msp430-tdep.c
index 771ac9c..834f4e6 100644
--- a/gdb/msp430-tdep.c
+++ b/gdb/msp430-tdep.c
@@ -229,7 +229,7 @@ msp430_pseudo_register_read (struct gdbarch *gdbarch,
       int regsize = register_size (gdbarch, regnum);
       int raw_regnum = regnum - MSP430_NUM_REGS;
 
-      status = regcache_raw_read_unsigned (regcache, raw_regnum, &val);
+      status = regcache->raw_read (raw_regnum, &val);
       if (status == REG_VALID)
 	store_unsigned_integer (buffer, regsize, byte_order, val);
 
diff --git a/gdb/nds32-tdep.c b/gdb/nds32-tdep.c
index 962b2e7..f4037b2 100644
--- a/gdb/nds32-tdep.c
+++ b/gdb/nds32-tdep.c
@@ -462,7 +462,7 @@ nds32_pseudo_register_read (struct gdbarch *gdbarch,
 	offset = (regnum & 1) ? 0 : 4;
 
       fdr_regnum = NDS32_FD0_REGNUM + (regnum >> 1);
-      status = regcache_raw_read (regcache, fdr_regnum, reg_buf);
+      status = regcache->raw_read (fdr_regnum, reg_buf);
       if (status == REG_VALID)
 	memcpy (buf, reg_buf + offset, 4);
 
diff --git a/gdb/rl78-tdep.c b/gdb/rl78-tdep.c
index 19f8098..76630af 100644
--- a/gdb/rl78-tdep.c
+++ b/gdb/rl78-tdep.c
@@ -650,68 +650,67 @@ rl78_pseudo_register_read (struct gdbarch *gdbarch,
       int raw_regnum = RL78_RAW_BANK0_R0_REGNUM
                        + (reg - RL78_BANK0_R0_REGNUM);
 
-      status = regcache_raw_read (regcache, raw_regnum, buffer);
+      status = regcache->raw_read (raw_regnum, buffer);
     }
   else if (RL78_BANK0_RP0_REGNUM <= reg && reg <= RL78_BANK3_RP3_REGNUM)
     {
       int raw_regnum = 2 * (reg - RL78_BANK0_RP0_REGNUM)
                        + RL78_RAW_BANK0_R0_REGNUM;
 
-      status = regcache_raw_read (regcache, raw_regnum, buffer);
+      status = regcache->raw_read (raw_regnum, buffer);
       if (status == REG_VALID)
-	status = regcache_raw_read (regcache, raw_regnum + 1, buffer + 1);
+	status = regcache->raw_read (raw_regnum + 1, buffer + 1);
     }
   else if (RL78_BANK0_RP0_PTR_REGNUM <= reg && reg <= RL78_BANK3_RP3_PTR_REGNUM)
     {
       int raw_regnum = 2 * (reg - RL78_BANK0_RP0_PTR_REGNUM)
                        + RL78_RAW_BANK0_R0_REGNUM;
 
-      status = regcache_raw_read (regcache, raw_regnum, buffer);
+      status = regcache->raw_read (raw_regnum, buffer);
       if (status == REG_VALID)
-	status = regcache_raw_read (regcache, raw_regnum + 1, buffer + 1);
+	status = regcache->raw_read (raw_regnum + 1, buffer + 1);
     }
   else if (reg == RL78_SP_REGNUM)
     {
-      status = regcache_raw_read (regcache, RL78_SPL_REGNUM, buffer);
+      status = regcache->raw_read (RL78_SPL_REGNUM, buffer);
       if (status == REG_VALID)
-	status = regcache_raw_read (regcache, RL78_SPH_REGNUM, buffer + 1);
+	status = regcache->raw_read (RL78_SPH_REGNUM, buffer + 1);
     }
   else if (reg == RL78_PC_REGNUM)
     {
       gdb_byte rawbuf[4];
 
-      status = regcache_raw_read (regcache, RL78_RAW_PC_REGNUM, rawbuf);
+      status = regcache->raw_read (RL78_RAW_PC_REGNUM, rawbuf);
       memcpy (buffer, rawbuf, 3);
     }
   else if (RL78_X_REGNUM <= reg && reg <= RL78_H_REGNUM)
     {
       ULONGEST psw;
 
-      status = regcache_raw_read_unsigned (regcache, RL78_PSW_REGNUM, &psw);
+      status = regcache->raw_read (RL78_PSW_REGNUM, &psw);
       if (status == REG_VALID)
 	{
 	  /* RSB0 is at bit 3; RSBS1 is at bit 5.  */
 	  int bank = ((psw >> 3) & 1) | ((psw >> 4) & 1);
 	  int raw_regnum = RL78_RAW_BANK0_R0_REGNUM + bank * RL78_REGS_PER_BANK
 	                   + (reg - RL78_X_REGNUM);
-	  status = regcache_raw_read (regcache, raw_regnum, buffer);
+	  status = regcache->raw_read (raw_regnum, buffer);
 	}
     }
   else if (RL78_AX_REGNUM <= reg && reg <= RL78_HL_REGNUM)
     {
       ULONGEST psw;
 
-      status = regcache_raw_read_unsigned (regcache, RL78_PSW_REGNUM, &psw);
+      status = regcache->raw_read (RL78_PSW_REGNUM, &psw);
       if (status == REG_VALID)
 	{
 	  /* RSB0 is at bit 3; RSBS1 is at bit 5.  */
 	  int bank = ((psw >> 3) & 1) | ((psw >> 4) & 1);
 	  int raw_regnum = RL78_RAW_BANK0_R0_REGNUM + bank * RL78_REGS_PER_BANK
 	                   + 2 * (reg - RL78_AX_REGNUM);
-	  status = regcache_raw_read (regcache, raw_regnum, buffer);
+	  status = regcache->raw_read (raw_regnum, buffer);
 	  if (status == REG_VALID)
-	    status = regcache_raw_read (regcache, raw_regnum + 1,
-	                                buffer + 1);
+	    status = regcache->raw_read (raw_regnum + 1, buffer + 1);
 	}
     }
   else
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index 456dbcc..c902daf 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -2747,19 +2747,19 @@ dfp_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
   if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
     {
       /* Read two FP registers to form a whole dl register.  */
-      status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-				  2 * reg_index, buffer);
+      status = regcache->raw_read (tdep->ppc_fp0_regnum +
+				   2 * reg_index, buffer);
       if (status == REG_VALID)
-	status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-				    2 * reg_index + 1, buffer + 8);
+	status = regcache->raw_read (tdep->ppc_fp0_regnum +
+				     2 * reg_index + 1, buffer + 8);
     }
   else
     {
-      status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-				  2 * reg_index + 1, buffer);
+      status = regcache->raw_read (tdep->ppc_fp0_regnum +
+				   2 * reg_index + 1, buffer);
       if (status == REG_VALID)
-	status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-				    2 * reg_index, buffer + 8);
+	status = regcache->raw_read (tdep->ppc_fp0_regnum +
+				     2 * reg_index, buffer + 8);
     }
 
   return status;
@@ -2802,25 +2802,25 @@ vsx_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 
   /* Read the portion that overlaps the VMX registers.  */
   if (reg_index > 31)
-    status = regcache_raw_read (regcache, tdep->ppc_vr0_regnum +
-				reg_index - 32, buffer);
+    status = regcache->raw_read (tdep->ppc_vr0_regnum +
+				 reg_index - 32, buffer);
   else
     /* Read the portion that overlaps the FPR registers.  */
     if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
       {
-	status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-				    reg_index, buffer);
+	status = regcache->raw_read (tdep->ppc_fp0_regnum +
+				     reg_index, buffer);
 	if (status == REG_VALID)
-	  status = regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
-				      reg_index, buffer + 8);
+	  status = regcache->raw_read (tdep->ppc_vsr0_upper_regnum +
+				       reg_index, buffer + 8);
       }
     else
       {
-	status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-				    reg_index, buffer + 8);
+	status = regcache->raw_read (tdep->ppc_fp0_regnum +
+				     reg_index, buffer + 8);
 	if (status == REG_VALID)
-	  status = regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
-				      reg_index, buffer);
+	  status = regcache->raw_read (tdep->ppc_vsr0_upper_regnum +
+				       reg_index, buffer);
       }
 
   return status;
diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index a0d4cdd..a016864 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -399,7 +399,7 @@ s390_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
     {
       enum register_status status;
 
-      status = regcache_raw_read_unsigned (regcache, S390_PSWA_REGNUM, &val);
+      status = regcache->raw_read (S390_PSWA_REGNUM, &val);
       if (status == REG_VALID)
 	{
 	  if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
@@ -413,7 +413,7 @@ s390_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
     {
       enum register_status status;
 
-      status = regcache_raw_read_unsigned (regcache, S390_PSWM_REGNUM, &val);
+      status = regcache->raw_read (S390_PSWM_REGNUM, &val);
       if (status == REG_VALID)
 	{
 	  if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
@@ -432,10 +432,10 @@ s390_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 
       regnum -= tdep->gpr_full_regnum;
 
-      status = regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + regnum, &val);
+      status = regcache->raw_read (S390_R0_REGNUM + regnum, &val);
       if (status == REG_VALID)
-	status = regcache_raw_read_unsigned (regcache, S390_R0_UPPER_REGNUM + regnum,
-					     &val_upper);
+	status = regcache->raw_read (S390_R0_UPPER_REGNUM + regnum,
+				     &val_upper);
       if (status == REG_VALID)
 	{
 	  val |= val_upper << 32;
@@ -450,10 +450,9 @@ s390_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 
       regnum -= tdep->v0_full_regnum;
 
-      status = regcache_raw_read (regcache, S390_F0_REGNUM + regnum, buf);
+      status = regcache->raw_read (S390_F0_REGNUM + regnum, buf);
       if (status == REG_VALID)
-	status = regcache_raw_read (regcache,
-				    S390_V0_LOWER_REGNUM + regnum, buf + 8);
+	status = regcache->raw_read (S390_V0_LOWER_REGNUM + regnum, buf + 8);
       return status;
     }
 
diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c
index 23675bb..6c4e5bb 100644
--- a/gdb/sh-tdep.c
+++ b/gdb/sh-tdep.c
@@ -1640,7 +1640,7 @@ pseudo_register_read_portions (struct gdbarch *gdbarch,
       gdb_byte *b;
 
       b = buffer + register_size (gdbarch, base_regnum) * portion;
-      status = regcache_raw_read (regcache, base_regnum + portion, b);
+      status = regcache->raw_read (base_regnum + portion, b);
       if (status != REG_VALID)
 	return status;
     }
@@ -1656,7 +1656,7 @@ sh_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
   enum register_status status;
 
   if (reg_nr == PSEUDO_BANK_REGNUM)
-    return regcache_raw_read (regcache, BANK_REGNUM, buffer);
+    return regcache->raw_read (BANK_REGNUM, buffer);
   else if (reg_nr >= DR0_REGNUM && reg_nr <= DR_LAST_REGNUM)
     {
       /* Enough space for two float registers.  */
diff --git a/gdb/sh64-tdep.c b/gdb/sh64-tdep.c
index 3004f15..ec87902 100644
--- a/gdb/sh64-tdep.c
+++ b/gdb/sh64-tdep.c
@@ -1516,7 +1516,7 @@ pseudo_register_read_portions (struct gdbarch *gdbarch,
       gdb_byte *b;
 
       b = buffer + register_size (gdbarch, base_regnum) * portion;
-      status = regcache_raw_read (regcache, base_regnum + portion, b);
+      status = regcache->raw_read (base_regnum + portion, b);
       if (status != REG_VALID)
 	return status;
     }
@@ -1587,7 +1587,7 @@ sh64_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
       base_regnum = sh64_compact_reg_base_num (gdbarch, reg_nr);
 
       /* Build the value in the provided buffer.  */ 
-      status = regcache_raw_read (regcache, base_regnum, temp_buffer);
+      status = regcache->raw_read (base_regnum, temp_buffer);
       if (status != REG_VALID)
 	return status;
       if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
@@ -1605,7 +1605,7 @@ sh64_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
       /* Build the value in the provided buffer.  */ 
       /* Floating point registers map 1-1 to the media fp regs,
 	 they have the same size and endianness.  */
-      return regcache_raw_read (regcache, base_regnum, buffer);
+      return regcache->raw_read (base_regnum, buffer);
     }
 
   else if (reg_nr >= DR0_C_REGNUM 
@@ -1692,7 +1692,7 @@ sh64_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 
       /* FPUL_C register is floating point register 32,
 	 same size, same endianness.  */
-      return regcache_raw_read (regcache, base_regnum, buffer);
+      return regcache->raw_read (base_regnum, buffer);
     }
   else
     gdb_assert_not_reached ("invalid pseudo register number");
diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c
index 809cb9a..0fb3481 100644
--- a/gdb/sparc-tdep.c
+++ b/gdb/sparc-tdep.c
@@ -512,9 +512,9 @@ sparc32_pseudo_register_read (struct gdbarch *gdbarch,
   gdb_assert (regnum >= SPARC32_D0_REGNUM && regnum <= SPARC32_D30_REGNUM);
 
   regnum = SPARC_F0_REGNUM + 2 * (regnum - SPARC32_D0_REGNUM);
-  status = regcache_raw_read (regcache, regnum, buf);
+  status = regcache->raw_read (regnum, buf);
   if (status == REG_VALID)
-    status = regcache_raw_read (regcache, regnum + 1, buf + 4);
+    status = regcache->raw_read (regnum + 1, buf + 4);
   return status;
 }
 
diff --git a/gdb/sparc64-tdep.c b/gdb/sparc64-tdep.c
index 55aef13..54af887 100644
--- a/gdb/sparc64-tdep.c
+++ b/gdb/sparc64-tdep.c
@@ -910,27 +910,27 @@ sparc64_pseudo_register_read (struct gdbarch *gdbarch,
   if (regnum >= SPARC64_D0_REGNUM && regnum <= SPARC64_D30_REGNUM)
     {
       regnum = SPARC_F0_REGNUM + 2 * (regnum - SPARC64_D0_REGNUM);
-      status = regcache_raw_read (regcache, regnum, buf);
+      status = regcache->raw_read (regnum, buf);
       if (status == REG_VALID)
-	status = regcache_raw_read (regcache, regnum + 1, buf + 4);
+	status = regcache->raw_read (regnum + 1, buf + 4);
       return status;
     }
   else if (regnum >= SPARC64_D32_REGNUM && regnum <= SPARC64_D62_REGNUM)
     {
       regnum = SPARC64_F32_REGNUM + (regnum - SPARC64_D32_REGNUM);
-      return regcache_raw_read (regcache, regnum, buf);
+      return regcache->raw_read (regnum, buf);
     }
   else if (regnum >= SPARC64_Q0_REGNUM && regnum <= SPARC64_Q28_REGNUM)
     {
       regnum = SPARC_F0_REGNUM + 4 * (regnum - SPARC64_Q0_REGNUM);
 
-      status = regcache_raw_read (regcache, regnum, buf);
+      status = regcache->raw_read (regnum, buf);
       if (status == REG_VALID)
-	status = regcache_raw_read (regcache, regnum + 1, buf + 4);
+	status = regcache->raw_read (regnum + 1, buf + 4);
       if (status == REG_VALID)
-	status = regcache_raw_read (regcache, regnum + 2, buf + 8);
+	status = regcache->raw_read (regnum + 2, buf + 8);
       if (status == REG_VALID)
-	status = regcache_raw_read (regcache, regnum + 3, buf + 12);
+	status = regcache->raw_read (regnum + 3, buf + 12);
 
       return status;
     }
@@ -938,9 +938,9 @@ sparc64_pseudo_register_read (struct gdbarch *gdbarch,
     {
       regnum = SPARC64_F32_REGNUM + 2 * (regnum - SPARC64_Q32_REGNUM);
 
-      status = regcache_raw_read (regcache, regnum, buf);
+      status = regcache->raw_read (regnum, buf);
       if (status == REG_VALID)
-	status = regcache_raw_read (regcache, regnum + 1, buf + 8);
+	status = regcache->raw_read (regnum + 1, buf + 8);
 
       return status;
     }
@@ -951,7 +951,7 @@ sparc64_pseudo_register_read (struct gdbarch *gdbarch,
     {
       ULONGEST state;
 
-      status = regcache_raw_read_unsigned (regcache, SPARC64_STATE_REGNUM, &state);
+      status = regcache->raw_read (SPARC64_STATE_REGNUM, &state);
       if (status != REG_VALID)
 	return status;
 
diff --git a/gdb/spu-tdep.c b/gdb/spu-tdep.c
index ecdc7fc..bc7ac77 100644
--- a/gdb/spu-tdep.c
+++ b/gdb/spu-tdep.c
@@ -193,7 +193,7 @@ spu_pseudo_register_read_spu (struct regcache *regcache, const char *regname,
   ULONGEST id;
   ULONGEST ul;
 
-  status = regcache_raw_read_unsigned (regcache, SPU_ID_REGNUM, &id);
+  status = regcache->raw_read (SPU_ID_REGNUM, &id);
   if (status != REG_VALID)
     return status;
   xsnprintf (annex, sizeof annex, "%d/%s", (int) id, regname);
@@ -218,14 +218,14 @@ spu_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
   switch (regnum)
     {
     case SPU_SP_REGNUM:
-      status = regcache_raw_read (regcache, SPU_RAW_SP_REGNUM, reg);
+      status = regcache->raw_read (SPU_RAW_SP_REGNUM, reg);
       if (status != REG_VALID)
 	return status;
       memcpy (buf, reg, 4);
       return status;
 
     case SPU_FPSCR_REGNUM:
-      status = regcache_raw_read_unsigned (regcache, SPU_ID_REGNUM, &id);
+      status = regcache->raw_read (SPU_ID_REGNUM, &id);
       if (status != REG_VALID)
 	return status;
       xsnprintf (annex, sizeof annex, "%d/fpcr", (int) id);
diff --git a/gdb/xtensa-tdep.c b/gdb/xtensa-tdep.c
index 0b0ec2e..9779c3a 100644
--- a/gdb/xtensa-tdep.c
+++ b/gdb/xtensa-tdep.c
@@ -564,9 +564,8 @@ xtensa_pseudo_register_read (struct gdbarch *gdbarch,
       ULONGEST value;
       enum register_status status;
 
-      status = regcache_raw_read_unsigned (regcache,
-					   gdbarch_tdep (gdbarch)->wb_regnum,
-					   &value);
+      status = regcache->raw_read (gdbarch_tdep (gdbarch)->wb_regnum,
+				   &value);
       if (status != REG_VALID)
 	return status;
       regnum = arreg_number (gdbarch, regnum, value);
@@ -574,7 +573,7 @@ xtensa_pseudo_register_read (struct gdbarch *gdbarch,
 
   /* We can always read non-pseudo registers.  */
   if (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch))
-    return regcache_raw_read (regcache, regnum, buffer);
+    return regcache->raw_read (regnum, buffer);
 
   /* We have to find out how to deal with priveleged registers.
      Let's treat them as pseudo-registers, but we cannot read/write them.  */
@@ -631,7 +630,7 @@ xtensa_pseudo_register_read (struct gdbarch *gdbarch,
 	return xtensa_register_read_masked (regcache, reg, buffer);
 
       /* Assume that we can read the register.  */
-      return regcache_raw_read (regcache, regnum, buffer);
+      return regcache->raw_read (regnum, buffer);
     }
   else
     internal_error (__FILE__, __LINE__,
-- 
1.9.1

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

* [PATCH 12/15] Replace regcache::dump with class register_dump
  2017-12-01 10:48 [RFC 00/15] Remove regcache::m_readonly_p Yao Qi
                   ` (11 preceding siblings ...)
  2017-12-01 10:48 ` [PATCH 06/15] regcache::cooked_write test Yao Qi
@ 2017-12-01 10:48 ` Yao Qi
  2017-12-01 10:48 ` [PATCH 07/15] Class reg_buffer Yao Qi
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 32+ messages in thread
From: Yao Qi @ 2017-12-01 10:48 UTC (permalink / raw)
  To: gdb-patches

Nowadays, we need to dump registers contents from "readwrite" regcache and
"readonly" regcache,

  if (target_has_registers)
    get_current_regcache ()->dump (out, what_to_dump);
  else
    {
      /* For the benefit of "maint print registers" & co when
         debugging an executable, allow dumping a regcache even when
         there is no thread selected / no registers.  */
      regcache dummy_regs (target_gdbarch ());
      dummy_regs.dump (out, what_to_dump);
    }

since we'll have two different types/classes for "readwrite" regcache and
"readonly" regcache, we have to move dump method to their parent class,
reg_buffer.  However, the functionality of "dump" looks unnecessary to
reg_buffer (because some dump modes like regcache_dump_none,
regcache_dump_remote and regcache_dump_groups don't need reg_buffer at
all, they need gdbarch to do the dump), so I decide to move "dump" into a
separate classes, and each sub-class is about each mode of dump.

gdb:

2017-11-28  Yao Qi  <yao.qi@linaro.org>

	* regcache.c (class register_dump): New class.
	(register_dump_regcache, register_dump_none): New class.
	(register_dump_remote, register_dump_groups): New class.
	(regcache_print): Update.
	* regcache.h (regcache_dump_what): Move it to regcache.c.
	(regcache) <dump>: Remove.
---
 gdb/regcache.c | 483 ++++++++++++++++++++++++++++++++++-----------------------
 gdb/regcache.h |   9 --
 2 files changed, 285 insertions(+), 207 deletions(-)

diff --git a/gdb/regcache.c b/gdb/regcache.c
index 9b5b02e..9195bff 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -1315,231 +1315,284 @@ reg_flush_command (const char *command, int from_tty)
     printf_filtered (_("Register cache flushed.\n"));
 }
 
-void
-regcache::dump (ui_file *file, enum regcache_dump_what what_to_dump)
+/* An abstract base class for register dump.  */
+
+class register_dump
 {
-  struct gdbarch *gdbarch = m_descr->gdbarch;
-  int regnum;
-  int footnote_nr = 0;
-  int footnote_register_offset = 0;
-  int footnote_register_type_name_null = 0;
-  long register_offset = 0;
+public:
+  void dump (ui_file *file)
+  {
+    auto descr = regcache_descr (m_gdbarch);
+    int regnum;
+    int footnote_nr = 0;
+    int footnote_register_offset = 0;
+    int footnote_register_type_name_null = 0;
+    long register_offset = 0;
+
+    gdb_assert (descr->nr_cooked_registers
+		== (gdbarch_num_regs (m_gdbarch)
+		    + gdbarch_num_pseudo_regs (m_gdbarch)));
+
+    for (regnum = -1; regnum < descr->nr_cooked_registers; regnum++)
+      {
+	/* Name.  */
+	if (regnum < 0)
+	  fprintf_unfiltered (file, " %-10s", "Name");
+	else
+	  {
+	    const char *p = gdbarch_register_name (m_gdbarch, regnum);
 
-  gdb_assert (m_descr->nr_cooked_registers
-	      == (gdbarch_num_regs (gdbarch)
-		  + gdbarch_num_pseudo_regs (gdbarch)));
+	    if (p == NULL)
+	      p = "";
+	    else if (p[0] == '\0')
+	      p = "''";
+	    fprintf_unfiltered (file, " %-10s", p);
+	  }
 
-  for (regnum = -1; regnum < m_descr->nr_cooked_registers; regnum++)
-    {
-      /* Name.  */
-      if (regnum < 0)
-	fprintf_unfiltered (file, " %-10s", "Name");
-      else
-	{
-	  const char *p = gdbarch_register_name (gdbarch, regnum);
+	/* Number.  */
+	if (regnum < 0)
+	  fprintf_unfiltered (file, " %4s", "Nr");
+	else
+	  fprintf_unfiltered (file, " %4d", regnum);
 
-	  if (p == NULL)
-	    p = "";
-	  else if (p[0] == '\0')
-	    p = "''";
-	  fprintf_unfiltered (file, " %-10s", p);
-	}
+	/* Relative number.  */
+	if (regnum < 0)
+	  fprintf_unfiltered (file, " %4s", "Rel");
+	else if (regnum < gdbarch_num_regs (m_gdbarch))
+	  fprintf_unfiltered (file, " %4d", regnum);
+	else
+	  fprintf_unfiltered (file, " %4d",
+			      (regnum - gdbarch_num_regs (m_gdbarch)));
 
-      /* Number.  */
-      if (regnum < 0)
-	fprintf_unfiltered (file, " %4s", "Nr");
-      else
-	fprintf_unfiltered (file, " %4d", regnum);
+	/* Offset.  */
+	if (regnum < 0)
+	  fprintf_unfiltered (file, " %6s  ", "Offset");
+	else
+	  {
+	    fprintf_unfiltered (file, " %6ld",
+				descr->register_offset[regnum]);
+	    if (register_offset != descr->register_offset[regnum]
+		|| (regnum > 0
+		    && (descr->register_offset[regnum]
+			!= (descr->register_offset[regnum - 1]
+			    + descr->sizeof_register[regnum - 1])))
+		)
+	      {
+		if (!footnote_register_offset)
+		  footnote_register_offset = ++footnote_nr;
+		fprintf_unfiltered (file, "*%d", footnote_register_offset);
+	      }
+	    else
+	      fprintf_unfiltered (file, "  ");
+	    register_offset = (descr->register_offset[regnum]
+			       + descr->sizeof_register[regnum]);
+	  }
 
-      /* Relative number.  */
-      if (regnum < 0)
-	fprintf_unfiltered (file, " %4s", "Rel");
-      else if (regnum < gdbarch_num_regs (gdbarch))
-	fprintf_unfiltered (file, " %4d", regnum);
-      else
-	fprintf_unfiltered (file, " %4d",
-			    (regnum - gdbarch_num_regs (gdbarch)));
+	/* Size.  */
+	if (regnum < 0)
+	  fprintf_unfiltered (file, " %5s ", "Size");
+	else
+	  fprintf_unfiltered (file, " %5ld", descr->sizeof_register[regnum]);
 
-      /* Offset.  */
-      if (regnum < 0)
-	fprintf_unfiltered (file, " %6s  ", "Offset");
-      else
+	/* Type.  */
 	{
-	  fprintf_unfiltered (file, " %6ld",
-			      m_descr->register_offset[regnum]);
-	  if (register_offset != m_descr->register_offset[regnum]
-	      || (regnum > 0
-		  && (m_descr->register_offset[regnum]
-		      != (m_descr->register_offset[regnum - 1]
-			  + m_descr->sizeof_register[regnum - 1])))
-	      )
+	  const char *t;
+	  std::string name_holder;
+
+	  if (regnum < 0)
+	    t = "Type";
+	  else
 	    {
-	      if (!footnote_register_offset)
-		footnote_register_offset = ++footnote_nr;
-	      fprintf_unfiltered (file, "*%d", footnote_register_offset);
+	      static const char blt[] = "builtin_type";
+
+	      t = TYPE_NAME (register_type (m_gdbarch, regnum));
+	      if (t == NULL)
+		{
+		  if (!footnote_register_type_name_null)
+		    footnote_register_type_name_null = ++footnote_nr;
+		  name_holder = string_printf ("*%d",
+					       footnote_register_type_name_null);
+		  t = name_holder.c_str ();
+		}
+	      /* Chop a leading builtin_type.  */
+	      if (startswith (t, blt))
+		t += strlen (blt);
 	    }
-	  else
-	    fprintf_unfiltered (file, "  ");
-	  register_offset = (m_descr->register_offset[regnum]
-			     + m_descr->sizeof_register[regnum]);
+	  fprintf_unfiltered (file, " %-15s", t);
 	}
 
-      /* Size.  */
-      if (regnum < 0)
-	fprintf_unfiltered (file, " %5s ", "Size");
-      else
-	fprintf_unfiltered (file, " %5ld", m_descr->sizeof_register[regnum]);
+	/* Leading space always present.  */
+	fprintf_unfiltered (file, " ");
 
-      /* Type.  */
-      {
-	const char *t;
-	std::string name_holder;
+	dump_reg (file, regnum);
 
-	if (regnum < 0)
-	  t = "Type";
+	fprintf_unfiltered (file, "\n");
+      }
+
+    if (footnote_register_offset)
+      fprintf_unfiltered (file, "*%d: Inconsistent register offsets.\n",
+			  footnote_register_offset);
+    if (footnote_register_type_name_null)
+      fprintf_unfiltered (file,
+			  "*%d: Register type's name NULL.\n",
+			  footnote_register_type_name_null);
+  }
+
+  virtual ~register_dump () {};
+
+protected:
+  register_dump (gdbarch *arch)
+    : m_gdbarch (arch)
+  {}
+
+  /* Dump the register REGNUM contents.  If REGNUM is -1, print the
+     header.  */
+  virtual void dump_reg (ui_file *file, int regnum) = 0;
+
+  gdbarch *m_gdbarch;
+};
+
+/* Dump registers from regcache, used for dump raw registers and
+   cooked registers.  */
+
+class register_dump_regcache : public register_dump
+{
+public:
+  register_dump_regcache (regcache *regcache, bool dump_pseudo)
+    : register_dump (regcache->arch ()), m_regcache (regcache),
+      m_dump_pseudo (dump_pseudo)
+  {
+  }
+
+protected:
+  void dump_reg (ui_file *file, int regnum) override
+  {
+    if (regnum < 0)
+      {
+	if (m_dump_pseudo)
+	  fprintf_unfiltered (file, "Cooked value");
 	else
+	  fprintf_unfiltered (file, "Raw value");
+      }
+    else
+      {
+	if (regnum < gdbarch_num_regs (m_gdbarch) || m_dump_pseudo)
 	  {
-	    static const char blt[] = "builtin_type";
+	    auto size = register_size (m_gdbarch, regnum);
+
+	    if (size == 0)
+	      return;
 
-	    t = TYPE_NAME (register_type (arch (), regnum));
-	    if (t == NULL)
+	    gdb::def_vector<gdb_byte> buf (size);
+	    auto status = m_regcache->cooked_read (regnum, buf.data ());
+
+	    if (status == REG_UNKNOWN)
+	      fprintf_unfiltered (file, "<invalid>");
+	    else if (status == REG_UNAVAILABLE)
+	      fprintf_unfiltered (file, "<unavailable>");
+	    else
 	      {
-		if (!footnote_register_type_name_null)
-		  footnote_register_type_name_null = ++footnote_nr;
-		name_holder = string_printf ("*%d",
-					     footnote_register_type_name_null);
-		t = name_holder.c_str ();
+		print_hex_chars (file, buf.data (), size,
+				 gdbarch_byte_order (m_gdbarch), true);
 	      }
-	    /* Chop a leading builtin_type.  */
-	    if (startswith (t, blt))
-	      t += strlen (blt);
 	  }
-	fprintf_unfiltered (file, " %-15s", t);
+	else
+	  {
+	    /* Just print "<cooked>" for pseudo register when
+	       regcache_dump_raw.  */
+	    fprintf_unfiltered (file, "<cooked>");
+	  }
       }
+  }
 
-      /* Leading space always present.  */
-      fprintf_unfiltered (file, " ");
+private:
+  regcache *m_regcache;
 
-      /* Value, raw.  */
-      if (what_to_dump == regcache_dump_raw)
-	{
-	  if (regnum < 0)
-	    fprintf_unfiltered (file, "Raw value");
-	  else if (regnum >= num_raw_registers ())
-	    fprintf_unfiltered (file, "<cooked>");
-	  else if (get_register_status (regnum) == REG_UNKNOWN)
-	    fprintf_unfiltered (file, "<invalid>");
-	  else if (get_register_status (regnum) == REG_UNAVAILABLE)
-	    fprintf_unfiltered (file, "<unavailable>");
-	  else
-	    {
-	      raw_update (regnum);
-	      print_hex_chars (file, register_buffer (regnum),
-			       m_descr->sizeof_register[regnum],
-			       gdbarch_byte_order (gdbarch), true);
-	    }
-	}
+  /* Dump pseudo registers or not.  */
+  const bool m_dump_pseudo;
+};
 
-      /* Value, cooked.  */
-      if (what_to_dump == regcache_dump_cooked)
-	{
-	  if (regnum < 0)
-	    fprintf_unfiltered (file, "Cooked value");
-	  else
-	    {
-	      const gdb_byte *buf = NULL;
-	      enum register_status status;
-	      struct value *value = NULL;
+/* For "maint print registers".  */
 
-	      if (regnum < num_raw_registers ())
-		{
-		  raw_update (regnum);
-		  status = get_register_status (regnum);
-		  buf = register_buffer (regnum);
-		}
-	      else
-		{
-		  value = cooked_read_value (regnum);
-
-		  if (!value_optimized_out (value)
-		      && value_entirely_available (value))
-		    {
-		      status = REG_VALID;
-		      buf = value_contents_all (value);
-		    }
-		  else
-		    status = REG_UNAVAILABLE;
-		}
+class register_dump_none : public register_dump
+{
+public:
+  register_dump_none (gdbarch *arch)
+    : register_dump (arch)
+  {}
 
-	      if (status == REG_UNKNOWN)
-		fprintf_unfiltered (file, "<invalid>");
-	      else if (status == REG_UNAVAILABLE)
-		fprintf_unfiltered (file, "<unavailable>");
-	      else
-		print_hex_chars (file, buf,
-				 m_descr->sizeof_register[regnum],
-				 gdbarch_byte_order (gdbarch), true);
+protected:
+  void dump_reg (ui_file *file, int regnum) override
+  {}
+};
 
-	      if (value != NULL)
-		{
-		  release_value (value);
-		  value_free (value);
-		}
-	    }
-	}
+/* For "maint print remote-registers".  */
 
-      /* Group members.  */
-      if (what_to_dump == regcache_dump_groups)
-	{
-	  if (regnum < 0)
-	    fprintf_unfiltered (file, "Groups");
-	  else
-	    {
-	      const char *sep = "";
-	      struct reggroup *group;
+class register_dump_remote : public register_dump
+{
+public:
+  register_dump_remote (gdbarch *arch)
+    : register_dump (arch)
+  {}
 
-	      for (group = reggroup_next (gdbarch, NULL);
-		   group != NULL;
-		   group = reggroup_next (gdbarch, group))
-		{
-		  if (gdbarch_register_reggroup_p (gdbarch, regnum, group))
-		    {
-		      fprintf_unfiltered (file,
-					  "%s%s", sep, reggroup_name (group));
-		      sep = ",";
-		    }
-		}
-	    }
-	}
+protected:
+  void dump_reg (ui_file *file, int regnum) override
+  {
+    if (regnum < 0)
+      {
+	fprintf_unfiltered (file, "Rmt Nr  g/G Offset");
+      }
+    else if (regnum < gdbarch_num_regs (m_gdbarch))
+      {
+	int pnum, poffset;
 
-      /* Remote packet configuration.  */
-      if (what_to_dump == regcache_dump_remote)
-	{
-	  if (regnum < 0)
-	    {
-	      fprintf_unfiltered (file, "Rmt Nr  g/G Offset");
-	    }
-	  else if (regnum < num_raw_registers ())
-	    {
-	      int pnum, poffset;
+	if (remote_register_number_and_offset (m_gdbarch, regnum,
+					       &pnum, &poffset))
+	  fprintf_unfiltered (file, "%7d %11d", pnum, poffset);
+      }
+  }
+};
 
-	      if (remote_register_number_and_offset (arch (), regnum,
-						     &pnum, &poffset))
-		fprintf_unfiltered (file, "%7d %11d", pnum, poffset);
-	    }
-	}
+/* For "maint print register-groups".  */
 
-      fprintf_unfiltered (file, "\n");
-    }
+class register_dump_groups : public register_dump
+{
+public:
+  register_dump_groups (gdbarch *arch)
+    : register_dump (arch)
+  {}
 
-  if (footnote_register_offset)
-    fprintf_unfiltered (file, "*%d: Inconsistent register offsets.\n",
-			footnote_register_offset);
-  if (footnote_register_type_name_null)
-    fprintf_unfiltered (file, 
-			"*%d: Register type's name NULL.\n",
-			footnote_register_type_name_null);
-}
+protected:
+  void dump_reg (ui_file *file, int regnum) override
+  {
+    if (regnum < 0)
+      fprintf_unfiltered (file, "Groups");
+    else
+      {
+	const char *sep = "";
+	struct reggroup *group;
+
+	for (group = reggroup_next (m_gdbarch, NULL);
+	     group != NULL;
+	     group = reggroup_next (m_gdbarch, group))
+	  {
+	    if (gdbarch_register_reggroup_p (m_gdbarch, regnum, group))
+	      {
+		fprintf_unfiltered (file,
+				    "%s%s", sep, reggroup_name (group));
+		sep = ",";
+	      }
+	  }
+      }
+  }
+};
+
+enum regcache_dump_what
+{
+  regcache_dump_none, regcache_dump_raw,
+  regcache_dump_cooked, regcache_dump_groups,
+  regcache_dump_remote
+};
 
 static void
 regcache_print (const char *args, enum regcache_dump_what what_to_dump)
@@ -1557,16 +1610,50 @@ regcache_print (const char *args, enum regcache_dump_what what_to_dump)
       out = &file;
     }
 
+  std::unique_ptr<register_dump> dump;
+  std::unique_ptr<regcache> regs;
+  gdbarch *gdbarch;
+
   if (target_has_registers)
-    get_current_regcache ()->dump (out, what_to_dump);
+    gdbarch = get_current_regcache ()->arch ();
   else
+    gdbarch = target_gdbarch ();
+
+  switch (what_to_dump)
     {
-      /* For the benefit of "maint print registers" & co when
-	 debugging an executable, allow dumping a regcache even when
-	 there is no thread selected / no registers.  */
-      regcache dummy_regs (target_gdbarch ());
-      dummy_regs.dump (out, what_to_dump);
+    case regcache_dump_none:
+      dump.reset (new register_dump_none (gdbarch));
+      break;
+    case regcache_dump_remote:
+      dump.reset (new register_dump_remote (gdbarch));
+      break;
+    case regcache_dump_groups:
+      dump.reset (new register_dump_groups (gdbarch));
+      break;
+    case regcache_dump_raw:
+    case regcache_dump_cooked:
+      {
+	regcache *reg;
+
+	if (target_has_registers)
+	  reg = get_current_regcache ();
+	else
+	  {
+	    /* For the benefit of "maint print registers" & co when
+	       debugging an executable, allow dumping a regcache even when
+	       there is no thread selected / no registers.  */
+	    reg = new regcache (target_gdbarch ());
+	    regs.reset (reg);
+	  }
+
+	auto dump_pseudo = (what_to_dump == regcache_dump_cooked);
+
+	dump.reset (new register_dump_regcache (reg, dump_pseudo));
+      }
+      break;
     }
+
+  dump->dump (out);
 }
 
 static void
diff --git a/gdb/regcache.h b/gdb/regcache.h
index 3de5d80..5c0850d 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -194,13 +194,6 @@ typedef enum register_status (regcache_cooked_read_ftype) (void *src,
 							   int regnum,
 							   gdb_byte *buf);
 
-enum regcache_dump_what
-{
-  regcache_dump_none, regcache_dump_raw,
-  regcache_dump_cooked, regcache_dump_groups,
-  regcache_dump_remote
-};
-
 /* A (register_number, register_value) pair.  */
 
 typedef struct cached_reg
@@ -372,8 +365,6 @@ public:
   void collect_regset (const struct regset *regset, int regnum,
 		       void *buf, size_t size) const;
 
-  void dump (ui_file *file, enum regcache_dump_what what_to_dump);
-
   ptid_t ptid () const
   {
     return m_ptid;
-- 
1.9.1

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

* [PATCH 06/15] regcache::cooked_write test
  2017-12-01 10:48 [RFC 00/15] Remove regcache::m_readonly_p Yao Qi
                   ` (10 preceding siblings ...)
  2017-12-01 10:48 ` [PATCH 11/15] Class reg_buffer_rw Yao Qi
@ 2017-12-01 10:48 ` Yao Qi
  2018-01-18 16:13   ` Simon Marchi
  2017-12-01 10:48 ` [PATCH 12/15] Replace regcache::dump with class register_dump Yao Qi
                   ` (3 subsequent siblings)
  15 siblings, 1 reply; 32+ messages in thread
From: Yao Qi @ 2017-12-01 10:48 UTC (permalink / raw)
  To: gdb-patches

Since my following patches will change how each gdbarch read and write
pseudo registers, it's better to write a unit test to
regcache::cooked_write, to make sure my following changes don't cause
any regressions.  See the comments on cooked_write_test.

gdb:

2017-11-27  Yao Qi  <yao.qi@linaro.org>

	* regcache.c (cooked_write_test): New function.
	(_initialize_regcache): Register the test.
---
 gdb/regcache.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 124 insertions(+)

diff --git a/gdb/regcache.c b/gdb/regcache.c
index a7a4683..4577913 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -1609,6 +1609,7 @@ maintenance_print_remote_registers (const char *args, int from_tty)
 #include "selftest.h"
 #include "selftest-arch.h"
 #include "gdbthread.h"
+#include "target-float.h"
 
 namespace selftests {
 
@@ -1926,6 +1927,127 @@ cooked_read_test (struct gdbarch *gdbarch)
     }
 }
 
+/* Test regcache::cooked_write by writing some expected contents to
+   registers, and checking that contents red from registers and the
+   expected contents are the same.  */
+
+static void
+cooked_write_test (struct gdbarch *gdbarch)
+{
+  /* Error out if debugging something, because we're going to push the
+     test target, which would pop any existing target.  */
+  if (current_target.to_stratum >= process_stratum)
+    error (_("target already pushed"));
+
+  /* Create a mock environment.  A process_stratum target pushed.  */
+
+  target_ops_no_register mock_target;
+
+  /* Push the process_stratum target so we can mock accessing
+     registers.  */
+  push_target (&mock_target);
+
+  /* Pop it again on exit (return/exception).  */
+  struct on_exit
+  {
+    ~on_exit ()
+    {
+      pop_all_targets_at_and_above (process_stratum);
+    }
+  } pop_targets;
+
+  readwrite_regcache readwrite (gdbarch);
+
+  const int num_regs = (gdbarch_num_regs (gdbarch)
+			+ gdbarch_num_pseudo_regs (gdbarch));
+
+  for (auto regnum = 0; regnum < num_regs; regnum++)
+    {
+      if (register_size (gdbarch, regnum) == 0
+	  || gdbarch_cannot_store_register (gdbarch, regnum))
+	continue;
+
+      auto bfd_arch = gdbarch_bfd_arch_info (gdbarch)->arch;
+
+      if ((bfd_arch == bfd_arch_sparc
+	   /* SPARC64_CWP_REGNUM, SPARC64_PSTATE_REGNUM,
+	      SPARC64_ASI_REGNUM and SPARC64_CCR_REGNUM are hard to test.  */
+	   && gdbarch_ptr_bit (gdbarch) == 64
+	   && (regnum >= gdbarch_num_regs (gdbarch)
+	       && regnum <= gdbarch_num_regs (gdbarch) + 4))
+	  || (bfd_arch == bfd_arch_sh
+	      /* FPSCR_C_REGNUM in sh64 is hard to test.  */
+	      && gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_sh5
+	      && regnum == 243)
+	  || (bfd_arch == bfd_arch_spu
+	      /* SPU pseudo registers except SPU_SP_REGNUM are got by
+		 TARGET_OBJECT_SPU.  */
+	      && regnum >= gdbarch_num_regs (gdbarch) && regnum != 130))
+	continue;
+
+      std::vector<gdb_byte> expected (register_size (gdbarch, regnum), 0);
+      std::vector<gdb_byte> buf (register_size (gdbarch, regnum), 0);
+      const auto type = register_type (gdbarch, regnum);
+
+      if (TYPE_CODE (type) == TYPE_CODE_FLT
+	  || TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
+	{
+	  /* Generate valid float format.  */
+	  target_float_from_string (expected.data (), type, "1.25");
+	}
+      else if (TYPE_CODE (type) == TYPE_CODE_INT
+	       || TYPE_CODE (type) == TYPE_CODE_ARRAY
+	       || TYPE_CODE (type) == TYPE_CODE_PTR
+	       || TYPE_CODE (type) == TYPE_CODE_UNION
+	       || TYPE_CODE (type) == TYPE_CODE_STRUCT)
+	{
+	  if (bfd_arch == bfd_arch_ia64
+	      || (regnum >= gdbarch_num_regs (gdbarch)
+		  && (bfd_arch == bfd_arch_xtensa
+		      || bfd_arch == bfd_arch_bfin
+		      || bfd_arch == bfd_arch_m32c
+		      /* m68hc11 pseudo registers are in memory.  */
+		      || bfd_arch == bfd_arch_m68hc11
+		      || bfd_arch == bfd_arch_m68hc12
+		      || bfd_arch == bfd_arch_s390))
+	      || (bfd_arch == bfd_arch_frv
+		  /* FRV pseudo registers except iacc0.  */
+		  && regnum > gdbarch_num_regs (gdbarch)))
+	    {
+	      /* Skip setting the expected values for some architecture
+		 registers.  */
+	    }
+	  else if (bfd_arch == bfd_arch_rl78 && regnum == 40)
+	    {
+	      /* RL78_PC_REGNUM */
+	      for (auto j = 0; j < register_size (gdbarch, regnum) - 1; j++)
+		expected[j] = j;
+	    }
+	  else
+	    {
+	      for (auto j = 0; j < register_size (gdbarch, regnum); j++)
+		expected[j] = j;
+	    }
+	}
+      else if (TYPE_CODE (type) == TYPE_CODE_FLAGS)
+	{
+	  /* No idea how to test flags.  */
+	  continue;
+	}
+      else
+	{
+	  /* If we don't know how to create the expected value for the
+	     this type, make it fail.  */
+	  SELF_CHECK (0);
+	}
+
+      readwrite.cooked_write (regnum, expected.data ());
+
+      SELF_CHECK (readwrite.cooked_read (regnum, buf.data ()) == REG_VALID);
+      SELF_CHECK (expected == buf);
+    }
+}
+
 } // namespace selftests
 #endif /* GDB_SELF_TEST */
 
@@ -1972,5 +2094,7 @@ Takes an optional file parameter."),
 
   selftests::register_test_foreach_arch ("regcache::cooked_read_test",
 					 selftests::cooked_read_test);
+  selftests::register_test_foreach_arch ("regcache::cooked_write_test",
+					 selftests::cooked_write_test);
 #endif
 }
-- 
1.9.1

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

* [PATCH 11/15] Class reg_buffer_rw
  2017-12-01 10:48 [RFC 00/15] Remove regcache::m_readonly_p Yao Qi
                   ` (9 preceding siblings ...)
  2017-12-01 10:48 ` [PATCH 14/15] Remove regcache::m_readonly_p Yao Qi
@ 2017-12-01 10:48 ` Yao Qi
  2017-12-01 10:48 ` [PATCH 06/15] regcache::cooked_write test Yao Qi
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 32+ messages in thread
From: Yao Qi @ 2017-12-01 10:48 UTC (permalink / raw)
  To: gdb-patches

jit.c uses the regcache in a slightly different way, the regcache dosn't
write through to target, but it has read and write methods.  If I apply
regcache in record-full.c, it has the similar use pattern.  This patch
adds a new class reg_buffer_rw, which is a register buffer, but can be
red and written.

Since jit.c doesn't want to write registers through to target, it uses
regcache as a readonly regcache (because only readonly regcache
disconnects from the target), but it adds a hole in regcache
(raw_set_cached_value) in order to modify a readonly regcache.  This patch
fixes this hole completely.

regcache inherits reg_buffer_rw, and reg_buffer_rw inherits regcache_read.
The ideal design is that both reg_buffer_rw and regcache_read inherit
reg_buffer, and regcache inherit reg_buffer_rw and regcache_read (virtual
inheritance).  I concern about the performance overhead of virtual
inheritance, so I don't do it in the patch.

gdb:

2017-11-28  Yao Qi  <yao.qi@linaro.org>

	* jit.c (struct jit_unwind_private) <regcache>: Change its type to
	 reg_buffer_rw *.
	(jit_unwind_reg_set_impl): Call raw_supply.
	(jit_frame_sniffer): Use reg_buffer_rw.
	* record-full.c (record_full_core_regbuf): Change its type.
	(record_full_core_open_1): Use reg_buffer_rw.
	(record_full_close): Likewise.
	(record_full_core_fetch_registers): Use regcache->raw_supply.
	(record_full_core_store_registers): Likewise.
	* regcache.c (regcache::get_register_status): Move it to
	reg_buffer.
	(regcache_raw_set_cached_value): Remove.
	(regcache::raw_set_cached_value): Remove.
	(regcache::raw_write): Call raw_supply.
	(regcache::raw_supply): Move it to reg_buffer_rw.
	* regcache.h (regcache_raw_set_cached_value): Remove.
	(reg_buffer_rw): New class.
---
 gdb/jit.c         | 10 ++++------
 gdb/record-full.c | 21 +++++++++------------
 gdb/regcache.c    | 32 +++++---------------------------
 gdb/regcache.h    | 42 ++++++++++++++++++++++++++----------------
 4 files changed, 44 insertions(+), 61 deletions(-)

diff --git a/gdb/jit.c b/gdb/jit.c
index 36aaefc..602aec9 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -1097,7 +1097,7 @@ struct jit_unwind_private
 {
   /* Cached register values.  See jit_frame_sniffer to see how this
      works.  */
-  struct regcache *regcache;
+  reg_buffer_rw *regcache;
 
   /* The frame being unwound.  */
   struct frame_info *this_frame;
@@ -1126,7 +1126,7 @@ jit_unwind_reg_set_impl (struct gdb_unwind_callbacks *cb, int dwarf_regnum,
       return;
     }
 
-  regcache_raw_set_cached_value (priv->regcache, gdb_reg, value->value);
+  priv->regcache->raw_supply (gdb_reg, value->value);
   value->free (value);
 }
 
@@ -1188,7 +1188,6 @@ jit_frame_sniffer (const struct frame_unwind *self,
   struct jit_unwind_private *priv_data;
   struct gdb_unwind_callbacks callbacks;
   struct gdb_reader_funcs *funcs;
-  struct gdbarch *gdbarch;
 
   callbacks.reg_get = jit_unwind_reg_get_impl;
   callbacks.reg_set = jit_unwind_reg_set_impl;
@@ -1201,11 +1200,10 @@ jit_frame_sniffer (const struct frame_unwind *self,
 
   gdb_assert (!*cache);
 
-  gdbarch = get_frame_arch (this_frame);
-
   *cache = XCNEW (struct jit_unwind_private);
   priv_data = (struct jit_unwind_private *) *cache;
-  priv_data->regcache = new regcache (gdbarch);
+  /* Take a snapshot of current regcache.  */
+  priv_data->regcache = new reg_buffer_rw (get_frame_arch (this_frame), true);
   priv_data->this_frame = this_frame;
 
   callbacks.priv_data = priv_data;
diff --git a/gdb/record-full.c b/gdb/record-full.c
index ec6fc69..65a2bfb 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -168,7 +168,7 @@ struct record_full_core_buf_entry
 };
 
 /* Record buf with core target.  */
-static gdb_byte *record_full_core_regbuf = NULL;
+static reg_buffer_rw *record_full_core_regbuf = NULL;
 static struct target_section *record_full_core_start;
 static struct target_section *record_full_core_end;
 static struct record_full_core_buf_entry *record_full_core_buf_list = NULL;
@@ -780,16 +780,16 @@ record_full_core_open_1 (const char *name, int from_tty)
 
   /* Get record_full_core_regbuf.  */
   target_fetch_registers (regcache, -1);
-  record_full_core_regbuf = (gdb_byte *) xmalloc (MAX_REGISTER_SIZE * regnum);
+  record_full_core_regbuf = new reg_buffer_rw (regcache->arch (), false);
+
   for (i = 0; i < regnum; i ++)
-    regcache_raw_collect (regcache, i,
-			  record_full_core_regbuf + MAX_REGISTER_SIZE * i);
+    record_full_core_regbuf->raw_supply (i, *regcache);
 
   /* Get record_full_core_start and record_full_core_end.  */
   if (build_section_table (core_bfd, &record_full_core_start,
 			   &record_full_core_end))
     {
-      xfree (record_full_core_regbuf);
+      delete record_full_core_regbuf;
       record_full_core_regbuf = NULL;
       error (_("\"%s\": Can't find sections: %s"),
 	     bfd_get_filename (core_bfd), bfd_errmsg (bfd_get_error ()));
@@ -871,7 +871,7 @@ record_full_close (struct target_ops *self)
   /* Release record_full_core_regbuf.  */
   if (record_full_core_regbuf)
     {
-      xfree (record_full_core_regbuf);
+      delete record_full_core_regbuf;
       record_full_core_regbuf = NULL;
     }
 
@@ -2032,12 +2032,10 @@ record_full_core_fetch_registers (struct target_ops *ops,
       int i;
 
       for (i = 0; i < num; i ++)
-        regcache_raw_supply (regcache, i,
-                             record_full_core_regbuf + MAX_REGISTER_SIZE * i);
+	regcache->raw_supply (i, *record_full_core_regbuf);
     }
   else
-    regcache_raw_supply (regcache, regno,
-                         record_full_core_regbuf + MAX_REGISTER_SIZE * regno);
+    regcache->raw_supply (regno, *record_full_core_regbuf);
 }
 
 /* "to_prepare_to_store" method for prec over corefile.  */
@@ -2056,8 +2054,7 @@ record_full_core_store_registers (struct target_ops *ops,
                              int regno)
 {
   if (record_full_gdb_operation_disable)
-    regcache_raw_collect (regcache, regno,
-                          record_full_core_regbuf + MAX_REGISTER_SIZE * regno);
+    record_full_core_regbuf->raw_supply (regno, *regcache);
   else
     error (_("You can't do that without a process to debug."));
 }
diff --git a/gdb/regcache.c b/gdb/regcache.c
index 4174a8c..9b5b02e 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -205,7 +205,7 @@ regcache::regcache (gdbarch *gdbarch, const address_space *aspace_,
 /* The register buffers.  A read-only register cache can hold the
    full [0 .. gdbarch_num_regs + gdbarch_num_pseudo_regs) while a
    read/write register cache can only hold [0 .. gdbarch_num_regs).  */
-  : regcache_read (gdbarch, readonly_p_),
+  : reg_buffer_rw (gdbarch, readonly_p_),
     m_aspace (aspace_), m_readonly_p (readonly_p_)
 {
   m_ptid = minus_one_ptid;
@@ -353,13 +353,9 @@ regcache_register_status (const struct regcache *regcache, int regnum)
 }
 
 enum register_status
-regcache::get_register_status (int regnum) const
+reg_buffer::get_register_status (int regnum) const
 {
-  gdb_assert (regnum >= 0);
-  if (m_readonly_p)
-    gdb_assert (regnum < m_descr->nr_cooked_registers);
-  else
-    gdb_assert (regnum < num_raw_registers ());
+  assert_regnum (regnum);
 
   return (enum register_status) m_register_status[regnum];
 }
@@ -802,23 +798,6 @@ regcache_cooked_write_unsigned (struct regcache *regcache, int regnum,
   regcache->cooked_write (regnum, val);
 }
 
-/* See regcache.h.  */
-
-void
-regcache_raw_set_cached_value (struct regcache *regcache, int regnum,
-			       const gdb_byte *buf)
-{
-  regcache->raw_set_cached_value (regnum, buf);
-}
-
-void
-regcache::raw_set_cached_value (int regnum, const gdb_byte *buf)
-{
-  memcpy (register_buffer (regnum), buf,
-	  m_descr->sizeof_register[regnum]);
-  m_register_status[regnum] = REG_VALID;
-}
-
 void
 regcache_raw_write (struct regcache *regcache, int regnum,
 		    const gdb_byte *buf)
@@ -848,7 +827,7 @@ regcache::raw_write (int regnum, const gdb_byte *buf)
     return;
 
   target_prepare_to_store (this);
-  raw_set_cached_value (regnum, buf);
+  raw_supply (regnum, buf);
 
   /* Invalidate the register after it is written, in case of a
      failure.  */
@@ -1024,13 +1003,12 @@ regcache_raw_supply (struct regcache *regcache, int regnum, const void *buf)
 }
 
 void
-regcache::raw_supply (int regnum, const void *buf)
+reg_buffer_rw::raw_supply (int regnum, const void *buf)
 {
   void *regbuf;
   size_t size;
 
   assert_regnum (regnum);
-  gdb_assert (!m_readonly_p);
 
   regbuf = register_buffer (regnum);
   size = m_descr->sizeof_register[regnum];
diff --git a/gdb/regcache.h b/gdb/regcache.h
index bd91bc6..3de5d80 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -68,14 +68,6 @@ extern void regcache_raw_write_unsigned (struct regcache *regcache,
 extern LONGEST regcache_raw_get_signed (struct regcache *regcache,
 					int regnum);
 
-/* Set a raw register's value in the regcache's buffer.  Unlike
-   regcache_raw_write, this is not write-through.  The intention is
-   allowing to change the buffer contents of a read-only regcache
-   allocated with new.  */
-
-extern void regcache_raw_set_cached_value
-  (struct regcache *regcache, int regnum, const gdb_byte *buf);
-
 /* Partial transfer of raw registers.  These perform read, modify,
    write style operations.  The read variant returns the status of the
    register.  */
@@ -229,12 +221,13 @@ public:
   /* Return regcache's architecture.  */
   gdbarch *arch () const;
 
+  enum register_status get_register_status (int regnum) const;
+
   virtual ~reg_buffer ()
   {
     xfree (m_registers);
     xfree (m_register_status);
   }
-
 protected:
   /* Assert on the range of REGNUM.  */
   void assert_regnum (int regnum) const;
@@ -257,6 +250,7 @@ protected:
   signed char *m_register_status;
 
   friend class regcache;
+  friend class reg_buffer_rw;
 };
 
 class regcache_read : public reg_buffer
@@ -289,11 +283,33 @@ protected:
 				  bool is_raw);
 };
 
+/* Buffer of registers, can be red and written.  */
+
+class reg_buffer_rw : public regcache_read
+{
+public:
+  reg_buffer_rw (gdbarch *gdbarch, bool has_pseudo)
+    : regcache_read (gdbarch, has_pseudo)
+  {}
+
+  void raw_supply (int regnum, const void *buf);
+
+  void raw_supply (int regnum, const reg_buffer &src)
+  {
+    raw_supply (regnum, src.register_buffer (regnum));
+  }
+
+  void raw_update (int regnum) override
+  {}
+
+  DISABLE_COPY_AND_ASSIGN (reg_buffer_rw);
+};
+
 class regcache_readonly;
 
 /* The register cache for storing raw register values.  */
 
-class regcache : public regcache_read
+class regcache : public reg_buffer_rw
 {
 public:
   regcache (gdbarch *gdbarch)
@@ -337,17 +353,11 @@ public:
   void raw_collect_integer (int regnum, gdb_byte *addr, int addr_len,
 			    bool is_signed) const;
 
-  void raw_supply (int regnum, const void *buf);
-
   void raw_supply_integer (int regnum, const gdb_byte *addr, int addr_len,
 			   bool is_signed);
 
   void raw_supply_zeroed (int regnum);
 
-  enum register_status get_register_status (int regnum) const;
-
-  void raw_set_cached_value (int regnum, const gdb_byte *buf);
-
   void invalidate (int regnum);
 
   void raw_write_part (int regnum, int offset, int len, const gdb_byte *buf);
-- 
1.9.1

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

* [PATCH 15/15] Move register_dump to regcache-dump.c
  2017-12-01 10:48 [RFC 00/15] Remove regcache::m_readonly_p Yao Qi
                   ` (2 preceding siblings ...)
  2017-12-01 10:48 ` [PATCH 04/15] Replace regcache_raw_read with regcache->raw_read Yao Qi
@ 2017-12-01 10:48 ` Yao Qi
  2017-12-01 10:48 ` [PATCH 08/15] class regcache_read and Pass regcache_read to gdbarch methods Yao Qi
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 32+ messages in thread
From: Yao Qi @ 2017-12-01 10:48 UTC (permalink / raw)
  To: gdb-patches

gdb:

2017-11-30  Yao Qi  <yao.qi@linaro.org>

	* Makefile.in (SFILES): Add regcache-dump.c
	(COMMON_OBS): Add regcache-dump.o.
	* regcache-dump.c: New file.
	* regcache.c: Move register_dump to regcache-dump.c.
	(maintenance_print_registers): Likewise.
	(maintenance_print_raw_registers): Likewise.
	(maintenance_print_cooked_registers): Likewise.
	(maintenance_print_register_groups): Likewise.
	(maintenance_print_remote_registers): Likewise.
	(_initialize_regcache): Likewise.
	* regcache.h (register_dump): Moved from regcache.c.
---
 gdb/Makefile.in     |   2 +
 gdb/regcache-dump.c | 335 ++++++++++++++++++++++++++++++++++
 gdb/regcache.c      | 505 +++++++++-------------------------------------------
 gdb/regcache.h      |  20 +++
 4 files changed, 446 insertions(+), 416 deletions(-)
 create mode 100644 gdb/regcache-dump.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 3d90fde..1e59919 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1188,6 +1188,7 @@ SFILES = \
 	record-btrace.c \
 	record-full.c \
 	regcache.c \
+	regcache-dump.c \
 	reggroups.c \
 	remote.c \
 	remote-fileio.c \
@@ -1811,6 +1812,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	record-btrace.o \
 	record-full.o \
 	regcache.o \
+	regcache-dump.o \
 	reggroups.o \
 	registry.o \
 	reverse.o \
diff --git a/gdb/regcache-dump.c b/gdb/regcache-dump.c
new file mode 100644
index 0000000..4780fc4
--- /dev/null
+++ b/gdb/regcache-dump.c
@@ -0,0 +1,335 @@
+/* Copyright (C) 1986-2017 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "gdbcmd.h"
+#include "regcache.h"
+#include "common/def-vector.h"
+#include "valprint.h"
+#include "remote.h"
+#include "reggroups.h"
+#include "target.h"
+
+/* Dump registers from regcache, used for dump raw registers and
+   cooked registers.  */
+
+class register_dump_regcache : public register_dump
+{
+public:
+  register_dump_regcache (regcache *regcache, bool dump_pseudo)
+    : register_dump (regcache->arch ()), m_regcache (regcache),
+      m_dump_pseudo (dump_pseudo)
+  {
+  }
+
+protected:
+  void dump_reg (ui_file *file, int regnum) override
+  {
+    if (regnum < 0)
+      {
+	if (m_dump_pseudo)
+	  fprintf_unfiltered (file, "Cooked value");
+	else
+	  fprintf_unfiltered (file, "Raw value");
+      }
+    else
+      {
+	if (regnum < gdbarch_num_regs (m_gdbarch) || m_dump_pseudo)
+	  {
+	    auto size = register_size (m_gdbarch, regnum);
+
+	    if (size == 0)
+	      return;
+
+	    gdb::def_vector<gdb_byte> buf (size);
+	    auto status = m_regcache->cooked_read (regnum, buf.data ());
+
+	    if (status == REG_UNKNOWN)
+	      fprintf_unfiltered (file, "<invalid>");
+	    else if (status == REG_UNAVAILABLE)
+	      fprintf_unfiltered (file, "<unavailable>");
+	    else
+	      {
+		print_hex_chars (file, buf.data (), size,
+				 gdbarch_byte_order (m_gdbarch), true);
+	      }
+	  }
+	else
+	  {
+	    /* Just print "<cooked>" for pseudo register when
+	       regcache_dump_raw.  */
+	    fprintf_unfiltered (file, "<cooked>");
+	  }
+      }
+  }
+
+private:
+  regcache *m_regcache;
+
+  /* Dump pseudo registers or not.  */
+  const bool m_dump_pseudo;
+};
+
+/* Dump from reg_buffer, used when there is no thread or
+   registers.  */
+
+class register_dump_reg_buffer : public register_dump, reg_buffer
+{
+public:
+  register_dump_reg_buffer (gdbarch *gdbarch, bool dump_pseudo)
+    : register_dump (gdbarch), reg_buffer (gdbarch, dump_pseudo)
+  {
+  }
+
+protected:
+  void dump_reg (ui_file *file, int regnum) override
+  {
+    if (regnum < 0)
+      {
+	if (m_has_pseudo)
+	  fprintf_unfiltered (file, "Cooked value");
+	else
+	  fprintf_unfiltered (file, "Raw value");
+      }
+    else
+      {
+	if (regnum < gdbarch_num_regs (m_gdbarch) || m_has_pseudo)
+	  {
+	    auto size = register_size (m_gdbarch, regnum);
+
+	    if (size == 0)
+	      return;
+
+	    auto status = get_register_status (regnum);
+
+	    gdb_assert (status != REG_VALID);
+
+	    if (status == REG_UNKNOWN)
+	      fprintf_unfiltered (file, "<invalid>");
+	    else
+	      fprintf_unfiltered (file, "<unavailable>");
+	  }
+	else
+	  {
+	    /* Just print "<cooked>" for pseudo register when
+	       regcache_dump_raw.  */
+	    fprintf_unfiltered (file, "<cooked>");
+	  }
+      }
+  }
+};
+
+/* For "maint print registers".  */
+
+class register_dump_none : public register_dump
+{
+public:
+  register_dump_none (gdbarch *arch)
+    : register_dump (arch)
+  {}
+
+protected:
+  void dump_reg (ui_file *file, int regnum) override
+  {}
+};
+
+/* For "maint print remote-registers".  */
+
+class register_dump_remote : public register_dump
+{
+public:
+  register_dump_remote (gdbarch *arch)
+    : register_dump (arch)
+  {}
+
+protected:
+  void dump_reg (ui_file *file, int regnum) override
+  {
+    if (regnum < 0)
+      {
+	fprintf_unfiltered (file, "Rmt Nr  g/G Offset");
+      }
+    else if (regnum < gdbarch_num_regs (m_gdbarch))
+      {
+	int pnum, poffset;
+
+	if (remote_register_number_and_offset (m_gdbarch, regnum,
+					       &pnum, &poffset))
+	  fprintf_unfiltered (file, "%7d %11d", pnum, poffset);
+      }
+  }
+};
+
+/* For "maint print register-groups".  */
+
+class register_dump_groups : public register_dump
+{
+public:
+  register_dump_groups (gdbarch *arch)
+    : register_dump (arch)
+  {}
+
+protected:
+  void dump_reg (ui_file *file, int regnum) override
+  {
+    if (regnum < 0)
+      fprintf_unfiltered (file, "Groups");
+    else
+      {
+	const char *sep = "";
+	struct reggroup *group;
+
+	for (group = reggroup_next (m_gdbarch, NULL);
+	     group != NULL;
+	     group = reggroup_next (m_gdbarch, group))
+	  {
+	    if (gdbarch_register_reggroup_p (m_gdbarch, regnum, group))
+	      {
+		fprintf_unfiltered (file,
+				    "%s%s", sep, reggroup_name (group));
+		sep = ",";
+	      }
+	  }
+      }
+  }
+};
+
+enum regcache_dump_what
+{
+  regcache_dump_none, regcache_dump_raw,
+  regcache_dump_cooked, regcache_dump_groups,
+  regcache_dump_remote
+};
+
+static void
+regcache_print (const char *args, enum regcache_dump_what what_to_dump)
+{
+  /* Where to send output.  */
+  stdio_file file;
+  ui_file *out;
+
+  if (args == NULL)
+    out = gdb_stdout;
+  else
+    {
+      if (!file.open (args, "w"))
+	perror_with_name (_("maintenance print architecture"));
+      out = &file;
+    }
+
+  std::unique_ptr<register_dump> dump;
+  std::unique_ptr<regcache> regs;
+  gdbarch *gdbarch;
+
+  if (target_has_registers)
+    gdbarch = get_current_regcache ()->arch ();
+  else
+    gdbarch = target_gdbarch ();
+
+  switch (what_to_dump)
+    {
+    case regcache_dump_none:
+      dump.reset (new register_dump_none (gdbarch));
+      break;
+    case regcache_dump_remote:
+      dump.reset (new register_dump_remote (gdbarch));
+      break;
+    case regcache_dump_groups:
+      dump.reset (new register_dump_groups (gdbarch));
+      break;
+    case regcache_dump_raw:
+    case regcache_dump_cooked:
+      {
+	auto dump_pseudo = (what_to_dump == regcache_dump_cooked);
+
+	if (target_has_registers)
+	  dump.reset (new register_dump_regcache (get_current_regcache (),
+						  dump_pseudo));
+	else
+	  {
+	    /* For the benefit of "maint print registers" & co when
+	       debugging an executable, allow dumping a regcache even when
+	       there is no thread selected / no registers.  */
+	    dump.reset (new register_dump_reg_buffer (target_gdbarch (),
+						      dump_pseudo));
+	  }
+      }
+      break;
+    }
+
+  dump->dump (out);
+}
+
+static void
+maintenance_print_registers (const char *args, int from_tty)
+{
+  regcache_print (args, regcache_dump_none);
+}
+
+static void
+maintenance_print_raw_registers (const char *args, int from_tty)
+{
+  regcache_print (args, regcache_dump_raw);
+}
+
+static void
+maintenance_print_cooked_registers (const char *args, int from_tty)
+{
+  regcache_print (args, regcache_dump_cooked);
+}
+
+static void
+maintenance_print_register_groups (const char *args, int from_tty)
+{
+  regcache_print (args, regcache_dump_groups);
+}
+
+static void
+maintenance_print_remote_registers (const char *args, int from_tty)
+{
+  regcache_print (args, regcache_dump_remote);
+}
+
+void
+_initialize_regcache_dump (void)
+{
+  add_cmd ("registers", class_maintenance, maintenance_print_registers,
+	   _("Print the internal register configuration.\n"
+	     "Takes an optional file parameter."), &maintenanceprintlist);
+  add_cmd ("raw-registers", class_maintenance,
+	   maintenance_print_raw_registers,
+	   _("Print the internal register configuration "
+	     "including raw values.\n"
+	     "Takes an optional file parameter."), &maintenanceprintlist);
+  add_cmd ("cooked-registers", class_maintenance,
+	   maintenance_print_cooked_registers,
+	   _("Print the internal register configuration "
+	     "including cooked values.\n"
+	     "Takes an optional file parameter."), &maintenanceprintlist);
+  add_cmd ("register-groups", class_maintenance,
+	   maintenance_print_register_groups,
+	   _("Print the internal register configuration "
+	     "including each register's group.\n"
+	     "Takes an optional file parameter."),
+	   &maintenanceprintlist);
+  add_cmd ("remote-registers", class_maintenance,
+	   maintenance_print_remote_registers, _("\
+Print the internal register configuration including each register's\n\
+remote register number and buffer offset in the g/G packets.\n\
+Takes an optional file parameter."),
+	   &maintenanceprintlist);
+}
diff --git a/gdb/regcache.c b/gdb/regcache.c
index 4ea4a5d..653c70e 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -25,8 +25,6 @@
 #include "regcache.h"
 #include "reggroups.h"
 #include "observer.h"
-#include "remote.h"
-#include "valprint.h"
 #include "regset.h"
 #include <forward_list>
 
@@ -1300,421 +1298,122 @@ reg_flush_command (const char *command, int from_tty)
     printf_filtered (_("Register cache flushed.\n"));
 }
 
-/* An abstract base class for register dump.  */
-
-class register_dump
+void register_dump::dump (ui_file *file)
 {
-public:
-  void dump (ui_file *file)
-  {
-    auto descr = regcache_descr (m_gdbarch);
-    int regnum;
-    int footnote_nr = 0;
-    int footnote_register_offset = 0;
-    int footnote_register_type_name_null = 0;
-    long register_offset = 0;
-
-    gdb_assert (descr->nr_cooked_registers
-		== (gdbarch_num_regs (m_gdbarch)
-		    + gdbarch_num_pseudo_regs (m_gdbarch)));
-
-    for (regnum = -1; regnum < descr->nr_cooked_registers; regnum++)
-      {
-	/* Name.  */
-	if (regnum < 0)
-	  fprintf_unfiltered (file, " %-10s", "Name");
-	else
-	  {
-	    const char *p = gdbarch_register_name (m_gdbarch, regnum);
+  auto descr = regcache_descr (m_gdbarch);
+  int regnum;
+  int footnote_nr = 0;
+  int footnote_register_offset = 0;
+  int footnote_register_type_name_null = 0;
+  long register_offset = 0;
 
-	    if (p == NULL)
-	      p = "";
-	    else if (p[0] == '\0')
-	      p = "''";
-	    fprintf_unfiltered (file, " %-10s", p);
-	  }
+  gdb_assert (descr->nr_cooked_registers
+	      == (gdbarch_num_regs (m_gdbarch)
+		  + gdbarch_num_pseudo_regs (m_gdbarch)));
 
-	/* Number.  */
-	if (regnum < 0)
-	  fprintf_unfiltered (file, " %4s", "Nr");
-	else
-	  fprintf_unfiltered (file, " %4d", regnum);
+  for (regnum = -1; regnum < descr->nr_cooked_registers; regnum++)
+    {
+      /* Name.  */
+      if (regnum < 0)
+	fprintf_unfiltered (file, " %-10s", "Name");
+      else
+	{
+	  const char *p = gdbarch_register_name (m_gdbarch, regnum);
 
-	/* Relative number.  */
-	if (regnum < 0)
-	  fprintf_unfiltered (file, " %4s", "Rel");
-	else if (regnum < gdbarch_num_regs (m_gdbarch))
-	  fprintf_unfiltered (file, " %4d", regnum);
-	else
-	  fprintf_unfiltered (file, " %4d",
-			      (regnum - gdbarch_num_regs (m_gdbarch)));
+	  if (p == NULL)
+	    p = "";
+	  else if (p[0] == '\0')
+	    p = "''";
+	  fprintf_unfiltered (file, " %-10s", p);
+	}
 
-	/* Offset.  */
-	if (regnum < 0)
-	  fprintf_unfiltered (file, " %6s  ", "Offset");
-	else
-	  {
-	    fprintf_unfiltered (file, " %6ld",
-				descr->register_offset[regnum]);
-	    if (register_offset != descr->register_offset[regnum]
-		|| (regnum > 0
-		    && (descr->register_offset[regnum]
-			!= (descr->register_offset[regnum - 1]
-			    + descr->sizeof_register[regnum - 1])))
-		)
-	      {
-		if (!footnote_register_offset)
-		  footnote_register_offset = ++footnote_nr;
-		fprintf_unfiltered (file, "*%d", footnote_register_offset);
-	      }
-	    else
-	      fprintf_unfiltered (file, "  ");
-	    register_offset = (descr->register_offset[regnum]
-			       + descr->sizeof_register[regnum]);
-	  }
+      /* Number.  */
+      if (regnum < 0)
+	fprintf_unfiltered (file, " %4s", "Nr");
+      else
+	fprintf_unfiltered (file, " %4d", regnum);
 
-	/* Size.  */
-	if (regnum < 0)
-	  fprintf_unfiltered (file, " %5s ", "Size");
-	else
-	  fprintf_unfiltered (file, " %5ld", descr->sizeof_register[regnum]);
+      /* Relative number.  */
+      if (regnum < 0)
+	fprintf_unfiltered (file, " %4s", "Rel");
+      else if (regnum < gdbarch_num_regs (m_gdbarch))
+	fprintf_unfiltered (file, " %4d", regnum);
+      else
+	fprintf_unfiltered (file, " %4d",
+			    (regnum - gdbarch_num_regs (m_gdbarch)));
 
-	/* Type.  */
+      /* Offset.  */
+      if (regnum < 0)
+	fprintf_unfiltered (file, " %6s  ", "Offset");
+      else
 	{
-	  const char *t;
-	  std::string name_holder;
-
-	  if (regnum < 0)
-	    t = "Type";
-	  else
+	  fprintf_unfiltered (file, " %6ld",
+			      descr->register_offset[regnum]);
+	  if (register_offset != descr->register_offset[regnum]
+	      || (regnum > 0
+		  && (descr->register_offset[regnum]
+		      != (descr->register_offset[regnum - 1]
+			  + descr->sizeof_register[regnum - 1])))
+	      )
 	    {
-	      static const char blt[] = "builtin_type";
-
-	      t = TYPE_NAME (register_type (m_gdbarch, regnum));
-	      if (t == NULL)
-		{
-		  if (!footnote_register_type_name_null)
-		    footnote_register_type_name_null = ++footnote_nr;
-		  name_holder = string_printf ("*%d",
-					       footnote_register_type_name_null);
-		  t = name_holder.c_str ();
-		}
-	      /* Chop a leading builtin_type.  */
-	      if (startswith (t, blt))
-		t += strlen (blt);
+	      if (!footnote_register_offset)
+		footnote_register_offset = ++footnote_nr;
+	      fprintf_unfiltered (file, "*%d", footnote_register_offset);
 	    }
-	  fprintf_unfiltered (file, " %-15s", t);
+	  else
+	    fprintf_unfiltered (file, "  ");
+	  register_offset = (descr->register_offset[regnum]
+			     + descr->sizeof_register[regnum]);
 	}
 
-	/* Leading space always present.  */
-	fprintf_unfiltered (file, " ");
-
-	dump_reg (file, regnum);
-
-	fprintf_unfiltered (file, "\n");
-      }
-
-    if (footnote_register_offset)
-      fprintf_unfiltered (file, "*%d: Inconsistent register offsets.\n",
-			  footnote_register_offset);
-    if (footnote_register_type_name_null)
-      fprintf_unfiltered (file,
-			  "*%d: Register type's name NULL.\n",
-			  footnote_register_type_name_null);
-  }
-
-  virtual ~register_dump () {};
-
-protected:
-  register_dump (gdbarch *arch)
-    : m_gdbarch (arch)
-  {}
-
-  /* Dump the register REGNUM contents.  If REGNUM is -1, print the
-     header.  */
-  virtual void dump_reg (ui_file *file, int regnum) = 0;
-
-  gdbarch *m_gdbarch;
-};
-
-/* Dump registers from regcache, used for dump raw registers and
-   cooked registers.  */
-
-class register_dump_regcache : public register_dump
-{
-public:
-  register_dump_regcache (regcache *regcache, bool dump_pseudo)
-    : register_dump (regcache->arch ()), m_regcache (regcache),
-      m_dump_pseudo (dump_pseudo)
-  {
-  }
-
-protected:
-  void dump_reg (ui_file *file, int regnum) override
-  {
-    if (regnum < 0)
-      {
-	if (m_dump_pseudo)
-	  fprintf_unfiltered (file, "Cooked value");
-	else
-	  fprintf_unfiltered (file, "Raw value");
-      }
-    else
-      {
-	if (regnum < gdbarch_num_regs (m_gdbarch) || m_dump_pseudo)
-	  {
-	    auto size = register_size (m_gdbarch, regnum);
-
-	    if (size == 0)
-	      return;
-
-	    gdb::def_vector<gdb_byte> buf (size);
-	    auto status = m_regcache->cooked_read (regnum, buf.data ());
-
-	    if (status == REG_UNKNOWN)
-	      fprintf_unfiltered (file, "<invalid>");
-	    else if (status == REG_UNAVAILABLE)
-	      fprintf_unfiltered (file, "<unavailable>");
-	    else
-	      {
-		print_hex_chars (file, buf.data (), size,
-				 gdbarch_byte_order (m_gdbarch), true);
-	      }
-	  }
-	else
-	  {
-	    /* Just print "<cooked>" for pseudo register when
-	       regcache_dump_raw.  */
-	    fprintf_unfiltered (file, "<cooked>");
-	  }
-      }
-  }
-
-private:
-  regcache *m_regcache;
-
-  /* Dump pseudo registers or not.  */
-  const bool m_dump_pseudo;
-};
-
-/* Dump from reg_buffer, used when there is no thread or
-   registers.  */
-
-class register_dump_reg_buffer : public register_dump, reg_buffer
-{
-public:
-  register_dump_reg_buffer (gdbarch *gdbarch, bool dump_pseudo)
-    : register_dump (gdbarch), reg_buffer (gdbarch, dump_pseudo)
-  {
-  }
+      /* Size.  */
+      if (regnum < 0)
+	fprintf_unfiltered (file, " %5s ", "Size");
+      else
+	fprintf_unfiltered (file, " %5ld", descr->sizeof_register[regnum]);
 
-protected:
-  void dump_reg (ui_file *file, int regnum) override
-  {
-    if (regnum < 0)
-      {
-	if (m_has_pseudo)
-	  fprintf_unfiltered (file, "Cooked value");
-	else
-	  fprintf_unfiltered (file, "Raw value");
-      }
-    else
+      /* Type.  */
       {
-	if (regnum < gdbarch_num_regs (m_gdbarch) || m_has_pseudo)
-	  {
-	    auto size = register_size (m_gdbarch, regnum);
-
-	    if (size == 0)
-	      return;
-
-	    auto status = get_register_status (regnum);
+	const char *t;
+	std::string name_holder;
 
-	    gdb_assert (status != REG_VALID);
-
-	    if (status == REG_UNKNOWN)
-	      fprintf_unfiltered (file, "<invalid>");
-	    else
-	      fprintf_unfiltered (file, "<unavailable>");
-	  }
+	if (regnum < 0)
+	  t = "Type";
 	else
 	  {
-	    /* Just print "<cooked>" for pseudo register when
-	       regcache_dump_raw.  */
-	    fprintf_unfiltered (file, "<cooked>");
-	  }
-      }
-  }
-};
-
-/* For "maint print registers".  */
-
-class register_dump_none : public register_dump
-{
-public:
-  register_dump_none (gdbarch *arch)
-    : register_dump (arch)
-  {}
-
-protected:
-  void dump_reg (ui_file *file, int regnum) override
-  {}
-};
-
-/* For "maint print remote-registers".  */
-
-class register_dump_remote : public register_dump
-{
-public:
-  register_dump_remote (gdbarch *arch)
-    : register_dump (arch)
-  {}
+	    static const char blt[] = "builtin_type";
 
-protected:
-  void dump_reg (ui_file *file, int regnum) override
-  {
-    if (regnum < 0)
-      {
-	fprintf_unfiltered (file, "Rmt Nr  g/G Offset");
-      }
-    else if (regnum < gdbarch_num_regs (m_gdbarch))
-      {
-	int pnum, poffset;
-
-	if (remote_register_number_and_offset (m_gdbarch, regnum,
-					       &pnum, &poffset))
-	  fprintf_unfiltered (file, "%7d %11d", pnum, poffset);
-      }
-  }
-};
-
-/* For "maint print register-groups".  */
-
-class register_dump_groups : public register_dump
-{
-public:
-  register_dump_groups (gdbarch *arch)
-    : register_dump (arch)
-  {}
-
-protected:
-  void dump_reg (ui_file *file, int regnum) override
-  {
-    if (regnum < 0)
-      fprintf_unfiltered (file, "Groups");
-    else
-      {
-	const char *sep = "";
-	struct reggroup *group;
-
-	for (group = reggroup_next (m_gdbarch, NULL);
-	     group != NULL;
-	     group = reggroup_next (m_gdbarch, group))
-	  {
-	    if (gdbarch_register_reggroup_p (m_gdbarch, regnum, group))
+	    t = TYPE_NAME (register_type (m_gdbarch, regnum));
+	    if (t == NULL)
 	      {
-		fprintf_unfiltered (file,
-				    "%s%s", sep, reggroup_name (group));
-		sep = ",";
+		if (!footnote_register_type_name_null)
+		  footnote_register_type_name_null = ++footnote_nr;
+		name_holder = string_printf ("*%d",
+					     footnote_register_type_name_null);
+		t = name_holder.c_str ();
 	      }
+	    /* Chop a leading builtin_type.  */
+	    if (startswith (t, blt))
+	      t += strlen (blt);
 	  }
+	fprintf_unfiltered (file, " %-15s", t);
       }
-  }
-};
 
-enum regcache_dump_what
-{
-  regcache_dump_none, regcache_dump_raw,
-  regcache_dump_cooked, regcache_dump_groups,
-  regcache_dump_remote
-};
+      /* Leading space always present.  */
+      fprintf_unfiltered (file, " ");
 
-static void
-regcache_print (const char *args, enum regcache_dump_what what_to_dump)
-{
-  /* Where to send output.  */
-  stdio_file file;
-  ui_file *out;
+      dump_reg (file, regnum);
 
-  if (args == NULL)
-    out = gdb_stdout;
-  else
-    {
-      if (!file.open (args, "w"))
-	perror_with_name (_("maintenance print architecture"));
-      out = &file;
+      fprintf_unfiltered (file, "\n");
     }
 
-  std::unique_ptr<register_dump> dump;
-  std::unique_ptr<regcache> regs;
-  gdbarch *gdbarch;
-
-  if (target_has_registers)
-    gdbarch = get_current_regcache ()->arch ();
-  else
-    gdbarch = target_gdbarch ();
-
-  switch (what_to_dump)
-    {
-    case regcache_dump_none:
-      dump.reset (new register_dump_none (gdbarch));
-      break;
-    case regcache_dump_remote:
-      dump.reset (new register_dump_remote (gdbarch));
-      break;
-    case regcache_dump_groups:
-      dump.reset (new register_dump_groups (gdbarch));
-      break;
-    case regcache_dump_raw:
-    case regcache_dump_cooked:
-      {
-	auto dump_pseudo = (what_to_dump == regcache_dump_cooked);
-
-	if (target_has_registers)
-	  dump.reset (new register_dump_regcache (get_current_regcache (),
-						  dump_pseudo));
-	else
-	  {
-	    /* For the benefit of "maint print registers" & co when
-	       debugging an executable, allow dumping a regcache even when
-	       there is no thread selected / no registers.  */
-	    dump.reset (new register_dump_reg_buffer (target_gdbarch (),
-						      dump_pseudo));
-	  }
-      }
-      break;
-    }
-
-  dump->dump (out);
-}
-
-static void
-maintenance_print_registers (const char *args, int from_tty)
-{
-  regcache_print (args, regcache_dump_none);
-}
-
-static void
-maintenance_print_raw_registers (const char *args, int from_tty)
-{
-  regcache_print (args, regcache_dump_raw);
-}
-
-static void
-maintenance_print_cooked_registers (const char *args, int from_tty)
-{
-  regcache_print (args, regcache_dump_cooked);
-}
-
-static void
-maintenance_print_register_groups (const char *args, int from_tty)
-{
-  regcache_print (args, regcache_dump_groups);
-}
-
-static void
-maintenance_print_remote_registers (const char *args, int from_tty)
-{
-  regcache_print (args, regcache_dump_remote);
+  if (footnote_register_offset)
+    fprintf_unfiltered (file, "*%d: Inconsistent register offsets.\n",
+			footnote_register_offset);
+  if (footnote_register_type_name_null)
+    fprintf_unfiltered (file,
+			"*%d: Register type's name NULL.\n",
+			footnote_register_type_name_null);
 }
 
 #if GDB_SELF_TEST
@@ -2175,32 +1874,6 @@ _initialize_regcache (void)
   add_com ("flushregs", class_maintenance, reg_flush_command,
 	   _("Force gdb to flush its register cache (maintainer command)"));
 
-  add_cmd ("registers", class_maintenance, maintenance_print_registers,
-	   _("Print the internal register configuration.\n"
-	     "Takes an optional file parameter."), &maintenanceprintlist);
-  add_cmd ("raw-registers", class_maintenance,
-	   maintenance_print_raw_registers,
-	   _("Print the internal register configuration "
-	     "including raw values.\n"
-	     "Takes an optional file parameter."), &maintenanceprintlist);
-  add_cmd ("cooked-registers", class_maintenance,
-	   maintenance_print_cooked_registers,
-	   _("Print the internal register configuration "
-	     "including cooked values.\n"
-	     "Takes an optional file parameter."), &maintenanceprintlist);
-  add_cmd ("register-groups", class_maintenance,
-	   maintenance_print_register_groups,
-	   _("Print the internal register configuration "
-	     "including each register's group.\n"
-	     "Takes an optional file parameter."),
-	   &maintenanceprintlist);
-  add_cmd ("remote-registers", class_maintenance,
-	   maintenance_print_remote_registers, _("\
-Print the internal register configuration including each register's\n\
-remote register number and buffer offset in the g/G packets.\n\
-Takes an optional file parameter."),
-	   &maintenanceprintlist);
-
 #if GDB_SELF_TEST
   selftests::register_test ("current_regcache", selftests::current_regcache_test);
 
diff --git a/gdb/regcache.h b/gdb/regcache.h
index d1e8506..ad7e0a1 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -425,4 +425,24 @@ public:
 extern void registers_changed (void);
 extern void registers_changed_ptid (ptid_t);
 
+/* An abstract base class for register dump.  */
+
+class register_dump
+{
+public:
+  void dump (ui_file *file);
+  virtual ~register_dump () {};
+
+protected:
+  register_dump (gdbarch *arch)
+    : m_gdbarch (arch)
+  {}
+
+  /* Dump the register REGNUM contents.  If REGNUM is -1, print the
+     header.  */
+  virtual void dump_reg (ui_file *file, int regnum) = 0;
+
+  gdbarch *m_gdbarch;
+};
+
 #endif /* REGCACHE_H */
-- 
1.9.1

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

* [PATCH 01/15] Call cooked_read in ppu2spu_prev_register
  2017-12-01 10:48 [RFC 00/15] Remove regcache::m_readonly_p Yao Qi
  2017-12-01 10:48 ` [PATCH 09/15] Remove regcache_save and regcache_cpy Yao Qi
@ 2017-12-01 10:48 ` Yao Qi
  2018-01-16 16:19   ` Yao Qi
  2017-12-01 10:48 ` [PATCH 04/15] Replace regcache_raw_read with regcache->raw_read Yao Qi
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 32+ messages in thread
From: Yao Qi @ 2017-12-01 10:48 UTC (permalink / raw)
  To: gdb-patches

The code in ppu2spu_prev_register is in fact regcache_cooked_read,
because spu doesn't have gdbarch method pseudo_register_read_value.

gdb:

2017-11-06  Yao Qi  <yao.qi@linaro.org>

	* ppc-linux-tdep.c (ppu2spu_prev_register): Call cooked_read.
---
 gdb/ppc-linux-tdep.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 0e43a64..70e5b95 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -1269,11 +1269,7 @@ ppu2spu_prev_register (struct frame_info *this_frame,
 
   buf = (gdb_byte *) alloca (register_size (gdbarch, regnum));
 
-  if (regnum < gdbarch_num_regs (gdbarch))
-    regcache_raw_read (cache->regcache, regnum, buf);
-  else
-    gdbarch_pseudo_register_read (gdbarch, cache->regcache, regnum, buf);
-
+  cache->regcache->cooked_read (regnum, buf);
   return frame_unwind_got_bytes (this_frame, regnum, buf);
 }
 
-- 
1.9.1

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

* [PATCH 14/15] Remove regcache::m_readonly_p
  2017-12-01 10:48 [RFC 00/15] Remove regcache::m_readonly_p Yao Qi
                   ` (8 preceding siblings ...)
  2017-12-01 10:48 ` [PATCH 02/15] Don't call gdbarch_pseudo_register_read_value in jit.c Yao Qi
@ 2017-12-01 10:48 ` Yao Qi
  2017-12-01 10:48 ` [PATCH 11/15] Class reg_buffer_rw Yao Qi
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 32+ messages in thread
From: Yao Qi @ 2017-12-01 10:48 UTC (permalink / raw)
  To: gdb-patches

Now, m_readonly_p is always false, so we can remove it, and regcache no
longer includes pseudo registers.  Some regcache methods are lift up to
its parent class, like reg_buffer or reg_buffer_rw.

gdb:

2017-11-07  Yao Qi  <yao.qi@linaro.org>

	* regcache.c (regcache::regcache): Update.
	(regcache::invalidate): Move it to reg_buffer_rw::invalidate.
	(get_thread_arch_aspace_regcache): Update.
	(regcache::raw_update): Update.
	(regcache::cooked_read): Remove some code.
	(regcache::cooked_read_value): Likewise.
	(regcache::raw_write): Remove assert on m_readonly_p.
	(regcache::raw_supply_integer): Move it to
	reg_buffer_rw::raw_supply_integer.
	(regcache::raw_supply_zeroed): Likewise.
	* regcache.h (reg_buffer_rw) <raw_supply_integer>: New declaration.
	<raw_supply_zeroed, invalidate>: Likewise.
	(regcache) <raw_supply_integer, raw_supply_zeroed>: Removed.
	<invalidate>: Likewise.
	<m_readonly_p>: Removed.
---
 gdb/regcache.c | 30 +++++++++++-------------------
 gdb/regcache.h | 22 ++++++++--------------
 2 files changed, 19 insertions(+), 33 deletions(-)

diff --git a/gdb/regcache.c b/gdb/regcache.c
index 4286f36..4ea4a5d 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -200,13 +200,10 @@ reg_buffer::reg_buffer (gdbarch *gdbarch, bool has_pseudo)
     }
 }
 
-regcache::regcache (gdbarch *gdbarch, const address_space *aspace_,
-		    bool readonly_p_)
-/* The register buffers.  A read-only register cache can hold the
-   full [0 .. gdbarch_num_regs + gdbarch_num_pseudo_regs) while a
-   read/write register cache can only hold [0 .. gdbarch_num_regs).  */
-  : reg_buffer_rw (gdbarch, readonly_p_),
-    m_aspace (aspace_), m_readonly_p (readonly_p_)
+regcache::regcache (gdbarch *gdbarch, const address_space *aspace_)
+/* The register buffers.  A read/write register cache can only hold
+   [0 .. gdbarch_num_regs).  */
+  : reg_buffer_rw (gdbarch, false), m_aspace (aspace_)
 {
   m_ptid = minus_one_ptid;
 }
@@ -319,7 +316,6 @@ regcache::restore (regcache_readonly *src)
   int regnum;
 
   gdb_assert (src != NULL);
-  gdb_assert (!m_readonly_p);
   gdb_assert (src->m_has_pseudo);
 
   gdb_assert (gdbarch == src->arch ());
@@ -361,9 +357,8 @@ regcache_invalidate (struct regcache *regcache, int regnum)
 }
 
 void
-regcache::invalidate (int regnum)
+reg_buffer_rw::invalidate (int regnum)
 {
-  gdb_assert (!m_readonly_p);
   assert_regnum (regnum);
   m_register_status[regnum] = REG_UNKNOWN;
 }
@@ -394,7 +389,7 @@ get_thread_arch_aspace_regcache (ptid_t ptid, struct gdbarch *gdbarch,
     if (ptid_equal (regcache->ptid (), ptid) && regcache->arch () == gdbarch)
       return regcache;
 
-  regcache *new_regcache = new regcache (gdbarch, aspace, false);
+  regcache *new_regcache = new regcache (gdbarch, aspace);
 
   regcache::current_regcache.push_front (new_regcache);
   new_regcache->set_ptid (ptid);
@@ -532,7 +527,7 @@ regcache::raw_update (int regnum)
      only there is still only one target side register cache.  Sigh!
      On the bright side, at least there is a regcache object.  */
 
-  if (!m_readonly_p && get_register_status (regnum) == REG_UNKNOWN)
+  if (get_register_status (regnum) == REG_UNKNOWN)
     {
       target_fetch_registers (this, regnum);
 
@@ -805,7 +800,6 @@ regcache::raw_write (int regnum, const gdb_byte *buf)
 
   gdb_assert (buf != NULL);
   assert_regnum (regnum);
-  gdb_assert (!m_readonly_p);
 
   /* On the sparc, writing %g0 is a no-op, so we don't even want to
      change the registers array if something writes to this register.  */
@@ -1028,15 +1022,14 @@ reg_buffer_rw::raw_supply (int regnum, const void *buf)
    most significant bytes of the integer will be truncated.  */
 
 void
-regcache::raw_supply_integer (int regnum, const gdb_byte *addr, int addr_len,
-			      bool is_signed)
+reg_buffer_rw::raw_supply_integer (int regnum, const gdb_byte *addr,
+				   int addr_len, bool is_signed)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (m_descr->gdbarch);
   gdb_byte *regbuf;
   size_t regsize;
 
   assert_regnum (regnum);
-  gdb_assert (!m_readonly_p);
 
   regbuf = register_buffer (regnum);
   regsize = m_descr->sizeof_register[regnum];
@@ -1051,13 +1044,12 @@ regcache::raw_supply_integer (int regnum, const gdb_byte *addr, int addr_len,
    unavailable).  */
 
 void
-regcache::raw_supply_zeroed (int regnum)
+reg_buffer_rw::raw_supply_zeroed (int regnum)
 {
   void *regbuf;
   size_t size;
 
   assert_regnum (regnum);
-  gdb_assert (!m_readonly_p);
 
   regbuf = register_buffer (regnum);
   size = m_descr->sizeof_register[regnum];
@@ -1871,7 +1863,7 @@ class readwrite_regcache : public regcache
 {
 public:
   readwrite_regcache (struct gdbarch *gdbarch)
-    : regcache (gdbarch, nullptr, false)
+    : regcache (gdbarch, nullptr)
   {}
 };
 
diff --git a/gdb/regcache.h b/gdb/regcache.h
index fc645c4..d1e8506 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -295,6 +295,13 @@ public:
   void raw_update (int regnum) override
   {}
 
+  void raw_supply_integer (int regnum, const gdb_byte *addr, int addr_len,
+			   bool is_signed);
+
+  void raw_supply_zeroed (int regnum);
+
+  void invalidate (int regnum);
+
   DISABLE_COPY_AND_ASSIGN (reg_buffer_rw);
 };
 
@@ -336,13 +343,6 @@ public:
   void raw_collect_integer (int regnum, gdb_byte *addr, int addr_len,
 			    bool is_signed) const;
 
-  void raw_supply_integer (int regnum, const gdb_byte *addr, int addr_len,
-			   bool is_signed);
-
-  void raw_supply_zeroed (int regnum);
-
-  void invalidate (int regnum);
-
   void raw_write_part (int regnum, int offset, int len, const gdb_byte *buf);
 
   void cooked_write_part (int regnum, int offset, int len,
@@ -371,7 +371,7 @@ public:
 
   static void regcache_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid);
 protected:
-  regcache (gdbarch *gdbarch, const address_space *aspace_, bool readonly_p_);
+  regcache (gdbarch *gdbarch, const address_space *aspace_);
   static std::forward_list<regcache *> current_regcache;
 
 private:
@@ -389,12 +389,6 @@ private:
      makes sense, like PC or SP).  */
   const address_space * const m_aspace;
 
-  /* Is this a read-only cache?  A read-only cache is used for saving
-     the target's register state (e.g, across an inferior function
-     call or just before forcing a function return).  A read-only
-     cache can only be created via a constructor.  The actual contents
-     are determined by the save and restore methods.  */
-  const bool m_readonly_p;
   /* If this is a read-write cache, which thread's registers is
      it connected to?  */
   ptid_t m_ptid;
-- 
1.9.1

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

* Re: [RFC 00/15] Remove regcache::m_readonly_p
  2017-12-01 10:48 [RFC 00/15] Remove regcache::m_readonly_p Yao Qi
                   ` (14 preceding siblings ...)
  2017-12-01 10:48 ` [PATCH 10/15] Class regcache_readonly Yao Qi
@ 2018-01-16 16:18 ` Yao Qi
  2018-01-18 16:56   ` Simon Marchi
  15 siblings, 1 reply; 32+ messages in thread
From: Yao Qi @ 2018-01-16 16:18 UTC (permalink / raw)
  To: gdb-patches

Yao Qi <qiyaoltc@gmail.com> writes:

> regcache is used in many places in gdb in different ways, so regcache
> becomes a flat and fat object.  That exposes some unnecessary APIs to
> different part, and some APIs are misused or abused:
>
>  1) gdbarch methods pseudo_register_read and pseudo_register_read_value
>  have a parameter 'regcache *', but these two gdbarch methods only need
>  raw_read* and cooked_read* methods.  So it is better to pass a class
>  which only has raw_read* and cooked_read* methods, and other regcache
>  methods are invisible to each gdbarch implementation.
>
>  2) target_ops methods to_fetch_registers and to_store_registers have a
>  parameter 'regcache *', but these two target_ops methods only need
>  raw_supply and raw_collect methods, because raw registers are from target
>  layer, pseudo registers are "composed" or "created" by gdbarch.
>
>  3) jit.c uses regcache in an odd way, and record-full.c should use
>  a simple version regcache instead of an array (see patch 11)
>
> Beside these api issues, one issue in regcache is that there is no
> type or class for readonly regcache.  We use a flag field m_readonly_p
> to indicate the regcache is readonly or not, so some regcache apis have
> assert that this regcache is or is not readonly.  The better way to do
> this is to create a new class for readonly regcache which doesn't have
> write methods at all.
>
> This patch series fixes all of the problems above except 2) (I had a
> patch to fix 2 in my tree, but still need more time to polish it.) by
> designing a class hierarchy about regcache, like this,
>
>                       reg_buffer
>                          ^
>                          |
>                    ------+-----
>                    ^
>                    |
>             regcache_read
>                  ^
>                  |
>            ------+------
>            ^           ^
>            |           |
>     reg_buffer_rw regcache_readonly
>           ^
>           |
>       regcache
>
> Class reg_buffer is a simple class, having register contents and status
> (in patch 7).  regcache_read is an abstract class only having raw_read*
> and cooked_read* methods (in patch 8).  reg_buffer_rw is a class which
> has read and write methods, but it disconnects from target, IOW, the
> write doesn't go through.  Class regcache_readonly is the readonly
> regcache, created from regcache::save method.
>
> This patch series is tested on {x86_64, aarch64, ppc64}-linux.  It is
> an RFC, want to get comments.  I write them in at least seven different
> ways, and this one is satisfying.  I don't push them in until 8.1 is
> branched.

Ping.  I'd like to know what do you think of this design, patches 7/15
to 15/15.

-- 
Yao (齐尧)

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

* Re: [PATCH 01/15] Call cooked_read in ppu2spu_prev_register
  2017-12-01 10:48 ` [PATCH 01/15] Call cooked_read in ppu2spu_prev_register Yao Qi
@ 2018-01-16 16:19   ` Yao Qi
  2018-01-16 18:05     ` Ulrich Weigand
  0 siblings, 1 reply; 32+ messages in thread
From: Yao Qi @ 2018-01-16 16:19 UTC (permalink / raw)
  To: gdb-patches; +Cc: uweigand

Yao Qi <qiyaoltc@gmail.com> writes:

> The code in ppu2spu_prev_register is in fact regcache_cooked_read,
> because spu doesn't have gdbarch method pseudo_register_read_value.
>
> gdb:
>
> 2017-11-06  Yao Qi  <yao.qi@linaro.org>
>
> 	* ppc-linux-tdep.c (ppu2spu_prev_register): Call cooked_read.

Hi Ulrich,
Can you review this patch?

-- 
Yao (齐尧)

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

* Re: [PATCH 01/15] Call cooked_read in ppu2spu_prev_register
  2018-01-16 16:19   ` Yao Qi
@ 2018-01-16 18:05     ` Ulrich Weigand
  2018-01-18 12:22       ` Yao Qi
  0 siblings, 1 reply; 32+ messages in thread
From: Ulrich Weigand @ 2018-01-16 18:05 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

Hi Yao,

> > The code in ppu2spu_prev_register is in fact regcache_cooked_read,
> > because spu doesn't have gdbarch method pseudo_register_read_value.
> >
> > gdb:
> >
> > 2017-11-06  Yao Qi  <yao.qi@linaro.org>
> >
> > 	* ppc-linux-tdep.c (ppu2spu_prev_register): Call cooked_read.
> 
> Hi Ulrich,
> Can you review this patch?

Yes, this patch is OK.

Thanks,
Ulrich

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

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

* Re: [PATCH 01/15] Call cooked_read in ppu2spu_prev_register
  2018-01-16 18:05     ` Ulrich Weigand
@ 2018-01-18 12:22       ` Yao Qi
  0 siblings, 0 replies; 32+ messages in thread
From: Yao Qi @ 2018-01-18 12:22 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: GDB Patches

On Tue, Jan 16, 2018 at 6:05 PM, Ulrich Weigand <uweigand@de.ibm.com> wrote:
>
> Yes, this patch is OK.
>

Thanks, pushed.

-- 
Yao (齐尧)

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

* Re: [PATCH 06/15] regcache::cooked_write test
  2017-12-01 10:48 ` [PATCH 06/15] regcache::cooked_write test Yao Qi
@ 2018-01-18 16:13   ` Simon Marchi
  2018-01-22 11:12     ` Yao Qi
  0 siblings, 1 reply; 32+ messages in thread
From: Simon Marchi @ 2018-01-18 16:13 UTC (permalink / raw)
  To: Yao Qi, gdb-patches

On 2017-12-01 05:47 AM, Yao Qi wrote:
> Since my following patches will change how each gdbarch read and write
> pseudo registers, it's better to write a unit test to
> regcache::cooked_write, to make sure my following changes don't cause
> any regressions.  See the comments on cooked_write_test.

Hi Yao,

I looked at patches up to this one (the preparatory patches), and they look
good to me.  However, I wasn't able to properly apply patch 3 "Remove mt port",
probably a git/email issue.

I think you can start pushing them when you feel like it, it will ligthen the
patch series a little bit, and they are good patches on their own.

I noted one nit below:

> gdb:
> 
> 2017-11-27  Yao Qi  <yao.qi@linaro.org>
> 
> 	* regcache.c (cooked_write_test): New function.
> 	(_initialize_regcache): Register the test.
> ---
>  gdb/regcache.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 124 insertions(+)
> 
> diff --git a/gdb/regcache.c b/gdb/regcache.c
> index a7a4683..4577913 100644
> --- a/gdb/regcache.c
> +++ b/gdb/regcache.c
> @@ -1609,6 +1609,7 @@ maintenance_print_remote_registers (const char *args, int from_tty)
>  #include "selftest.h"
>  #include "selftest-arch.h"
>  #include "gdbthread.h"
> +#include "target-float.h"
>  
>  namespace selftests {
>  
> @@ -1926,6 +1927,127 @@ cooked_read_test (struct gdbarch *gdbarch)
>      }
>  }
>  
> +/* Test regcache::cooked_write by writing some expected contents to
> +   registers, and checking that contents red from registers and the

red -> read

Simon

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

* Re: [RFC 00/15] Remove regcache::m_readonly_p
  2018-01-16 16:18 ` [RFC 00/15] Remove regcache::m_readonly_p Yao Qi
@ 2018-01-18 16:56   ` Simon Marchi
  2018-01-22 14:58     ` Yao Qi
  0 siblings, 1 reply; 32+ messages in thread
From: Simon Marchi @ 2018-01-18 16:56 UTC (permalink / raw)
  To: Yao Qi, gdb-patches

On 2018-01-16 11:18 AM, Yao Qi wrote:
> Yao Qi <qiyaoltc@gmail.com> writes:
> 
>> regcache is used in many places in gdb in different ways, so regcache
>> becomes a flat and fat object.  That exposes some unnecessary APIs to
>> different part, and some APIs are misused or abused:
>>
>>  1) gdbarch methods pseudo_register_read and pseudo_register_read_value
>>  have a parameter 'regcache *', but these two gdbarch methods only need
>>  raw_read* and cooked_read* methods.  So it is better to pass a class
>>  which only has raw_read* and cooked_read* methods, and other regcache
>>  methods are invisible to each gdbarch implementation.
>>
>>  2) target_ops methods to_fetch_registers and to_store_registers have a
>>  parameter 'regcache *', but these two target_ops methods only need
>>  raw_supply and raw_collect methods, because raw registers are from target
>>  layer, pseudo registers are "composed" or "created" by gdbarch.
>>
>>  3) jit.c uses regcache in an odd way, and record-full.c should use
>>  a simple version regcache instead of an array (see patch 11)
>>
>> Beside these api issues, one issue in regcache is that there is no
>> type or class for readonly regcache.  We use a flag field m_readonly_p
>> to indicate the regcache is readonly or not, so some regcache apis have
>> assert that this regcache is or is not readonly.  The better way to do
>> this is to create a new class for readonly regcache which doesn't have
>> write methods at all.
>>
>> This patch series fixes all of the problems above except 2) (I had a
>> patch to fix 2 in my tree, but still need more time to polish it.) by
>> designing a class hierarchy about regcache, like this,
>>
>>                       reg_buffer
>>                          ^
>>                          |
>>                    ------+-----
>>                    ^
>>                    |
>>             regcache_read
>>                  ^
>>                  |
>>            ------+------
>>            ^           ^
>>            |           |
>>     reg_buffer_rw regcache_readonly
>>           ^
>>           |
>>       regcache
>>
>> Class reg_buffer is a simple class, having register contents and status
>> (in patch 7).  regcache_read is an abstract class only having raw_read*
>> and cooked_read* methods (in patch 8).  reg_buffer_rw is a class which
>> has read and write methods, but it disconnects from target, IOW, the
>> write doesn't go through.  Class regcache_readonly is the readonly
>> regcache, created from regcache::save method.
>>
>> This patch series is tested on {x86_64, aarch64, ppc64}-linux.  It is
>> an RFC, want to get comments.  I write them in at least seven different
>> ways, and this one is satisfying.  I don't push them in until 8.1 is
>> branched.

Hi Yao,

The design you propose makes sense to me in general, but I have some
questions.

Which of these types will have actual instances of them, and which ones
are only interfaces?

I have some problem understanding the difference between regcache_read
and regcache_readonly.  I think the fact that the name is so similar
doesn't help.  Would there be a better name for regcache_readonly?

Simon

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

* Re: [PATCH 06/15] regcache::cooked_write test
  2018-01-18 16:13   ` Simon Marchi
@ 2018-01-22 11:12     ` Yao Qi
  0 siblings, 0 replies; 32+ messages in thread
From: Yao Qi @ 2018-01-22 11:12 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches

Simon Marchi <simon.marchi@ericsson.com> writes:

> I looked at patches up to this one (the preparatory patches), and they look
> good to me.  However, I wasn't able to properly apply patch 3 "Remove mt port",
> probably a git/email issue.
>

The patch 3 failed to apply because of the new-year procedural update.

> I think you can start pushing them when you feel like it, it will ligthen the
> patch series a little bit, and they are good patches on their own.

I pushed patches 01 ~ 06 in.  I'll push the rest to a branch, and answer
your question to the cover letter.

>
> I noted one nit below:

>
> red -> read

Fixed.

-- 
Yao (齐尧)

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

* Re: [RFC 00/15] Remove regcache::m_readonly_p
  2018-01-18 16:56   ` Simon Marchi
@ 2018-01-22 14:58     ` Yao Qi
  0 siblings, 0 replies; 32+ messages in thread
From: Yao Qi @ 2018-01-22 14:58 UTC (permalink / raw)
  To: Simon Marchi; +Cc: GDB Patches

On Thu, Jan 18, 2018 at 4:56 PM, Simon Marchi <simon.marchi@ericsson.com> wrote:
>
> Which of these types will have actual instances of them, and which ones
> are only interfaces?
>

 reg_buffer_rw, regcache_readonly and regcache have instances.
regcache_read is abstract.  reg_buffer is not abstract, but it has no
instances.

> I have some problem understanding the difference between regcache_read
> and regcache_readonly.  I think the fact that the name is so similar
> doesn't help.  Would there be a better name for regcache_readonly?

regcache_readonly is a type used when the instance of regcache is
readonly.  regcache_readonly extends regcache_read, and implement
virtual function raw_update doing nothing.  regcache_read is an abstract
class, in which raw_update is a pure virtual function.  It only has methods
to do the read.

I pushed them to branch users/qiyao/regcache-split-4-1 I also generate
doxygen doc
http://people.linaro.org/~yao.qi/gdb/doxy/regcache-split-4/doxy/gdb-xref/classreg__buffer.html

I am open to the naming.

-- 
Yao (齐尧)

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

* Re: [PATCH 08/15] class regcache_read and Pass regcache_read to gdbarch methods
  2017-12-01 10:48 ` [PATCH 08/15] class regcache_read and Pass regcache_read to gdbarch methods Yao Qi
@ 2018-01-23 21:51   ` Simon Marchi
  2018-01-23 22:28     ` Yao Qi
  0 siblings, 1 reply; 32+ messages in thread
From: Simon Marchi @ 2018-01-23 21:51 UTC (permalink / raw)
  To: Yao Qi, gdb-patches

Hi Yao,

On 2017-12-01 05:47 AM, Yao Qi wrote:
> pseudo registers are either from raw registers or memory, so
> gdbarch methods pseudo_register_read and pseudo_register_read_value
> should have regcache object which only have read methods.  In other
> words, we should disallow writing to regcache in these two gdbarch
> methods.  In order to apply this restriction, this patch adds a new
> class regcache_read, derived from reg_buffer, and it only has
> raw_read and cooked_read methods.  regcache is derived from
> regcache_read.  This patch also passes regcache_read instead of
> regcache to gdbarch methods pseudo_register_read and
> pseudo_register_read_value.

Did you consider changing other gdbarch methods that only need to read the
registers?  read_pc comes to mind, but there are perhaps others.

> This patch moves raw_read* and cooked_read* methods to regcache_read,
> which is straightforward.  One thing not straightforward is that I split
> regcache::xfer_part to regcache_read::read_part and regcache::write_part,
> because regcache_read can only have methods to read.

That is fine with me.

> regcache_read is an abstract base class, and it has a pure virtual
> function raw_update, because I don't want regcache_read know where these
> raw registers are from.  They can be from either the target (readwrite
> regcache) or the regcache itself (readonly regcache).

About the naming, I think that readcache_read sounds like a function (it
sounds like an action).  Instinctively, I would call it readable_regcache.

Simon

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

* Re: [PATCH 08/15] class regcache_read and Pass regcache_read to gdbarch methods
  2018-01-23 21:51   ` Simon Marchi
@ 2018-01-23 22:28     ` Yao Qi
  0 siblings, 0 replies; 32+ messages in thread
From: Yao Qi @ 2018-01-23 22:28 UTC (permalink / raw)
  To: Simon Marchi; +Cc: GDB Patches

On Tue, Jan 23, 2018 at 9:51 PM, Simon Marchi <simon.marchi@ericsson.com> wrote:
>
> Did you consider changing other gdbarch methods that only need to read the
> registers?  read_pc comes to mind, but there are perhaps others.
>

I didn't think about this, but you are right, other gdbarch methods can be
changed too.  read_pc and breakpoint_kind_from_current_state should
use the right type of regcache which only has read methods.  I'll do the
change.

>> regcache_read is an abstract base class, and it has a pure virtual
>> function raw_update, because I don't want regcache_read know where these
>> raw registers are from.  They can be from either the target (readwrite
>> regcache) or the regcache itself (readonly regcache).
>
> About the naming, I think that readcache_read sounds like a function (it
> sounds like an action).  Instinctively, I would call it readable_regcache.
>

If we take regcache_readonly into account too, we need some naming
consistency here.  We either use "readable_regcache/readonly_regcache"
or "regcache_readable/regcache_readonly".  I can choose the former
scheme.

-- 
Yao (齐尧)

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

* Re: [PATCH 10/15] Class regcache_readonly
  2017-12-01 10:48 ` [PATCH 10/15] Class regcache_readonly Yao Qi
@ 2018-01-24  3:05   ` Simon Marchi
  2018-01-24  9:43     ` Yao Qi
  0 siblings, 1 reply; 32+ messages in thread
From: Simon Marchi @ 2018-01-24  3:05 UTC (permalink / raw)
  To: Yao Qi, gdb-patches

On 2017-12-01 05:48 AM, Yao Qi wrote:
> This patch adds a new class (type) for readonly regcache, which is
> created via regcache::save.  regcache_readonly inherts from
> regcache_read.

Hi Yao,

Just a note about the naming.  IIUC, the important thing about this
kind of regcache is that it's detached from any target.  Did you
think about naming it detached_regcache or something like that ?

Simon

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

* Re: [PATCH 10/15] Class regcache_readonly
  2018-01-24  3:05   ` Simon Marchi
@ 2018-01-24  9:43     ` Yao Qi
  2018-01-24 16:57       ` Simon Marchi
  0 siblings, 1 reply; 32+ messages in thread
From: Yao Qi @ 2018-01-24  9:43 UTC (permalink / raw)
  To: Simon Marchi; +Cc: GDB Patches

On Wed, Jan 24, 2018 at 3:05 AM, Simon Marchi <simon.marchi@ericsson.com> wrote:
> On 2017-12-01 05:48 AM, Yao Qi wrote:
>> This patch adds a new class (type) for readonly regcache, which is
>> created via regcache::save.  regcache_readonly inherts from
>> regcache_read.
>
> Hi Yao,
>
> Just a note about the naming.  IIUC, the important thing about this
> kind of regcache is that it's detached from any target.  Did you
> think about naming it detached_regcache or something like that ?
>

This kind of regcache is both detached and readonly.  As I said in
https://sourceware.org/ml/gdb-patches/2017-07/msg00031.html,
detached and readonly are orthogonal in design.  We have four
different kinds of regcache,

 - readony detached regcache, this is what "class regcache_readonly"
   about.  It has several uses,  1) record infcall state, 2) give a
   regcache view to frame,

 - read-write detached regcache, this is what "class reg_buffer_rw"
   about.  It is used jit.c and record-full.c, where GDB keeps a detached
   regcache, but can read and write to it.

 - read-write attached regcache, that is what "class regcache" about.  It
   is attached to target, read and write will go through target,

 - readonly attached regcache.  It can be used for target 'core', but this
   piece is not included in this series,

so in this patch series, "readonly" implies "detached".

The major motivation of this patch series is to differentiate these kinds
of regcache by different types, instead of by fields "m_readonly_p" or
"m_detached_p" in "class regcache".

-- 
Yao (齐尧)

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

* Re: [PATCH 10/15] Class regcache_readonly
  2018-01-24  9:43     ` Yao Qi
@ 2018-01-24 16:57       ` Simon Marchi
  2018-01-24 17:37         ` Yao Qi
  0 siblings, 1 reply; 32+ messages in thread
From: Simon Marchi @ 2018-01-24 16:57 UTC (permalink / raw)
  To: Yao Qi; +Cc: GDB Patches

On 2018-01-24 04:42 AM, Yao Qi wrote:
> On Wed, Jan 24, 2018 at 3:05 AM, Simon Marchi <simon.marchi@ericsson.com> wrote:
>> On 2017-12-01 05:48 AM, Yao Qi wrote:
>>> This patch adds a new class (type) for readonly regcache, which is
>>> created via regcache::save.  regcache_readonly inherts from
>>> regcache_read.
>>
>> Hi Yao,
>>
>> Just a note about the naming.  IIUC, the important thing about this
>> kind of regcache is that it's detached from any target.  Did you
>> think about naming it detached_regcache or something like that ?
>>
> 
> This kind of regcache is both detached and readonly.  As I said in
> https://sourceware.org/ml/gdb-patches/2017-07/msg00031.html,
> detached and readonly are orthogonal in design.  We have four
> different kinds of regcache,
> 
>  - readony detached regcache, this is what "class regcache_readonly"
>    about.  It has several uses,  1) record infcall state, 2) give a
>    regcache view to frame,
> 
>  - read-write detached regcache, this is what "class reg_buffer_rw"
>    about.  It is used jit.c and record-full.c, where GDB keeps a detached
>    regcache, but can read and write to it.
> 
>  - read-write attached regcache, that is what "class regcache" about.  It
>    is attached to target, read and write will go through target,
> 
>  - readonly attached regcache.  It can be used for target 'core', but this
>    piece is not included in this series,
> 
> so in this patch series, "readonly" implies "detached".
> 
> The major motivation of this patch series is to differentiate these kinds
> of regcache by different types, instead of by fields "m_readonly_p" or
> "m_detached_p" in "class regcache".

Just pitching some ideas, I don't think I understand the situation as well as
you do.

I assume we want to keep the "regcache" type to mean read/write and attached,
since that's the most common use case.  Keeping this will reduce the amount of
changes needed throughout the code base.  We can then qualify the other types
based on how they differ from "read/write" and "attached".  That would give us
(in the same order as your list above):

- readonly_detached_regcache
- detached_regcache
- regcache
- readonly_regcache

This would give a predictable naming, and makes it maybe easier to know what
to expect from each type.  The graph you used in message 0/15 would become:

                      reg_buffer
                         ^
                         |
                   ------+-----
                   ^
                   |
            readable_regcache (abstract)
                 ^
                 |
           ------+------
           ^           ^
           |           |
    detached_regcache readonly_detached_regcache
          ^
          |
      regcache

Simon

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

* Re: [PATCH 10/15] Class regcache_readonly
  2018-01-24 16:57       ` Simon Marchi
@ 2018-01-24 17:37         ` Yao Qi
  2018-01-24 18:01           ` Simon Marchi
  0 siblings, 1 reply; 32+ messages in thread
From: Yao Qi @ 2018-01-24 17:37 UTC (permalink / raw)
  To: Simon Marchi; +Cc: GDB Patches

On Wed, Jan 24, 2018 at 4:57 PM, Simon Marchi <simon.marchi@ericsson.com> wrote:
>
> Just pitching some ideas, I don't think I understand the situation as well as
> you do.
>
> I assume we want to keep the "regcache" type to mean read/write and attached,
> since that's the most common use case.  Keeping this will reduce the amount of
> changes needed throughout the code base.  We can then qualify the other types

Yes.

> based on how they differ from "read/write" and "attached".  That would give us
> (in the same order as your list above):
>
> - readonly_detached_regcache
> - detached_regcache
> - regcache
> - readonly_regcache

This should be readonly_attached_regcache.

>
> This would give a predictable naming, and makes it maybe easier to know what
> to expect from each type.  The graph you used in message 0/15 would become:
>
>                       reg_buffer
>                          ^
>                          |
>                    ------+-----
>                    ^
>                    |
>             readable_regcache (abstract)
>                  ^
>                  |
>            ------+------
>            ^           ^
>            |           |
>     detached_regcache readonly_detached_regcache
>           ^
>           |
>       regcache
>

This naming is fine to me except for readonly_detached_regcache
as it is too long.  As "readonly" implies "detached" in current context,
can we name it readonly_regcache?


-- 
Yao (齐尧)

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

* Re: [PATCH 10/15] Class regcache_readonly
  2018-01-24 17:37         ` Yao Qi
@ 2018-01-24 18:01           ` Simon Marchi
  2018-01-24 21:01             ` Yao Qi
  0 siblings, 1 reply; 32+ messages in thread
From: Simon Marchi @ 2018-01-24 18:01 UTC (permalink / raw)
  To: Yao Qi; +Cc: Simon Marchi, GDB Patches

On 2018-01-24 12:37, Yao Qi wrote:
> On Wed, Jan 24, 2018 at 4:57 PM, Simon Marchi 
> <simon.marchi@ericsson.com> wrote:
>> 
>> Just pitching some ideas, I don't think I understand the situation as 
>> well as
>> you do.
>> 
>> I assume we want to keep the "regcache" type to mean read/write and 
>> attached,
>> since that's the most common use case.  Keeping this will reduce the 
>> amount of
>> changes needed throughout the code base.  We can then qualify the 
>> other types
> 
> Yes.
> 
>> based on how they differ from "read/write" and "attached".  That would 
>> give us
>> (in the same order as your list above):
>> 
>> - readonly_detached_regcache
>> - detached_regcache
>> - regcache
>> - readonly_regcache
> 
> This should be readonly_attached_regcache.

The logic was that by "default" a regcache would be attached, unless 
specified otherwise (because that's what the plain regcache is).  So 
that's why I suggested qualifying the detached regcache as such, while 
the attached ones would be implicit.

>> 
>> This would give a predictable naming, and makes it maybe easier to 
>> know what
>> to expect from each type.  The graph you used in message 0/15 would 
>> become:
>> 
>>                       reg_buffer
>>                          ^
>>                          |
>>                    ------+-----
>>                    ^
>>                    |
>>             readable_regcache (abstract)
>>                  ^
>>                  |
>>            ------+------
>>            ^           ^
>>            |           |
>>     detached_regcache readonly_detached_regcache
>>           ^
>>           |
>>       regcache
>> 
> 
> This naming is fine to me except for readonly_detached_regcache
> as it is too long.  As "readonly" implies "detached" in current 
> context,
> can we name it readonly_regcache?

In this context readonly == detached, but aren't we going to want 
readonly attached regcaches at some point?  If so, there will be a 
clash.

Simon

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

* Re: [PATCH 10/15] Class regcache_readonly
  2018-01-24 18:01           ` Simon Marchi
@ 2018-01-24 21:01             ` Yao Qi
  0 siblings, 0 replies; 32+ messages in thread
From: Yao Qi @ 2018-01-24 21:01 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Simon Marchi, GDB Patches

On Wed, Jan 24, 2018 at 6:00 PM, Simon Marchi <simon.marchi@polymtl.ca> wrote:
>
> In this context readonly == detached, but aren't we going to want readonly
> attached regcaches at some point?  If so, there will be a clash.
>

OK, I'll use readonly_detached_regcache.

-- 
Yao (齐尧)

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

end of thread, other threads:[~2018-01-24 21:01 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-01 10:48 [RFC 00/15] Remove regcache::m_readonly_p Yao Qi
2017-12-01 10:48 ` [PATCH 09/15] Remove regcache_save and regcache_cpy Yao Qi
2017-12-01 10:48 ` [PATCH 01/15] Call cooked_read in ppu2spu_prev_register Yao Qi
2018-01-16 16:19   ` Yao Qi
2018-01-16 18:05     ` Ulrich Weigand
2018-01-18 12:22       ` Yao Qi
2017-12-01 10:48 ` [PATCH 04/15] Replace regcache_raw_read with regcache->raw_read Yao Qi
2017-12-01 10:48 ` [PATCH 15/15] Move register_dump to regcache-dump.c Yao Qi
2017-12-01 10:48 ` [PATCH 08/15] class regcache_read and Pass regcache_read to gdbarch methods Yao Qi
2018-01-23 21:51   ` Simon Marchi
2018-01-23 22:28     ` Yao Qi
2017-12-01 10:48 ` [PATCH 13/15] No longer create readonly regcache Yao Qi
2017-12-01 10:48 ` [PATCH 05/15] regcache_cooked_read -> regcache->cooked_read Yao Qi
2017-12-01 10:48 ` [PATCH 03/15] Remove mt port Yao Qi
2017-12-01 10:48 ` [PATCH 02/15] Don't call gdbarch_pseudo_register_read_value in jit.c Yao Qi
2017-12-01 10:48 ` [PATCH 14/15] Remove regcache::m_readonly_p Yao Qi
2017-12-01 10:48 ` [PATCH 11/15] Class reg_buffer_rw Yao Qi
2017-12-01 10:48 ` [PATCH 06/15] regcache::cooked_write test Yao Qi
2018-01-18 16:13   ` Simon Marchi
2018-01-22 11:12     ` Yao Qi
2017-12-01 10:48 ` [PATCH 12/15] Replace regcache::dump with class register_dump Yao Qi
2017-12-01 10:48 ` [PATCH 07/15] Class reg_buffer Yao Qi
2017-12-01 10:48 ` [PATCH 10/15] Class regcache_readonly Yao Qi
2018-01-24  3:05   ` Simon Marchi
2018-01-24  9:43     ` Yao Qi
2018-01-24 16:57       ` Simon Marchi
2018-01-24 17:37         ` Yao Qi
2018-01-24 18:01           ` Simon Marchi
2018-01-24 21:01             ` Yao Qi
2018-01-16 16:18 ` [RFC 00/15] Remove regcache::m_readonly_p Yao Qi
2018-01-18 16:56   ` Simon Marchi
2018-01-22 14:58     ` Yao Qi

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