Expand the regcache so that there is space for pseudo-registers.
authorAndrew Cagney <cagney@redhat.com>
Thu, 6 Dec 2001 20:49:47 +0000 (20:49 +0000)
committerAndrew Cagney <cagney@redhat.com>
Thu, 6 Dec 2001 20:49:47 +0000 (20:49 +0000)
gdb/ChangeLog
gdb/gdbarch.c
gdb/gdbarch.h
gdb/gdbarch.sh
gdb/regcache.c

index 9478ccd379a57ce4fd41113b3cb1bb12ba882f20..4ba02574e72bf6a761903eca90556fd412d1ad9c 100644 (file)
@@ -1,3 +1,20 @@
+2001-12-06  Andrew Cagney  <ac131313@redhat.com>
+
+       * regcache.c (store_register, fetch_register): Only use
+       fetch/store pseudo-register when function is present.  Assume
+       target can handle all registers.
+       (registers_changed): Simplify invalidate loop.
+       (registers_fetched): Add comments.
+       (register_buffer): Add regnum range assertion.  Remove code
+       handling -ve regnum.
+       (build_regcache): Make space for pseudo-registers when computing
+       sizeof_registers.  Initialize register_offset.
+
+       * gdbarch.sh (FETCH_PSEUDO_REGISTER): Change to a function with
+       predicate.
+       (STORE_PSEUDO_REGISTER): Ditto.
+       * gdbarch.h, gdbarch.c: Re-generate.
+       
 2001-12-06  Jim Blandy  <jimb@redhat.com>
 
        * config/s390/nm-linux.h: Watchpoints are either continuable or
index 85ebde7dc1b6b57cf77a445b041357d10b7f4dc5..83895a4594de6d7e353e10a48cfb72c436e32722 100644 (file)
@@ -667,8 +667,8 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of register_convertible, invalid_p == 0 */
   /* Skip verify of register_convert_to_virtual, invalid_p == 0 */
   /* Skip verify of register_convert_to_raw, invalid_p == 0 */
-  /* Skip verify of fetch_pseudo_register, invalid_p == 0 */
-  /* Skip verify of store_pseudo_register, invalid_p == 0 */
+  /* Skip verify of fetch_pseudo_register, has predicate */
+  /* Skip verify of store_pseudo_register, has predicate */
   /* Skip verify of pointer_to_address, invalid_p == 0 */
   /* Skip verify of address_to_pointer, invalid_p == 0 */
   /* Skip verify of integer_to_address, has predicate */
@@ -3326,6 +3326,12 @@ set_gdbarch_register_convert_to_raw (struct gdbarch *gdbarch,
   gdbarch->register_convert_to_raw = register_convert_to_raw;
 }
 
