mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-08-06 14:49:38 +08:00
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:
@ -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>
|
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
|
* valops.c (value_cast): Allow cast from INT, ENUM or RANGE to
|
||||||
|
@ -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
|
/* This macro gives the number of registers actually in use by the
|
||||||
inferior. This may be less than the total number of registers,
|
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
|
#ifndef ARCH_NUM_REGS
|
||||||
#define ARCH_NUM_REGS NUM_REGS
|
#define ARCH_NUM_REGS NUM_REGS
|
||||||
#endif
|
#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 set_sigint_trap (void);
|
||||||
|
|
||||||
extern void clear_sigint_trap (void);
|
extern void clear_sigint_trap (void);
|
||||||
|
@ -282,7 +282,6 @@ void
|
|||||||
registers_changed (void)
|
registers_changed (void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int numregs = ARCH_NUM_REGS;
|
|
||||||
|
|
||||||
registers_pid = -1;
|
registers_pid = -1;
|
||||||
|
|
||||||
@ -293,7 +292,12 @@ registers_changed (void)
|
|||||||
gdb gives control to the user (ie watchpoints). */
|
gdb gives control to the user (ie watchpoints). */
|
||||||
alloca (0);
|
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;
|
register_valid[i] = 0;
|
||||||
|
|
||||||
if (registers_changed_hook)
|
if (registers_changed_hook)
|
||||||
@ -309,10 +313,11 @@ void
|
|||||||
registers_fetched (void)
|
registers_fetched (void)
|
||||||
{
|
{
|
||||||
int i;
|
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;
|
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*
|
/* 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,
|
/* See if we are trying to read bytes from out-of-date registers. If so,
|
||||||
update just those registers. */
|
update just those registers. */
|
||||||
|
|
||||||
for (regno = 0; regno < NUM_REGS; regno++)
|
for (regno = 0; regno < NUM_REGS + NUM_PSEUDO_REGS; regno++)
|
||||||
{
|
{
|
||||||
int regstart, regend;
|
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. */
|
/* The range the user wants to read doesn't overlap with regno. */
|
||||||
continue;
|
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. */
|
Update it from the target. */
|
||||||
|
if (regno < NUM_REGS)
|
||||||
target_fetch_registers (regno);
|
target_fetch_registers (regno);
|
||||||
|
else if (regno < NUM_PSEUDO_REGS)
|
||||||
|
ARCH_FETCH_PSEUDO_REGISTERS (regno);
|
||||||
|
|
||||||
if (!register_valid[regno])
|
if (!register_valid[regno])
|
||||||
error ("read_register_bytes: Couldn't update register %d.", 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])
|
if (!register_valid[regno])
|
||||||
|
{
|
||||||
|
if (regno < NUM_REGS)
|
||||||
target_fetch_registers (regno);
|
target_fetch_registers (regno);
|
||||||
|
else if (regno < NUM_REGS + NUM_PSEUDO_REGS)
|
||||||
|
ARCH_FETCH_PSEUDO_REGISTERS (regno);
|
||||||
|
}
|
||||||
memcpy (myaddr, ®isters[REGISTER_BYTE (regno)],
|
memcpy (myaddr, ®isters[REGISTER_BYTE (regno)],
|
||||||
REGISTER_RAW_SIZE (regno));
|
REGISTER_RAW_SIZE (regno));
|
||||||
}
|
}
|
||||||
@ -433,13 +446,17 @@ write_register_gen (int regno, char *myaddr)
|
|||||||
&& memcmp (®isters[REGISTER_BYTE (regno)], myaddr, size) == 0)
|
&& memcmp (®isters[REGISTER_BYTE (regno)], myaddr, size) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (regno < NUM_REGS)
|
||||||
target_prepare_to_store ();
|
target_prepare_to_store ();
|
||||||
|
|
||||||
memcpy (®isters[REGISTER_BYTE (regno)], myaddr, size);
|
memcpy (®isters[REGISTER_BYTE (regno)], myaddr, size);
|
||||||
|
|
||||||
register_valid[regno] = 1;
|
register_valid[regno] = 1;
|
||||||
|
|
||||||
|
if (regno < NUM_REGS)
|
||||||
target_store_registers (regno);
|
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
|
/* 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
|
nice things like handling threads, and avoiding updates when the
|
||||||
new and old contents are the same. */
|
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;
|
int regstart, regend;
|
||||||
|
|
||||||
@ -490,7 +507,10 @@ write_register_bytes (int myregstart, char *myaddr, int inlen)
|
|||||||
myaddr + (overlapstart - myregstart),
|
myaddr + (overlapstart - myregstart),
|
||||||
overlapend - overlapstart);
|
overlapend - overlapstart);
|
||||||
|
|
||||||
|
if (regno < NUM_REGS)
|
||||||
target_store_registers (regno);
|
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])
|
if (!register_valid[regno])
|
||||||
|
{
|
||||||
|
if (regno < NUM_REGS)
|
||||||
target_fetch_registers (regno);
|
target_fetch_registers (regno);
|
||||||
|
else if (regno < NUM_PSEUDO_REGS)
|
||||||
|
ARCH_FETCH_PSEUDO_REGISTERS (regno);
|
||||||
|
}
|
||||||
|
|
||||||
return (extract_unsigned_integer (®isters[REGISTER_BYTE (regno)],
|
return (extract_unsigned_integer (®isters[REGISTER_BYTE (regno)],
|
||||||
REGISTER_RAW_SIZE (regno)));
|
REGISTER_RAW_SIZE (regno)));
|
||||||
@ -604,13 +629,17 @@ write_register (int regno, LONGEST val)
|
|||||||
&& memcmp (®isters[REGISTER_BYTE (regno)], buf, size) == 0)
|
&& memcmp (®isters[REGISTER_BYTE (regno)], buf, size) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (regno < NUM_REGS)
|
||||||
target_prepare_to_store ();
|
target_prepare_to_store ();
|
||||||
|
|
||||||
memcpy (®isters[REGISTER_BYTE (regno)], buf, size);
|
memcpy (®isters[REGISTER_BYTE (regno)], buf, size);
|
||||||
|
|
||||||
register_valid[regno] = 1;
|
register_valid[regno] = 1;
|
||||||
|
|
||||||
|
if (regno < NUM_REGS)
|
||||||
target_store_registers (regno);
|
target_store_registers (regno);
|
||||||
|
else if (regno < NUM_REGS + NUM_PSEUDO_REGS)
|
||||||
|
ARCH_STORE_PSEUDO_REGISTERS (regno);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -859,7 +888,8 @@ build_regcache (void)
|
|||||||
/* We allocate some extra slop since we do a lot of memcpy's around
|
/* We allocate some extra slop since we do a lot of memcpy's around
|
||||||
`registers', and failing-soft is better than failing hard. */
|
`registers', and failing-soft is better than failing hard. */
|
||||||
int sizeof_registers = REGISTER_BYTES + /* SLOP */ 256;
|
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);
|
registers = xmalloc (sizeof_registers);
|
||||||
memset (registers, 0, sizeof_registers);
|
memset (registers, 0, sizeof_registers);
|
||||||
register_valid = xmalloc (sizeof_register_valid);
|
register_valid = xmalloc (sizeof_register_valid);
|
||||||
|
Reference in New Issue
Block a user