Change inferior thread list to be a thread map
[deliverable/binutils-gdb.git] / gdb / regcache.c
index 389c016972f8bd910520e0991e75cae7d1aa3d8a..6912b14d06e85834c14e55897dd71afdb956f839 100644 (file)
@@ -1,6 +1,6 @@
 /* Cache and manage the values of registers for GDB, the GNU debugger.
 
-   Copyright (C) 1986-2018 Free Software Foundation, Inc.
+   Copyright (C) 1986-2019 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 
 #include "defs.h"
 #include "inferior.h"
+#include "gdbthread.h"
 #include "target.h"
+#include "test-target.h"
 #include "gdbarch.h"
 #include "gdbcmd.h"
 #include "regcache.h"
 #include "reggroups.h"
-#include "observer.h"
-#include "remote.h"
-#include "valprint.h"
+#include "observable.h"
 #include "regset.h"
 #include <forward_list>
 
@@ -87,8 +87,7 @@ init_regcache_descr (struct gdbarch *gdbarch)
   /* Total size of the register space.  The raw registers are mapped
      directly onto the raw register cache while the pseudo's are
      either mapped onto raw-registers or memory.  */
-  descr->nr_cooked_registers = gdbarch_num_regs (gdbarch)
-                              + gdbarch_num_pseudo_regs (gdbarch);
+  descr->nr_cooked_registers = gdbarch_num_cooked_regs (gdbarch);
 
   /* Fill in a table of register types.  */
   descr->register_type
@@ -119,7 +118,6 @@ init_regcache_descr (struct gdbarch *gdbarch)
        descr->sizeof_register[i] = TYPE_LENGTH (descr->register_type[i]);
        descr->register_offset[i] = offset;
        offset += descr->sizeof_register[i];
-       gdb_assert (MAX_REGISTER_SIZE >= descr->sizeof_register[i]);
       }
     /* Set the real size of the raw register cache buffer.  */
     descr->sizeof_raw_registers = offset;
@@ -129,7 +127,6 @@ init_regcache_descr (struct gdbarch *gdbarch)
        descr->sizeof_register[i] = TYPE_LENGTH (descr->register_type[i]);
        descr->register_offset[i] = offset;
        offset += descr->sizeof_register[i];
-       gdb_assert (MAX_REGISTER_SIZE >= descr->sizeof_register[i]);
       }
     /* Set the real size of the readonly register cache buffer.  */
     descr->sizeof_cooked_registers = offset;
@@ -166,14 +163,12 @@ register_size (struct gdbarch *gdbarch, int regnum)
   struct regcache_descr *descr = regcache_descr (gdbarch);
   int size;
 
-  gdb_assert (regnum >= 0
-             && regnum < (gdbarch_num_regs (gdbarch)
-                          + gdbarch_num_pseudo_regs (gdbarch)));
+  gdb_assert (regnum >= 0 && regnum < gdbarch_num_cooked_regs (gdbarch));
   size = descr->sizeof_register[regnum];
   return size;
 }
 
-/* See common/common-regcache.h.  */
+/* See gdbsupport/common-regcache.h.  */
 
 int
 regcache_register_size (const struct regcache *regcache, int n)
@@ -189,45 +184,32 @@ reg_buffer::reg_buffer (gdbarch *gdbarch, bool has_pseudo)
 
   if (has_pseudo)
     {
-      m_registers = XCNEWVEC (gdb_byte, m_descr->sizeof_cooked_registers);
-      m_register_status = XCNEWVEC (signed char,
-                                   m_descr->nr_cooked_registers);
+      m_registers.reset (new gdb_byte[m_descr->sizeof_cooked_registers] ());
+      m_register_status.reset
+       (new register_status[m_descr->nr_cooked_registers] ());
     }
   else
     {
-      m_registers = XCNEWVEC (gdb_byte, m_descr->sizeof_raw_registers);
-      m_register_status = XCNEWVEC (signed char, gdbarch_num_regs (gdbarch));
+      m_registers.reset (new gdb_byte[m_descr->sizeof_raw_registers] ());
+      m_register_status.reset
+       (new register_status[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).  */
-  : detached_regcache (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).  */
+  : detached_regcache (gdbarch, false), m_aspace (aspace_)
 {
   m_ptid = minus_one_ptid;
 }
 
-static enum register_status
-do_cooked_read (void *src, int regnum, gdb_byte *buf)
-{
-  struct regcache *regcache = (struct regcache *) src;
-
-  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);
-}
-
-readonly_detached_regcache::readonly_detached_regcache (const regcache &src)
-  : readonly_detached_regcache (src.arch (), do_cooked_read, (void *) &src)
+readonly_detached_regcache::readonly_detached_regcache (regcache &src)
+  : readonly_detached_regcache (src.arch (),
+                               [&src] (int regnum, gdb_byte *buf)
+                                 {
+                                   return src.cooked_read (regnum, buf);
+                                 })
 {
 }
 
@@ -237,58 +219,16 @@ reg_buffer::arch () const
   return m_descr->gdbarch;
 }
 
