aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Snyder <msnyder@vmware.com>2000-07-12 22:01:17 +0000
committerMichael Snyder <msnyder@vmware.com>2000-07-12 22:01:17 +0000
commitfcdc5976b34caefdbc10b76bd953394916a44856 (patch)
treef6f69f0eb569787ee747572c130f99ad926908ec
parent86d65c94b28348d0f70a9bac843ae3b2d4f43b85 (diff)
downloadgdb-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/ChangeLog27
-rw-r--r--gdb/inferior.h26
-rw-r--r--gdb/regcache.c62
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, &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);