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]

Re: [patch/rfc] register_offset_hack()


Hello,

The attached adds a number of ``hacks'' to the regcache.  The intent is for these hacks to replace the far worse and much dreaded read_register_bytes() and write_register_bytes().

The struct value and expression evaluator view the register cache as a linear byte array.  Hence, to read adjacent registers, a ``memcpy'' of the relevant bytes is all that is needed.

The attached provides the following methods:

register_offset_hack(gdbarch,regnum)
  Replaces REGISTER_BYTE().  Returns the ``offset'' of regnum in the register buffer.

regcache_cooked read/write using_offset_hack(regcache,offset,len,buf)
  read/write the cooked register cache treating the cache as a big array.

While similar to the read_register_bytes() and write_register_bytes() methods they have far simpler interfaces.  Hacks such as reading, or even allowing, gaps between registers have been removed.

Other than a couple cases related to the expression evaluator and struct value, there should be no reason for using these functions.

I'll look to commit this code in a few days but won't even consider changing things over until post 5.3 branch.
I've updated this patch (use some newer functions) and committed the attached.

Andrew

2002-08-25  Andrew Cagney  <ac131313@redhat.com>

	* regcache.h (register_offset_hack): Declare.
	(regcache_cooked_read_using_offset_hack): Declare.
	(regcache_cooked_write_using_offset_hack): Declare.

	* regcache.c (register_offset_hack): New function.
	(regcache_cooked_read_using_offset_hack): New function.
	(regcache_cooked_write_using_offset_hack): New function.
	(regcache_dump): Check that the registers, according to their
	offset, are packed hard against each other.
	(cooked_xfer_using_offset_hack): New function.

Index: regcache.c
===================================================================
RCS file: /cvs/src/src/gdb/regcache.c,v
retrieving revision 1.56
diff -u -r1.56 regcache.c
--- regcache.c	25 Aug 2002 15:36:11 -0000	1.56
+++ regcache.c	25 Aug 2002 17:01:49 -0000
@@ -1029,6 +1029,95 @@
 		      regcache_cooked_read, regcache_cooked_write);
 }
 
+/* Hack to keep code that view the register buffer as raw bytes
+   working.  */
+
+int
+register_offset_hack (struct gdbarch *gdbarch, int regnum)
+{
+  struct regcache_descr *descr = regcache_descr (gdbarch);
+  gdb_assert (regnum >= 0 && regnum < descr->nr_cooked_registers);
+  return descr->register_offset[regnum];
+}
+
+static void
+cooked_xfer_using_offset_hack (struct regcache *regcache,
+			       int buf_start, int buf_len, void *in_b,
+			       const void *out_b)
+{
+  struct regcache_descr *descr = regcache->descr;
+  struct gdbarch *gdbarch = descr->gdbarch;
+  bfd_byte *in_buf = in_b;
+  const bfd_byte *out_buf = out_b;
+  int buf_end = buf_start + buf_len;
+  int regnum;
+  char *reg_buf = alloca (descr->max_register_size);
+
+  /* NOTE: cagney/2002-08-17: This code assumes that the register
+     offsets are strictly increasing and do not overlap.  If this
+     isn't the case then the bug is in the target architecture and NOT
+     this code.  */
+
+  /* NOTE: cagney/2002-08-17: This code assumes that only the
+     registers covered by BUF_START:BUF_LEN should be transfered.  If,
+     for some reason, there is a gap between two registers, then that
+     gap isn't transfered.  (The gap shouldn't be there but that is
+     another story.)  */
+
+  /* Iterate through all registers looking for those that lie within
+     BUF_START:BUF_LEN.  */
+
+  for (regnum = 0; regnum < descr->nr_cooked_registers; regnum++)
+    {
+      /* The register's location.  */
+      int reg_start = descr->register_offset[regnum];
+      int reg_len = descr->sizeof_register[regnum];
+      int reg_end = reg_start + reg_len;
+
+      /* The START, END and LEN that falls within the current
+         register.  */
+      int xfer_start;
+      int xfer_end;
+      int xfer_len;
+
+      /* start = max (reg_start, buf_start) */
+      if (reg_start > buf_start)
+	xfer_start = reg_start;
+      else
+	xfer_start = buf_start;
+      
+      /* end = min (reg_end, buf_end) */
+      if (reg_end < buf_end)
+	xfer_end = reg_end;
+      else
+	xfer_end = buf_end;
+      
+      /* The number of bytes to transfer.  If there isn't anything to
+         transfer (the end is before the start) this will be -ve.  */
+      xfer_len = xfer_end - xfer_start;
+
+      if (xfer_len > 0)
+	regcache_xfer_part (regcache, regnum, xfer_start - reg_start,
+			    xfer_len, in_b, out_b, regcache_cooked_read,
+			    regcache_cooked_write);
+    }
+}
+
+void
+regcache_cooked_read_using_offset_hack (struct regcache *regcache,
+					int buf_start, int buf_len, void *b)
+{
+  cooked_xfer_using_offset_hack (regcache, buf_start, buf_len, b, NULL);
+}
+
+void
+regcache_cooked_write_using_offset_hack (struct regcache *regcache,
+					 int buf_start, int buf_len,
+					 const void *b)
+{
+  cooked_xfer_using_offset_hack (regcache, buf_start, buf_len, NULL, b);
+}
+
 /* Return the contents of register REGNUM as an unsigned integer.  */
 
 ULONGEST