-/* See regcache.h.  */
-
-ptid_t
-regcache_get_ptid (const struct regcache *regcache)
-{
-  gdb_assert (!ptid_equal (regcache->ptid (), minus_one_ptid));
-
-  return regcache->ptid ();
-}
-
-/* Cleanup class for invalidating a register.  */
-
-class regcache_invalidator
-{
-public:
-
-  regcache_invalidator (struct regcache *regcache, int regnum)
-    : m_regcache (regcache),
-      m_regnum (regnum)
-  {
-  }
-
-  ~regcache_invalidator ()
-  {
-    if (m_regcache != nullptr)
-      regcache_invalidate (m_regcache, m_regnum);
-  }
-
-  DISABLE_COPY_AND_ASSIGN (regcache_invalidator);
-
-  void release ()
-  {
-    m_regcache = nullptr;
-  }
-
-private:
-
-  struct regcache *m_regcache;
-  int m_regnum;
-};
-
 /* Return  a pointer to register REGNUM's buffer cache.  */
 
 gdb_byte *
 reg_buffer::register_buffer (int regnum) const
 {
-  return m_registers + m_descr->register_offset[regnum];
+  return m_registers.get () + m_descr->register_offset[regnum];
 }
 
 void
-reg_buffer::save (regcache_cooked_read_ftype *cooked_read,
-                 void *src)
+reg_buffer::save (register_read_ftype cooked_read)
 {
   struct gdbarch *gdbarch = m_descr->gdbarch;
   int regnum;
@@ -296,8 +236,8 @@ reg_buffer::save (regcache_cooked_read_ftype *cooked_read,
   /* 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);
+  memset (m_registers.get (), 0, m_descr->sizeof_cooked_registers);
+  memset (m_register_status.get (), REG_UNKNOWN, m_descr->nr_cooked_registers);
   /* Copy over any registers (identified by their membership in the
      save_reggroup) and mark them as valid.  The full [0 .. gdbarch_num_regs +
      gdbarch_num_pseudo_regs) range is checked since some architectures need
@@ -307,7 +247,7 @@ reg_buffer::save (regcache_cooked_read_ftype *cooked_read,
       if (gdbarch_register_reggroup_p (gdbarch, regnum, save_reggroup))
        {
          gdb_byte *dst_buf = register_buffer (regnum);
-         enum register_status status = cooked_read (src, regnum, dst_buf);
+         enum register_status status = cooked_read (regnum, dst_buf);
 
          gdb_assert (status != REG_UNKNOWN);
 
@@ -326,7 +266,6 @@ regcache::restore (readonly_detached_regcache *src)
   int regnum;
 
   gdb_assert (src != NULL);
-  gdb_assert (!m_readonly_p);
   gdb_assert (src->m_has_pseudo);
 
   gdb_assert (gdbarch == src->arch ());
@@ -345,32 +284,19 @@ regcache::restore (readonly_detached_regcache *src)
     }
 }
 
-enum register_status
-regcache_register_status (const struct regcache *regcache, int regnum)
-{
-  gdb_assert (regcache != NULL);
-  return regcache->get_register_status (regnum);
-}
+/* See gdbsupport/common-regcache.h.  */
 
 enum register_status
 reg_buffer::get_register_status (int regnum) const
 {
   assert_regnum (regnum);
 
-  return (enum register_status) m_register_status[regnum];
-}
-
-void
-regcache_invalidate (struct regcache *regcache, int regnum)
-{
-  gdb_assert (regcache != NULL);
-  regcache->invalidate (regnum);
+  return m_register_status[regnum];
 }
 
 void
-regcache::invalidate (int regnum)
+reg_buffer::invalidate (int regnum)
 {
-  gdb_assert (!m_readonly_p);
   assert_regnum (regnum);
   m_register_status[regnum] = REG_UNKNOWN;
 }
@@ -398,10 +324,10 @@ get_thread_arch_aspace_regcache (ptid_t ptid, struct gdbarch *gdbarch,
                                 struct address_space *aspace)
 {
   for (const auto &regcache : regcache::current_regcache)
-    if (ptid_equal (regcache->ptid (), ptid) && regcache->arch () == gdbarch)
+    if (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);
@@ -423,7 +349,7 @@ static struct gdbarch *current_thread_arch;
 struct regcache *
 get_thread_regcache (ptid_t ptid)
 {
-  if (!current_thread_arch || !ptid_equal (current_thread_ptid, ptid))
+  if (!current_thread_arch || current_thread_ptid != ptid)
     {
       current_thread_ptid = ptid;
       current_thread_arch = target_thread_architecture (ptid);
@@ -432,13 +358,21 @@ get_thread_regcache (ptid_t ptid)
   return get_thread_arch_regcache (ptid, current_thread_arch);
 }
 
+/* See regcache.h.  */
+
+struct regcache *
+get_thread_regcache (thread_info *thread)
+{
+  return get_thread_regcache (thread->ptid);
+}
+
 struct regcache *
 get_current_regcache (void)
 {
-  return get_thread_regcache (inferior_ptid);
+  return get_thread_regcache (inferior_thread ());
 }
 
-/* See common/common-regcache.h.  */
+/* See gdbsupport/common-regcache.h.  */
 
 struct regcache *
 get_thread_regcache_for_ptid (ptid_t ptid)
@@ -461,7 +395,7 @@ regcache::regcache_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid)
 {
   for (auto &regcache : regcache::current_regcache)
     {
-      if (ptid_equal (regcache->ptid (), old_ptid))
+      if (regcache->ptid () == old_ptid)
        regcache->set_ptid (new_ptid);
     }
 }
@@ -485,7 +419,7 @@ registers_changed_ptid (ptid_t ptid)
        it != regcache::current_regcache.end ();
        )
     {
-      if (ptid_match ((*it)->ptid (), ptid))
+      if ((*it)->ptid ().matches (ptid))
        {
          delete *it;
          it = regcache::current_regcache.erase_after (oit);
@@ -494,13 +428,13 @@ registers_changed_ptid (ptid_t ptid)
        oit = it++;
     }
 
-  if (ptid_match (current_thread_ptid, ptid))
+  if (current_thread_ptid.matches (ptid))
     {
       current_thread_ptid = null_ptid;
       current_thread_arch = NULL;
     }
 
-  if (ptid_match (inferior_ptid, ptid))
+  if (inferior_ptid.matches (ptid))
     {
       /* We just deleted the regcache of the current thread.  Need to
         forget about any frames we have cached, too.  */
@@ -508,25 +442,18 @@ registers_changed_ptid (ptid_t ptid)
     }
 }
 
+/* See regcache.h.  */
+
 void
-registers_changed (void)
+registers_changed_thread (thread_info *thread)
 {
-  registers_changed_ptid (minus_one_ptid);
-
-  /* Force cleanup of any alloca areas if using C alloca instead of
-     a builtin alloca.  This particular call is used to clean up
-     areas allocated by low level target code which may build up
-     during lengthy interactions between gdb and the target before
-     gdb gives control to the user (ie watchpoints).  */
-  alloca (0);
+  registers_changed_ptid (thread->ptid);
 }
 
 void
-regcache_raw_update (struct regcache *regcache, int regnum)
+registers_changed (void)
 {
-  gdb_assert (regcache != NULL);
-
-  regcache->raw_update (regnum);
+  registers_changed_ptid (minus_one_ptid);
 }
 
 void
@@ -539,7 +466,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);
 
@@ -551,12 +478,6 @@ regcache::raw_update (int regnum)
     }
 }
 
