2000-07-12 Michael Snyder <msnyder@cleaver.cygnus.com>
authorMichael Snyder <msnyder@vmware.com>
Wed, 12 Jul 2000 22:01:17 +0000 (22:01 +0000)
committerMichael Snyder <msnyder@vmware.com>
Wed, 12 Jul 2000 22:01:17 +0000 (22:01 +0000)
        * 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.

gdb/ChangeLog
gdb/inferior.h
gdb/regcache.c

index c23d07c..326025d 100644 (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
index 26798a5..95a8c61 100644 (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);
index ec64eac..9ccaf82 100644 (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);