Expand the regcache so that there is space for pseudo-registers.

This commit is contained in:
Andrew Cagney 2001-12-06 20:49:47 +00:00
parent 3793abc306
commit 31e9866ea6
5 changed files with 123 additions and 27 deletions

View File

@ -1,3 +1,20 @@
2001-12-06 Andrew Cagney <ac131313@redhat.com>
* regcache.c (store_register, fetch_register): Only use
fetch/store pseudo-register when function is present. Assume
target can handle all registers.
(registers_changed): Simplify invalidate loop.
(registers_fetched): Add comments.
(register_buffer): Add regnum range assertion. Remove code
handling -ve regnum.
(build_regcache): Make space for pseudo-registers when computing
sizeof_registers. Initialize register_offset.
* gdbarch.sh (FETCH_PSEUDO_REGISTER): Change to a function with
predicate.
(STORE_PSEUDO_REGISTER): Ditto.
* gdbarch.h, gdbarch.c: Re-generate.
2001-12-06 Jim Blandy <jimb@redhat.com>
* config/s390/nm-linux.h: Watchpoints are either continuable or

View File

@ -667,8 +667,8 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of register_convertible, invalid_p == 0 */
/* Skip verify of register_convert_to_virtual, invalid_p == 0 */
/* Skip verify of register_convert_to_raw, invalid_p == 0 */
/* Skip verify of fetch_pseudo_register, invalid_p == 0 */
/* Skip verify of store_pseudo_register, invalid_p == 0 */
/* Skip verify of fetch_pseudo_register, has predicate */
/* Skip verify of store_pseudo_register, has predicate */
/* Skip verify of pointer_to_address, invalid_p == 0 */
/* Skip verify of address_to_pointer, invalid_p == 0 */
/* Skip verify of integer_to_address, has predicate */
@ -3326,6 +3326,12 @@ set_gdbarch_register_convert_to_raw (struct gdbarch *gdbarch,
gdbarch->register_convert_to_raw = register_convert_to_raw;
}
int
gdbarch_fetch_pseudo_register_p (struct gdbarch *gdbarch)
{
return gdbarch->fetch_pseudo_register != 0;
}
void
gdbarch_fetch_pseudo_register (struct gdbarch *gdbarch, int regnum)
{
@ -3344,6 +3350,12 @@ set_gdbarch_fetch_pseudo_register (struct gdbarch *gdbarch,
gdbarch->fetch_pseudo_register = fetch_pseudo_register;
}
int
gdbarch_store_pseudo_register_p (struct gdbarch *gdbarch)
{
return gdbarch->store_pseudo_register != 0;
}
void
gdbarch_store_pseudo_register (struct gdbarch *gdbarch, int regnum)
{

View File

@ -1170,6 +1170,26 @@ extern void set_gdbarch_register_convert_to_raw (struct gdbarch *gdbarch, gdbarc
be updated. Typically it will be defined on a per-architecture
basis. */
#if defined (FETCH_PSEUDO_REGISTER)
/* Legacy for systems yet to multi-arch FETCH_PSEUDO_REGISTER */
#if !defined (FETCH_PSEUDO_REGISTER_P)
#define FETCH_PSEUDO_REGISTER_P() (1)
#endif
#endif
/* Default predicate for non- multi-arch targets. */
#if (!GDB_MULTI_ARCH) && !defined (FETCH_PSEUDO_REGISTER_P)
#define FETCH_PSEUDO_REGISTER_P() (0)
#endif
extern int gdbarch_fetch_pseudo_register_p (struct gdbarch *gdbarch);
#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (FETCH_PSEUDO_REGISTER_P)
#error "Non multi-arch definition of FETCH_PSEUDO_REGISTER"
#endif
#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) || !defined (FETCH_PSEUDO_REGISTER_P)
#define FETCH_PSEUDO_REGISTER_P() (gdbarch_fetch_pseudo_register_p (current_gdbarch))
#endif
/* Default (function) for non- multi-arch platforms. */
#if (!GDB_MULTI_ARCH) && !defined (FETCH_PSEUDO_REGISTER)
#define FETCH_PSEUDO_REGISTER(regnum) (internal_error (__FILE__, __LINE__, "FETCH_PSEUDO_REGISTER"), 0)
@ -1191,6 +1211,26 @@ extern void set_gdbarch_fetch_pseudo_register (struct gdbarch *gdbarch, gdbarch_
be set or stored. Typically it will be defined on a
per-architecture basis. */
#if defined (STORE_PSEUDO_REGISTER)
/* Legacy for systems yet to multi-arch STORE_PSEUDO_REGISTER */
#if !defined (STORE_PSEUDO_REGISTER_P)
#define STORE_PSEUDO_REGISTER_P() (1)
#endif
#endif
/* Default predicate for non- multi-arch targets. */
#if (!GDB_MULTI_ARCH) && !defined (STORE_PSEUDO_REGISTER_P)
#define STORE_PSEUDO_REGISTER_P() (0)
#endif
extern int gdbarch_store_pseudo_register_p (struct gdbarch *gdbarch);
#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (STORE_PSEUDO_REGISTER_P)
#error "Non multi-arch definition of STORE_PSEUDO_REGISTER"
#endif
#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) || !defined (STORE_PSEUDO_REGISTER_P)
#define STORE_PSEUDO_REGISTER_P() (gdbarch_store_pseudo_register_p (current_gdbarch))
#endif
/* Default (function) for non- multi-arch platforms. */
#if (!GDB_MULTI_ARCH) && !defined (STORE_PSEUDO_REGISTER)
#define STORE_PSEUDO_REGISTER(regnum) (internal_error (__FILE__, __LINE__, "STORE_PSEUDO_REGISTER"), 0)

View File

@ -468,11 +468,11 @@ f:2:REGISTER_CONVERT_TO_RAW:void:register_convert_to_raw:struct type *type, int
# This function is called when the value of a pseudo-register needs to
# be updated. Typically it will be defined on a per-architecture
# basis.
f:2:FETCH_PSEUDO_REGISTER:void:fetch_pseudo_register:int regnum:regnum:::0::0
F:2:FETCH_PSEUDO_REGISTER:void:fetch_pseudo_register:int regnum:regnum:
# This function is called when the value of a pseudo-register needs to
# be set or stored. Typically it will be defined on a
# per-architecture basis.
f:2:STORE_PSEUDO_REGISTER:void:store_pseudo_register:int regnum:regnum:::0::0
F:2:STORE_PSEUDO_REGISTER:void:store_pseudo_register:int regnum:regnum:
#
f:2:POINTER_TO_ADDRESS:CORE_ADDR:pointer_to_address:struct type *type, void *buf:type, buf:::unsigned_pointer_to_address::0
f:2:ADDRESS_TO_POINTER:void:address_to_pointer:struct type *type, void *buf, CORE_ADDR addr:type, buf, addr:::unsigned_address_to_pointer::0

View File

@ -93,10 +93,8 @@ register_changed (int regnum)
static char *
register_buffer (int regnum)
{
if (regnum < 0)
return registers;
else
return &registers[REGISTER_BYTE (regnum)];
gdb_assert (regnum >= 0 && regnum < (NUM_REGS + NUM_PSEUDO_REGS));
return &registers[REGISTER_BYTE (regnum)];
}
/* Return whether register REGNUM is a real register. */
@ -120,10 +118,14 @@ pseudo_register (int regnum)
static void
fetch_register (int regnum)
{
if (real_register (regnum))
target_fetch_registers (regnum);
else if (pseudo_register (regnum))
/* NOTE: cagney/2001-12-04: Legacy targets were using fetch/store
pseudo-register as a way of handling registers that needed to be
constructed from one or more raw registers. New targets instead
use gdbarch register read/write. */
if (FETCH_PSEUDO_REGISTER_P ()
&& pseudo_register (regnum))
FETCH_PSEUDO_REGISTER (regnum);
target_fetch_registers (regnum);
}
/* Write register REGNUM cached value to the target. */
@ -131,10 +133,14 @@ fetch_register (int regnum)
static void
store_register (int regnum)
{
if (real_register (regnum))
target_store_registers (regnum);
else if (pseudo_register (regnum))
/* NOTE: cagney/2001-12-04: Legacy targets were using fetch/store
pseudo-register as a way of handling registers that needed to be
constructed from one or more raw registers. New targets instead
use gdbarch register read/write. */
if (STORE_PSEUDO_REGISTER_P ()
&& pseudo_register (regnum))
STORE_PSEUDO_REGISTER (regnum);
target_store_registers (regnum);
}
/* Low level examining and depositing of registers.
@ -162,12 +168,7 @@ registers_changed (void)
gdb gives control to the user (ie watchpoints). */
alloca (0);
for (i = 0; i < NUM_REGS; i++)
set_register_cached (i, 0);
/* Assume that if all the hardware regs have changed,
then so have the pseudo-registers. */
for (i = NUM_REGS; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
set_register_cached (i, 0);
if (registers_changed_hook)
@ -178,6 +179,13 @@ registers_changed (void)
Indicate that all registers have been fetched, so mark them all valid. */
/* NOTE: cagney/2001-12-04: This function does not set valid on the
pseudo-register range since pseudo registers are always supplied
using supply_register(). */
/* FIXME: cagney/2001-12-04: This function is DEPRECATED. The target
code was blatting the registers[] array and then calling this.
Since targets should only be using supply_register() the need for
this function/hack is eliminated. */
void
registers_fetched (void)
@ -187,7 +195,7 @@ registers_fetched (void)
for (i = 0; i < NUM_REGS; i++)
set_register_cached (i, 1);
/* Do not assume that the pseudo-regs have also been fetched.
Fetching all real regs might not account for all pseudo-regs. */
Fetching all real regs NEVER accounts for pseudo-regs. */
}
/* read_register_bytes and write_register_bytes are generally a *BAD*
@ -758,17 +766,36 @@ reg_flush_command (char *command, int from_tty)
printf_filtered ("Register cache flushed.\n");
}
#undef XCALLOC
#define XCALLOC(NR,TYPE) ((TYPE*) xcalloc ((NR), sizeof (TYPE)))
static void
build_regcache (void)
{
/* We allocate some extra slop since we do a lot of memcpy's around
`registers', and failing-soft is better than failing hard. */
int sizeof_registers = REGISTER_BYTES + /* SLOP */ 256;
int sizeof_register_valid =
(NUM_REGS + NUM_PSEUDO_REGS) * sizeof (*register_valid);
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);
memset (registers, 0, 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);
}