-enum register_status
-regcache_raw_read (struct regcache *regcache, int regnum, gdb_byte *buf)
-{
-  return regcache->raw_read (regnum, buf);
-}
-
 enum register_status
 readable_regcache::raw_read (int regnum, gdb_byte *buf)
 {
@@ -569,7 +490,7 @@ readable_regcache::raw_read (int regnum, gdb_byte *buf)
     memcpy (buf, register_buffer (regnum),
            m_descr->sizeof_register[regnum]);
 
-  return (enum register_status) m_register_status[regnum];
+  return m_register_status[regnum];
 }
 
 enum register_status
@@ -647,12 +568,6 @@ regcache_raw_get_signed (struct regcache *regcache, int regnum)
   return value;
 }
 
-enum register_status
-regcache_cooked_read (struct regcache *regcache, int regnum, gdb_byte *buf)
-{
-  return regcache->cooked_read (regnum, buf);
-}
-
 enum register_status
 readable_regcache::cooked_read (int regnum, gdb_byte *buf)
 {
@@ -669,7 +584,7 @@ readable_regcache::cooked_read (int regnum, gdb_byte *buf)
       else
        memset (buf, 0, m_descr->sizeof_register[regnum]);
 
-      return (enum register_status) m_register_status[regnum];
+      return m_register_status[regnum];
     }
   else if (gdbarch_pseudo_register_read_value_p (m_descr->gdbarch))
     {
@@ -698,12 +613,6 @@ readable_regcache::cooked_read (int regnum, gdb_byte *buf)
                                         regnum, buf);
 }
 
-struct value *
-regcache_cooked_read_value (struct regcache *regcache, int regnum)
-{
-  return regcache->cooked_read_value (regnum);
-}
-
 struct value *
 readable_regcache::cooked_read_value (int regnum)
 {
@@ -798,21 +707,12 @@ regcache_cooked_write_unsigned (struct regcache *regcache, int regnum,
   regcache->cooked_write (regnum, val);
 }
 
-void
-regcache_raw_write (struct regcache *regcache, int regnum,
-                   const gdb_byte *buf)
-{
-  gdb_assert (regcache != NULL && buf != NULL);
-  regcache->raw_write (regnum, buf);
-}
-
 void
 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.  */
@@ -831,7 +731,8 @@ regcache::raw_write (int regnum, const gdb_byte *buf)
 
   /* Invalidate the register after it is written, in case of a
      failure.  */
-  regcache_invalidator invalidator (this, regnum);
+  auto invalidator
+    = make_scope_exit ([&] { this->invalidate (regnum); });
 
   target_store_registers (this, regnum);
 
@@ -840,13 +741,6 @@ regcache::raw_write (int regnum, const gdb_byte *buf)
   invalidator.release ();
 }
 
-void
-regcache_cooked_write (struct regcache *regcache, int regnum,
-                      const gdb_byte *buf)
-{
-  regcache->cooked_write (regnum, buf);
-}
-
 void
 regcache::cooked_write (int regnum, const gdb_byte *buf)
 {
@@ -859,100 +753,155 @@ regcache::cooked_write (int regnum, const gdb_byte *buf)
                                   regnum, buf);
 }
 
