2000-07-12 Michael Snyder <msnyder@cleaver.cygnus.com>

* regcache.c (registers_changed, registers_fetched): Use
        ARCH_NUM_REGS directly, eliminating an unnecessary variable.

        This change adds pseudo-register capability to GDB.
        Pseudo-registers are handled like registers, but they
        don't come from or live on the target.  They may be
        aliases for an existing register, or they may be computed.
        * defs.h (NUM_PSEUDO_REGISTERS): Define default of zero.
        (ARCH_FETCH_PSEUDO_REGISTERS): Define default of no-op.
        (ARCH_STORE_PSEUDO_REGISTERS): Define default of no-op.
        # regcache.c (registers_changed): Mark pseudo-registers
        invalid, as well as real registers.
        (registers_fetched): Do not mark pseudo-registers as fetched
        at the same time as other (real) registers.
        (read_register_bytes): Fetch pseudo-registers (if any) from
        the target architecture module instead of from the target.
        (read_register_gen): Ditto.
        (read_register): Ditto.
        (write_register_bytes): Store pseudo-registers (if any) to
        the target architecture module instead of to the target.
        (write_register_gen): Ditto.
        (write_register): Ditto.
        (build_regcache): Allocate enough register_valid space for
        pseudo-registers as well as normal (real) ones.
This commit is contained in:
Michael Snyder 2000-07-12 22:01:17 +00:00
parent 86d65c94b2
commit fcdc5976b3
3 changed files with 98 additions and 17 deletions

View File

@ -1,3 +1,30 @@
2000-07-12 Michael Snyder <msnyder@cleaver.cygnus.com>
* regcache.c (registers_changed, registers_fetched): Use
ARCH_NUM_REGS directly, eliminating an unnecessary variable.
This change adds pseudo-register capability to GDB.
Pseudo-registers are handled like registers, but they
don't come from or live on the target. They may be
aliases for an existing register, or they may be computed.
* defs.h (NUM_PSEUDO_REGISTERS): Define default of zero.
(ARCH_FETCH_PSEUDO_REGISTERS): Define default of no-op.
(ARCH_STORE_PSEUDO_REGISTERS): Define default of no-op.
# regcache.c (registers_changed): Mark pseudo-registers
invalid, as well as real registers.
(registers_fetched): Do not mark pseudo-registers as fetched
at the same time as other (real) registers.
(read_register_bytes): Fetch pseudo-registers (if any) from
the target architecture module instead of from the target.
(read_register_gen): Ditto.
(read_register): Ditto.
(write_register_bytes): Store pseudo-registers (if any) to
the target architecture module instead of to the target.
(write_register_gen): Ditto.
(write_register): Ditto.
(build_regcache): Allocate enough register_valid space for
pseudo-registers as well as normal (real) ones.
Tue Jul 11 19:45:42 2000 Andrew Cagney <cagney@b1.cygnus.com>
* valops.c (value_cast): Allow cast from INT, ENUM or RANGE to

View File

