Re-vamp the register code so that a lot more is routed through
authorAndrew Cagney <cagney@redhat.com>
Sat, 24 Mar 2001 01:26:09 +0000 (01:26 +0000)
committerAndrew Cagney <cagney@redhat.com>
Sat, 24 Mar 2001 01:26:09 +0000 (01:26 +0000)
{read,write}_register_gen.  Hook that function with multi-arch.

gdb/ChangeLog
gdb/TODO
gdb/gdbarch.c
gdb/gdbarch.h
gdb/gdbarch.sh
gdb/regcache.c
gdb/regcache.h

index 6f7cbda9a192f7c9edd22fc71962713670433ee1..8ab4e59f1eff86c036c97c8ddc2054c145dce292 100644 (file)
@@ -1,3 +1,27 @@
+2001-03-23  Andrew Cagney  <ac131313@redhat.com>
+
+       * gdbarch.sh (gdbarch_register_read, gdbarch_register_write): Add.
+       * gdbarch.h, gdbarch.c: Regenerate.
+       
+       * regcache.h (regcache_read, regcache_write): Declare.
+       (registers, register_valid, register_buffer): Add note that these
+       interfaces are deprecated.
+       
+       * regcache.c: Include "gdb_assert.h".
+       (legacy_write_register_gen): Rename write_register_gen.
+       (legacy_read_register_gen): Rename read_register_gen.
+       (regcache_read, regcache_write): New function.
+       (read_register_gen, write_register_gen): New function.
+       (write_register): Simplify.  Use write_register_gen.
+       (read_register): Ditto using read_register_gen.
+       (read_signed_register): Ditto.
+       (read_register_bytes): Ditto!!!!
+       (supply_register): Add note that CLEANUP_REGISTER_VALUE is being
+       replaced by gdbarch_register_read.
+
+       * TODO (GDB 5.2 - Cleanups): Add list of gdbarch methods to
+       deprecate.
+
 2001-03-23  Jim Blandy  <jimb@redhat.com>
 
        * stabsread.c (read_cpp_abbrev): Properly construct the names of
index 55f6084cb8d9c2c453c9cf982721232ed07ac5a0..a74005559bab7fd8743a24dc37d0301964758a99 100644 (file)
--- a/gdb/TODO
+++ b/gdb/TODO
@@ -305,6 +305,58 @@ Eliminate all warnings for at least one host/target for the flags:
 
 --
 
+Deprecate, if not delete, the following:
+
+        register[]
+        register_valid[]
+        register_buffer()
+       REGISTER_BYTE()
+                Replaced by, on the target side
+                  supply_register()
+                and on core-gdb side:
+                  {read,write}_register_gen()
+               Remote.c will need to use something
+               other than REGISTER_BYTE() and
+               REGISTER_RAW_SIZE() when unpacking
+               [gG] packets.
+
+        STORE_PSEUDO_REGISTER
+        FETCH_PSEUDO_REGISTER
+                Now handed by the methods
+                  gdbarch_{read,write}_register()
+                which sits between core GDB and
+                the register cache.
+
+        REGISTER_CONVERTIBLE
+        REGISTER_CONVERT_TO_RAW
+        REGISTER_CONVERT_TO_VIRTUAL
+                I think these three are redundant.
+                gdbarch_register_{read,write} can
+                do any conversion it likes.
+
+        REGISTER_VIRTUAL_SIZE
+        MAX_REGISTER_VIRTUAL_SIZE
+        REGISTER_VIRTUAL_TYPE
+                I think these can be replaced by
+               the pair:
+                  FRAME_REGISTER_TYPE(frame, regnum)
+                  REGISTER_TYPE(regnum)
+
+       DO_REGISTERS_INFO
+               Replace with
+                FRAME_REGISTER_INFO (frame, ...)
+
+       REGISTER_SIM_REGNO()
+               If nothing else rename this so that
+               how it relates to rawreg and the
+               regnum is clear.
+
+       REGISTER_BYTES
+               The size of the cache can be computed
+               on the fly.
+
+--
+
 Restructure gdb directory tree so that it avoids any 8.3 and 14
 filename problems.
 