-/* Perform a partial register transfer using a read, modify, write
-   operation.  */
-
-typedef void (regcache_read_ftype) (struct regcache *regcache, int regnum,
-                                   void *buf);
-typedef void (regcache_write_ftype) (struct regcache *regcache, int regnum,
-                                    const void *buf);
+/* See regcache.h.  */
 
 enum register_status
-readable_regcache::read_part (int regnum, int offset, int len, void *in,
-                             bool is_raw)
+readable_regcache::read_part (int regnum, int offset, int len,
+                             gdb_byte *out, bool is_raw)
 {
-  struct gdbarch *gdbarch = arch ();
-  gdb_byte *reg = (gdb_byte *) alloca (register_size (gdbarch, regnum));
+  int reg_size = register_size (arch (), regnum);
+
+  gdb_assert (out != NULL);
+  gdb_assert (offset >= 0 && offset <= reg_size);
+  gdb_assert (len >= 0 && offset + len <= reg_size);
+
+  if (offset == 0 && len == 0)
+    {
+      /* Nothing to do.  */
+      return REG_VALID;
+    }
+
+  if (offset == 0 && len == reg_size)
+    {
+      /* Read the full register.  */
+      return (is_raw) ? raw_read (regnum, out) : cooked_read (regnum, out);
+    }
 
-  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;
+  gdb_byte *reg = (gdb_byte *) alloca (reg_size);
 
-  if (is_raw)
-    status = raw_read (regnum, reg);
-  else
-    status = cooked_read (regnum, reg);
+  /* Read full register to buffer.  */
+  status = (is_raw) ? raw_read (regnum, reg) : cooked_read (regnum, reg);
   if (status != REG_VALID)
     return status;
 
-  /* ... modify ...  */
-  memcpy (in, reg + offset, len);
-
+  /* Copy out.  */
+  memcpy (out, reg + offset, len);
   return REG_VALID;
 }
 
