/* Useful constant. Largest of all the registers. */
long max_register_size;
+
+ /* Cached table containing the type of each register. */
+ struct type **register_type;
};
-static void *
-init_legacy_regcache_descr (struct gdbarch *gdbarch)
+void
+init_legacy_regcache_descr (struct gdbarch *gdbarch,
+ struct regcache_descr *descr)
{
int i;
- struct regcache_descr *descr;
/* FIXME: cagney/2002-05-11: gdbarch_data() should take that
``gdbarch'' as a parameter. */
gdb_assert (gdbarch != NULL);
- descr = XMALLOC (struct regcache_descr);
- descr->gdbarch = gdbarch;
- descr->legacy_p = 1;
-
/* FIXME: cagney/2002-05-11: Shouldn't be including pseudo-registers
in the register buffer. Unfortunatly some architectures do. */
- descr->nr_cooked_registers = NUM_REGS + NUM_PSEUDO_REGS;
descr->nr_raw_registers = descr->nr_cooked_registers;
descr->sizeof_raw_register_valid_p = descr->nr_cooked_registers;
descr->sizeof_register[i] = REGISTER_RAW_SIZE (i);
if (descr->max_register_size < REGISTER_RAW_SIZE (i))
descr->max_register_size = REGISTER_RAW_SIZE (i);
+ if (descr->max_register_size < REGISTER_VIRTUAL_SIZE (i))
+ descr->max_register_size = REGISTER_VIRTUAL_SIZE (i);
}
/* Come up with the real size of the registers buffer. */
if (descr->sizeof_raw_registers < regend)
descr->sizeof_raw_registers = regend;
}
- return descr;
}
static void *
struct regcache_descr *descr;
gdb_assert (gdbarch != NULL);
- /* If an old style architecture, construct the register cache
- description using all the register macros. */
- if (!gdbarch_pseudo_register_read_p (gdbarch)
- && !gdbarch_pseudo_register_write_p (gdbarch))
- return init_legacy_regcache_descr (gdbarch);
-
- descr = XMALLOC (struct regcache_descr);
+ /* Create an initial, zero filled, table. */
+ descr = XCALLOC (1, struct regcache_descr);
descr->gdbarch = gdbarch;
- descr->legacy_p = 0;
/* Total size of the register space. The raw registers are mapped
directly onto the raw register cache while the pseudo's are
either mapped onto raw-registers or memory. */
descr->nr_cooked_registers = NUM_REGS + NUM_PSEUDO_REGS;
+ /* Fill in a table of register types. */
+ descr->register_type = XCALLOC (descr->nr_cooked_registers,
+ struct type *);
+ for (i = 0; i < descr->nr_cooked_registers; i++)
+ {
+ descr->register_type[i] = REGISTER_VIRTUAL_TYPE (i);
+ }
+
+ /* If an old style architecture, fill in the remainder of the
+ register cache descriptor using the register macros. */
+ if (!gdbarch_pseudo_register_read_p (gdbarch)
+ && !gdbarch_pseudo_register_write_p (gdbarch))
+ {
+ descr->legacy_p = 1;
+ init_legacy_regcache_descr (gdbarch, descr);
+ return descr;
+ }
+
/* Construct a strictly RAW register cache. Don't allow pseudo's
into the register cache. */
descr->nr_raw_registers = NUM_REGS;
cache. Some code, via read_register_bytes() access a register
using an offset/length rather than a register number.
- NOTE: cagney/2002-05-22: Only REGISTER_VIRTUAL_TYPE() needs to be
- used when constructing the register cache. It is assumed that
- register raw size, virtual size and type length of the type are
- all the same. */
+ NOTE: cagney/2002-05-22: Only register_type() is used when
+ constructing the register cache. It is assumed that the
+ register's raw size, virtual size and type length are all the
+ same. */
{
long offset = 0;
descr->max_register_size = 0;
for (i = 0; i < descr->nr_cooked_registers; i++)
{
- descr->sizeof_register[i] = TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (i));
+ descr->sizeof_register[i] = TYPE_LENGTH (descr->register_type[i]);
descr->register_offset[i] = offset;
offset += descr->sizeof_register[i];
if (descr->max_register_size < descr->sizeof_register[i])
xfree (descr);
}
+/* Utility functions returning useful register attributes stored in
+ the regcache descr. */
+
+struct type *
+register_type (struct gdbarch *gdbarch, int regnum)
+{
+ struct regcache_descr *descr = regcache_descr (gdbarch);
+ gdb_assert (regnum >= 0 && regnum < descr->nr_cooked_registers);
+ return descr->register_type[regnum];
+}
+
+/* Utility functions returning useful register attributes stored in
+ the regcache descr. */
+
+int
+max_register_size (struct gdbarch *gdbarch)
+{
+ struct regcache_descr *descr = regcache_descr (gdbarch);
+ return descr->max_register_size;
+}
+
/* The register cache for storing raw register values. */
struct regcache
regcache->descr->sizeof_register[regnum]);
}
+void
+regcache_raw_write_signed (struct regcache *regcache, int regnum, LONGEST val)
+{
+ void *buf;
+ gdb_assert (regcache != NULL);
+ gdb_assert (regnum >=0 && regnum < regcache->descr->nr_raw_registers);
+ buf = alloca (regcache->descr->sizeof_register[regnum]);
+ store_signed_integer (buf, regcache->descr->sizeof_register[regnum], val);
+ regcache_raw_write (regcache, regnum, buf);
+}
+
+void
+regcache_raw_write_unsigned (struct regcache *regcache, int regnum,
+ ULONGEST val)
+{
+ void *buf;
+ gdb_assert (regcache != NULL);
+ gdb_assert (regnum >=0 && regnum < regcache->descr->nr_raw_registers);
+ buf = alloca (regcache->descr->sizeof_register[regnum]);
+ store_unsigned_integer (buf, regcache->descr->sizeof_register[regnum], val);
+ regcache_raw_write (regcache, regnum, buf);
+}
+
void
read_register_gen (int regnum, char *buf)
{
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
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;
|| (regcache->descr->sizeof_register[regnum]
!= REGISTER_VIRTUAL_SIZE (regnum))
|| (regcache->descr->sizeof_register[regnum]
- != TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (regnum)))
+ != TYPE_LENGTH (register_type (regcache->descr->gdbarch,
+ regnum)))
)
{
if (!footnote_register_size)
else
{
static const char blt[] = "builtin_type";
- const char *t = TYPE_NAME (REGISTER_VIRTUAL_TYPE (regnum));
+ const char *t = TYPE_NAME (register_type (regcache->descr->gdbarch,
+ regnum));
if (t == NULL)
{
char *n;