diff options
author | Michael Snyder <msnyder@vmware.com> | 2000-07-12 22:01:17 +0000 |
---|---|---|
committer | Michael Snyder <msnyder@vmware.com> | 2000-07-12 22:01:17 +0000 |
commit | fcdc5976b34caefdbc10b76bd953394916a44856 (patch) | |
tree | f6f69f0eb569787ee747572c130f99ad926908ec | |
parent | 86d65c94b28348d0f70a9bac843ae3b2d4f43b85 (diff) | |
download | gdb-fcdc5976b34caefdbc10b76bd953394916a44856.zip gdb-fcdc5976b34caefdbc10b76bd953394916a44856.tar.gz gdb-fcdc5976b34caefdbc10b76bd953394916a44856.tar.bz2 |
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.
-rw-r--r-- | gdb/ChangeLog | 27 | ||||
-rw-r--r-- | gdb/inferior.h | 26 | ||||
-rw-r--r-- | gdb/regcache.c | 62 |
3 files changed, 98 insertions, 17 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c23d07c..326025d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -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 diff --git a/gdb/inferior.h b/gdb/inferior.h index 26798a5..95a8c61 100644 --- a/gdb/inferior.h +++ b/gdb/inferior.h @@ -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); diff --git a/gdb/regcache.c b/gdb/regcache.c index ec64eac..9ccaf82 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -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, ®isters[REGISTER_BYTE (regno)], REGISTER_RAW_SIZE (regno)); } @@ -433,13 +446,17 @@ write_register_gen (int regno, char *myaddr) && memcmp (®isters[REGISTER_BYTE (regno)], myaddr, size) == 0) return; - target_prepare_to_store (); + if (regno < NUM_REGS) + target_prepare_to_store (); memcpy (®isters[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 (®isters[REGISTER_BYTE (regno)], REGISTER_RAW_SIZE (regno))); @@ -604,13 +629,17 @@ write_register (int regno, LONGEST val) && memcmp (®isters[REGISTER_BYTE (regno)], buf, size) == 0) return; - target_prepare_to_store (); + if (regno < NUM_REGS) + target_prepare_to_store (); memcpy (®isters[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); |