aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorAndrew Cagney <cagney@redhat.com>2002-08-25 18:47:16 +0000
committerAndrew Cagney <cagney@redhat.com>2002-08-25 18:47:16 +0000
commitd3b22ed57cf5e17e4172752a17f61a719bf9103a (patch)
tree05bc81ffda8d77748be7d300c319ac10c3c7b5ae /gdb
parent90949d06a32b215ed910106ac175f56f531cfecf (diff)
downloadgdb-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.
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog13
-rw-r--r--gdb/regcache.c96
-rw-r--r--gdb/regcache.h27
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.