This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[commit] Generalize regcache_{save,restore}


Hello,

The attached generalizes the regcache_save() and regcache_restore() methods by replacing the regcache SRC with an arbitrary buffer + cooked_read function. This generic interface makes it possible for registers to be saved/restored using an arbitrary register source, even a frame:

regcache_save (dst, frame_register_read, frame);

(ok, it needs a few wrapper methods to avoid -Werror).

commited,
Andrew
2003-03-10  Andrew Cagney  <cagney at redhat dot com>

	* regcache.h (regcache_cooked_read_ftype): Define.
	(regcache_save, regcache_restore): Add a cooked_read parameter.
	* regcache.c (regcache_save, regcache_restore): Update.
	(do_cooked_read): New function.
	(regcache_cpy): Pass do_cooked_read to regcache_save and
	regcache_restore.

Index: regcache.c
===================================================================
RCS file: /cvs/src/src/gdb/regcache.c,v
retrieving revision 1.71
diff -u -r1.71 regcache.c
--- regcache.c	3 Mar 2003 20:50:19 -0000	1.71
+++ regcache.c	10 Mar 2003 19:08:04 -0000
@@ -389,59 +389,79 @@
 }
 
 void
-regcache_save (struct regcache *dst, struct regcache *src)
+regcache_save (struct regcache *dst, regcache_cooked_read_ftype *cooked_read,
+	       void *src)
 {
   struct gdbarch *gdbarch = dst->descr->gdbarch;
+  void *buf = alloca (max_register_size (gdbarch));
   int regnum;
-  /* The SRC and DST register caches had better belong to the same
-     architecture.  */
-  gdb_assert (src->descr->gdbarch == dst->descr->gdbarch);
   /* The DST should be `read-only', if it wasn't then the save would
-     end up trying to write the register values out through to the
+     end up trying to write the register values back out to the
      target.  */
-  gdb_assert (!src->readonly_p);
   gdb_assert (dst->readonly_p);
   /* Clear the dest.  */
   memset (dst->registers, 0, dst->descr->sizeof_cooked_registers);
   memset (dst->register_valid_p, 0, dst->descr->sizeof_cooked_register_valid_p);
   /* Copy over any registers (identified by their membership in the
-     save_reggroup) and mark them as valid.  The full [0
-     .. NUM_REGS+NUM_PSEUDO_REGS) range is checked since some
-     architectures need to save/restore `cooked' registers that live
-     in memory.  */
+     save_reggroup) and mark them as valid.  The full [0 .. NUM_REGS +
+     NUM_PSEUDO_REGS) range is checked since some architectures need
+     to save/restore `cooked' registers that live in memory.  */
   for (regnum = 0; regnum < dst->descr->nr_cooked_registers; regnum++)
     {
       if (gdbarch_register_reggroup_p (gdbarch, regnum, save_reggroup))
 	{
-	  regcache_cooked_read (src, regnum, register_buffer (dst, regnum));
-	  dst->register_valid_p[regnum] = 1;
+	  int valid = cooked_read (src, regnum, buf);
+	  if (valid)
+	    {
+	      memcpy (register_buffer (dst, regnum), buf,
+		      register_size (gdbarch, regnum));
+	      dst->register_valid_p[regnum] = 1;
+	    }
 	}
     }
 }
 
 void
-regcache_restore (struct regcache *dst, struct regcache *src)
+regcache_restore (struct regcache *dst,
+		  regcache_cooked_read_ftype *cooked_read,
+		  void *src)
 {
   struct gdbarch *gdbarch = dst->descr->gdbarch;
+  void *buf = alloca (max_register_size (gdbarch));
   int regnum;
-  gdb_assert (src->descr->gdbarch == dst->descr->gdbarch);
+  /* The dst had better not be read-only.  If it is, the `restore'
+     doesn't make much sense.  */
   gdb_assert (!dst->readonly_p);
