summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Hayward <alan.hayward@arm.com>2017-08-15 16:39:04 +0100
committerAlan Hayward <alan.hayward@arm.com>2017-08-15 16:39:04 +0100
commitc14731f7e9563ca9cd92dddc1e0cd47184f36969 (patch)
tree18bfd355198d85b5a25763facde01e5546da6905
parent15587be5bd4f8e1db324aa4f8950369a628ccc21 (diff)
downloadbinutils-gdb-c14731f7e9563ca9cd92dddc1e0cd47184f36969.tar.gz
[PATCH 2/7] Regcache: Only target_regcache reads/writes go to the target
-rw-r--r--gdb/regcache.c33
-rw-r--r--gdb/regcache.h24
2 files changed, 40 insertions, 17 deletions
diff --git a/gdb/regcache.c b/gdb/regcache.c
index 3d6ca86006f..524ac5754f6 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -597,16 +597,14 @@ regcache_raw_update (struct regcache *regcache, int regnum)
}
void
-regcache::raw_update (int regnum)
+target_regcache::raw_update (int regnum)
{
gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
/* Make certain that the register cache is up-to-date with respect
- to the current thread. This switching shouldn't be necessary
- only there is still only one target side register cache. Sigh!
- On the bright side, at least there is a regcache object. */
+ to the current thread. */
- if (!m_readonly_p && get_register_status (regnum) == REG_UNKNOWN)
+ if (get_register_status (regnum) == REG_UNKNOWN)
{
target_fetch_registers (this, regnum);
@@ -627,7 +625,16 @@ regcache_raw_read (struct regcache *regcache, int regnum, gdb_byte *buf)
enum register_status
regcache::raw_read (int regnum, gdb_byte *buf)
{
+ raw_collect (regnum, buf);
+ return (enum register_status) m_register_status[regnum];
+}
+
+enum register_status
+target_regcache::raw_read (int regnum, gdb_byte *buf)
+{
gdb_assert (buf != NULL);
+
+ /* Read register value from the target into the regcache. */
raw_update (regnum);
if (m_register_status[regnum] != REG_VALID)
@@ -895,11 +902,25 @@ regcache_raw_write (struct regcache *regcache, int regnum,
void
regcache::raw_write (int regnum, const gdb_byte *buf)
{
+ gdb_assert (buf != NULL);
+ gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
+ 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. */
+ if (gdbarch_cannot_store_register (arch (), regnum))
+ return;
+
+ raw_set_cached_value (regnum, buf);
+}
+
+void
+target_regcache::raw_write (int regnum, const gdb_byte *buf)
+{
struct cleanup *old_chain;
gdb_assert (buf != NULL);
gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
- 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. */
diff --git a/gdb/regcache.h b/gdb/regcache.h
index bc3f24cffe1..aeac54e8d7b 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -242,7 +242,8 @@ typedef struct cached_reg
} cached_reg_t;
-/* A register cache. This is not connected to a target and ptid is unset. */
+/* A register cache. This is not connected to a target - reads and writes will
+ not be passed through to a target and ptid is unset. */
class regcache
{
@@ -283,14 +284,8 @@ public:
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);
-
- /* class regcache is only extended in unit test, so only mark it
- virtual when selftest is enabled. */
-#if GDB_SELF_TEST
- virtual
-#endif
- void raw_write (int regnum, const gdb_byte *buf);
+ virtual enum register_status raw_read (int regnum, gdb_byte *buf);
+ virtual void raw_write (int regnum, const gdb_byte *buf);
template<typename T, typename = RequireLongest<T>>
enum register_status raw_read (int regnum, T *val);
@@ -306,7 +301,7 @@ public:
template<typename T, typename = RequireLongest<T>>
void cooked_write (int regnum, T val);
- void raw_update (int regnum);
+ virtual void raw_update (int regnum) {}
void raw_collect (int regnum, void *buf) const;
@@ -403,12 +398,19 @@ private:
};
-/* A register cache that can be attached to a target. ptid can be set. */
+/* A register cache attached to a target. Reads and writes of register values
+ will be passed through to the target and ptid can be set. */
class target_regcache : public regcache
{
public:
+ /* Overridden regcache methods. These versions will pass the read/write
+ through to the target. */
+ enum register_status raw_read (int regnum, gdb_byte *buf);
+ virtual void raw_write (int regnum, const gdb_byte *buf);
+ void raw_update (int regnum);
+
ptid_t ptid () const
{
return m_ptid;