aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Hayward <alan.hayward@arm.com>2018-06-20 09:31:37 +0100
committerAlan Hayward <alan.hayward@arm.com>2018-06-21 16:27:15 +0100
commit33bab475a6984afedac8a036b3bb40b5555b4127 (patch)
tree90001a8f3d2240a6bb406e5d9916e4475c70d35a
parentd388f64333fb977c1b975cb9d26c762b143f4cb9 (diff)
downloadgdb-33bab475a6984afedac8a036b3bb40b5555b4127.zip
gdb-33bab475a6984afedac8a036b3bb40b5555b4127.tar.gz
gdb-33bab475a6984afedac8a036b3bb40b5555b4127.tar.bz2
Avoid memcpys in regcache read_part/write_part for full registers.
Additionally, tidy up the functions: Remove asserts, use gdb_byte, update comments. gdb/ * regcache.c (readable_regcache::read_part): Avoid memcpy when possible. (regcache::write_part): Likewise. (readable_regcache::cooked_read_part): Update comment. (readable_regcache::cooked_write_part): Likewise. * regcache.h: (readable_regcache::read_part): Likewise. (regcache::write_part): Likewise.
-rw-r--r--gdb/ChangeLog10
-rw-r--r--gdb/regcache.c104
-rw-r--r--gdb/regcache.h12
3 files changed, 76 insertions, 50 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b48f58c..6345d85 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,13 @@
+2018-06-21 Alan Hayward <alan.hayward@arm.com>
+
+ * regcache.c (readable_regcache::read_part): Avoid memcpy when
+ possible.
+ (regcache::write_part): Likewise.
+ (readable_regcache::cooked_read_part): Update comment.
+ (readable_regcache::cooked_write_part): Likewise.
+ * regcache.h: (readable_regcache::read_part): Likewise.
+ (regcache::write_part): Likewise.
+
2018-06-21 Richard Bunt <richard.bunt@arm.com>
Dirk Schubert <dirk.schubert@arm.com>
diff --git a/gdb/regcache.c b/gdb/regcache.c
index 25436bb..536322b 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -775,77 +775,85 @@ regcache::cooked_write (int regnum, const gdb_byte *buf)
regnum, buf);
}
-/* Perform a partial register transfer using a read, modify, write
- operation. */
+/* 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 && 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. */
+
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 && 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;
}
+/* See regcache.h. */
+
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);
@@ -861,6 +869,8 @@ regcache::raw_write_part (int regnum, int offset, int len,
write_part (regnum, offset, len, buf, true);
}
+/* See regcache.h. */
+
enum register_status
readable_regcache::cooked_read_part (int regnum, int offset, int len,
gdb_byte *buf)
@@ -869,6 +879,8 @@ readable_regcache::cooked_read_part (int regnum, int offset, int len,
return read_part (regnum, offset, len, buf, false);
}
+/* See regcache.h. */
+
void
regcache::cooked_write_part (int regnum, int offset, int len,
const gdb_byte *buf)
diff --git a/gdb/regcache.h b/gdb/regcache.h
index 74ac858..5e96a7a 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -253,8 +253,11 @@ public:
struct value *cooked_read_value (int regnum);
protected:
- enum register_status read_part (int regnum, int offset, int len, void *in,
- bool is_raw);
+
+ /* Perform a partial register transfer using a read, modify, write
+ operation. Will fail if register is currently invalid. */
+ enum register_status read_part (int regnum, int offset, int len,
+ gdb_byte *out, bool is_raw);
};
/* Buffer of registers, can be read and written. */
@@ -355,9 +358,10 @@ private:
int regnum, const void *in_buf,
void *out_buf, size_t size) const;
+ /* Perform a partial register transfer using a read, modify, write
+ operation. */
enum register_status write_part (int regnum, int offset, int len,
- const void *out, bool is_raw);
-
+ const gdb_byte *in, bool is_raw);
/* The address space of this register cache (for registers where it
makes sense, like PC or SP). */