diff options
author | Andrew Cagney <cagney@redhat.com> | 2002-08-25 18:47:16 +0000 |
---|---|---|
committer | Andrew Cagney <cagney@redhat.com> | 2002-08-25 18:47:16 +0000 |
commit | d3b22ed57cf5e17e4172752a17f61a719bf9103a (patch) | |
tree | 05bc81ffda8d77748be7d300c319ac10c3c7b5ae | |
parent | 90949d06a32b215ed910106ac175f56f531cfecf (diff) | |
download | gdb-d3b22ed57cf5e17e4172752a17f61a719bf9103a.zip gdb-d3b22ed57cf5e17e4172752a17f61a719bf9103a.tar.gz gdb-d3b22ed57cf5e17e4172752a17f61a719bf9103a.tar.bz2 |
2002-08-25 Andrew Cagney <ac131313@redhat.com>
* regcache.h (register_offset_hack): Declare.
(regcache_cooked_read_using_offset_hack): Declare.
(regcache_cooked_write_using_offset_hack): Declare.
* regcache.c (register_offset_hack): New function.
(regcache_cooked_read_using_offset_hack): New function.
(regcache_cooked_write_using_offset_hack): New function.
(regcache_dump): Check that the registers, according to their
offset, are packed hard against each other.
(cooked_xfer_using_offset_hack): New function.
-rw-r--r-- | gdb/ChangeLog | 13 | ||||
-rw-r--r-- | gdb/regcache.c | 96 | ||||
-rw-r--r-- | gdb/regcache.h | 27 |
3 files changed, 135 insertions, 1 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 30edafe..3d9bb66 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,18 @@ 2002-08-25 Andrew Cagney <ac131313@redhat.com> + * regcache.h (register_offset_hack): Declare. + (regcache_cooked_read_using_offset_hack): Declare. + (regcache_cooked_write_using_offset_hack): Declare. + + * regcache.c (register_offset_hack): New function. + (regcache_cooked_read_using_offset_hack): New function. + (regcache_cooked_write_using_offset_hack): New function. + (regcache_dump): Check that the registers, according to their + offset, are packed hard against each other. + (cooked_xfer_using_offset_hack): New function. + +2002-08-25 Andrew Cagney <ac131313@redhat.com> + * regcache.c (struct regcache_descr): Add field register_type. (init_legacy_regcache_descr): Pass a pre-allocated regcache_descr in as a parameter diff --git a/gdb/regcache.c b/gdb/regcache.c index 8fd8015..6c86ba9 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -1029,6 +1029,95 @@ regcache_cooked_write_part (struct regcache *regcache, int regnum, regcache_cooked_read, regcache_cooked_write); } +/* Hack to keep code that view the register buffer as raw bytes + working. */ + +int +register_offset_hack (struct gdbarch *gdbarch, int regnum) +{ + struct regcache_descr *descr = regcache_descr (gdbarch); + gdb_assert (regnum >= 0 && regnum < descr->nr_cooked_registers); + return descr->register_offset[regnum]; +} + +static void +cooked_xfer_using_offset_hack (struct regcache *regcache, + int buf_start, int buf_len, void *in_b, + const void *out_b) +{ + struct regcache_descr *descr = regcache->descr; + struct gdbarch *gdbarch = descr->gdbarch; + bfd_byte *in_buf = in_b; + const bfd_byte *out_buf = out_b; + int buf_end = buf_start + buf_len; + int regnum; + char *reg_buf = alloca (descr->max_register_size); + + /* NOTE: cagney/2002-08-17: This code assumes that the register + offsets are strictly increasing and do not overlap. If this + isn't the case then the bug is in the target architecture and NOT + this code. */ + + /* NOTE: cagney/2002-08-17: This code assumes that only the + registers covered by BUF_START:BUF_LEN should be transfered. If, + for some reason, there is a gap between two registers, then that + gap isn't transfered. (The gap shouldn't be there but that is + another story.) */ + + /* Iterate through all registers looking for those that lie within + BUF_START:BUF_LEN. */ + + for (regnum = 0; regnum < descr->nr_cooked_registers; regnum++) + { + /* The register's location. */ + int reg_start = descr->register_offset[regnum]; + int reg_len = descr->sizeof_register[regnum]; + int reg_end = reg_start + reg_len; + + /* The START, END and LEN that falls within the current + register. */ + int xfer_start; + int xfer_end; + int xfer_len; + + /* start = max (reg_start, buf_start) */ + if (reg_start > buf_start) + xfer_start = reg_start; + else + xfer_start = buf_start; + + /* end = min (reg_end, buf_end) */ + if (reg_end < buf_end) + xfer_end = reg_end; + else + xfer_end = buf_end; + + /* The number of bytes to transfer. If there isn't anything to + transfer (the end is before the start) this will be -ve. */ + xfer_len = xfer_end - xfer_start; + + if (xfer_len > 0) + regcache_xfer_part (regcache, regnum, xfer_start - reg_start, + xfer_len, in_b, out_b, regcache_cooked_read, + regcache_cooked_write); + } +} + +void +regcache_cooked_read_using_offset_hack (struct regcache *regcache, + int buf_start, int buf_len, void *b) +{ + cooked_xfer_using_offset_hack (regcache, buf_start, buf_len, b, NULL); +} + +void +regcache_cooked_write_using_offset_hack (struct regcache *regcache, + int buf_start, int buf_len, + const void *b) +{ + cooked_xfer_using_offset_hack (regcache, buf_start, buf_len, NULL, b); +} + /* Return the contents of register REGNUM as an unsigned integer. */ ULONGEST @@ -1439,7 +1528,12 @@ regcache_dump (struct regcache *regcache, struct ui_file *file, fprintf_unfiltered (file, " %6ld", regcache->descr->register_offset[regnum]); if (register_offset != regcache->descr->register_offset[regnum] - || register_offset != REGISTER_BYTE (regnum)) + || register_offset != REGISTER_BYTE (regnum) + || (regnum > 0 + && (regcache->descr->register_offset[regnum] + != (regcache->descr->register_offset[regnum - 1] + + regcache->descr->sizeof_register[regnum - 1]))) + ) { if (!footnote_register_offset) footnote_register_offset = ++footnote_nr; diff --git a/gdb/regcache.h b/gdb/regcache.h index 3c2dbeb..1db42e3 100644 --- a/gdb/regcache.h +++ b/gdb/regcache.h @@ -88,6 +88,33 @@ extern void supply_register (int regnum, const void *val); extern void regcache_collect (int regnum, void *buf); +/* The register's ``offset''. + + NOTE: cagney/2002-08-17: The ``struct value'' and expression + evaluator treat the register cache as a large liner buffer. + Instead of reading/writing a register using its register number, + the code read/writes registers by specifying their offset into the + buffer and a number of bytes. The code also assumes that these + byte read/writes can cross register boundaries, adjacent registers + treated as a contiguous set of bytes. + + The below map that model onto the real register cache. New code + should go out of their way to avoid using these interfaces. + + FIXME: cagney/2002-08-17: The ``struct value'' and expression + evaluator should be fixed. Instead of using the { offset, length } + pair to describe a value within one or more registers, the code + should use a chain of { regnum, offset, len } tripples. */ + +extern int register_offset_hack (struct gdbarch *gdbarch, int regnum); +extern void regcache_cooked_read_using_offset_hack (struct regcache *regcache, + int offset, int len, + void *buf); +extern void regcache_cooked_write_using_offset_hack (struct regcache *regcache, + int offset, int len, + const void *buf); + + /* The type of a register. This function is slightly more efficient then its gdbarch vector counterpart since it returns a precomputed value stored in a table. |