@ -52,12 +52,36 @@ extern void write_inferior_status_register (struct inferior_status
/* This macro gives the number of registers actually in use by the
inferior. This may be less than the total number of registers,
perhaps depending on the actual CPU in use or program being run. */
perhaps depending on the actual CPU in use or program being run.
FIXME: This could be replaced by the new MULTI_ARCH capability. */
#ifndef ARCH_NUM_REGS
#define ARCH_NUM_REGS NUM_REGS
#endif
/* This macro gives the number of pseudo-registers that live in the
register namespace but do not get fetched or stored on the target.
These pseudo-registers may be aliases for other registers,
combinations of other registers, or they may be computed by GDB.
FIXME: move into gdbarch.[ch] */
#ifndef NUM_PSEUDO_REGS
#define NUM_PSEUDO_REGS 0
#endif
/* 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. FIXME: move into gdbarch.[ch]. */
#ifndef ARCH_FETCH_PSEUDO_REGISTERS
#define ARCH_FETCH_PSEUDO_REGISTERS(REGNUM) /* no-op */
#endif
/* 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. FIXME: move into gdbarch.[ch]. */
#ifndef ARCH_STORE_PSEUDO_REGISTERS
#define ARCH_STORE_PSEUDO_REGISTERS(REGNUM) /* no-op */
#endif
extern void set_sigint_trap (void);
extern void clear_sigint_trap (void);

View File

@ -282,7 +282,6 @@ void
registers_changed (void)
{
int i;
int numregs = ARCH_NUM_REGS;
registers_pid = -1;
@ -293,7 +292,12 @@ registers_changed (void)
gdb gives control to the user (ie watchpoints). */
alloca (0);
for (i = 0; i < numregs; i++)
for (i = 0; i < ARCH_NUM_REGS; i++)
register_valid[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++)
register_valid[i] = 0;
if (registers_changed_hook)
@ -309,10 +313,11 @@ void
registers_fetched (void)
{
int i;
int numregs = ARCH_NUM_REGS;
for (i = 0; i < numregs; i++)
for (i = 0; i < ARCH_NUM_REGS; i++)
register_valid[i] = 1;
/* Do not assume that the pseudo-regs have also been fetched.
Fetching all real regs might not account for all pseudo-regs. */
}
/* read_register_bytes and write_register_bytes are generally a *BAD*
@ -351,7 +356,7 @@ read_register_bytes (int inregbyte, char *myaddr, int inlen)
/* See if we are trying to read bytes from out-of-date registers. If so,
update just those registers. */
for (regno = 0; regno < NUM_REGS; regno++)
for (regno = 0; regno < NUM_REGS + NUM_PSEUDO_REGS; regno++)
{
int regstart, regend;
@ -368,9 +373,12 @@ read_register_bytes (int inregbyte, char *myaddr, int inlen)
/* The range the user wants to read doesn't overlap with regno. */
continue;
/* We've found an invalid register where at least one byte will be read.
/* We've found an uncached register where at least one byte will be read.
Update it from the target. */
target_fetch_registers (regno);
if (regno < NUM_REGS)
target_fetch_registers (regno);
else if (regno < NUM_PSEUDO_REGS)
ARCH_FETCH_PSEUDO_REGISTERS (regno);
if (!register_valid[regno])
error ("read_register_bytes: Couldn't update register %d.", regno);
@ -395,7 +403,12 @@ read_register_gen (int regno, char *myaddr)
}
if (!register_valid[regno])
target_fetch_registers (regno);
{
if (regno < NUM_REGS)
target_fetch_registers (regno);
else if (regno < NUM_REGS + NUM_PSEUDO_REGS)
ARCH_FETCH_PSEUDO_REGISTERS (regno);
}
memcpy (myaddr, &registers[REGISTER_BYTE (regno)],
REGISTER_RAW_SIZE (regno));
}
@ -433,13 +446,17 @@ write_register_gen (int regno, char *myaddr)
&& memcmp (&registers[REGISTER_BYTE (regno)], myaddr, size) == 0)
return;
target_prepare_to_store ();
if (regno < NUM_REGS)
target_prepare_to_store ();
memcpy (&registers[REGISTER_BYTE (regno)], myaddr, size);
register_valid[regno] = 1;
target_store_registers (regno);
if (regno < NUM_REGS)
target_store_registers (regno);
else if (regno < NUM_REGS + NUM_PSEUDO_REGS)
ARCH_STORE_PSEUDO_REGISTERS (regno);
}
/* Copy INLEN bytes of consecutive data from memory at MYADDR
@ -458,7 +475,7 @@ write_register_bytes (int myregstart, char *myaddr, int inlen)
nice things like handling threads, and avoiding updates when the
new and old contents are the same. */
for (regno = 0; regno < NUM_REGS; regno++)
for (regno = 0; regno < NUM_REGS + NUM_PSEUDO_REGS; regno++)
{
int regstart, regend;
@ -490,7 +507,10 @@ write_register_bytes (int myregstart, char *myaddr, int inlen)
myaddr + (overlapstart - myregstart),
overlapend - overlapstart);
target_store_registers (regno);
if (regno < NUM_REGS)
target_store_registers (regno);
else if (regno < NUM_REGS + NUM_PSEUDO_REGS)
ARCH_STORE_PSEUDO_REGISTERS (regno);
}
}
}
@ -509,7 +529,12 @@ read_register (int regno)
}
if (!register_valid[regno])
target_fetch_registers (regno);
{
if (regno < NUM_REGS)
target_fetch_registers (regno);
else if (regno < NUM_PSEUDO_REGS)
ARCH_FETCH_PSEUDO_REGISTERS (regno);
}
return (extract_unsigned_integer (&registers[REGISTER_BYTE (regno)],
REGISTER_RAW_SIZE (regno)));
@ -604,13 +629,17 @@ write_register (int regno, LONGEST val)
&& memcmp (&registers[REGISTER_BYTE (regno)], buf, size) == 0)
return;
target_prepare_to_store ();
if (regno < NUM_REGS)
target_prepare_to_store ();
memcpy (&registers[REGISTER_BYTE (regno)], buf, size);
register_valid[regno] = 1;
target_store_registers (regno);
if (regno < NUM_REGS)
target_store_registers (regno);
else if (regno < NUM_REGS + NUM_PSEUDO_REGS)
ARCH_STORE_PSEUDO_REGISTERS (regno);
}
void
@ -859,7 +888,8 @@ 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 * sizeof (*register_valid);
int sizeof_register_valid =
(NUM_REGS + NUM_PSEUDO_REGS) * sizeof (*register_valid);
registers = xmalloc (sizeof_registers);
memset (registers, 0, sizeof_registers);
register_valid = xmalloc (sizeof_register_valid);