-  gdb_assert (src->readonly_p);
   /* Copy over any registers, being careful to only restore those that
-     were both saved and need to be restored.  The full [0
-     .. NUM_REGS+NUM_PSEUDO_REGS) range is checked since some
-     architectures need to save/restore `cooked' registers that live
-     in memory.  */
-  for (regnum = 0; regnum < src->descr->nr_cooked_registers; regnum++)
+     were both saved and need to be restored.  The full [0 .. NUM_REGS
+     + NUM_PSEUDO_REGS) range is checked since some architectures need
+     to save/restore `cooked' registers that live in memory.  */
+  for (regnum = 0; regnum < dst->descr->nr_cooked_registers; regnum++)
     {
-      if (gdbarch_register_reggroup_p (gdbarch, regnum, restore_reggroup)
-	  && src->register_valid_p[regnum])
+      if (gdbarch_register_reggroup_p (gdbarch, regnum, restore_reggroup))
 	{
-	  regcache_cooked_write (dst, regnum, register_buffer (src, regnum));
+	  int valid = cooked_read (src, regnum, buf);
+	  if (valid)
+	    regcache_cooked_write (dst, regnum, buf);
 	}
     }
 }
 
+static int
+do_cooked_read (void *src, int regnum, void *buf)
+{
+  struct regcache *regcache = src;
+  if (!regcache_valid_p (regcache, regnum)
+      && regcache->readonly_p)
+    /* Don't even think about fetching a register from a read-only
+       cache when the register isn't yet valid.  There isn't a target
+       from which the register value can be fetched.  */
+    return 0;
+  regcache_cooked_read (regcache, regnum, buf);
+  return 1;
+}
+
+
 void
 regcache_cpy (struct regcache *dst, struct regcache *src)
 {
@@ -452,9 +472,9 @@
   gdb_assert (src != dst);
   gdb_assert (src->readonly_p || dst->readonly_p);
   if (!src->readonly_p)
-    regcache_save (dst, src);
+    regcache_save (dst, do_cooked_read, src);
   else if (!dst->readonly_p)
-    regcache_restore (dst, src);
+    regcache_restore (dst, do_cooked_read, src);
   else
     regcache_cpy_no_passthrough (dst, src);
 }
Index: regcache.h
===================================================================
RCS file: /cvs/src/src/gdb/regcache.h,v
retrieving revision 1.29
diff -u -r1.29 regcache.h
--- regcache.h	28 Feb 2003 17:47:43 -0000	1.29
+++ regcache.h	10 Mar 2003 19:08:04 -0000
@@ -155,15 +155,19 @@
 extern int register_size (struct gdbarch *gdbarch, int regnum);
 
 
-/* Save/restore a register cache.  The registers saved/restored is
-   determined by the save_reggroup and restore_reggroup (although you
-   can't restore a register that wasn't saved as well :-).  You can
-   only save to a read-only cache (default from regcache_xmalloc())
-   from a live cache and you can only restore from a read-only cache
-   to a live cache.  */
+/* Save/restore a register cache.  The set of registers saved /
+   restored into the DST regcache determined by the save_reggroup /
+   restore_reggroup respectively.  COOKED_READ returns zero iff the
+   register's value can't be returned.  */
 
-extern void regcache_save (struct regcache *dst, struct regcache *src);
-extern void regcache_restore (struct regcache *dst, struct regcache *src);
+typedef int (regcache_cooked_read_ftype) (void *src, int regnum, void *buf);
+
+extern void regcache_save (struct regcache *dst,
+			   regcache_cooked_read_ftype *cooked_read,
+			   void *src);
+extern void regcache_restore (struct regcache *dst,
+			      regcache_cooked_read_ftype *cooked_read,
+			      void *src);
 
 /* Copy/duplicate the contents of a register cache.  By default, the
    operation is pass-through.  Writes to DST and reads from SRC will

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]