index 4ff794c23b5eedd9dd8ca89dac01f9bae11d7804..8145d99a755b604933c8012c593fb11005e8f66f 100644 (file)
@@ -149,6 +149,8 @@ struct gdbarch
   gdbarch_write_fp_ftype *write_fp;
   gdbarch_read_sp_ftype *read_sp;
   gdbarch_write_sp_ftype *write_sp;
+  gdbarch_register_read_ftype *register_read;
+  gdbarch_register_write_ftype *register_write;
   int num_regs;
   int num_pseudo_regs;
   int sp_regnum;
@@ -321,6 +323,8 @@ struct gdbarch startup_gdbarch =
   0,
   0,
   0,
+  0,
+  0,
   generic_get_saved_register,
   0,
   0,
@@ -512,6 +516,8 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of write_fp, invalid_p == 0 */
   /* Skip verify of read_sp, invalid_p == 0 */
   /* Skip verify of write_sp, invalid_p == 0 */
+  /* Skip verify of register_read, has predicate */
+  /* Skip verify of register_write, has predicate */
   if ((GDB_MULTI_ARCH >= 2)
       && (gdbarch->num_regs == -1))
     internal_error (__FILE__, __LINE__,
@@ -1534,6 +1540,14 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                         (long) current_gdbarch->write_sp
                         /*TARGET_WRITE_SP ()*/);
 #endif
