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.
This commit is contained in:
parent
d388f64333
commit
33bab475a6
|
@ -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>
|
2018-06-21 Richard Bunt <richard.bunt@arm.com>
|
||||||
Dirk Schubert <dirk.schubert@arm.com>
|
Dirk Schubert <dirk.schubert@arm.com>
|
||||||
|
|
||||||
|
|
106
gdb/regcache.c
106
gdb/regcache.c
|
@ -775,77 +775,85 @@ regcache::cooked_write (int regnum, const gdb_byte *buf)
|
||||||
regnum, buf);
|
regnum, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform a partial register transfer using a read, modify, write
|
/* See regcache.h. */
|
||||||
operation. */
|
|
||||||
|
|
||||||
enum register_status
|
enum register_status
|
||||||
readable_regcache::read_part (int regnum, int offset, int len, void *in,
|
readable_regcache::read_part (int regnum, int offset, int len,
|
||||||
bool is_raw)
|
gdb_byte *out, bool is_raw)
|
||||||
{
|
{
|
||||||
struct gdbarch *gdbarch = arch ();
|
int reg_size = register_size (arch (), regnum);
|
||||||
gdb_byte *reg = (gdb_byte *) alloca (register_size (gdbarch, 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;
|
enum register_status status;
|
||||||
|
gdb_byte *reg = (gdb_byte *) alloca (reg_size);
|
||||||
|
|
||||||
if (is_raw)
|
/* Read full register to buffer. */
|
||||||
status = raw_read (regnum, reg);
|
status = (is_raw) ? raw_read (regnum, reg) : cooked_read (regnum, reg);
|
||||||
else
|
|
||||||
status = cooked_read (regnum, reg);
|
|
||||||
if (status != REG_VALID)
|
if (status != REG_VALID)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
/* ... modify ... */
|
/* Copy out. */
|
||||||
memcpy (in, reg + offset, len);
|
memcpy (out, reg + offset, len);
|
||||||
|
|
||||||
return REG_VALID;
|
return REG_VALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See regcache.h. */
|
||||||
|
|
||||||
enum register_status
|
enum register_status
|
||||||
regcache::write_part (int regnum, int offset, int len,
|
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 ();
|
int reg_size = register_size (arch (), regnum);
|
||||||
gdb_byte *reg = (gdb_byte *) alloca (register_size (gdbarch, regnum));
|
|
||||||
|
|
||||||
gdb_assert (out != NULL);
|
gdb_assert (in != NULL);
|
||||||
gdb_assert (offset >= 0 && offset <= m_descr->sizeof_register[regnum]);
|
gdb_assert (offset >= 0 && len >= 0 && offset + len <= reg_size);
|
||||||
gdb_assert (len >= 0 && offset + len <= m_descr->sizeof_register[regnum]);
|
|
||||||
/* Something to do? */
|
if (offset == 0 && len == 0)
|
||||||
if (offset + len == 0)
|
|
||||||
return REG_VALID;
|
|
||||||
/* Read (when needed) ... */
|
|
||||||
if (offset > 0
|
|
||||||
|| offset + len < m_descr->sizeof_register[regnum])
|
|
||||||
{
|
{
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy (reg + offset, out, len);
|
if (offset == 0 && len == reg_size)
|
||||||
/* ... write (when needed). */
|
{
|
||||||
if (is_raw)
|
/* Write the full register. */
|
||||||
raw_write (regnum, reg);
|
(is_raw) ? raw_write (regnum, in) : cooked_write (regnum, in);
|
||||||
else
|
return REG_VALID;
|
||||||
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;
|
return REG_VALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See regcache.h. */
|
||||||
|
|
||||||
enum register_status
|
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);
|
assert_regnum (regnum);
|
||||||
return read_part (regnum, offset, len, buf, true);
|
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);
|
write_part (regnum, offset, len, buf, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See regcache.h. */
|
||||||
|
|
||||||
enum register_status
|
enum register_status
|
||||||
readable_regcache::cooked_read_part (int regnum, int offset, int len,
|
readable_regcache::cooked_read_part (int regnum, int offset, int len,
|
||||||
gdb_byte *buf)
|
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);
|
return read_part (regnum, offset, len, buf, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See regcache.h. */
|
||||||
|
|
||||||
void
|
void
|
||||||
regcache::cooked_write_part (int regnum, int offset, int len,
|
regcache::cooked_write_part (int regnum, int offset, int len,
|
||||||
const gdb_byte *buf)
|
const gdb_byte *buf)
|
||||||
|
|
|
@ -253,8 +253,11 @@ public:
|
||||||
struct value *cooked_read_value (int regnum);
|
struct value *cooked_read_value (int regnum);
|
||||||
|
|
||||||
protected:
|
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. */
|
/* Buffer of registers, can be read and written. */
|
||||||
|
@ -355,9 +358,10 @@ private:
|
||||||
int regnum, const void *in_buf,
|
int regnum, const void *in_buf,
|
||||||
void *out_buf, size_t size) const;
|
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,
|
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
|
/* The address space of this register cache (for registers where it
|
||||||
makes sense, like PC or SP). */
|
makes sense, like PC or SP). */
|
||||||
|
|
Loading…
Reference in New Issue