+int
+gdbarch_fetch_pseudo_register_p (struct gdbarch *gdbarch)
+{
+  return gdbarch->fetch_pseudo_register != 0;
+}
+
 void
 gdbarch_fetch_pseudo_register (struct gdbarch *gdbarch, int regnum)
 {
@@ -3344,6 +3350,12 @@ set_gdbarch_fetch_pseudo_register (struct gdbarch *gdbarch,
   gdbarch->fetch_pseudo_register = fetch_pseudo_register;
 }
 
+int
+gdbarch_store_pseudo_register_p (struct gdbarch *gdbarch)
+{
+  return gdbarch->store_pseudo_register != 0;
+}
+
 void
 gdbarch_store_pseudo_register (struct gdbarch *gdbarch, int regnum)
 {
index 52fb9d719d5dcdbbd1293d2eeec265ba3bfca68e..22945959eff9fcaa4de752b7d390dccc6762bc36 100644 (file)
@@ -1170,6 +1170,26 @@ extern void set_gdbarch_register_convert_to_raw (struct gdbarch *gdbarch, gdbarc
    be updated.  Typically it will be defined on a per-architecture
    basis. */
 
+#if defined (FETCH_PSEUDO_REGISTER)
+/* Legacy for systems yet to multi-arch FETCH_PSEUDO_REGISTER */
+#if !defined (FETCH_PSEUDO_REGISTER_P)
+#define FETCH_PSEUDO_REGISTER_P() (1)
+#endif
+#endif
+
+/* Default predicate for non- multi-arch targets. */
+#if (!GDB_MULTI_ARCH) && !defined (FETCH_PSEUDO_REGISTER_P)
+#define FETCH_PSEUDO_REGISTER_P() (0)
+#endif
+
+extern int gdbarch_fetch_pseudo_register_p (struct gdbarch *gdbarch);
+#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (FETCH_PSEUDO_REGISTER_P)
+#error "Non multi-arch definition of FETCH_PSEUDO_REGISTER"
+#endif
+#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) || !defined (FETCH_PSEUDO_REGISTER_P)
+#define FETCH_PSEUDO_REGISTER_P() (gdbarch_fetch_pseudo_register_p (current_gdbarch))
+#endif
+
 /* Default (function) for non- multi-arch platforms. */
 #if (!GDB_MULTI_ARCH) && !defined (FETCH_PSEUDO_REGISTER)
 #define FETCH_PSEUDO_REGISTER(regnum) (internal_error (__FILE__, __LINE__, "FETCH_PSEUDO_REGISTER"), 0)
@@ -1191,6 +1211,26 @@ extern void set_gdbarch_fetch_pseudo_register (struct gdbarch *gdbarch, gdbarch_
    be set or stored.  Typically it will be defined on a
    per-architecture basis. */
 
+#if defined (STORE_PSEUDO_REGISTER)
+/* Legacy for systems yet to multi-arch STORE_PSEUDO_REGISTER */
+#if !defined (STORE_PSEUDO_REGISTER_P)
+#define STORE_PSEUDO_REGISTER_P() (1)
+#endif
+#endif
+
+/* Default predicate for non- multi-arch targets. */
+#if (!GDB_MULTI_ARCH) && !defined (STORE_PSEUDO_REGISTER_P)
+#define STORE_PSEUDO_REGISTER_P() (0)
+#endif
+
+extern int gdbarch_store_pseudo_register_p (struct gdbarch *gdbarch);
+#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (STORE_PSEUDO_REGISTER_P)
+#error "Non multi-arch definition of STORE_PSEUDO_REGISTER"
+#endif
+#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) || !defined (STORE_PSEUDO_REGISTER_P)
+#define STORE_PSEUDO_REGISTER_P() (gdbarch_store_pseudo_register_p (current_gdbarch))
+#endif
+
 /* Default (function) for non- multi-arch platforms. */
 #if (!GDB_MULTI_ARCH) && !defined (STORE_PSEUDO_REGISTER)
 #define STORE_PSEUDO_REGISTER(regnum) (internal_error (__FILE__, __LINE__, "STORE_PSEUDO_REGISTER"), 0)
index b77dacb0d12418de8a652c0f5c32aa6b271a3e58..16b01a5fea38f2046d1fd9e15f9852833930f546 100755 (executable)
@@ -468,11 +468,11 @@ f:2:REGISTER_CONVERT_TO_RAW:void:register_convert_to_raw:struct type *type, int
 # 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.
-f:2:FETCH_PSEUDO_REGISTER:void:fetch_pseudo_register:int regnum:regnum:::0::0
+F:2:FETCH_PSEUDO_REGISTER:void:fetch_pseudo_register:int regnum:regnum:
 # 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.
-f:2:STORE_PSEUDO_REGISTER:void:store_pseudo_register:int regnum:regnum:::0::0
+F:2:STORE_PSEUDO_REGISTER:void:store_pseudo_register:int regnum:regnum:
 #
 f:2:POINTER_TO_ADDRESS:CORE_ADDR:pointer_to_address:struct type *type, void *buf:type, buf:::unsigned_pointer_to_address::0
 f:2:ADDRESS_TO_POINTER:void:address_to_pointer:struct type *type, void *buf, CORE_ADDR addr:type, buf, addr:::unsigned_address_to_pointer::0
index ae893454312e4e8cb4ad92d39881cb3fcba4a888..9b3d6edcc86e31989beee0dafcaac352d24f4456 100644 (file)
@@ -93,10 +93,8 @@ register_changed (int regnum)
 static char *
 register_buffer (int regnum)
 {
-  if (regnum < 0)
-    return registers;
-  else
-    return &registers[REGISTER_BYTE (regnum)];
+  gdb_assert (regnum >= 0 && regnum < (NUM_REGS + NUM_PSEUDO_REGS));
+  return &registers[REGISTER_BYTE (regnum)];
 }
 
 /* Return whether register REGNUM is a real register.  */
@@ -120,10 +118,14 @@ pseudo_register (int regnum)
 static void
 fetch_register (int regnum)
 {
-  if (real_register (regnum))
-    target_fetch_registers (regnum);
-  else if (pseudo_register (regnum))
+  /* NOTE: cagney/2001-12-04: Legacy targets were using fetch/store
+     pseudo-register as a way of handling registers that needed to be
+     constructed from one or more raw registers.  New targets instead
+     use gdbarch register read/write.  */
+  if (FETCH_PSEUDO_REGISTER_P ()
+      && pseudo_register (regnum))
     FETCH_PSEUDO_REGISTER (regnum);
+  target_fetch_registers (regnum);
 }
 
 /* Write register REGNUM cached value to the target.  */
@@ -131,10 +133,14 @@ fetch_register (int regnum)
 static void
 store_register (int regnum)
 {
-  if (real_register (regnum))
-    target_store_registers (regnum);
-  else if (pseudo_register (regnum))
+  /* NOTE: cagney/2001-12-04: Legacy targets were using fetch/store
+     pseudo-register as a way of handling registers that needed to be
+     constructed from one or more raw registers.  New targets instead
+     use gdbarch register read/write.  */
+  if (STORE_PSEUDO_REGISTER_P ()
+      && pseudo_register (regnum))
     STORE_PSEUDO_REGISTER (regnum);
+  target_store_registers (regnum);
 }
 
 /* Low level examining and depositing of registers.
@@ -162,12 +168,7 @@ registers_changed (void)
      gdb gives control to the user (ie watchpoints).  */
   alloca (0);
 
-  for (i = 0; i < NUM_REGS; i++)
-    set_register_cached (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++)
+  for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
     set_register_cached (i, 0);
 
   if (registers_changed_hook)
@@ -178,6 +179,13 @@ registers_changed (void)
 
    Indicate that all registers have been fetched, so mark them all valid.  */
 
+/* NOTE: cagney/2001-12-04: This function does not set valid on the
+   pseudo-register range since pseudo registers are always supplied
+   using supply_register().  */
+/* FIXME: cagney/2001-12-04: This function is DEPRECATED.  The target
+   code was blatting the registers[] array and then calling this.
+   Since targets should only be using supply_register() the need for
+   this function/hack is eliminated.  */
 
 void
 registers_fetched (void)
@@ -187,7 +195,7 @@ registers_fetched (void)
   for (i = 0; i < NUM_REGS; i++)
     set_register_cached (i, 1);
   /* Do not assume that the pseudo-regs have also been fetched.
-     Fetching all real regs might not account for all pseudo-regs.  */
+     Fetching all real regs NEVER accounts for pseudo-regs.  */
 }
 
 /* read_register_bytes and write_register_bytes are generally a *BAD*
@@ -758,17 +766,36 @@ reg_flush_command (char *command, int from_tty)
     printf_filtered ("Register cache flushed.\n");
 }
 
+#undef XCALLOC
+#define XCALLOC(NR,TYPE) ((TYPE*) xcalloc ((NR), sizeof (TYPE)))
 
 static void
 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 + NUM_PSEUDO_REGS) * sizeof (*register_valid);
+  int i;
+  int sizeof_register_valid;
+  /* Come up with the real size of the registers buffer.  */
+  int sizeof_registers = REGISTER_BYTES; /* OK use.  */
+  for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
+    {
+      long regend;
+      /* Keep extending the buffer so that there is always enough
+         space for all registers.  The comparison is necessary since
+         legacy code is free to put registers in random places in the
+         buffer separated by holes.  Once REGISTER_BYTE() is killed
+         this can be greatly simplified.  */
+      /* FIXME: cagney/2001-12-04: This code shouldn't need to use
+         REGISTER_BYTE().  Unfortunatly, legacy code likes to lay the
+         buffer out so that certain registers just happen to overlap.
+         Ulgh!  New targets use gdbarch's register read/write and
+         entirely avoid this uglyness.  */
+      regend = REGISTER_BYTE (i) + REGISTER_RAW_SIZE (i);
+      if (sizeof_registers < regend)
+       sizeof_registers = regend;
+    }
   registers = xmalloc (sizeof_registers);
-  memset (registers, 0, sizeof_registers);
+  sizeof_register_valid = ((NUM_REGS + NUM_PSEUDO_REGS)
+                          * sizeof (*register_valid));
   register_valid = xmalloc (sizeof_register_valid);
   memset (register_valid, 0, sizeof_register_valid);
 }