* regcache.h: Update copyright.
(struct regcache, struct gdbarch): Add opaque declarations. (current_regcache): Declare global variable. (regcache_read, regcache_write): Add gdbarch parameter. (regcache_save, regcache_save_no_passthrough) (regcache_restore, regcache_restore_no_passthrough) (regcache_dup, regcache_dup_no_passthrough) (regcache_cpy, regcache_cpy_no_passthrough) (deprecated_grub_regcache_for_registers) (deprecated_grub_regcache_for_register_valid) (regcache_valid_p): Add function declarations. * regcache.c: Update copyright. (regcache_descr_handle): New global variable. (struct regcache_descr): Define. (init_legacy_regcache_descr, init_regcache_descr): New functions. (regcache_descr, xfree_regcache_descr): New functions. (struct regcache): Define. (regcache_xmalloc, regcache_xfree): New functions. (regcache_cpy, regcache_cpy_no_passthrough): New functions. (regcache_dup, regcache_dup_no_passthrough): New functions. (regcache_valid_p, regcache_read_as_address): New functions. (deprecated_grub_regcache_for_registers): New function. (deprecated_grub_regcache_for_register_valid): New function. (current_regcache): New global variable. (register_buffer): Add regcache parameter. Update calls. (regcache_read, regcache_write): Add regcache parameter. Rewrite. (read_register_gen, write_register_gen): Update register_buffer call. Test for legacy_p instead of gdbarch_register_read_p or gdbarch_register_write_p. (regcache_collect): Update register_buffer call. (build_regcache): Rewrite. Use deprecated grub functions. (regcache_save, regcache_save_no_passthrough): New functions. (regcache_restore, regcache_restore_no_passthrough): New functions. (_initialize_regcache): Create the regcache_data_handle. Swap current_regcache global variable. * sh-tdep.c (sh_pseudo_register_read): Add current_regcache parameter to regcache_read and regcache_write calls. (sh4_register_read): Ditto. (sh64_pseudo_register_read): Ditto. (sh64_register_read): Ditto. (sh_pseudo_register_write): Ditto. (sh4_register_write): Ditto. (sh64_pseudo_register_write): Ditto. (sh64_register_write): Ditto. * defs.h (XCALLOC): Define.
This commit is contained in:
parent
e1820627dc
commit
3fadccb31d
5 changed files with 620 additions and 94 deletions
|
@ -1,3 +1,55 @@
|
||||||
|
2002-06-19 Andrew Cagney <cagney@redhat.com>
|
||||||
|
|
||||||
|
* regcache.h: Update copyright.
|
||||||
|
(struct regcache, struct gdbarch): Add opaque declarations.
|
||||||
|
(current_regcache): Declare global variable.
|
||||||
|
(regcache_read, regcache_write): Add gdbarch parameter.
|
||||||
|
(regcache_save, regcache_save_no_passthrough)
|
||||||
|
(regcache_restore, regcache_restore_no_passthrough)
|
||||||
|
(regcache_dup, regcache_dup_no_passthrough)
|
||||||
|
(regcache_cpy, regcache_cpy_no_passthrough)
|
||||||
|
(deprecated_grub_regcache_for_registers)
|
||||||
|
(deprecated_grub_regcache_for_register_valid)
|
||||||
|
(regcache_valid_p): Add function declarations.
|
||||||
|
|
||||||
|
* regcache.c: Update copyright.
|
||||||
|
(regcache_descr_handle): New global variable.
|
||||||
|
(struct regcache_descr): Define.
|
||||||
|
(init_legacy_regcache_descr, init_regcache_descr): New functions.
|
||||||
|
(regcache_descr, xfree_regcache_descr): New functions.
|
||||||
|
(struct regcache): Define.
|
||||||
|
(regcache_xmalloc, regcache_xfree): New functions.
|
||||||
|
(regcache_cpy, regcache_cpy_no_passthrough): New functions.
|
||||||
|
(regcache_dup, regcache_dup_no_passthrough): New functions.
|
||||||
|
(regcache_valid_p, regcache_read_as_address): New functions.
|
||||||
|
(deprecated_grub_regcache_for_registers): New function.
|
||||||
|
(deprecated_grub_regcache_for_register_valid): New function.
|
||||||
|
(current_regcache): New global variable.
|
||||||
|
(register_buffer): Add regcache parameter. Update calls.
|
||||||
|
(regcache_read, regcache_write): Add regcache parameter. Rewrite.
|
||||||
|
(read_register_gen, write_register_gen): Update register_buffer
|
||||||
|
call. Test for legacy_p instead of gdbarch_register_read_p or
|
||||||
|
gdbarch_register_write_p.
|
||||||
|
(regcache_collect): Update register_buffer call.
|
||||||
|
(build_regcache): Rewrite. Use deprecated grub functions.
|
||||||
|
(regcache_save, regcache_save_no_passthrough): New functions.
|
||||||
|
(regcache_restore, regcache_restore_no_passthrough): New
|
||||||
|
functions.
|
||||||
|
(_initialize_regcache): Create the regcache_data_handle. Swap
|
||||||
|
current_regcache global variable.
|
||||||
|
|
||||||
|
* sh-tdep.c (sh_pseudo_register_read): Add current_regcache
|
||||||
|
parameter to regcache_read and regcache_write calls.
|
||||||
|
(sh4_register_read): Ditto.
|
||||||
|
(sh64_pseudo_register_read): Ditto.
|
||||||
|
(sh64_register_read): Ditto.
|
||||||
|
(sh_pseudo_register_write): Ditto.
|
||||||
|
(sh4_register_write): Ditto.
|
||||||
|
(sh64_pseudo_register_write): Ditto.
|
||||||
|
(sh64_register_write): Ditto.
|
||||||
|
|
||||||
|
* defs.h (XCALLOC): Define.
|
||||||
|
|
||||||
2002-06-19 Grace Sainsbury <graces@redhat.com>
|
2002-06-19 Grace Sainsbury <graces@redhat.com>
|
||||||
|
|
||||||
* config/m68k/tm-m68k.h (GDB_MULTI_ARCH): Added (set to 0).
|
* config/m68k/tm-m68k.h (GDB_MULTI_ARCH): Added (set to 0).
|
||||||
|
|
|
@ -844,10 +844,11 @@ extern void xmfree (void *md, void *ptr);
|
||||||
"libiberty.h". */
|
"libiberty.h". */
|
||||||
extern void xfree (void *);
|
extern void xfree (void *);
|
||||||
|
|
||||||
/* Utility macro to allocate typed memory. Avoids errors like
|
/* Utility macros to allocate typed memory. Avoids errors like
|
||||||
``struct foo *foo = xmalloc (sizeof bar)'' and ``struct foo *foo =
|
``struct foo *foo = xmalloc (sizeof bar)'' and ``struct foo *foo =
|
||||||
(struct foo *) xmalloc (sizeof bar)''. */
|
(struct foo *) xmalloc (sizeof bar)''. */
|
||||||
#define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE)))
|
#define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE)))
|
||||||
|
#define XCALLOC(NMEMB, TYPE) ((TYPE*) xcalloc ((NMEMB), sizeof (TYPE)))
|
||||||
|
|
||||||
/* Like asprintf/vasprintf but get an internal_error if the call
|
/* Like asprintf/vasprintf but get an internal_error if the call
|
||||||
fails. */
|
fails. */
|
||||||
|
|
532
gdb/regcache.c
532
gdb/regcache.c
|
@ -1,6 +1,7 @@
|
||||||
/* Cache and manage the values of registers for GDB, the GNU debugger.
|
/* Cache and manage the values of registers for GDB, the GNU debugger.
|
||||||
Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000, 2001
|
|
||||||
Free Software Foundation, Inc.
|
Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000,
|
||||||
|
2001, 2002 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GDB.
|
This file is part of GDB.
|
||||||
|
|
||||||
|
@ -33,6 +34,349 @@
|
||||||
* Here is the actual register cache.
|
* Here is the actual register cache.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Per-architecture object describing the layout of a register cache.
|
||||||
|
Computed once when the architecture is created */
|
||||||
|
|
||||||
|
struct gdbarch_data *regcache_descr_handle;
|
||||||
|
|
||||||
|
struct regcache_descr
|
||||||
|
{
|
||||||
|
/* The architecture this descriptor belongs to. */
|
||||||
|
struct gdbarch *gdbarch;
|
||||||
|
|
||||||
|
/* Is this a ``legacy'' register cache? Such caches reserve space
|
||||||
|
for raw and pseudo registers and allow access to both. */
|
||||||
|
int legacy_p;
|
||||||
|
|
||||||
|
/* The raw register cache. This should contain just [0
|
||||||
|
.. NUM_RAW_REGISTERS). However, for older targets, it contains
|
||||||
|
space for the full [0 .. NUM_RAW_REGISTERS +
|
||||||
|
NUM_PSEUDO_REGISTERS). */
|
||||||
|
int nr_raw_registers;
|
||||||
|
long sizeof_raw_registers;
|
||||||
|
long sizeof_raw_register_valid_p;
|
||||||
|
|
||||||
|
/* Offset, in bytes, of reach register in the raw register cache.
|
||||||
|
Pseudo registers have an offset even though they don't
|
||||||
|
(shouldn't) have a correspoinding space in the register cache.
|
||||||
|
It is to keep existing code, that relies on
|
||||||
|
write/write_register_bytes working. */
|
||||||
|
long *register_offset;
|
||||||
|
|
||||||
|
/* The cooked / frame / virtual register space. The registers in
|
||||||
|
the range [0..NR_RAW_REGISTERS) should be mapped directly onto
|
||||||
|
the corresponding raw register. The next [NR_RAW_REGISTERS
|
||||||
|
.. NR_REGISTERS) should have been mapped, via
|
||||||
|
gdbarch_register_read/write onto either raw registers or memory. */
|
||||||
|
int nr_registers;
|
||||||
|
long *sizeof_register;
|
||||||
|
long max_register_size;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static void *
|
||||||
|
init_legacy_regcache_descr (struct gdbarch *gdbarch)
|
||||||
|
{
|
||||||
|
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_registers = NUM_REGS + NUM_PSEUDO_REGS;
|
||||||
|
descr->nr_raw_registers = descr->nr_registers;
|
||||||
|
descr->sizeof_raw_register_valid_p = descr->nr_registers;
|
||||||
|
|
||||||
|
/* FIXME: cagney/2002-05-11: Instead of using REGISTER_BYTE() this
|
||||||
|
code should compute the offets et.al. at runtime. This currently
|
||||||
|
isn't possible because some targets overlap register locations -
|
||||||
|
see the mess in read_register_bytes() and write_register_bytes()
|
||||||
|
registers. */
|
||||||
|
descr->sizeof_register = XCALLOC (descr->nr_registers, long);
|
||||||
|
descr->register_offset = XCALLOC (descr->nr_registers, long);
|
||||||
|
descr->max_register_size = 0;
|
||||||
|
for (i = 0; i < descr->nr_registers; i++)
|
||||||
|
{
|
||||||
|
descr->register_offset[i] = REGISTER_BYTE (i);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Come up with the real size of the registers buffer. */
|
||||||
|
descr->sizeof_raw_registers = REGISTER_BYTES; /* OK use. */
|
||||||
|
for (i = 0; i < descr->nr_registers; i++)
|
||||||
|
{
|
||||||
|
long regend;
|
||||||
|
/* Keep extending the buffer so that there is always enough
|
||||||
|
space for all registers. The comparison is necessary since
|
||||||
|
legacy code is free to put registers in random places in the
|
||||||
|
buffer separated by holes. Once REGISTER_BYTE() is killed
|
||||||
|
this can be greatly simplified. */
|
||||||
|
/* FIXME: cagney/2001-12-04: This code shouldn't need to use
|
||||||
|
REGISTER_BYTE(). Unfortunatly, legacy code likes to lay the
|
||||||
|
buffer out so that certain registers just happen to overlap.
|
||||||
|
Ulgh! New targets use gdbarch's register read/write and
|
||||||
|
entirely avoid this uglyness. */
|
||||||
|
regend = descr->register_offset[i] + descr->sizeof_register[i];
|
||||||
|
if (descr->sizeof_raw_registers < regend)
|
||||||
|
descr->sizeof_raw_registers = regend;
|
||||||
|
}
|
||||||
|
return descr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
init_regcache_descr (struct gdbarch *gdbarch)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
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_register_read_p (gdbarch)
|
||||||
|
&& !gdbarch_register_write_p (gdbarch))
|
||||||
|
return init_legacy_regcache_descr (gdbarch);
|
||||||
|
|
||||||
|
descr = XMALLOC (struct regcache_descr);
|
||||||
|
descr->gdbarch = gdbarch;
|
||||||
|
descr->legacy_p = 0;
|
||||||
|
|
||||||
|
/* Total size of the register space. The raw registers should
|
||||||
|
directly map onto the raw register cache while the pseudo's are
|
||||||
|
either mapped onto raw-registers or memory. */
|
||||||
|
descr->nr_registers = NUM_REGS + NUM_PSEUDO_REGS;
|
||||||
|
|
||||||
|
/* Construct a strictly RAW register cache. Don't allow pseudo's
|
||||||
|
into the register cache. */
|
||||||
|
descr->nr_raw_registers = NUM_REGS;
|
||||||
|
descr->sizeof_raw_register_valid_p = NUM_REGS;
|
||||||
|
|
||||||
|
/* Lay out the register cache. The pseud-registers are included in
|
||||||
|
the layout even though their value isn't stored in the register
|
||||||
|
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. */
|
||||||
|
|
||||||
|
{
|
||||||
|
long offset = 0;
|
||||||
|
descr->sizeof_register = XCALLOC (descr->nr_registers, long);
|
||||||
|
descr->register_offset = XCALLOC (descr->nr_registers, long);
|
||||||
|
descr->max_register_size = 0;
|
||||||
|
for (i = 0; i < descr->nr_registers; i++)
|
||||||
|
{
|
||||||
|
descr->sizeof_register[i] = TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (i));
|
||||||
|
descr->register_offset[i] = offset;
|
||||||
|
offset += descr->sizeof_register[i];
|
||||||
|
if (descr->max_register_size < descr->sizeof_register[i])
|
||||||
|
descr->max_register_size = descr->sizeof_register[i];
|
||||||
|
}
|
||||||
|
/* Set the real size of the register cache buffer. */
|
||||||
|
/* FIXME: cagney/2002-05-22: Should only need to allocate space
|
||||||
|
for the raw registers. Unfortunatly some code still accesses
|
||||||
|
the register array directly using the global registers[].
|
||||||
|
Until that code has been purged, play safe and over allocating
|
||||||
|
the register buffer. Ulgh! */
|
||||||
|
descr->sizeof_raw_registers = offset;
|
||||||
|
/* = descr->register_offset[descr->nr_raw_registers]; */
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* Sanity check. Confirm that the assumptions about gdbarch are
|
||||||
|
true. The REGCACHE_DESCR_HANDLE is set before doing the checks
|
||||||
|
so that targets using the generic methods supplied by regcache
|
||||||
|
don't go into infinite recursion trying to, again, create the
|
||||||
|
regcache. */
|
||||||
|
set_gdbarch_data (gdbarch, regcache_descr_handle, descr);
|
||||||
|
for (i = 0; i < descr->nr_registers; i++)
|
||||||
|
{
|
||||||
|
gdb_assert (descr->sizeof_register[i] == REGISTER_RAW_SIZE (i));
|
||||||
|
gdb_assert (descr->sizeof_register[i] == REGISTER_VIRTUAL_SIZE (i));
|
||||||
|
gdb_assert (descr->register_offset[i] == REGISTER_BYTE (i));
|
||||||
|
}
|
||||||
|
/* gdb_assert (descr->sizeof_raw_registers == REGISTER_BYTES (i)); */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return descr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct regcache_descr *
|
||||||
|
regcache_descr (struct gdbarch *gdbarch)
|
||||||
|
{
|
||||||
|
return gdbarch_data (gdbarch, regcache_descr_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xfree_regcache_descr (struct gdbarch *gdbarch, void *ptr)
|
||||||
|
{
|
||||||
|
struct regcache_descr *descr = ptr;
|
||||||
|
if (descr == NULL)
|
||||||
|
return;
|
||||||
|
xfree (descr->register_offset);
|
||||||
|
xfree (descr->sizeof_register);
|
||||||
|
descr->register_offset = NULL;
|
||||||
|
descr->sizeof_register = NULL;
|
||||||
|
xfree (descr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The register cache for storing raw register values. */
|
||||||
|
|
||||||
|
struct regcache
|
||||||
|
{
|
||||||
|
struct regcache_descr *descr;
|
||||||
|
char *raw_registers;
|
||||||
|
char *raw_register_valid_p;
|
||||||
|
/* If a value isn't in the cache should the corresponding target be
|
||||||
|
queried for a value. */
|
||||||
|
int passthrough_p;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct regcache *
|
||||||
|
regcache_xmalloc (struct gdbarch *gdbarch)
|
||||||
|
{
|
||||||
|
struct regcache_descr *descr;
|
||||||
|
struct regcache *regcache;
|
||||||
|
gdb_assert (gdbarch != NULL);
|
||||||
|
descr = regcache_descr (gdbarch);
|
||||||
|
regcache = XMALLOC (struct regcache);
|
||||||
|
regcache->descr = descr;
|
||||||
|
regcache->raw_registers
|
||||||
|
= XCALLOC (descr->sizeof_raw_registers, char);
|
||||||
|
regcache->raw_register_valid_p
|
||||||
|
= XCALLOC (descr->sizeof_raw_register_valid_p, char);
|
||||||
|
regcache->passthrough_p = 0;
|
||||||
|
return regcache;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
regcache_xfree (struct regcache *regcache)
|
||||||
|
{
|
||||||
|
if (regcache == NULL)
|
||||||
|
return;
|
||||||
|
xfree (regcache->raw_registers);
|
||||||
|
xfree (regcache->raw_register_valid_p);
|
||||||
|
xfree (regcache);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
regcache_cpy (struct regcache *dst, struct regcache *src)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *buf;
|
||||||
|
gdb_assert (src != NULL && dst != NULL);
|
||||||
|
gdb_assert (src->descr->gdbarch == dst->descr->gdbarch);
|
||||||
|
gdb_assert (src != dst);
|
||||||
|
/* FIXME: cagney/2002-05-17: To say this bit is bad is being polite.
|
||||||
|
It keeps the existing code working where things rely on going
|
||||||
|
through to the register cache. */
|
||||||
|
if (src == current_regcache && src->descr->legacy_p)
|
||||||
|
{
|
||||||
|
/* ULGH!!!! Old way. Use REGISTER bytes and let code below
|
||||||
|
untangle fetch. */
|
||||||
|
read_register_bytes (0, dst->raw_registers, REGISTER_BYTES);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* FIXME: cagney/2002-05-17: To say this bit is bad is being polite.
|
||||||
|
It keeps the existing code working where things rely on going
|
||||||
|
through to the register cache. */
|
||||||
|
if (dst == current_regcache && dst->descr->legacy_p)
|
||||||
|
{
|
||||||
|
/* ULGH!!!! Old way. Use REGISTER bytes and let code below
|
||||||
|
untangle fetch. */
|
||||||
|
write_register_bytes (0, src->raw_registers, REGISTER_BYTES);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
buf = alloca (src->descr->max_register_size);
|
||||||
|
for (i = 0; i < src->descr->nr_raw_registers; i++)
|
||||||
|
{
|
||||||
|
/* Should we worry about the valid bit here? */
|
||||||
|
regcache_read (src, i, buf);
|
||||||
|
regcache_write (dst, i, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
regcache_cpy_no_passthrough (struct regcache *dst, struct regcache *src)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
gdb_assert (src != NULL && dst != NULL);
|
||||||
|
gdb_assert (src->descr->gdbarch == dst->descr->gdbarch);
|
||||||
|
/* NOTE: cagney/2002-05-17: Don't let the caller do a no-passthrough
|
||||||
|
move of data into the current_regcache(). Doing this would be
|
||||||
|
silly - it would mean that valid_p would be completly invalid. */
|
||||||
|
gdb_assert (dst != current_regcache);
|
||||||
|
memcpy (dst->raw_registers, src->raw_registers,
|
||||||
|
dst->descr->sizeof_raw_registers);
|
||||||
|
memcpy (dst->raw_register_valid_p, src->raw_register_valid_p,
|
||||||
|
dst->descr->sizeof_raw_register_valid_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct regcache *
|
||||||
|
regcache_dup (struct regcache *src)
|
||||||
|
{
|
||||||
|
struct regcache *newbuf;
|
||||||
|
gdb_assert (current_regcache != NULL);
|
||||||
|
newbuf = regcache_xmalloc (src->descr->gdbarch);
|
||||||
|
regcache_cpy (newbuf, src);
|
||||||
|
return newbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct regcache *
|
||||||
|
regcache_dup_no_passthrough (struct regcache *src)
|
||||||
|
{
|
||||||
|
struct regcache *newbuf;
|
||||||
|
gdb_assert (current_regcache != NULL);
|
||||||
|
newbuf = regcache_xmalloc (src->descr->gdbarch);
|
||||||
|
regcache_cpy_no_passthrough (newbuf, src);
|
||||||
|
return newbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
regcache_valid_p (struct regcache *regcache, int regnum)
|
||||||
|
{
|
||||||
|
gdb_assert (regcache != NULL);
|
||||||
|
gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
|
||||||
|
return regcache->raw_register_valid_p[regnum];
|
||||||
|
}
|
||||||
|
|
||||||
|
CORE_ADDR
|
||||||
|
regcache_read_as_address (struct regcache *regcache, int regnum)
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
gdb_assert (regcache != NULL);
|
||||||
|
gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
|
||||||
|
buf = alloca (regcache->descr->sizeof_register[regnum]);
|
||||||
|
regcache_read (regcache, regnum, buf);
|
||||||
|
return extract_address (buf, regcache->descr->sizeof_register[regnum]);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
deprecated_grub_regcache_for_registers (struct regcache *regcache)
|
||||||
|
{
|
||||||
|
return regcache->raw_registers;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
deprecated_grub_regcache_for_register_valid (struct regcache *regcache)
|
||||||
|
{
|
||||||
|
return regcache->raw_register_valid_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Global structure containing the current regcache. */
|
||||||
|
/* FIXME: cagney/2002-05-11: The two global arrays registers[] and
|
||||||
|
register_valid[] currently point into this structure. */
|
||||||
|
struct regcache *current_regcache;
|
||||||
|
|
||||||
/* NOTE: this is a write-through cache. There is no "dirty" bit for
|
/* NOTE: this is a write-through cache. There is no "dirty" bit for
|
||||||
recording if the register values have been changed (eg. by the
|
recording if the register values have been changed (eg. by the
|
||||||
user). Therefore all registers must be written back to the
|
user). Therefore all registers must be written back to the
|
||||||
|
@ -97,10 +441,9 @@ register_changed (int regnum)
|
||||||
else return a pointer to the start of the cache buffer. */
|
else return a pointer to the start of the cache buffer. */
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
register_buffer (int regnum)
|
register_buffer (struct regcache *regcache, int regnum)
|
||||||
{
|
{
|
||||||
gdb_assert (regnum >= 0 && regnum < (NUM_REGS + NUM_PSEUDO_REGS));
|
return regcache->raw_registers + regcache->descr->register_offset[regnum];
|
||||||
return ®isters[REGISTER_BYTE (regnum)];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return whether register REGNUM is a real register. */
|
/* Return whether register REGNUM is a real register. */
|
||||||
|
@ -311,22 +654,52 @@ legacy_read_register_gen (int regnum, char *myaddr)
|
||||||
if (!register_cached (regnum))
|
if (!register_cached (regnum))
|
||||||
fetch_register (regnum);
|
fetch_register (regnum);
|
||||||
|
|
||||||
memcpy (myaddr, register_buffer (regnum),
|
memcpy (myaddr, register_buffer (current_regcache, regnum),
|
||||||
REGISTER_RAW_SIZE (regnum));
|
REGISTER_RAW_SIZE (regnum));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
regcache_read (int rawnum, char *buf)
|
regcache_read (struct regcache *regcache, int regnum, char *buf)
|
||||||
{
|
{
|
||||||
gdb_assert (rawnum >= 0 && rawnum < (NUM_REGS + NUM_PSEUDO_REGS));
|
gdb_assert (regcache != NULL && buf != NULL);
|
||||||
/* For moment, just use underlying legacy code. Ulgh!!! */
|
gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
|
||||||
legacy_read_register_gen (rawnum, buf);
|
if (regcache->descr->legacy_p
|
||||||
|
&& regcache->passthrough_p)
|
||||||
|
{
|
||||||
|
gdb_assert (regcache == current_regcache);
|
||||||
|
/* For moment, just use underlying legacy code. Ulgh!!! This
|
||||||
|
silently and very indirectly updates the regcache's regcache
|
||||||
|
via the global register_valid[]. */
|
||||||
|
legacy_read_register_gen (regnum, buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Make certain that the register cache is up-to-date with respect
|
||||||
|
to the current thread. This switching shouldn't be necessary
|
||||||
|
only there is still only one target side register cache. Sigh!
|
||||||
|
On the bright side, at least there is a regcache object. */
|
||||||
|
if (regcache->passthrough_p)
|
||||||
|
{
|
||||||
|
gdb_assert (regcache == current_regcache);
|
||||||
|
if (! ptid_equal (registers_ptid, inferior_ptid))
|
||||||
|
{
|
||||||
|
registers_changed ();
|
||||||
|
registers_ptid = inferior_ptid;
|
||||||
|
}
|
||||||
|
if (!register_cached (regnum))
|
||||||
|
fetch_register (regnum);
|
||||||
|
}
|
||||||
|
/* Copy the value directly into the register cache. */
|
||||||
|
memcpy (buf, (regcache->raw_registers
|
||||||
|
+ regcache->descr->register_offset[regnum]),
|
||||||
|
regcache->descr->sizeof_register[regnum]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
read_register_gen (int regnum, char *buf)
|
read_register_gen (int regnum, char *buf)
|
||||||
{
|
{
|
||||||
if (! gdbarch_register_read_p (current_gdbarch))
|
gdb_assert (current_regcache != NULL);
|
||||||
|
gdb_assert (current_regcache->descr->gdbarch == current_gdbarch);
|
||||||
|
if (current_regcache->descr->legacy_p)
|
||||||
{
|
{
|
||||||
legacy_read_register_gen (regnum, buf);
|
legacy_read_register_gen (regnum, buf);
|
||||||
return;
|
return;
|
||||||
|
@ -362,30 +735,80 @@ legacy_write_register_gen (int regnum, char *myaddr)
|
||||||
/* If we have a valid copy of the register, and new value == old
|
/* If we have a valid copy of the register, and new value == old
|
||||||
value, then don't bother doing the actual store. */
|
value, then don't bother doing the actual store. */
|
||||||
if (register_cached (regnum)
|
if (register_cached (regnum)
|
||||||
&& memcmp (register_buffer (regnum), myaddr, size) == 0)
|
&& (memcmp (register_buffer (current_regcache, regnum), myaddr, size)
|
||||||
|
== 0))
|
||||||
return;
|
return;
|
||||||
else
|
else
|
||||||
target_prepare_to_store ();
|
target_prepare_to_store ();
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy (register_buffer (regnum), myaddr, size);
|
memcpy (register_buffer (current_regcache, regnum), myaddr, size);
|
||||||
|
|
||||||
set_register_cached (regnum, 1);
|
set_register_cached (regnum, 1);
|
||||||
store_register (regnum);
|
store_register (regnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
regcache_write (int rawnum, char *buf)
|
regcache_write (struct regcache *regcache, int regnum, char *buf)
|
||||||
{
|
{
|
||||||
gdb_assert (rawnum >= 0 && rawnum < (NUM_REGS + NUM_PSEUDO_REGS));
|
gdb_assert (regcache != NULL && buf != NULL);
|
||||||
/* For moment, just use underlying legacy code. Ulgh!!! */
|
gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
|
||||||
legacy_write_register_gen (rawnum, buf);
|
|
||||||
|
if (regcache->passthrough_p
|
||||||
|
&& regcache->descr->legacy_p)
|
||||||
|
{
|
||||||
|
/* For moment, just use underlying legacy code. Ulgh!!! This
|
||||||
|
silently and very indirectly updates the regcache's buffers
|
||||||
|
via the globals register_valid[] and registers[]. */
|
||||||
|
gdb_assert (regcache == current_regcache);
|
||||||
|
legacy_write_register_gen (regnum, buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* On the sparc, writing %g0 is a no-op, so we don't even want to
|
||||||
|
change the registers array if something writes to this register. */
|
||||||
|
if (CANNOT_STORE_REGISTER (regnum))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Handle the simple case first -> not write through so just store
|
||||||
|
value in cache. */
|
||||||
|
if (!regcache->passthrough_p)
|
||||||
|
{
|
||||||
|
memcpy ((regcache->raw_registers
|
||||||
|
+ regcache->descr->register_offset[regnum]), buf,
|
||||||
|
regcache->descr->sizeof_register[regnum]);
|
||||||
|
regcache->raw_register_valid_p[regnum] = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make certain that the correct cache is selected. */
|
||||||
|
gdb_assert (regcache == current_regcache);
|
||||||
|
if (! ptid_equal (registers_ptid, inferior_ptid))
|
||||||
|
{
|
||||||
|
registers_changed ();
|
||||||
|
registers_ptid = inferior_ptid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have a valid copy of the register, and new value == old
|
||||||
|
value, then don't bother doing the actual store. */
|
||||||
|
if (regcache_valid_p (regcache, regnum)
|
||||||
|
&& (memcmp (register_buffer (regcache, regnum), buf,
|
||||||
|
regcache->descr->sizeof_register[regnum]) == 0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
target_prepare_to_store ();
|
||||||
|
memcpy (register_buffer (regcache, regnum), buf,
|
||||||
|
regcache->descr->sizeof_register[regnum]);
|
||||||
|
regcache->raw_register_valid_p[regnum] = 1;
|
||||||
|
store_register (regnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
write_register_gen (int regnum, char *buf)
|
write_register_gen (int regnum, char *buf)
|
||||||
{
|
{
|
||||||
if (! gdbarch_register_write_p (current_gdbarch))
|
gdb_assert (current_regcache != NULL);
|
||||||
|
gdb_assert (current_regcache->descr->gdbarch == current_gdbarch);
|
||||||
|
if (current_regcache->descr->legacy_p)
|
||||||
{
|
{
|
||||||
legacy_write_register_gen (regnum, buf);
|
legacy_write_register_gen (regnum, buf);
|
||||||
return;
|
return;
|
||||||
|
@ -564,10 +987,10 @@ supply_register (int regnum, char *val)
|
||||||
|
|
||||||
set_register_cached (regnum, 1);
|
set_register_cached (regnum, 1);
|
||||||
if (val)
|
if (val)
|
||||||
memcpy (register_buffer (regnum), val,
|
memcpy (register_buffer (current_regcache, regnum), val,
|
||||||
REGISTER_RAW_SIZE (regnum));
|
REGISTER_RAW_SIZE (regnum));
|
||||||
else
|
else
|
||||||
memset (register_buffer (regnum), '\000',
|
memset (register_buffer (current_regcache, regnum), '\000',
|
||||||
REGISTER_RAW_SIZE (regnum));
|
REGISTER_RAW_SIZE (regnum));
|
||||||
|
|
||||||
/* On some architectures, e.g. HPPA, there are a few stray bits in
|
/* On some architectures, e.g. HPPA, there are a few stray bits in
|
||||||
|
@ -587,7 +1010,8 @@ supply_register (int regnum, char *val)
|
||||||
void
|
void
|
||||||
regcache_collect (int regnum, void *buf)
|
regcache_collect (int regnum, void *buf)
|
||||||
{
|
{
|
||||||
memcpy (buf, register_buffer (regnum), REGISTER_RAW_SIZE (regnum));
|
memcpy (buf, register_buffer (current_regcache, regnum),
|
||||||
|
REGISTER_RAW_SIZE (regnum));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -755,37 +1179,53 @@ reg_flush_command (char *command, int from_tty)
|
||||||
static void
|
static void
|
||||||
build_regcache (void)
|
build_regcache (void)
|
||||||
{
|
{
|
||||||
int i;
|
current_regcache = regcache_xmalloc (current_gdbarch);
|
||||||
int sizeof_register_valid;
|
current_regcache->passthrough_p = 1;
|
||||||
/* Come up with the real size of the registers buffer. */
|
registers = deprecated_grub_regcache_for_registers (current_regcache);
|
||||||
int sizeof_registers = REGISTER_BYTES; /* OK use. */
|
register_valid = deprecated_grub_regcache_for_register_valid (current_regcache);
|
||||||
for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
|
|
||||||
{
|
|
||||||
long regend;
|
|
||||||
/* Keep extending the buffer so that there is always enough
|
|
||||||
space for all registers. The comparison is necessary since
|
|
||||||
legacy code is free to put registers in random places in the
|
|
||||||
buffer separated by holes. Once REGISTER_BYTE() is killed
|
|
||||||
this can be greatly simplified. */
|
|
||||||
/* FIXME: cagney/2001-12-04: This code shouldn't need to use
|
|
||||||
REGISTER_BYTE(). Unfortunatly, legacy code likes to lay the
|
|
||||||
buffer out so that certain registers just happen to overlap.
|
|
||||||
Ulgh! New targets use gdbarch's register read/write and
|
|
||||||
entirely avoid this uglyness. */
|
|
||||||
regend = REGISTER_BYTE (i) + REGISTER_RAW_SIZE (i);
|
|
||||||
if (sizeof_registers < regend)
|
|
||||||
sizeof_registers = regend;
|
|
||||||
}
|
}
|
||||||
registers = xmalloc (sizeof_registers);
|
|
||||||
sizeof_register_valid = ((NUM_REGS + NUM_PSEUDO_REGS)
|
void
|
||||||
* sizeof (*register_valid));
|
regcache_save (struct regcache *regcache)
|
||||||
register_valid = xmalloc (sizeof_register_valid);
|
{
|
||||||
memset (register_valid, 0, sizeof_register_valid);
|
int i;
|
||||||
|
gdb_assert (current_regcache != NULL && regcache != NULL);
|
||||||
|
gdb_assert (current_regcache->descr->gdbarch == regcache->descr->gdbarch);
|
||||||
|
regcache_cpy (regcache, current_regcache);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
regcache_save_no_passthrough (struct regcache *regcache)
|
||||||
|
{
|
||||||
|
gdb_assert (current_regcache != NULL && regcache != NULL);
|
||||||
|
gdb_assert (current_regcache->descr->gdbarch == regcache->descr->gdbarch);
|
||||||
|
regcache_cpy_no_passthrough (regcache, current_regcache);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
regcache_restore (struct regcache *regcache)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
gdb_assert (current_regcache != NULL && regcache != NULL);
|
||||||
|
gdb_assert (current_regcache->descr->gdbarch == regcache->descr->gdbarch);
|
||||||
|
regcache_cpy (current_regcache, regcache);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
regcache_restore_no_passthrough (struct regcache *regcache)
|
||||||
|
{
|
||||||
|
char *regcache_registers;
|
||||||
|
gdb_assert (current_regcache != NULL && regcache != NULL);
|
||||||
|
gdb_assert (current_regcache->descr->gdbarch == regcache->descr->gdbarch);
|
||||||
|
regcache_cpy_no_passthrough (current_regcache, regcache);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_initialize_regcache (void)
|
_initialize_regcache (void)
|
||||||
{
|
{
|
||||||
|
regcache_descr_handle = register_gdbarch_data (init_regcache_descr,
|
||||||
|
xfree_regcache_descr);
|
||||||
|
REGISTER_GDBARCH_SWAP (current_regcache);
|
||||||
register_gdbarch_swap (®isters, sizeof (registers), NULL);
|
register_gdbarch_swap (®isters, sizeof (registers), NULL);
|
||||||
register_gdbarch_swap (®ister_valid, sizeof (register_valid), NULL);
|
register_gdbarch_swap (®ister_valid, sizeof (register_valid), NULL);
|
||||||
register_gdbarch_swap (NULL, 0, build_regcache);
|
register_gdbarch_swap (NULL, 0, build_regcache);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/* Cache and manage the values of registers for GDB, the GNU debugger.
|
/* Cache and manage the values of registers for GDB, the GNU debugger.
|
||||||
Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000, 2001
|
|
||||||
Free Software Foundation, Inc.
|
Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000,
|
||||||
|
2001, 2002 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GDB.
|
This file is part of GDB.
|
||||||
|
|
||||||
|
@ -22,11 +23,21 @@
|
||||||
#ifndef REGCACHE_H
|
#ifndef REGCACHE_H
|
||||||
#define REGCACHE_H
|
#define REGCACHE_H
|
||||||
|
|
||||||
|
struct regcache;
|
||||||
|
struct gdbarch;
|
||||||
|
|
||||||
|
extern struct regcache *current_regcache;
|
||||||
|
|
||||||
|
void regcache_xfree (struct regcache *regcache);
|
||||||
|
struct regcache *regcache_xmalloc (struct gdbarch *gdbarch);
|
||||||
|
|
||||||
/* Transfer a raw register [0..NUM_REGS) between core-gdb and the
|
/* Transfer a raw register [0..NUM_REGS) between core-gdb and the
|
||||||
regcache. */
|
regcache. */
|
||||||
|
|
||||||
void regcache_read (int rawnum, char *buf);
|
void regcache_read (struct regcache *regcache, int rawnum, char *buf);
|
||||||
void regcache_write (int rawnum, char *buf);
|
void regcache_write (struct regcache *regcache, int rawnum, char *buf);
|
||||||
|
int regcache_valid_p (struct regcache *regcache, int regnum);
|
||||||
|
CORE_ADDR regcache_read_as_address (struct regcache *regcache, int rawnum);
|
||||||
|
|
||||||
/* Transfer a raw register [0..NUM_REGS) between the regcache and the
|
/* Transfer a raw register [0..NUM_REGS) between the regcache and the
|
||||||
target. These functions are called by the target in response to a
|
target. These functions are called by the target in response to a
|
||||||
|
@ -47,6 +58,25 @@ extern char *registers;
|
||||||
|
|
||||||
extern signed char *register_valid;
|
extern signed char *register_valid;
|
||||||
|
|
||||||
|
/* Save/restore the register cache using the regbuf. The operation is
|
||||||
|
write through - it is strictly for code that needs to restore the
|
||||||
|
target's registers to a previous state.
|
||||||
|
|
||||||
|
``no passthrough'' versions do not go through to the target. They
|
||||||
|
only save values already in the cache. */
|
||||||
|
|
||||||
|
extern void regcache_save (struct regcache *regcache);
|
||||||
|
extern void regcache_restore (struct regcache *regcache);
|
||||||
|
extern struct regcache *regcache_dup (struct regcache *regcache);
|
||||||
|
extern void regcache_save_no_passthrough (struct regcache *regcache);
|
||||||
|
extern void regcache_restore_no_passthrough (struct regcache *regcache);
|
||||||
|
extern struct regcache *regcache_dup_no_passthrough (struct regcache *regcache);
|
||||||
|
extern void regcache_cpy (struct regcache *dest, struct regcache *src);
|
||||||
|
extern void regcache_cpy_no_passthrough (struct regcache *dest, struct regcache *src);
|
||||||
|
|
||||||
|
extern char *deprecated_grub_regcache_for_registers (struct regcache *);
|
||||||
|
extern char *deprecated_grub_regcache_for_register_valid (struct regcache *);
|
||||||
|
|
||||||
extern int register_cached (int regnum);
|
extern int register_cached (int regnum);
|
||||||
|
|
||||||
extern void set_register_cached (int regnum, int state);
|
extern void set_register_cached (int regnum, int state);
|
||||||
|
|
|
@ -3385,9 +3385,9 @@ sh_pseudo_register_read (int reg_nr, char *buffer)
|
||||||
/* Build the value in the provided buffer. */
|
/* Build the value in the provided buffer. */
|
||||||
/* Read the real regs for which this one is an alias. */
|
/* Read the real regs for which this one is an alias. */
|
||||||
for (portion = 0; portion < 2; portion++)
|
for (portion = 0; portion < 2; portion++)
|
||||||
regcache_read (base_regnum + portion,
|
regcache_read (current_regcache, base_regnum + portion,
|
||||||
temp_buffer
|
(temp_buffer
|
||||||
+ REGISTER_RAW_SIZE (base_regnum) * portion);
|
+ REGISTER_RAW_SIZE (base_regnum) * portion));
|
||||||
/* We must pay attention to the endiannes. */
|
/* We must pay attention to the endiannes. */
|
||||||
sh_sh4_register_convert_to_virtual (reg_nr,
|
sh_sh4_register_convert_to_virtual (reg_nr,
|
||||||
REGISTER_VIRTUAL_TYPE (reg_nr),
|
REGISTER_VIRTUAL_TYPE (reg_nr),
|
||||||
|
@ -3400,7 +3400,7 @@ sh_pseudo_register_read (int reg_nr, char *buffer)
|
||||||
|
|
||||||
/* Read the real regs for which this one is an alias. */
|
/* Read the real regs for which this one is an alias. */
|
||||||
for (portion = 0; portion < 4; portion++)
|
for (portion = 0; portion < 4; portion++)
|
||||||
regcache_read (base_regnum + portion,
|
regcache_read (current_regcache, base_regnum + portion,
|
||||||
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3410,7 +3410,7 @@ sh4_register_read (struct gdbarch *gdbarch, int reg_nr, char *buffer)
|
||||||
{
|
{
|
||||||
if (reg_nr >= 0 && reg_nr < gdbarch_tdep (current_gdbarch)->DR0_REGNUM)
|
if (reg_nr >= 0 && reg_nr < gdbarch_tdep (current_gdbarch)->DR0_REGNUM)
|
||||||
/* It is a regular register. */
|
/* It is a regular register. */
|
||||||
regcache_read (reg_nr, buffer);
|
regcache_read (current_regcache, reg_nr, buffer);
|
||||||
else
|
else
|
||||||
/* It is a pseudo register and we need to construct its value */
|
/* It is a pseudo register and we need to construct its value */
|
||||||
sh_pseudo_register_read (reg_nr, buffer);
|
sh_pseudo_register_read (reg_nr, buffer);
|
||||||
|
@ -3434,9 +3434,9 @@ sh64_pseudo_register_read (int reg_nr, char *buffer)
|
||||||
/* DR regs are double precision registers obtained by
|
/* DR regs are double precision registers obtained by
|
||||||
concatenating 2 single precision floating point registers. */
|
concatenating 2 single precision floating point registers. */
|
||||||
for (portion = 0; portion < 2; portion++)
|
for (portion = 0; portion < 2; portion++)
|
||||||
regcache_read (base_regnum + portion,
|
regcache_read (current_regcache, base_regnum + portion,
|
||||||
temp_buffer
|
(temp_buffer
|
||||||
+ REGISTER_RAW_SIZE (base_regnum) * portion);
|
+ REGISTER_RAW_SIZE (base_regnum) * portion));
|
||||||
|
|
||||||
/* We must pay attention to the endiannes. */
|
/* We must pay attention to the endiannes. */
|
||||||
sh_sh64_register_convert_to_virtual (reg_nr, REGISTER_VIRTUAL_TYPE (reg_nr),
|
sh_sh64_register_convert_to_virtual (reg_nr, REGISTER_VIRTUAL_TYPE (reg_nr),
|
||||||
|
@ -3453,7 +3453,7 @@ sh64_pseudo_register_read (int reg_nr, char *buffer)
|
||||||
/* FPP regs are pairs of single precision registers obtained by
|
/* FPP regs are pairs of single precision registers obtained by
|
||||||
concatenating 2 single precision floating point registers. */
|
concatenating 2 single precision floating point registers. */
|
||||||
for (portion = 0; portion < 2; portion++)
|
for (portion = 0; portion < 2; portion++)
|
||||||
regcache_read (base_regnum + portion,
|
regcache_read (current_regcache, base_regnum + portion,
|
||||||
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3466,7 +3466,7 @@ sh64_pseudo_register_read (int reg_nr, char *buffer)
|
||||||
/* FV regs are vectors of single precision registers obtained by
|
/* FV regs are vectors of single precision registers obtained by
|
||||||
concatenating 4 single precision floating point registers. */
|
concatenating 4 single precision floating point registers. */
|
||||||
for (portion = 0; portion < 4; portion++)
|
for (portion = 0; portion < 4; portion++)
|
||||||
regcache_read (base_regnum + portion,
|
regcache_read (current_regcache, base_regnum + portion,
|
||||||
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3477,7 +3477,7 @@ sh64_pseudo_register_read (int reg_nr, char *buffer)
|
||||||
base_regnum = sh64_compact_reg_base_num (reg_nr);
|
base_regnum = sh64_compact_reg_base_num (reg_nr);
|
||||||
|
|
||||||
/* Build the value in the provided buffer. */
|
/* Build the value in the provided buffer. */
|
||||||
regcache_read (base_regnum, temp_buffer);
|
regcache_read (current_regcache, base_regnum, temp_buffer);
|
||||||
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
|
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
|
||||||
offset = 4;
|
offset = 4;
|
||||||
memcpy (buffer, temp_buffer + offset, 4); /* get LOWER 32 bits only????*/
|
memcpy (buffer, temp_buffer + offset, 4); /* get LOWER 32 bits only????*/
|
||||||
|
@ -3491,7 +3491,7 @@ sh64_pseudo_register_read (int reg_nr, char *buffer)
|
||||||
/* Build the value in the provided buffer. */
|
/* Build the value in the provided buffer. */
|
||||||
/* Floating point registers map 1-1 to the media fp regs,
|
/* Floating point registers map 1-1 to the media fp regs,
|
||||||
they have the same size and endienness. */
|
they have the same size and endienness. */
|
||||||
regcache_read (base_regnum, buffer);
|
regcache_read (current_regcache, base_regnum, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (reg_nr >= tdep->DR0_C_REGNUM
|
else if (reg_nr >= tdep->DR0_C_REGNUM
|
||||||
|
@ -3502,9 +3502,9 @@ sh64_pseudo_register_read (int reg_nr, char *buffer)
|
||||||
/* DR_C regs are double precision registers obtained by
|
/* DR_C regs are double precision registers obtained by
|
||||||
concatenating 2 single precision floating point registers. */
|
concatenating 2 single precision floating point registers. */
|
||||||
for (portion = 0; portion < 2; portion++)
|
for (portion = 0; portion < 2; portion++)
|
||||||
regcache_read (base_regnum + portion,
|
regcache_read (current_regcache, base_regnum + portion,
|
||||||
temp_buffer
|
(temp_buffer
|
||||||
+ REGISTER_RAW_SIZE (base_regnum) * portion);
|
+ REGISTER_RAW_SIZE (base_regnum) * portion));
|
||||||
|
|
||||||
/* We must pay attention to the endiannes. */
|
/* We must pay attention to the endiannes. */
|
||||||
sh_sh64_register_convert_to_virtual (reg_nr, REGISTER_VIRTUAL_TYPE (reg_nr),
|
sh_sh64_register_convert_to_virtual (reg_nr, REGISTER_VIRTUAL_TYPE (reg_nr),
|
||||||
|
@ -3520,7 +3520,7 @@ sh64_pseudo_register_read (int reg_nr, char *buffer)
|
||||||
/* FV_C regs are vectors of single precision registers obtained by
|
/* FV_C regs are vectors of single precision registers obtained by
|
||||||
concatenating 4 single precision floating point registers. */
|
concatenating 4 single precision floating point registers. */
|
||||||
for (portion = 0; portion < 4; portion++)
|
for (portion = 0; portion < 4; portion++)
|
||||||
regcache_read (base_regnum + portion,
|
regcache_read (current_regcache, base_regnum + portion,
|
||||||
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3552,11 +3552,11 @@ sh64_pseudo_register_read (int reg_nr, char *buffer)
|
||||||
*/
|
*/
|
||||||
/* *INDENT-ON* */
|
/* *INDENT-ON* */
|
||||||
/* Get FPSCR into a local buffer */
|
/* Get FPSCR into a local buffer */
|
||||||
regcache_read (fpscr_base_regnum, temp_buffer);
|
regcache_read (current_regcache, fpscr_base_regnum, temp_buffer);
|
||||||
/* Get value as an int. */
|
/* Get value as an int. */
|
||||||
fpscr_value = extract_unsigned_integer (temp_buffer, 4);
|
fpscr_value = extract_unsigned_integer (temp_buffer, 4);
|
||||||
/* Get SR into a local buffer */
|
/* Get SR into a local buffer */
|
||||||
regcache_read (sr_base_regnum, temp_buffer);
|
regcache_read (current_regcache, sr_base_regnum, temp_buffer);
|
||||||
/* Get value as an int. */
|
/* Get value as an int. */
|
||||||
sr_value = extract_unsigned_integer (temp_buffer, 4);
|
sr_value = extract_unsigned_integer (temp_buffer, 4);
|
||||||
/* Build the new value. */
|
/* Build the new value. */
|
||||||
|
@ -3574,7 +3574,7 @@ sh64_pseudo_register_read (int reg_nr, char *buffer)
|
||||||
|
|
||||||
/* FPUL_C register is floating point register 32,
|
/* FPUL_C register is floating point register 32,
|
||||||
same size, same endianness. */
|
same size, same endianness. */
|
||||||
regcache_read (base_regnum, buffer);
|
regcache_read (current_regcache, base_regnum, buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3584,7 +3584,7 @@ sh64_register_read (struct gdbarch *gdbarch, int reg_nr, char *buffer)
|
||||||
|
|
||||||
if (reg_nr >= 0 && reg_nr < gdbarch_tdep (current_gdbarch)->DR0_REGNUM)
|
if (reg_nr >= 0 && reg_nr < gdbarch_tdep (current_gdbarch)->DR0_REGNUM)
|
||||||
/* It is a regular register. */
|
/* It is a regular register. */
|
||||||
regcache_read (reg_nr, buffer);
|
regcache_read (current_regcache, reg_nr, buffer);
|
||||||
else
|
else
|
||||||
/* It is a pseudo register and we need to construct its value */
|
/* It is a pseudo register and we need to construct its value */
|
||||||
sh64_pseudo_register_read (reg_nr, buffer);
|
sh64_pseudo_register_read (reg_nr, buffer);
|
||||||
|
@ -3608,8 +3608,9 @@ sh_pseudo_register_write (int reg_nr, char *buffer)
|
||||||
|
|
||||||
/* Write the real regs for which this one is an alias. */
|
/* Write the real regs for which this one is an alias. */
|
||||||
for (portion = 0; portion < 2; portion++)
|
for (portion = 0; portion < 2; portion++)
|
||||||
regcache_write (base_regnum + portion,
|
regcache_write (current_regcache, base_regnum + portion,
|
||||||
temp_buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
(temp_buffer
|
||||||
|
+ REGISTER_RAW_SIZE (base_regnum) * portion));
|
||||||
}
|
}
|
||||||
else if (reg_nr >= tdep->FV0_REGNUM
|
else if (reg_nr >= tdep->FV0_REGNUM
|
||||||
&& reg_nr <= tdep->FV_LAST_REGNUM)
|
&& reg_nr <= tdep->FV_LAST_REGNUM)
|
||||||
|
@ -3618,7 +3619,7 @@ sh_pseudo_register_write (int reg_nr, char *buffer)
|
||||||
|
|
||||||
/* Write the real regs for which this one is an alias. */
|
/* Write the real regs for which this one is an alias. */
|
||||||
for (portion = 0; portion < 4; portion++)
|
for (portion = 0; portion < 4; portion++)
|
||||||
regcache_write (base_regnum + portion,
|
regcache_write (current_regcache, base_regnum + portion,
|
||||||
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3628,7 +3629,7 @@ sh4_register_write (struct gdbarch *gdbarch, int reg_nr, char *buffer)
|
||||||
{
|
{
|
||||||
if (reg_nr >= 0 && reg_nr < gdbarch_tdep (current_gdbarch)->DR0_REGNUM)
|
if (reg_nr >= 0 && reg_nr < gdbarch_tdep (current_gdbarch)->DR0_REGNUM)
|
||||||
/* It is a regular register. */
|
/* It is a regular register. */
|
||||||
regcache_write (reg_nr, buffer);
|
regcache_write (current_regcache, reg_nr, buffer);
|
||||||
else
|
else
|
||||||
/* It is a pseudo register and we need to construct its value */
|
/* It is a pseudo register and we need to construct its value */
|
||||||
sh_pseudo_register_write (reg_nr, buffer);
|
sh_pseudo_register_write (reg_nr, buffer);
|
||||||
|
@ -3653,8 +3654,9 @@ sh64_pseudo_register_write (int reg_nr, char *buffer)
|
||||||
|
|
||||||
/* Write the real regs for which this one is an alias. */
|
/* Write the real regs for which this one is an alias. */
|
||||||
for (portion = 0; portion < 2; portion++)
|
for (portion = 0; portion < 2; portion++)
|
||||||
regcache_write (base_regnum + portion,
|
regcache_write (current_regcache, base_regnum + portion,
|
||||||
temp_buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
(temp_buffer
|
||||||
|
+ REGISTER_RAW_SIZE (base_regnum) * portion));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (reg_nr >= tdep->FPP0_REGNUM
|
else if (reg_nr >= tdep->FPP0_REGNUM
|
||||||
|
@ -3664,7 +3666,7 @@ sh64_pseudo_register_write (int reg_nr, char *buffer)
|
||||||
|
|
||||||
/* Write the real regs for which this one is an alias. */
|
/* Write the real regs for which this one is an alias. */
|
||||||
for (portion = 0; portion < 2; portion++)
|
for (portion = 0; portion < 2; portion++)
|
||||||
regcache_write (base_regnum + portion,
|
regcache_write (current_regcache, base_regnum + portion,
|
||||||
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3675,7 +3677,7 @@ sh64_pseudo_register_write (int reg_nr, char *buffer)
|
||||||
|
|
||||||
/* Write the real regs for which this one is an alias. */
|
/* Write the real regs for which this one is an alias. */
|
||||||
for (portion = 0; portion < 4; portion++)
|
for (portion = 0; portion < 4; portion++)
|
||||||
regcache_write (base_regnum + portion,
|
regcache_write (current_regcache, base_regnum + portion,
|
||||||
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3693,10 +3695,10 @@ sh64_pseudo_register_write (int reg_nr, char *buffer)
|
||||||
/* Let's read the value of the base register into a temporary
|
/* Let's read the value of the base register into a temporary
|
||||||
buffer, so that overwriting the last four bytes with the new
|
buffer, so that overwriting the last four bytes with the new
|
||||||
value of the pseudo will leave the upper 4 bytes unchanged. */
|
value of the pseudo will leave the upper 4 bytes unchanged. */
|
||||||
regcache_read (base_regnum, temp_buffer);
|
regcache_read (current_regcache, base_regnum, temp_buffer);
|
||||||
/* Write as an 8 byte quantity */
|
/* Write as an 8 byte quantity */
|
||||||
memcpy (temp_buffer + offset, buffer, 4);
|
memcpy (temp_buffer + offset, buffer, 4);
|
||||||
regcache_write (base_regnum, temp_buffer);
|
regcache_write (current_regcache, base_regnum, temp_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sh floating point compact pseudo registers. 1-to-1 with a shmedia
|
/* sh floating point compact pseudo registers. 1-to-1 with a shmedia
|
||||||
|
@ -3705,7 +3707,7 @@ sh64_pseudo_register_write (int reg_nr, char *buffer)
|
||||||
&& reg_nr <= tdep->FP_LAST_C_REGNUM)
|
&& reg_nr <= tdep->FP_LAST_C_REGNUM)
|
||||||
{
|
{
|
||||||
base_regnum = sh64_compact_reg_base_num (reg_nr);
|
base_regnum = sh64_compact_reg_base_num (reg_nr);
|
||||||
regcache_write (base_regnum, buffer);
|
regcache_write (current_regcache, base_regnum, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (reg_nr >= tdep->DR0_C_REGNUM
|
else if (reg_nr >= tdep->DR0_C_REGNUM
|
||||||
|
@ -3718,8 +3720,9 @@ sh64_pseudo_register_write (int reg_nr, char *buffer)
|
||||||
sh_sh64_register_convert_to_raw (REGISTER_VIRTUAL_TYPE (reg_nr), reg_nr,
|
sh_sh64_register_convert_to_raw (REGISTER_VIRTUAL_TYPE (reg_nr), reg_nr,
|
||||||
buffer, temp_buffer);
|
buffer, temp_buffer);
|
||||||
|
|
||||||
regcache_write (base_regnum + portion,
|
regcache_write (current_regcache, base_regnum + portion,
|
||||||
temp_buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
(temp_buffer
|
||||||
|
+ REGISTER_RAW_SIZE (base_regnum) * portion));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3730,7 +3733,7 @@ sh64_pseudo_register_write (int reg_nr, char *buffer)
|
||||||
|
|
||||||
for (portion = 0; portion < 4; portion++)
|
for (portion = 0; portion < 4; portion++)
|
||||||
{
|
{
|
||||||
regcache_write (base_regnum + portion,
|
regcache_write (current_regcache, base_regnum + portion,
|
||||||
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3773,25 +3776,25 @@ sh64_pseudo_register_write (int reg_nr, char *buffer)
|
||||||
fpscr_value = fpscr_c_value & fpscr_mask;
|
fpscr_value = fpscr_c_value & fpscr_mask;
|
||||||
sr_value = (fpscr_value & sr_mask) >> 6;
|
sr_value = (fpscr_value & sr_mask) >> 6;
|
||||||
|
|
||||||
regcache_read (fpscr_base_regnum, temp_buffer);
|
regcache_read (current_regcache, fpscr_base_regnum, temp_buffer);
|
||||||
old_fpscr_value = extract_unsigned_integer (temp_buffer, 4);
|
old_fpscr_value = extract_unsigned_integer (temp_buffer, 4);
|
||||||
old_fpscr_value &= 0xfffc0002;
|
old_fpscr_value &= 0xfffc0002;
|
||||||
fpscr_value |= old_fpscr_value;
|
fpscr_value |= old_fpscr_value;
|
||||||
store_unsigned_integer (temp_buffer, 4, fpscr_value);
|
store_unsigned_integer (temp_buffer, 4, fpscr_value);
|
||||||
regcache_write (fpscr_base_regnum, temp_buffer);
|
regcache_write (current_regcache, fpscr_base_regnum, temp_buffer);
|
||||||
|
|
||||||
regcache_read (sr_base_regnum, temp_buffer);
|
regcache_read (current_regcache, sr_base_regnum, temp_buffer);
|
||||||
old_sr_value = extract_unsigned_integer (temp_buffer, 4);
|
old_sr_value = extract_unsigned_integer (temp_buffer, 4);
|
||||||
old_sr_value &= 0xffff8fff;
|
old_sr_value &= 0xffff8fff;
|
||||||
sr_value |= old_sr_value;
|
sr_value |= old_sr_value;
|
||||||
store_unsigned_integer (temp_buffer, 4, sr_value);
|
store_unsigned_integer (temp_buffer, 4, sr_value);
|
||||||
regcache_write (sr_base_regnum, temp_buffer);
|
regcache_write (current_regcache, sr_base_regnum, temp_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (reg_nr == tdep->FPUL_C_REGNUM)
|
else if (reg_nr == tdep->FPUL_C_REGNUM)
|
||||||
{
|
{
|
||||||
base_regnum = sh64_compact_reg_base_num (reg_nr);
|
base_regnum = sh64_compact_reg_base_num (reg_nr);
|
||||||
regcache_write (base_regnum, buffer);
|
regcache_write (current_regcache, base_regnum, buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3800,7 +3803,7 @@ sh64_register_write (struct gdbarch *gdbarch, int reg_nr, char *buffer)
|
||||||
{
|
{
|
||||||
if (reg_nr >= 0 && reg_nr < gdbarch_tdep (current_gdbarch)->DR0_REGNUM)
|
if (reg_nr >= 0 && reg_nr < gdbarch_tdep (current_gdbarch)->DR0_REGNUM)
|
||||||
/* It is a regular register. */
|
/* It is a regular register. */
|
||||||
regcache_write (reg_nr, buffer);
|
regcache_write (current_regcache, reg_nr, buffer);
|
||||||
else
|
else
|
||||||
/* It is a pseudo register and we need to construct its value */
|
/* It is a pseudo register and we need to construct its value */
|
||||||
sh64_pseudo_register_write (reg_nr, buffer);
|
sh64_pseudo_register_write (reg_nr, buffer);
|
||||||
|
|
Loading…
Add table
Reference in a new issue