* 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>
|
||||
|
||||
* 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". */
|
||||
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 *) xmalloc (sizeof bar)''. */
|
||||
#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
|
||||
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.
|
||||
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.
|
||||
|
||||
|
@ -33,6 +34,349 @@
|
|||
* 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
|
||||
recording if the register values have been changed (eg. by 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. */
|
||||
|
||||
static char *
|
||||
register_buffer (int regnum)
|
||||
register_buffer (struct regcache *regcache, int regnum)
|
||||
{
|
||||
gdb_assert (regnum >= 0 && regnum < (NUM_REGS + NUM_PSEUDO_REGS));
|
||||
return ®isters[REGISTER_BYTE (regnum)];
|
||||
return regcache->raw_registers + regcache->descr->register_offset[regnum];
|
||||
}
|
||||
|
||||
/* Return whether register REGNUM is a real register. */
|
||||
|
@ -311,22 +654,52 @@ legacy_read_register_gen (int regnum, char *myaddr)
|
|||
if (!register_cached (regnum))
|
||||
fetch_register (regnum);
|
||||
|
||||
memcpy (myaddr, register_buffer (regnum),
|
||||
memcpy (myaddr, register_buffer (current_regcache, regnum),
|
||||
REGISTER_RAW_SIZE (regnum));
|
||||
}
|
||||
|
||||
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));
|
||||
/* For moment, just use underlying legacy code. Ulgh!!! */
|
||||
legacy_read_register_gen (rawnum, buf);
|
||||
gdb_assert (regcache != NULL && buf != NULL);
|
||||
gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
|
||||
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
|
||||
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);
|
||||
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
|
||||
value, then don't bother doing the actual store. */
|
||||
if (register_cached (regnum)
|
||||
&& memcmp (register_buffer (regnum), myaddr, size) == 0)
|
||||
&& (memcmp (register_buffer (current_regcache, regnum), myaddr, size)
|
||||
== 0))
|
||||
return;
|
||||
else
|
||||
target_prepare_to_store ();
|
||||
}
|
||||
|
||||
memcpy (register_buffer (regnum), myaddr, size);
|
||||
memcpy (register_buffer (current_regcache, regnum), myaddr, size);
|
||||
|
||||
set_register_cached (regnum, 1);
|
||||
store_register (regnum);
|
||||
}
|
||||
|
||||
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));
|
||||
/* For moment, just use underlying legacy code. Ulgh!!! */
|
||||
legacy_write_register_gen (rawnum, buf);
|
||||
gdb_assert (regcache != NULL && buf != NULL);
|
||||
gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
|
||||
|
||||
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
|
||||
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);
|
||||
return;
|
||||
|
@ -564,10 +987,10 @@ supply_register (int regnum, char *val)
|
|||
|
||||
set_register_cached (regnum, 1);
|
||||
if (val)
|
||||
memcpy (register_buffer (regnum), val,
|
||||
memcpy (register_buffer (current_regcache, regnum), val,
|
||||
REGISTER_RAW_SIZE (regnum));
|
||||
else
|
||||
memset (register_buffer (regnum), '\000',
|
||||
memset (register_buffer (current_regcache, regnum), '\000',
|
||||
REGISTER_RAW_SIZE (regnum));
|
||||
|
||||
/* On some architectures, e.g. HPPA, there are a few stray bits in
|
||||
|
@ -587,7 +1010,8 @@ supply_register (int regnum, char *val)
|
|||
void
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
|
@ -754,38 +1178,54 @@ reg_flush_command (char *command, int from_tty)
|
|||
|
||||
static void
|
||||
build_regcache (void)
|
||||
{
|
||||
current_regcache = regcache_xmalloc (current_gdbarch);
|
||||
current_regcache->passthrough_p = 1;
|
||||
registers = deprecated_grub_regcache_for_registers (current_regcache);
|
||||
register_valid = deprecated_grub_regcache_for_register_valid (current_regcache);
|
||||
}
|
||||
|
||||
void
|
||||
regcache_save (struct regcache *regcache)
|
||||
{
|
||||
int i;
|
||||
int sizeof_register_valid;
|
||||
/* Come up with the real size of the registers buffer. */
|
||||
int sizeof_registers = REGISTER_BYTES; /* OK use. */
|
||||
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)
|
||||
* sizeof (*register_valid));
|
||||
register_valid = xmalloc (sizeof_register_valid);
|
||||
memset (register_valid, 0, sizeof_register_valid);
|
||||
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
|
||||
_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 (®ister_valid, sizeof (register_valid), NULL);
|
||||
register_gdbarch_swap (NULL, 0, build_regcache);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* 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.
|
||||
|
||||
|
@ -22,11 +23,21 @@
|
|||
#ifndef 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
|
||||
regcache. */
|
||||
|
||||
void regcache_read (int rawnum, char *buf);
|
||||
void regcache_write (int rawnum, char *buf);
|
||||
void regcache_read (struct regcache *regcache, 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
|
||||
target. These functions are called by the target in response to a
|
||||
|
@ -47,6 +58,25 @@ extern char *registers;
|
|||
|
||||
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 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. */
|
||||
/* Read the real regs for which this one is an alias. */
|
||||
for (portion = 0; portion < 2; portion++)
|
||||
regcache_read (base_regnum + portion,
|
||||
temp_buffer
|
||||
+ REGISTER_RAW_SIZE (base_regnum) * portion);
|
||||
regcache_read (current_regcache, base_regnum + portion,
|
||||
(temp_buffer
|
||||
+ REGISTER_RAW_SIZE (base_regnum) * portion));
|
||||
/* We must pay attention to the endiannes. */
|
||||
sh_sh4_register_convert_to_virtual (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. */
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
/* It is a regular register. */
|
||||
regcache_read (reg_nr, buffer);
|
||||
regcache_read (current_regcache, reg_nr, buffer);
|
||||
else
|
||||
/* It is a pseudo register and we need to construct its value */
|
||||
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
|
||||
concatenating 2 single precision floating point registers. */
|
||||
for (portion = 0; portion < 2; portion++)
|
||||
regcache_read (base_regnum + portion,
|
||||
temp_buffer
|
||||
+ REGISTER_RAW_SIZE (base_regnum) * portion);
|
||||
regcache_read (current_regcache, base_regnum + portion,
|
||||
(temp_buffer
|
||||
+ REGISTER_RAW_SIZE (base_regnum) * portion));
|
||||
|
||||
/* We must pay attention to the endiannes. */
|
||||
sh_sh64_register_convert_to_virtual (reg_nr, REGISTER_VIRTUAL_TYPE (reg_nr),
|
||||
|
@ -3453,8 +3453,8 @@ sh64_pseudo_register_read (int reg_nr, char *buffer)
|
|||
/* FPP regs are pairs of single precision registers obtained by
|
||||
concatenating 2 single precision floating point registers. */
|
||||
for (portion = 0; portion < 2; portion++)
|
||||
regcache_read (base_regnum + portion,
|
||||
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
||||
regcache_read (current_regcache, base_regnum + portion,
|
||||
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
||||
}
|
||||
|
||||
else if (reg_nr >= tdep->FV0_REGNUM
|
||||
|
@ -3466,8 +3466,8 @@ sh64_pseudo_register_read (int reg_nr, char *buffer)
|
|||
/* FV regs are vectors of single precision registers obtained by
|
||||
concatenating 4 single precision floating point registers. */
|
||||
for (portion = 0; portion < 4; portion++)
|
||||
regcache_read (base_regnum + portion,
|
||||
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
||||
regcache_read (current_regcache, base_regnum + portion,
|
||||
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
||||
}
|
||||
|
||||
/* sh compact pseudo registers. 1-to-1 with a shmedia register */
|
||||
|
@ -3477,7 +3477,7 @@ sh64_pseudo_register_read (int reg_nr, char *buffer)
|
|||
base_regnum = sh64_compact_reg_base_num (reg_nr);
|
||||
|
||||
/* 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)
|
||||
offset = 4;
|
||||
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. */
|
||||
/* Floating point registers map 1-1 to the media fp regs,
|
||||
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
|
||||
|
@ -3502,9 +3502,9 @@ sh64_pseudo_register_read (int reg_nr, char *buffer)
|
|||
/* DR_C regs are double precision registers obtained by
|
||||
concatenating 2 single precision floating point registers. */
|
||||
for (portion = 0; portion < 2; portion++)
|
||||
regcache_read (base_regnum + portion,
|
||||
temp_buffer
|
||||
+ REGISTER_RAW_SIZE (base_regnum) * portion);
|
||||
regcache_read (current_regcache, base_regnum + portion,
|
||||
(temp_buffer
|
||||
+ REGISTER_RAW_SIZE (base_regnum) * portion));
|
||||
|
||||
/* We must pay attention to the endiannes. */
|
||||
sh_sh64_register_convert_to_virtual (reg_nr, REGISTER_VIRTUAL_TYPE (reg_nr),
|
||||
|
@ -3520,8 +3520,8 @@ sh64_pseudo_register_read (int reg_nr, char *buffer)
|
|||
/* FV_C regs are vectors of single precision registers obtained by
|
||||
concatenating 4 single precision floating point registers. */
|
||||
for (portion = 0; portion < 4; portion++)
|
||||
regcache_read (base_regnum + portion,
|
||||
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
||||
regcache_read (current_regcache, base_regnum + portion,
|
||||
buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
||||
}
|
||||
|
||||
else if (reg_nr == tdep->FPSCR_C_REGNUM)
|
||||
|
@ -3552,11 +3552,11 @@ sh64_pseudo_register_read (int reg_nr, char *buffer)
|
|||
*/
|
||||
/* *INDENT-ON* */
|
||||
/* 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. */
|
||||
fpscr_value = extract_unsigned_integer (temp_buffer, 4);
|
||||
/* 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. */
|
||||
sr_value = extract_unsigned_integer (temp_buffer, 4);
|
||||
/* 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,
|
||||
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)
|
||||
/* It is a regular register. */
|
||||
regcache_read (reg_nr, buffer);
|
||||
regcache_read (current_regcache, reg_nr, buffer);
|
||||
else
|
||||
/* It is a pseudo register and we need to construct its value */
|
||||
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. */
|
||||
for (portion = 0; portion < 2; portion++)
|
||||
regcache_write (base_regnum + portion,
|
||||
temp_buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
||||
regcache_write (current_regcache, base_regnum + portion,
|
||||
(temp_buffer
|
||||
+ REGISTER_RAW_SIZE (base_regnum) * portion));
|
||||
}
|
||||
else if (reg_nr >= tdep->FV0_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. */
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
/* It is a regular register. */
|
||||
regcache_write (reg_nr, buffer);
|
||||
regcache_write (current_regcache, reg_nr, buffer);
|
||||
else
|
||||
/* It is a pseudo register and we need to construct its value */
|
||||
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. */
|
||||
for (portion = 0; portion < 2; portion++)
|
||||
regcache_write (base_regnum + portion,
|
||||
temp_buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
||||
regcache_write (current_regcache, base_regnum + portion,
|
||||
(temp_buffer
|
||||
+ REGISTER_RAW_SIZE (base_regnum) * portion));
|
||||
}
|
||||
|
||||
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. */
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -3675,7 +3677,7 @@ sh64_pseudo_register_write (int reg_nr, char *buffer)
|
|||
|
||||
/* Write the real regs for which this one is an alias. */
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
buffer, so that overwriting the last four bytes with the new
|
||||
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 */
|
||||
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
|
||||
|
@ -3705,7 +3707,7 @@ sh64_pseudo_register_write (int reg_nr, char *buffer)
|
|||
&& reg_nr <= tdep->FP_LAST_C_REGNUM)
|
||||
{
|
||||
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
|
||||
|
@ -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,
|
||||
buffer, temp_buffer);
|
||||
|
||||
regcache_write (base_regnum + portion,
|
||||
temp_buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
|
||||
regcache_write (current_regcache, 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++)
|
||||
{
|
||||
regcache_write (base_regnum + portion,
|
||||
regcache_write (current_regcache, 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;
|
||||
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 &= 0xfffc0002;
|
||||
fpscr_value |= old_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 &= 0xffff8fff;
|
||||
sr_value |= old_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)
|
||||
{
|
||||
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)
|
||||
/* It is a regular register. */
|
||||
regcache_write (reg_nr, buffer);
|
||||
regcache_write (current_regcache, reg_nr, buffer);
|
||||
else
|
||||
/* It is a pseudo register and we need to construct its value */
|
||||
sh64_pseudo_register_write (reg_nr, buffer);
|
||||
|
|
Loading…
Add table
Reference in a new issue