+/* See regcache.h.  */
+
+void
+reg_buffer::raw_collect_part (int regnum, int offset, int len,
+                             gdb_byte *out) const
+{
+  int reg_size = register_size (arch (), regnum);
+
+  gdb_assert (out != nullptr);
+  gdb_assert (offset >= 0 && offset <= reg_size);
+  gdb_assert (len >= 0 && offset + len <= reg_size);
+
+  if (offset == 0 && len == 0)
+    {
+      /* Nothing to do.  */
+      return;
+    }
+
+  if (offset == 0 && len == reg_size)
+    {
+      /* Collect the full register.  */
+      return raw_collect (regnum, out);
+    }
+
+  /* Read to buffer, then write out.  */
+  gdb_byte *reg = (gdb_byte *) alloca (reg_size);
+  raw_collect (regnum, reg);
+  memcpy (out, reg + offset, len);
+}
+
+/* See regcache.h.  */
+
 enum register_status
 regcache::write_part (int regnum, int offset, int len,
-                    const void *out, bool is_raw)
+                     const gdb_byte *in, bool is_raw)
 {
-  struct gdbarch *gdbarch = arch ();
-  gdb_byte *reg = (gdb_byte *) alloca (register_size (gdbarch, regnum));
+  int reg_size = register_size (arch (), 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 (offset > 0
-      || offset + len < m_descr->sizeof_register[regnum])
+  gdb_assert (in != NULL);
+  gdb_assert (offset >= 0 && offset <= reg_size);
+  gdb_assert (len >= 0 && offset + len <= reg_size);
+
+  if (offset == 0 && len == 0)
     {
-      enum register_status status;
+      /* Nothing to do.  */
+      return REG_VALID;
+    }
 
-      if (is_raw)
-       status = raw_read (regnum, reg);
-      else
-       status = cooked_read (regnum, reg);
-      if (status != REG_VALID)
-       return status;
+  if (offset == 0 && len == reg_size)
+    {
+      /* Write the full register.  */
+      (is_raw) ? raw_write (regnum, in) : cooked_write (regnum, in);
+      return REG_VALID;
     }
 
-  memcpy (reg + offset, out, len);
-  /* ... write (when needed).  */
-  if (is_raw)
-    raw_write (regnum, reg);
-  else
-    cooked_write (regnum, reg);
+  enum register_status status;
+  gdb_byte *reg = (gdb_byte *) alloca (reg_size);
 
+  /* Read existing register to buffer.  */
+  status = (is_raw) ? raw_read (regnum, reg) : cooked_read (regnum, reg);
+  if (status != REG_VALID)
+    return status;
+
+  /* Update buffer, then write back to regcache.  */
+  memcpy (reg + offset, in, len);
+  is_raw ? raw_write (regnum, reg) : cooked_write (regnum, reg);
   return REG_VALID;
 }
 
-enum register_status
-regcache_raw_read_part (struct regcache *regcache, int regnum,
-                       int offset, int len, gdb_byte *buf)
+/* See regcache.h.  */
+
+void
+reg_buffer::raw_supply_part (int regnum, int offset, int len,
+                            const gdb_byte *in)
 {
-  return regcache->raw_read_part (regnum, offset, len, buf);
+  int reg_size = register_size (arch (), regnum);
+
+  gdb_assert (in != nullptr);
+  gdb_assert (offset >= 0 && offset <= reg_size);
+  gdb_assert (len >= 0 && offset + len <= reg_size);
+
+  if (offset == 0 && len == 0)
+    {
+      /* Nothing to do.  */
+      return;
+    }
+
+  if (offset == 0 && len == reg_size)
+    {
+      /* Supply the full register.  */
+      return raw_supply (regnum, in);
+    }
+
+  gdb_byte *reg = (gdb_byte *) alloca (reg_size);
+
+  /* Read existing value to buffer.  */
+  raw_collect (regnum, reg);
+
+  /* Write to buffer, then write out.  */
+  memcpy (reg + offset, in, len);
+  raw_supply (regnum, reg);
 }
 
 enum register_status
-readable_regcache::raw_read_part (int regnum, int offset, int len, gdb_byte *buf)
+readable_regcache::raw_read_part (int regnum, int offset, int len,
+                                 gdb_byte *buf)
 {
   assert_regnum (regnum);
   return read_part (regnum, offset, len, buf, true);
 }
 
-void
-regcache_raw_write_part (struct regcache *regcache, int regnum,
-                        int offset, int len, const gdb_byte *buf)
-{
-  regcache->raw_write_part (regnum, offset, len, buf);
-}
+/* See regcache.h.  */
 
 void
 regcache::raw_write_part (int regnum, int offset, int len,
@@ -962,13 +911,7 @@ regcache::raw_write_part (int regnum, int offset, int len,
   write_part (regnum, offset, len, buf, true);
 }
 
-enum register_status
-regcache_cooked_read_part (struct regcache *regcache, int regnum,
-                          int offset, int len, gdb_byte *buf)
-{
-  return regcache->cooked_read_part (regnum, offset, len, buf);
-}
-
+/* See regcache.h.  */
 
 enum register_status
 readable_regcache::cooked_read_part (int regnum, int offset, int len,
@@ -978,12 +921,7 @@ readable_regcache::cooked_read_part (int regnum, int offset, int len,
   return read_part (regnum, offset, len, buf, false);
 }
 
-void
-regcache_cooked_write_part (struct regcache *regcache, int regnum,
-                           int offset, int len, const gdb_byte *buf)
-{
-  regcache->cooked_write_part (regnum, offset, len, buf);
-}
+/* See regcache.h.  */
 
 void
 regcache::cooked_write_part (int regnum, int offset, int len,
@@ -993,17 +931,10 @@ regcache::cooked_write_part (int regnum, int offset, int len,
   write_part (regnum, offset, len, buf, false);
 }
 
-/* Supply register REGNUM, whose contents are stored in BUF, to REGCACHE.  */
-
-void
-regcache_raw_supply (struct regcache *regcache, int regnum, const void *buf)
-{
-  gdb_assert (regcache != NULL);
-  regcache->raw_supply (regnum, buf);
-}
+/* See gdbsupport/common-regcache.h.  */
 
 void
-detached_regcache::raw_supply (int regnum, const void *buf)
+reg_buffer::raw_supply (int regnum, const void *buf)
 {
   void *regbuf;
   size_t size;
@@ -1028,22 +959,17 @@ detached_regcache::raw_supply (int regnum, const void *buf)
     }
 }
 
-/* Supply register REGNUM to REGCACHE.  Value to supply is an integer stored at
-   address ADDR, in target endian, with length ADDR_LEN and sign IS_SIGNED.  If
-   the register size is greater than ADDR_LEN, then the integer will be sign or
-   zero extended.  If the register size is smaller than the integer, then the
-   most significant bytes of the integer will be truncated.  */
+/* See regcache.h.  */
 
 void
-regcache::raw_supply_integer (int regnum, const gdb_byte *addr, int addr_len,
-                             bool is_signed)
+reg_buffer::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];
@@ -1053,18 +979,15 @@ regcache::raw_supply_integer (int regnum, const gdb_byte *addr, int addr_len,
   m_register_status[regnum] = REG_VALID;
 }
 
-/* Supply register REGNUM with zeroed value to REGCACHE.  This is not the same
-   as calling raw_supply with NULL (which will set the state to
-   unavailable).  */
+/* See regcache.h.  */
 
 void
-regcache::raw_supply_zeroed (int regnum)
+reg_buffer::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];
@@ -1073,17 +996,10 @@ regcache::raw_supply_zeroed (int regnum)
   m_register_status[regnum] = REG_VALID;
 }
 
-/* Collect register REGNUM from REGCACHE and store its contents in BUF.  */
-
-void
-regcache_raw_collect (const struct regcache *regcache, int regnum, void *buf)
-{
-  gdb_assert (regcache != NULL && buf != NULL);
-  regcache->raw_collect (regnum, buf);
-}
+/* See gdbsupport/common-regcache.h.  */
 
 void
-regcache::raw_collect (int regnum, void *buf) const
+reg_buffer::raw_collect (int regnum, void *buf) const
 {
   const void *regbuf;
   size_t size;
@@ -1096,19 +1012,11 @@ regcache::raw_collect (int regnum, void *buf) const
   memcpy (buf, regbuf, size);
 }
 
-/* Transfer a single or all registers belonging to a certain register
-   set to or from a buffer.  This is the main worker function for
-   regcache_supply_regset and regcache_collect_regset.  */
-
-/* Collect register REGNUM from REGCACHE.  Store collected value as an integer
-   at address ADDR, in target endian, with length ADDR_LEN and sign IS_SIGNED.
-   If ADDR_LEN is greater than the register size, then the integer will be sign
-   or zero extended.  If ADDR_LEN is smaller than the register size, then the
-   most significant bytes of the integer will be truncated.  */
+/* See regcache.h.  */
 
 void