@@ -1439,7 +1528,12 @@
 	  fprintf_unfiltered (file, " %6ld",
 			      regcache->descr->register_offset[regnum]);
 	  if (register_offset != regcache->descr->register_offset[regnum]
-	      || register_offset != REGISTER_BYTE (regnum))
+	      || register_offset != REGISTER_BYTE (regnum)
+	      || (regnum > 0
+		  && (regcache->descr->register_offset[regnum]
+		      != (regcache->descr->register_offset[regnum - 1]
+			  + regcache->descr->sizeof_register[regnum - 1])))
+	      )
 	    {
 	      if (!footnote_register_offset)
 		footnote_register_offset = ++footnote_nr;
Index: regcache.h
===================================================================
RCS file: /cvs/src/src/gdb/regcache.h,v
retrieving revision 1.17
diff -u -r1.17 regcache.h
--- regcache.h	25 Aug 2002 15:36:11 -0000	1.17
+++ regcache.h	25 Aug 2002 17:01:50 -0000
@@ -88,6 +88,33 @@
 extern void regcache_collect (int regnum, void *buf);
 
 
+/* The register's ``offset''.
+
+   NOTE: cagney/2002-08-17: The ``struct value'' and expression
+   evaluator treat the register cache as a large liner buffer.
+   Instead of reading/writing a register using its register number,
+   the code read/writes registers by specifying their offset into the
+   buffer and a number of bytes.  The code also assumes that these
+   byte read/writes can cross register boundaries, adjacent registers
+   treated as a contiguous set of bytes.
+
+   The below map that model onto the real register cache.  New code
+   should go out of their way to avoid using these interfaces.
+
+   FIXME: cagney/2002-08-17: The ``struct value'' and expression
+   evaluator should be fixed.  Instead of using the { offset, length }
+   pair to describe a value within one or more registers, the code
+   should use a chain of { regnum, offset, len } tripples.  */
+
+extern int register_offset_hack (struct gdbarch *gdbarch, int regnum);
+extern void regcache_cooked_read_using_offset_hack (struct regcache *regcache,
+						    int offset, int len,
+						    void *buf);
+extern void regcache_cooked_write_using_offset_hack (struct regcache *regcache,
+						     int offset, int len,
+						     const void *buf);
+
+
 /* The type of a register.  This function is slightly more efficient
    then its gdbarch vector counterpart since it returns a precomputed
    value stored in a table.

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