+  if (GDB_MULTI_ARCH)
+    fprintf_unfiltered (file,
+                        "gdbarch_dump: register_read = 0x%08lx\n",
+                        (long) current_gdbarch->register_read);
+  if (GDB_MULTI_ARCH)
+    fprintf_unfiltered (file,
+                        "gdbarch_dump: register_write = 0x%08lx\n",
+                        (long) current_gdbarch->register_write);
 #ifdef NUM_REGS
   fprintf_unfiltered (file,
                       "gdbarch_dump: NUM_REGS = %ld\n",
@@ -2451,6 +2465,54 @@ set_gdbarch_write_sp (struct gdbarch *gdbarch,
   gdbarch->write_sp = write_sp;
 }
 
+int
+gdbarch_register_read_p (struct gdbarch *gdbarch)
+{
+  return gdbarch->register_read != 0;
+}
+
+void
+gdbarch_register_read (struct gdbarch *gdbarch, int regnum, char *buf)
+{
+  if (gdbarch->register_read == 0)
+    internal_error (__FILE__, __LINE__,
+                    "gdbarch: gdbarch_register_read invalid");
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_register_read called\n");
+  gdbarch->register_read (gdbarch, regnum, buf);
+}
+
+void
+set_gdbarch_register_read (struct gdbarch *gdbarch,
+                           gdbarch_register_read_ftype register_read)
+{
+  gdbarch->register_read = register_read;
+}
+
+int
+gdbarch_register_write_p (struct gdbarch *gdbarch)
+{
+  return gdbarch->register_write != 0;
+}
+
+void
+gdbarch_register_write (struct gdbarch *gdbarch, int regnum, char *buf)
+{
+  if (gdbarch->register_write == 0)
+    internal_error (__FILE__, __LINE__,
+                    "gdbarch: gdbarch_register_write invalid");
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_register_write called\n");
+  gdbarch->register_write (gdbarch, regnum, buf);
+}
+
+void
+set_gdbarch_register_write (struct gdbarch *gdbarch,
+                            gdbarch_register_write_ftype register_write)
+{
+  gdbarch->register_write = register_write;
+}
+
 int
 gdbarch_num_regs (struct gdbarch *gdbarch)
 {
index f5b1b440055c59a00845a8a2889de2cbf17c86c6..a9f0e158f95ad935bfbe5d9059783b49415e8cb2 100644 (file)
@@ -339,6 +339,18 @@ extern void set_gdbarch_write_sp (struct gdbarch *gdbarch, gdbarch_write_sp_ftyp
 #endif
 #endif
 
+extern int gdbarch_register_read_p (struct gdbarch *gdbarch);
+
+typedef void (gdbarch_register_read_ftype) (struct gdbarch *gdbarch, int regnum, char *buf);
+extern void gdbarch_register_read (struct gdbarch *gdbarch, int regnum, char *buf);
+extern void set_gdbarch_register_read (struct gdbarch *gdbarch, gdbarch_register_read_ftype *register_read);
+
+extern int gdbarch_register_write_p (struct gdbarch *gdbarch);
+
+typedef void (gdbarch_register_write_ftype) (struct gdbarch *gdbarch, int regnum, char *buf);
+extern void gdbarch_register_write (struct gdbarch *gdbarch, int regnum, char *buf);
+extern void set_gdbarch_register_write (struct gdbarch *gdbarch, gdbarch_register_write_ftype *register_write);
+
 extern int gdbarch_num_regs (struct gdbarch *gdbarch);
 extern void set_gdbarch_num_regs (struct gdbarch *gdbarch, int num_regs);
 #if GDB_MULTI_ARCH
index a4ad4cca747359dc0eb7eb234289eaafd134fa69..ac6d3e971da2a3ed80150769ae7f40272d965cf1 100755 (executable)
@@ -383,6 +383,9 @@ f::TARGET_WRITE_FP:void:write_fp:CORE_ADDR val:val::0:generic_target_write_fp::0
 f::TARGET_READ_SP:CORE_ADDR:read_sp:void:::0:generic_target_read_sp::0
 f::TARGET_WRITE_SP:void:write_sp:CORE_ADDR val:val::0:generic_target_write_sp::0
 #
+M:::void:register_read:int regnum, char *buf:regnum, buf:
+M:::void:register_write:int regnum, char *buf:regnum, buf:
+#
 v:2:NUM_REGS:int:num_regs::::0:-1
 # This macro gives the number of pseudo-registers that live in the
 # register namespace but do not get fetched or stored on the target.
index 7b462dedcc9afc182fb859e78b6dc3a0d5f2dcb1..5128c1e6fd4f7d00b05690a60f2f092e4c61d360 100644 (file)
@@ -26,6 +26,7 @@
 #include "gdbarch.h"
 #include "gdbcmd.h"
 #include "regcache.h"
+#include "gdb_assert.h"
 
 /*
  * DATA STRUCTURE
@@ -213,54 +214,62 @@ registers_fetched (void)
    into memory at MYADDR.  */
 
 void
-read_register_bytes (int inregbyte, char *myaddr, int inlen)
+read_register_bytes (int in_start, char *in_buf, int in_len)
 {
-  int inregend = inregbyte + inlen;
+  int in_end = in_start + in_len;
   int regnum;
-
-  if (registers_pid != inferior_pid)
-    {
-      registers_changed ();
-      registers_pid = inferior_pid;
-    }
+  char *reg_buf = alloca (MAX_REGISTER_RAW_SIZE);
 
   /* See if we are trying to read bytes from out-of-date registers.  If so,
      update just those registers.  */
 
   for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++)
     {
-      int regstart, regend;
-
-      if (register_cached (regnum))
-       continue;
+      int reg_start;
+      int reg_end;
+      int reg_len;
+      int start;
+      int end;
+      int byte;
 
       if (REGISTER_NAME (regnum) == NULL || *REGISTER_NAME (regnum) == '\0')
        continue;
 
-      regstart = REGISTER_BYTE (regnum);
-      regend = regstart + REGISTER_RAW_SIZE (regnum);
+      reg_start = REGISTER_BYTE (regnum);
+      reg_len = REGISTER_RAW_SIZE (regnum);
+      reg_end = reg_start + reg_len;
 
-      if (regend <= inregbyte || inregend <= regstart)
+      if (reg_end <= in_start || in_end <= reg_start)
        /* The range the user wants to read doesn't overlap with regnum.  */
        continue;
 
-      /* We've found an uncached register where at least one byte will be read.
-         Update it from the target.  */
-      fetch_register (regnum);
+      /* Force the cache to fetch the entire register. */
+      read_register_gen (regnum, reg_buf);
 
-      if (!register_cached (regnum))
+      /* Legacy note: This function, for some reason, allows a NULL
+         input buffer.  If the buffer is NULL, the registers are still
+         fetched, just the final transfer is skipped. */
+      if (in_buf == NULL)
+       continue;
+
+      /* start = max (reg_start, in_start) */
+      if (reg_start > in_start)
+       start = reg_start;
+      else
+       start = in_start;
+
+      /* end = min (reg_end, in_end) */
+      if (reg_end < in_end)
+       end = reg_end;
+      else
+       end = in_end;
+
+      /* Transfer just the bytes common to both IN_BUF and REG_BUF */
+      for (byte = start; byte < end; byte++)
        {
-         /* Sometimes pseudoregs are never marked valid, so that they 
-            will be fetched every time (it can be complicated to know
-            if a pseudoreg is valid, while "fetching" them can be cheap). 
-            */
-         if (regnum < NUM_REGS)
-           error ("read_register_bytes:  Couldn't update register %d.", regnum);
+         in_buf[byte - in_start] = reg_buf[byte - reg_start];
        }
     }
-
-  if (myaddr != NULL)
-    memcpy (myaddr, register_buffer (-1) + inregbyte, inlen);
 }
 
 /* Read register REGNUM into memory at MYADDR, which must be large
@@ -268,9 +277,10 @@ read_register_bytes (int inregbyte, char *myaddr, int inlen)
    register is known to be the size of a CORE_ADDR or smaller,
    read_register can be used instead.  */
 
-void
-read_register_gen (int regnum, char *myaddr)
+static void
+legacy_read_register_gen (int regnum, char *myaddr)
 {
+  gdb_assert (regnum >= 0 && regnum < (NUM_REGS + NUM_PSEUDO_REGS));
   if (registers_pid != inferior_pid)
     {
       registers_changed ();
@@ -284,6 +294,26 @@ read_register_gen (int regnum, char *myaddr)
          REGISTER_RAW_SIZE (regnum));
 }
 
+void
+regcache_read (int rawnum, char *buf)
+{
+  gdb_assert (rawnum >= 0 && rawnum < NUM_REGS);
+  /* For moment, just use underlying legacy code. Ulgh!!! */
+  legacy_read_register_gen (rawnum, buf);
+}
+
+void
+read_register_gen (int regnum, char *buf)
+{
+  if (! gdbarch_register_read_p (current_gdbarch))
+    {
+      legacy_read_register_gen (regnum, buf);
+      return;
+    }
+  gdbarch_register_read (current_gdbarch, regnum, buf);
+}
+
+
 /* Write register REGNUM at MYADDR to the target.  MYADDR points at
    REGISTER_RAW_BYTES(REGNUM), which must be in target byte-order.  */
 
@@ -292,10 +322,11 @@ read_register_gen (int regnum, char *myaddr)
 #define CANNOT_STORE_REGISTER(regnum) 0
 #endif
 
-void
-write_register_gen (int regnum, char *myaddr)
+static void
+legacy_write_register_gen (int regnum, char *myaddr)
 {
   int size;
+  gdb_assert (regnum >= 0 && regnum < (NUM_REGS + NUM_PSEUDO_REGS));
 
   /* On the sparc, writing %g0 is a no-op, so we don't even want to
      change the registers array if something writes to this register.  */
@@ -326,6 +357,25 @@ write_register_gen (int regnum, char *myaddr)
   store_register (regnum);
 }
 
+void
+regcache_write (int rawnum, char *buf)
+{
+  gdb_assert (rawnum >= 0 && rawnum < NUM_REGS);
+  /* For moment, just use underlying legacy code. Ulgh!!! */
+  legacy_write_register_gen (rawnum, buf);
+}
+
+void
+write_register_gen (int regnum, char *buf)
+{
+  if (! gdbarch_register_write_p (current_gdbarch))
+    {
+      legacy_write_register_gen (regnum, buf);
+      return;
+    }
+  gdbarch_register_write (current_gdbarch, regnum, buf);
+}
+
 /* Copy INLEN bytes of consecutive data from memory at MYADDR
    into registers starting with the MYREGSTART'th byte of register data.  */
 
@@ -385,17 +435,9 @@ write_register_bytes (int myregstart, char *myaddr, int inlen)
 ULONGEST
 read_register (int regnum)
 {
-  if (registers_pid != inferior_pid)
-    {
-      registers_changed ();
-      registers_pid = inferior_pid;
-    }
-
-  if (!register_cached (regnum))
-    fetch_register (regnum);
-
-  return (extract_unsigned_integer (register_buffer (regnum),
-                                   REGISTER_RAW_SIZE (regnum)));
+  char *buf = alloca (REGISTER_RAW_SIZE (regnum));
+  read_register_gen (regnum, buf);
+  return (extract_unsigned_integer (buf, REGISTER_RAW_SIZE (regnum)));
 }
 
 ULONGEST
@@ -423,17 +465,9 @@ read_register_pid (int regnum, int pid)
 LONGEST
 read_signed_register (int regnum)
 {
-  if (registers_pid != inferior_pid)
-    {
-      registers_changed ();
-      registers_pid = inferior_pid;
-    }
-
-  if (!register_cached (regnum))
-    fetch_register (regnum);
-
-  return (extract_signed_integer (register_buffer (regnum),
-                                 REGISTER_RAW_SIZE (regnum)));
+  void *buf = alloca (REGISTER_RAW_SIZE (regnum));
+  read_register_gen (regnum, buf);
+  return (extract_signed_integer (buf, REGISTER_RAW_SIZE (regnum)));
 }
 
 LONGEST
@@ -461,38 +495,12 @@ read_signed_register_pid (int regnum, int pid)
 void
 write_register (int regnum, LONGEST val)
 {
-  PTR buf;
+  void *buf;
   int size;
-
-  /* On the sparc, writing %g0 is a no-op, so we don't even want to
-     change the registers array if something writes to this register.  */
-  if (CANNOT_STORE_REGISTER (regnum))
-    return;
-
-  if (registers_pid != inferior_pid)
-    {
-      registers_changed ();
-      registers_pid = inferior_pid;
-    }
-
   size = REGISTER_RAW_SIZE (regnum);
   buf = alloca (size);
   store_signed_integer (buf, size, (LONGEST) val);
-
-  /* If we have a valid copy of the register, and new value == old value,
-     then don't bother doing the actual store. */
-
-  if (register_cached (regnum)
-      && memcmp (register_buffer (regnum), buf, size) == 0)
-    return;
-
-  if (real_register (regnum))
-    target_prepare_to_store ();
-
-  memcpy (register_buffer (regnum), buf, size);
-
-  set_register_cached (regnum, 1);
-  store_register (regnum);
+  write_register_gen (regnum, buf);
 }
 
 void
@@ -547,6 +555,12 @@ supply_register (int regnum, char *val)
   /* On some architectures, e.g. HPPA, there are a few stray bits in
      some registers, that the rest of the code would like to ignore.  */
 
+  /* NOTE: cagney/2001-03-16: The macro CLEAN_UP_REGISTER_VALUE is
+     going to be deprecated.  Instead architectures will leave the raw
+     register value as is and instead clean things up as they pass
+     through the method gdbarch_register_read() clean up the
+     values. */
+
 #ifdef CLEAN_UP_REGISTER_VALUE
   CLEAN_UP_REGISTER_VALUE (regnum, register_buffer (regnum));
 #endif
index cb5754ba618f61023651540d0d25a2ee078f490f..dbffb5792e927c5acc4cb69e5e32c9f19c7c3013 100644 (file)
 #ifndef REGCACHE_H
 #define REGCACHE_H
 
-/* Character array containing an image of the inferior programs'
-   registers. */
+/* Transfer a raw register [0..NUM_REGS) between core-gdb and the
+   regcache. */
+
+void regcache_read (int rawnum, char *buf);
+void regcache_write (int rawnum, char *buf);
+
+/* DEPRECATED: Character array containing an image of the inferior
+   programs' registers for the most recently referenced thread. */
 
 extern char *registers;
 
-/* Character array containing the current state of each register
-   (unavailable<0, invalid=0, valid>0). */
+/* DEPRECATED: Character array containing the current state of each
+   register (unavailable<0, invalid=0, valid>0) for the most recently
+   referenced thread. */
 
 extern signed char *register_valid;
 
@@ -38,6 +45,9 @@ extern void set_register_cached (int regnum, int state);
 
 extern void register_changed (int regnum);
 
+/* DEPRECATED: Functional interface returning pointer into registers[]
+   array. */
+
 extern char *register_buffer (int regnum);
 
 extern void registers_changed (void);