-regcache::raw_collect_integer (int regnum, gdb_byte *addr, int addr_len,
-                              bool is_signed) const
+reg_buffer::raw_collect_integer (int regnum, gdb_byte *addr, int addr_len,
+                                bool is_signed) const
 {
   enum bfd_endian byte_order = gdbarch_byte_order (m_descr->gdbarch);
   const gdb_byte *regbuf;
@@ -1123,11 +1031,43 @@ regcache::raw_collect_integer (int regnum, gdb_byte *addr, int addr_len,
                        byte_order);
 }
 
+/* See regcache.h.  */
+
+void
+regcache::transfer_regset_register (struct regcache *out_regcache, int regnum,
+                                   const gdb_byte *in_buf, gdb_byte *out_buf,
+                                   int slot_size, int offs) const
+{
+  struct gdbarch *gdbarch = arch ();
+  int reg_size = std::min (register_size (gdbarch, regnum), slot_size);
+
+  /* Use part versions and reg_size to prevent possible buffer overflows when
+     accessing the regcache.  */
+
+  if (out_buf != nullptr)
+    {
+      raw_collect_part (regnum, 0, reg_size, out_buf + offs);
+
+      /* Ensure any additional space is cleared.  */
+      if (slot_size > reg_size)
+       memset (out_buf + offs + reg_size, 0, slot_size - reg_size);
+    }
+  else if (in_buf != nullptr)
+    out_regcache->raw_supply_part (regnum, 0, reg_size, in_buf + offs);
+  else
+    {
+      /* Invalidate the register.  */
+      out_regcache->raw_supply (regnum, nullptr);
+    }
+}
+
+/* See regcache.h.  */
+
 void
 regcache::transfer_regset (const struct regset *regset,
                           struct regcache *out_regcache,
-                          int regnum, const void *in_buf,
-                          void *out_buf, size_t size) const
+                          int regnum, const gdb_byte *in_buf,
+                          gdb_byte *out_buf, size_t size) const
 {
   const struct regcache_map_entry *map;
   int offs = 0, count;
@@ -1153,12 +1093,8 @@ regcache::transfer_regset (const struct regset *regset,
            if (offs + slot_size > size)
              break;
 
-           if (out_buf)
-             raw_collect (regno, (gdb_byte *) out_buf + offs);
-           else
-             out_regcache->raw_supply (regno, in_buf
-                                       ? (const gdb_byte *) in_buf + offs
-                                       : NULL);
+           transfer_regset_register (out_regcache, regno, in_buf, out_buf,
+                                     slot_size, offs);
          }
       else
        {
@@ -1167,12 +1103,8 @@ regcache::transfer_regset (const struct regset *regset,
          if (offs + slot_size > size)
            return;
 
-         if (out_buf)
-           raw_collect (regnum, (gdb_byte *) out_buf + offs);
-         else
-           out_regcache->raw_supply (regnum, in_buf
-                                     ? (const gdb_byte *) in_buf + offs
-                                     : NULL);
+         transfer_regset_register (out_regcache, regnum, in_buf, out_buf,
+                                   slot_size, offs);
          return;
        }
     }
@@ -1187,14 +1119,14 @@ regcache_supply_regset (const struct regset *regset,
                        struct regcache *regcache,
                        int regnum, const void *buf, size_t size)
 {
-  regcache->supply_regset (regset, regnum, buf, size);
+  regcache->supply_regset (regset, regnum, (const gdb_byte *) buf, size);
 }
 
 void
 regcache::supply_regset (const struct regset *regset,
                         int regnum, const void *buf, size_t size)
 {
-  transfer_regset (regset, this, regnum, buf, NULL, size);
+  transfer_regset (regset, this, regnum, (const gdb_byte *) buf, nullptr, size);
 }
 
 /* Collect register REGNUM from REGCACHE to BUF, using the register
@@ -1206,16 +1138,30 @@ regcache_collect_regset (const struct regset *regset,
                         const struct regcache *regcache,
                         int regnum, void *buf, size_t size)
 {
-  regcache->collect_regset (regset, regnum, buf, size);
+  regcache->collect_regset (regset, regnum, (gdb_byte *) buf, size);
 }
 
 void
 regcache::collect_regset (const struct regset *regset,
                         int regnum, void *buf, size_t size) const
 {
-  transfer_regset (regset, NULL, regnum, NULL, buf, size);
+  transfer_regset (regset, nullptr, regnum, nullptr, (gdb_byte *) buf, size);
 }
 
+/* See gdbsupport/common-regcache.h.  */
+
+bool
+reg_buffer::raw_compare (int regnum, const void *buf, int offset) const
+{
+  gdb_assert (buf != NULL);
+  assert_regnum (regnum);
+
+  const char *regbuf = (const char *) register_buffer (regnum);
+  size_t size = m_descr->sizeof_register[regnum];
+  gdb_assert (size >= offset);
+
+  return (memcmp (buf, regbuf + offset, size - offset) == 0);
+}
 
 /* Special handling for register PC.  */
 
@@ -1315,381 +1261,127 @@ 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_cooked_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)
-  {
-  }
+      /* 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_dump_pseudo)
-         fprintf_unfiltered (file, "Cooked value");
-       else
-         fprintf_unfiltered (file, "Raw value");
-      }
-    else
+      /* Type.  */
       {
-       if (regnum < gdbarch_num_regs (m_gdbarch) || m_dump_pseudo)
-         {
-           auto size = register_size (m_gdbarch, regnum);
-
-           if (size == 0)
-             return;
+       const char *t;
+       std::string name_holder;
 
-           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);
-             }
-         }
+       if (regnum < 0)
+         t = "Type";
        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;
-};
-
-/* 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;
+           static const char blt[] = "builtin_type";
 
-       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:
-      {
-       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
-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
-#include "selftest.h"
+#include "gdbsupport/selftest.h"
 #include "selftest-arch.h"
-#include "gdbthread.h"
 #include "target-float.h"
 
 namespace selftests {
@@ -1759,30 +1451,12 @@ current_regcache_test (void)
   SELF_CHECK (regcache_access::current_regcache_size () == 2);
 }
 
-static void test_target_fetch_registers (target_ops *self, regcache *regs,
-                                        int regno);
-static void test_target_store_registers (target_ops *self, regcache *regs,
-                                        int regno);
-static enum target_xfer_status
-  test_target_xfer_partial (struct target_ops *ops,
-                           enum target_object object,
-                           const char *annex, gdb_byte *readbuf,
-                           const gdb_byte *writebuf,
-                           ULONGEST offset, ULONGEST len,
-                           ULONGEST *xfered_len);
-
 class target_ops_no_register : public test_target_ops
 {
 public:
   target_ops_no_register ()
     : test_target_ops {}
-  {
-    to_fetch_registers = test_target_fetch_registers;
-    to_store_registers = test_target_store_registers;
-    to_xfer_partial = test_target_xfer_partial;
-
-    to_data = this;
-  }
+  {}
 
   void reset ()
   {
@@ -1791,38 +1465,42 @@ public:
     xfer_partial_called = 0;
   }
 
+  void fetch_registers (regcache *regs, int regno) override;
+  void store_registers (regcache *regs, int regno) override;
+
+  enum target_xfer_status xfer_partial (enum target_object object,
+                                       const char *annex, gdb_byte *readbuf,
+                                       const gdb_byte *writebuf,
+                                       ULONGEST offset, ULONGEST len,
+                                       ULONGEST *xfered_len) override;
+
   unsigned int fetch_registers_called = 0;
   unsigned int store_registers_called = 0;
   unsigned int xfer_partial_called = 0;
 };
 
-static void
-test_target_fetch_registers (target_ops *self, regcache *regs, int regno)
+void
+target_ops_no_register::fetch_registers (regcache *regs, int regno)
 {
-  auto ops = static_cast<target_ops_no_register *> (self->to_data);
-
   /* Mark register available.  */
   regs->raw_supply_zeroed (regno);
-  ops->fetch_registers_called++;
+  this->fetch_registers_called++;
 }
 
-static void
-test_target_store_registers (target_ops *self, regcache *regs, int regno)
+void
+target_ops_no_register::store_registers (regcache *regs, int regno)
 {
-  auto ops = static_cast<target_ops_no_register *> (self->to_data);
-
-  ops->store_registers_called++;
+  this->store_registers_called++;
 }
 
-static enum target_xfer_status
-test_target_xfer_partial (struct target_ops *self, enum target_object object,
-                         const char *annex, gdb_byte *readbuf,
-                         const gdb_byte *writebuf,
-                         ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
+enum target_xfer_status
+target_ops_no_register::xfer_partial (enum target_object object,
+                                     const char *annex, gdb_byte *readbuf,
+                                     const gdb_byte *writebuf,
+                                     ULONGEST offset, ULONGEST len,
+                                     ULONGEST *xfered_len)
 {
-  auto ops = static_cast<target_ops_no_register *> (self->to_data);
-
-  ops->xfer_partial_called++;
+  this->xfer_partial_called++;
 
   *xfered_len = len;
   return TARGET_XFER_OK;
@@ -1832,7 +1510,7 @@ class readwrite_regcache : public regcache
 {
 public:
   readwrite_regcache (struct gdbarch *gdbarch)
-    : regcache (gdbarch, nullptr, false)
+    : regcache (gdbarch, nullptr)
   {}
 };
 
@@ -1844,7 +1522,7 @@ cooked_read_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)
+  if (current_top_target ()->stratum () >= process_stratum)
     error (_("target already pushed"));
 
   /* Create a mock environment.  An inferior with a thread, with a
@@ -1857,9 +1535,7 @@ cooked_read_test (struct gdbarch *gdbarch)
   mock_inferior.gdbarch = gdbarch;
   mock_inferior.aspace = &mock_aspace;
   thread_info mock_thread (&mock_inferior, mock_ptid);
-
-  scoped_restore restore_thread_list
-    = make_scoped_restore (&thread_list, &mock_thread);
+  mock_inferior.thread_map[mock_ptid] = &mock_thread;
 
   /* Add the mock inferior to the inferior list so that look ups by
      target+ptid can find it.  */
@@ -1890,19 +1566,21 @@ cooked_read_test (struct gdbarch *gdbarch)
 
   /* Test that read one raw register from regcache_no_target will go
      to the target layer.  */
-  int regnum;
 
   /* Find a raw register which size isn't zero.  */
-  for (regnum = 0; regnum < gdbarch_num_regs (gdbarch); regnum++)
+  int nonzero_regnum;
+  for (nonzero_regnum = 0;
+       nonzero_regnum < gdbarch_num_regs (gdbarch);
+       nonzero_regnum++)
     {
-      if (register_size (gdbarch, regnum) != 0)
+      if (register_size (gdbarch, nonzero_regnum) != 0)
        break;
     }
 
   readwrite_regcache readwrite (gdbarch);
-  gdb::def_vector<gdb_byte> buf (register_size (gdbarch, regnum));
+  gdb::def_vector<gdb_byte> buf (register_size (gdbarch, nonzero_regnum));
 
-  readwrite.raw_read (regnum, buf.data ());
+  readwrite.raw_read (nonzero_regnum, buf.data ());
 
   /* raw_read calls target_fetch_registers.  */
   SELF_CHECK (mock_target.fetch_registers_called > 0);
@@ -1916,43 +1594,37 @@ cooked_read_test (struct gdbarch *gdbarch)
   mock_target.reset ();
   /* Then, read all raw and pseudo registers, and don't expect calling
      to_{fetch,store}_registers.  */
-  for (int regnum = 0;
-       regnum < gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
-       regnum++)
+  for (int regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
     {
       if (register_size (gdbarch, regnum) == 0)
        continue;
 
-      gdb::def_vector<gdb_byte> buf (register_size (gdbarch, regnum));
+      gdb::def_vector<gdb_byte> inner_buf (register_size (gdbarch, regnum));
 
-      SELF_CHECK (REG_VALID == readwrite.cooked_read (regnum, buf.data ()));
+      SELF_CHECK (REG_VALID == readwrite.cooked_read (regnum,
+                                                     inner_buf.data ()));
 
       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)
-       SELF_CHECK (mock_target.xfer_partial_called == 0);
+      SELF_CHECK (mock_target.xfer_partial_called == 0);
 
       mock_target.reset ();
     }
 
-  regcache readonly (regcache::readonly, readwrite);
+  readonly_detached_regcache readonly (readwrite);
 
   /* GDB may go to target layer to fetch all registers and memory for
      readonly regcache.  */
   mock_target.reset ();
 
-  for (int regnum = 0;
-       regnum < gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
-       regnum++)
+  for (int regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
     {
       if (register_size (gdbarch, regnum) == 0)
        continue;
 
-      gdb::def_vector<gdb_byte> buf (register_size (gdbarch, regnum));
+      gdb::def_vector<gdb_byte> inner_buf (register_size (gdbarch, regnum));
       enum register_status status = readonly.cooked_read (regnum,
-                                                         buf.data ());
+                                                         inner_buf.data ());
 
       if (regnum < gdbarch_num_regs (gdbarch))
        {
@@ -1964,7 +1636,8 @@ cooked_read_test (struct gdbarch *gdbarch)
              || bfd_arch == bfd_arch_msp430 || bfd_arch == bfd_arch_mep
              || bfd_arch == bfd_arch_mips || bfd_arch == bfd_arch_v850_rh850
              || bfd_arch == bfd_arch_tic6x || bfd_arch == bfd_arch_mn10300
-             || bfd_arch == bfd_arch_rl78 || bfd_arch == bfd_arch_score)
+             || bfd_arch == bfd_arch_rl78 || bfd_arch == bfd_arch_score
+             || bfd_arch == bfd_arch_riscv || bfd_arch == bfd_arch_csky)
            {
              /* Raw registers.  If raw registers are not in save_reggroup,
                 their status are unknown.  */
@@ -2017,7 +1690,7 @@ 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)
+  if (current_top_target ()->stratum () >= process_stratum)
     error (_("target already pushed"));
 
   /* Create a mock environment.  A process_stratum target pushed.  */
@@ -2039,8 +1712,7 @@ cooked_write_test (struct gdbarch *gdbarch)
 
   readwrite_regcache readwrite (gdbarch);
 
-  const int num_regs = (gdbarch_num_regs (gdbarch)
-                       + gdbarch_num_pseudo_regs (gdbarch));
+  const int num_regs = gdbarch_num_cooked_regs (gdbarch);
 
   for (auto regnum = 0; regnum < num_regs; regnum++)
     {
@@ -2050,20 +1722,12 @@ cooked_write_test (struct gdbarch *gdbarch)
 
       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))
+      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))
        continue;
 
       std::vector<gdb_byte> expected (register_size (gdbarch, regnum), 0);
@@ -2138,37 +1802,12 @@ _initialize_regcache (void)
   regcache_descr_handle
     = gdbarch_data_register_post_init (init_regcache_descr);
 
-  observer_attach_target_changed (regcache_observer_target_changed);
-  observer_attach_thread_ptid_changed (regcache::regcache_thread_ptid_changed);
+  gdb::observers::target_changed.attach (regcache_observer_target_changed);
+  gdb::observers::thread_ptid_changed.attach
+    (regcache::regcache_thread_ptid_changed);
 
   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);
+          _("Force gdb to flush its register cache (maintainer command)."));
 
 #if GDB_SELF_TEST
   selftests::register_test ("current_regcache", selftests::current_regcache_test);
This page took 0.044958 seconds and 4 git commands to generate.