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] Rewrite regcache.[hc], add ``struct regcache'' object


I've checked this in.....  I guess I now wait a bit.

(I've attached the final patch for reference).

Andrew
2002-06-19  Andrew Cagney  <cagney@redhat.com>

	* regcache.h: Update copyright.
	(struct regcache, struct gdbarch): Add opaque declarations.
	(current_regcache): Declare global variable.
	(regcache_read, regcache_write): Add gdbarch parameter.
	(regcache_save, regcache_save_no_passthrough)
	(regcache_restore, regcache_restore_no_passthrough)
	(regcache_dup, regcache_dup_no_passthrough)
	(regcache_cpy, regcache_cpy_no_passthrough)
	(deprecated_grub_regcache_for_registers)
	(deprecated_grub_regcache_for_register_valid)
	(regcache_valid_p): Add function declarations.
	
	* regcache.c: Update copyright.
	(regcache_descr_handle): New global variable.
	(struct regcache_descr): Define.
	(init_legacy_regcache_descr, init_regcache_descr): New functions.
	(regcache_descr, xfree_regcache_descr): New functions.
	(struct regcache): Define.
	(regcache_xmalloc, regcache_xfree): New functions.
	(regcache_cpy, regcache_cpy_no_passthrough): New functions.
	(regcache_dup, regcache_dup_no_passthrough): New functions.
	(regcache_valid_p, regcache_read_as_address): New functions.
	(deprecated_grub_regcache_for_registers): New function.
	(deprecated_grub_regcache_for_register_valid): New function.
	(current_regcache): New global variable.
	(register_buffer): Add regcache parameter.  Update calls.
	(regcache_read, regcache_write): Add regcache parameter.  Rewrite.
	(read_register_gen, write_register_gen): Update register_buffer
	call.  Test for legacy_p instead of gdbarch_register_read_p or
	gdbarch_register_write_p.
	(regcache_collect): Update register_buffer call.
	(build_regcache): Rewrite.  Use deprecated grub functions.
	(regcache_save, regcache_save_no_passthrough): New functions.
	(regcache_restore, regcache_restore_no_passthrough): New
	functions.
	(_initialize_regcache): Create the regcache_data_handle. Swap
	current_regcache global variable.
	
	* sh-tdep.c (sh_pseudo_register_read): Add current_regcache
	parameter to regcache_read and regcache_write calls.
	(sh4_register_read): Ditto.
	(sh64_pseudo_register_read): Ditto.
	(sh64_register_read): Ditto.
	(sh_pseudo_register_write): Ditto.
	(sh4_register_write): Ditto.
	(sh64_pseudo_register_write): Ditto.
	(sh64_register_write): Ditto.

	* defs.h (XCALLOC): Define.

Index: defs.h
===================================================================
RCS file: /cvs/src/src/gdb/defs.h,v
retrieving revision 1.89
diff -u -r1.89 defs.h
--- defs.h	15 Jun 2002 18:45:31 -0000	1.89
+++ defs.h	20 Jun 2002 01:46:05 -0000
@@ -844,10 +844,11 @@
    "libiberty.h". */
 extern void xfree (void *);
 
-/* Utility macro to allocate typed memory.  Avoids errors like
+/* Utility macros to allocate typed memory.  Avoids errors like
    ``struct foo *foo = xmalloc (sizeof bar)'' and ``struct foo *foo =
    (struct foo *) xmalloc (sizeof bar)''.  */
 #define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE)))
+#define XCALLOC(NMEMB, TYPE) ((TYPE*) xcalloc ((NMEMB), sizeof (TYPE)))
 
 /* Like asprintf/vasprintf but get an internal_error if the call
    fails. */
Index: regcache.c
===================================================================
RCS file: /cvs/src/src/gdb/regcache.c,v
retrieving revision 1.36
diff -u -r1.36 regcache.c
--- regcache.c	15 May 2002 01:01:56 -0000	1.36
+++ regcache.c	20 Jun 2002 01:46:06 -0000
@@ -1,6 +1,7 @@
 /* Cache and manage the values of registers for GDB, the GNU debugger.
-   Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000, 2001
-   Free Software Foundation, Inc.
+
+   Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000,
+   2001, 2002 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -33,6 +34,349 @@
  * Here is the actual register cache.
  */
 
+/* Per-architecture object describing the layout of a register cache.
+   Computed once when the architecture is created */
+
+struct gdbarch_data *regcache_descr_handle;
+
+struct regcache_descr
+{
+  /* The architecture this descriptor belongs to.  */
+  struct gdbarch *gdbarch;
+
+  /* Is this a ``legacy'' register cache?  Such caches reserve space
+     for raw and pseudo registers and allow access to both.  */
+  int legacy_p;
+
+  /* The raw register cache.  This should contain just [0
+     .. NUM_RAW_REGISTERS).  However, for older targets, it contains
+     space for the full [0 .. NUM_RAW_REGISTERS +
+     NUM_PSEUDO_REGISTERS).  */
+  int nr_raw_registers;
+  long sizeof_raw_registers;
+  long sizeof_raw_register_valid_p;
+
+  /* Offset, in bytes, of reach register in the raw register cache.
+     Pseudo registers have an offset even though they don't
+     (shouldn't) have a correspoinding space in the register cache.
+     It is to keep existing code, that relies on
+     write/write_register_bytes working.  */
+  long *register_offset;
+
+  /* The cooked / frame / virtual register space.  The registers in
+     the range [0..NR_RAW_REGISTERS) should be mapped directly onto
+     the corresponding raw register.  The next [NR_RAW_REGISTERS
+     .. NR_REGISTERS) should have been mapped, via
+     gdbarch_register_read/write onto either raw registers or memory.  */
+  int nr_registers;
+  long *sizeof_register;
+  long max_register_size;
+
+};
+
+static void *
+init_legacy_regcache_descr (struct gdbarch *gdbarch)
+{
+  int i;
+  struct regcache_descr *descr;
+  /* FIXME: cagney/2002-05-11: gdbarch_data() should take that
+     ``gdbarch'' as a parameter.  */
+  gdb_assert (gdbarch != NULL);
+
+  descr = XMALLOC (struct regcache_descr);
+  descr->gdbarch = gdbarch;
+  descr->legacy_p = 1;
+
+  /* FIXME: cagney/2002-05-11: Shouldn't be including pseudo-registers
+     in the register buffer.  Unfortunatly some architectures do.  */
+  descr->nr_registers = NUM_REGS + NUM_PSEUDO_REGS;
+  descr->nr_raw_registers = descr->nr_registers;
+  descr->sizeof_raw_register_valid_p = descr->nr_registers;
+
+  /* FIXME: cagney/2002-05-11: Instead of using REGISTER_BYTE() this
+     code should compute the offets et.al. at runtime.  This currently
+     isn't possible because some targets overlap register locations -
+     see the mess in read_register_bytes() and write_register_bytes()
+     registers.  */
+  descr->sizeof_register = XCALLOC (descr->nr_registers, long);
+  descr->register_offset = XCALLOC (descr->nr_registers, long);
+  descr->max_register_size = 0;
+  for (i = 0; i < descr->nr_registers; i++)
+    {
+      descr->register_offset[i] = REGISTER_BYTE (i);
+      descr->sizeof_register[i] = REGISTER_RAW_SIZE (i);
+      if (descr->max_register_size < REGISTER_RAW_SIZE (i))
+	descr->max_register_size = REGISTER_RAW_SIZE (i);
+    }
+
+  /* Come up with the real size of the registers buffer.  */
+  descr->sizeof_raw_registers = REGISTER_BYTES; /* OK use.  */
+  for (i = 0; i < descr->nr_registers; 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 = descr->register_offset[i] + descr->sizeof_register[i];
+      if (descr->sizeof_raw_registers < regend)
+	descr->sizeof_raw_registers = regend;
+    }
+  return descr;
+}
+
+static void *
+init_regcache_descr (struct gdbarch *gdbarch)
+{
+  int i;
+  struct regcache_descr *descr;
+  gdb_assert (gdbarch != NULL);
+
+  /* If an old style architecture, construct the register cache
+     description using all the register macros.  */
+  if (!gdbarch_register_read_p (gdbarch)
+      && !gdbarch_register_write_p (gdbarch))
+    return init_legacy_regcache_descr (gdbarch);
+
+  descr = XMALLOC (struct regcache_descr);
+  descr->gdbarch = gdbarch;
+  descr->legacy_p = 0;
+
+  /* Total size of the register space.  The raw registers should
+     directly map onto the raw register cache while the pseudo's are
+     either mapped onto raw-registers or memory.  */
+  descr->nr_registers = NUM_REGS + NUM_PSEUDO_REGS;
+
+  /* Construct a strictly RAW register cache.  Don't allow pseudo's
+     into the register cache.  */
+  descr->nr_raw_registers = NUM_REGS;
+  descr->sizeof_raw_register_valid_p = NUM_REGS;
+
+  /* Lay out the register cache.  The pseud-registers are included in
+     the layout even though their value isn't stored in the register
+     cache.  Some code, via read_register_bytes() access a register
+     using an offset/length rather than a register number.
+
+     NOTE: cagney/2002-05-22: Only REGISTER_VIRTUAL_TYPE() needs to be
+     used when constructing the register cache.  It is assumed that
+     register raw size, virtual size and type length of the type are
+     all the same.  */
+
+  {
+    long offset = 0;
+    descr->sizeof_register = XCALLOC (descr->nr_registers, long);
+    descr->register_offset = XCALLOC (descr->nr_registers, long);
+    descr->max_register_size = 0;
+    for (i = 0; i < descr->nr_registers; i++)
+      {
+	descr->sizeof_register[i] = TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (i));
+	descr->register_offset[i] = offset;
+	offset += descr->sizeof_register[i];
+	if (descr->max_register_size < descr->sizeof_register[i])
+	  descr->max_register_size = descr->sizeof_register[i];
+      }
+    /* Set the real size of the register cache buffer.  */
+    /* FIXME: cagney/2002-05-22: Should only need to allocate space
+       for the raw registers.  Unfortunatly some code still accesses
+       the register array directly using the global registers[].
+       Until that code has been purged, play safe and over allocating
+       the register buffer.  Ulgh!  */
+    descr->sizeof_raw_registers = offset;
+    /* = descr->register_offset[descr->nr_raw_registers]; */
+  }
+
+#if 0
+  /* Sanity check.  Confirm that the assumptions about gdbarch are
+     true.  The REGCACHE_DESCR_HANDLE is set before doing the checks
+     so that targets using the generic methods supplied by regcache
+     don't go into infinite recursion trying to, again, create the
+     regcache.  */
+  set_gdbarch_data (gdbarch, regcache_descr_handle, descr);
+  for (i = 0; i < descr->nr_registers; i++)
+    {
+      gdb_assert (descr->sizeof_register[i] == REGISTER_RAW_SIZE (i));
+      gdb_assert (descr->sizeof_register[i] == REGISTER_VIRTUAL_SIZE (i));
+      gdb_assert (descr->register_offset[i] == REGISTER_BYTE (i));
+    }
+  /* gdb_assert (descr->sizeof_raw_registers == REGISTER_BYTES (i));  */
+#endif
+
+  return descr;
+}
+
+static struct regcache_descr *
+regcache_descr (struct gdbarch *gdbarch)
+{
+  return gdbarch_data (gdbarch, regcache_descr_handle);
+}
+
+static void
+xfree_regcache_descr (struct gdbarch *gdbarch, void *ptr)
+{
+  struct regcache_descr *descr = ptr;
+  if (descr == NULL)
+    return;
+  xfree (descr->register_offset);
+  xfree (descr->sizeof_register);
+  descr->register_offset = NULL;
+  descr->sizeof_register = NULL;
+  xfree (descr);
+}
+
+/* The register cache for storing raw register values.  */
+
+struct regcache
+{
+  struct regcache_descr *descr;
+  char *raw_registers;
+  char *raw_register_valid_p;
+  /* If a value isn't in the cache should the corresponding target be
+     queried for a value.  */
+  int passthrough_p;
+};
+
+struct regcache *
+regcache_xmalloc (struct gdbarch *gdbarch)
+{
+  struct regcache_descr *descr;
+  struct regcache *regcache;
+  gdb_assert (gdbarch != NULL);
+  descr = regcache_descr (gdbarch);
+  regcache = XMALLOC (struct regcache);
+  regcache->descr = descr;
+  regcache->raw_registers
+    = XCALLOC (descr->sizeof_raw_registers, char);
+  regcache->raw_register_valid_p
+    = XCALLOC (descr->sizeof_raw_register_valid_p, char);
+  regcache->passthrough_p = 0;
+  return regcache;
+}
+
+void
+regcache_xfree (struct regcache *regcache)
+{
+  if (regcache == NULL)
+    return;
+  xfree (regcache->raw_registers);
+  xfree (regcache->raw_register_valid_p);
+  xfree (regcache);
+}
+
+void
+regcache_cpy (struct regcache *dst, struct regcache *src)
+{
+  int i;
+  char *buf;
+  gdb_assert (src != NULL && dst != NULL);
+  gdb_assert (src->descr->gdbarch == dst->descr->gdbarch);
+  gdb_assert (src != dst);
+  /* FIXME: cagney/2002-05-17: To say this bit is bad is being polite.
+     It keeps the existing code working where things rely on going
+     through to the register cache.  */
+  if (src == current_regcache && src->descr->legacy_p)
+    {
+      /* ULGH!!!!  Old way.  Use REGISTER bytes and let code below
+	 untangle fetch.  */
+      read_register_bytes (0, dst->raw_registers, REGISTER_BYTES);
+      return;
+    }
+  /* FIXME: cagney/2002-05-17: To say this bit is bad is being polite.
+     It keeps the existing code working where things rely on going
+     through to the register cache.  */
+  if (dst == current_regcache && dst->descr->legacy_p)
+    {
+      /* ULGH!!!!  Old way.  Use REGISTER bytes and let code below
+	 untangle fetch.  */
+      write_register_bytes (0, src->raw_registers, REGISTER_BYTES);
+      return;
+    }
+  buf = alloca (src->descr->max_register_size);
+  for (i = 0; i < src->descr->nr_raw_registers; i++)
+    {
+      /* Should we worry about the valid bit here?  */
+      regcache_read (src, i, buf);
+      regcache_write (dst, i, buf);
+    }
+}
+
+void
+regcache_cpy_no_passthrough (struct regcache *dst, struct regcache *src)
+{
+  int i;
+  gdb_assert (src != NULL && dst != NULL);
+  gdb_assert (src->descr->gdbarch == dst->descr->gdbarch);
+  /* NOTE: cagney/2002-05-17: Don't let the caller do a no-passthrough
+     move of data into the current_regcache().  Doing this would be
+     silly - it would mean that valid_p would be completly invalid.  */
+  gdb_assert (dst != current_regcache);
+  memcpy (dst->raw_registers, src->raw_registers,
+	  dst->descr->sizeof_raw_registers);
+  memcpy (dst->raw_register_valid_p, src->raw_register_valid_p,
+	  dst->descr->sizeof_raw_register_valid_p);
+}
+
+struct regcache *
+regcache_dup (struct regcache *src)
+{
+  struct regcache *newbuf;
+  gdb_assert (current_regcache != NULL);
+  newbuf = regcache_xmalloc (src->descr->gdbarch);
+  regcache_cpy (newbuf, src);
+  return newbuf;
+}
+
+struct regcache *
+regcache_dup_no_passthrough (struct regcache *src)
+{
+  struct regcache *newbuf;
+  gdb_assert (current_regcache != NULL);
+  newbuf = regcache_xmalloc (src->descr->gdbarch);
+  regcache_cpy_no_passthrough (newbuf, src);
+  return newbuf;
+}
+
+int
+regcache_valid_p (struct regcache *regcache, int regnum)
+{
+  gdb_assert (regcache != NULL);
+  gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
+  return regcache->raw_register_valid_p[regnum];
+}
+
+CORE_ADDR
+regcache_read_as_address (struct regcache *regcache, int regnum)
+{
+  char *buf;
+  gdb_assert (regcache != NULL);
+  gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
+  buf = alloca (regcache->descr->sizeof_register[regnum]);
+  regcache_read (regcache, regnum, buf);
+  return extract_address (buf, regcache->descr->sizeof_register[regnum]);
+}
+
+char *
+deprecated_grub_regcache_for_registers (struct regcache *regcache)
+{
+  return regcache->raw_registers;
+}
+
+char *
+deprecated_grub_regcache_for_register_valid (struct regcache *regcache)
+{
+  return regcache->raw_register_valid_p;
+}
+
+/* Global structure containing the current regcache.  */
+/* FIXME: cagney/2002-05-11: The two global arrays registers[] and
+   register_valid[] currently point into this structure.  */
+struct regcache *current_regcache;
+
 /* NOTE: this is a write-through cache.  There is no "dirty" bit for
    recording if the register values have been changed (eg. by the
    user).  Therefore all registers must be written back to the
@@ -97,10 +441,9 @@
    else return a pointer to the start of the cache buffer.  */
 
 static char *
-register_buffer (int regnum)
+register_buffer (struct regcache *regcache, int regnum)
 {
-  gdb_assert (regnum >= 0 && regnum < (NUM_REGS + NUM_PSEUDO_REGS));
-  return &registers[REGISTER_BYTE (regnum)];
+  return regcache->raw_registers + regcache->descr->register_offset[regnum];
 }
 
 /* Return whether register REGNUM is a real register.  */
@@ -311,22 +654,52 @@
   if (!register_cached (regnum))
     fetch_register (regnum);
 
-  memcpy (myaddr, register_buffer (regnum),
+  memcpy (myaddr, register_buffer (current_regcache, regnum),
 	  REGISTER_RAW_SIZE (regnum));
 }
 
 void
-regcache_read (int rawnum, char *buf)
+regcache_read (struct regcache *regcache, int regnum, char *buf)
 {
-  gdb_assert (rawnum >= 0 && rawnum < (NUM_REGS + NUM_PSEUDO_REGS));
-  /* For moment, just use underlying legacy code. Ulgh!!! */
-  legacy_read_register_gen (rawnum, buf);
+  gdb_assert (regcache != NULL && buf != NULL);
+  gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
+  if (regcache->descr->legacy_p
+      && regcache->passthrough_p)
+    {
+      gdb_assert (regcache == current_regcache);
+      /* For moment, just use underlying legacy code.  Ulgh!!! This
+	 silently and very indirectly updates the regcache's regcache
+	 via the global register_valid[].  */
+      legacy_read_register_gen (regnum, buf);
+      return;
+    }
+  /* Make certain that the register cache is up-to-date with respect
+     to the current thread.  This switching shouldn't be necessary
+     only there is still only one target side register cache.  Sigh!
+     On the bright side, at least there is a regcache object.  */
+  if (regcache->passthrough_p)
+    {
+      gdb_assert (regcache == current_regcache);
+      if (! ptid_equal (registers_ptid, inferior_ptid))
+	{
+	  registers_changed ();
+	  registers_ptid = inferior_ptid;
+	}
+      if (!register_cached (regnum))
+	fetch_register (regnum);
+    }
+  /* Copy the value directly into the register cache.  */
+  memcpy (buf, (regcache->raw_registers
+		+ regcache->descr->register_offset[regnum]),
+	  regcache->descr->sizeof_register[regnum]);
 }
 
 void
 read_register_gen (int regnum, char *buf)
 {
-  if (! gdbarch_register_read_p (current_gdbarch))
+  gdb_assert (current_regcache != NULL);
+  gdb_assert (current_regcache->descr->gdbarch == current_gdbarch);
+  if (current_regcache->descr->legacy_p)
     {
       legacy_read_register_gen (regnum, buf);
       return;
@@ -362,30 +735,80 @@
       /* 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), myaddr, size) == 0)
+	  && (memcmp (register_buffer (current_regcache, regnum), myaddr, size)
+	      == 0))
 	return;
       else
 	target_prepare_to_store ();
     }
 
-  memcpy (register_buffer (regnum), myaddr, size);
+  memcpy (register_buffer (current_regcache, regnum), myaddr, size);
 
   set_register_cached (regnum, 1);
   store_register (regnum);
 }
 
 void
-regcache_write (int rawnum, char *buf)
+regcache_write (struct regcache *regcache, int regnum, char *buf)
 {
-  gdb_assert (rawnum >= 0 && rawnum < (NUM_REGS + NUM_PSEUDO_REGS));
-  /* For moment, just use underlying legacy code. Ulgh!!! */
-  legacy_write_register_gen (rawnum, buf);
+  gdb_assert (regcache != NULL && buf != NULL);
+  gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
+
+  if (regcache->passthrough_p
+      && regcache->descr->legacy_p)
+    {
+      /* For moment, just use underlying legacy code.  Ulgh!!! This
+	 silently and very indirectly updates the regcache's buffers
+	 via the globals register_valid[] and registers[].  */
+      gdb_assert (regcache == current_regcache);
+      legacy_write_register_gen (regnum, buf);
+      return;
+    }
+
+  /* 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;
+
+  /* Handle the simple case first -> not write through so just store
+     value in cache.  */
+  if (!regcache->passthrough_p)
+    {
+      memcpy ((regcache->raw_registers
+	       + regcache->descr->register_offset[regnum]), buf,
+	      regcache->descr->sizeof_register[regnum]);
+      regcache->raw_register_valid_p[regnum] = 1;
+      return;
+    }
+
+  /* Make certain that the correct cache is selected.  */
+  gdb_assert (regcache == current_regcache);
+  if (! ptid_equal (registers_ptid, inferior_ptid))
+    {
+      registers_changed ();
+      registers_ptid = inferior_ptid;
+    }
+
+  /* If we have a valid copy of the register, and new value == old
+     value, then don't bother doing the actual store. */
+  if (regcache_valid_p (regcache, regnum)
+      && (memcmp (register_buffer (regcache, regnum), buf,
+		  regcache->descr->sizeof_register[regnum]) == 0))
+    return;
+
+  target_prepare_to_store ();
+  memcpy (register_buffer (regcache, regnum), buf,
+	  regcache->descr->sizeof_register[regnum]);
+  regcache->raw_register_valid_p[regnum] = 1;
+  store_register (regnum);
 }
 
 void
 write_register_gen (int regnum, char *buf)
 {
-  if (! gdbarch_register_write_p (current_gdbarch))
+  gdb_assert (current_regcache != NULL);
+  gdb_assert (current_regcache->descr->gdbarch == current_gdbarch);
+  if (current_regcache->descr->legacy_p)
     {
       legacy_write_register_gen (regnum, buf);
       return;
@@ -564,10 +987,10 @@
 
   set_register_cached (regnum, 1);
   if (val)
-    memcpy (register_buffer (regnum), val, 
+    memcpy (register_buffer (current_regcache, regnum), val, 
 	    REGISTER_RAW_SIZE (regnum));
   else
-    memset (register_buffer (regnum), '\000', 
+    memset (register_buffer (current_regcache, regnum), '\000', 
 	    REGISTER_RAW_SIZE (regnum));
 
   /* On some architectures, e.g. HPPA, there are a few stray bits in
@@ -587,7 +1010,8 @@
 void
 regcache_collect (int regnum, void *buf)
 {
-  memcpy (buf, register_buffer (regnum), REGISTER_RAW_SIZE (regnum));
+  memcpy (buf, register_buffer (current_regcache, regnum),
+	  REGISTER_RAW_SIZE (regnum));
 }
 
 
@@ -755,37 +1179,53 @@
 static void
 build_regcache (void)
 {
+  current_regcache = regcache_xmalloc (current_gdbarch);
+  current_regcache->passthrough_p = 1;
+  registers = deprecated_grub_regcache_for_registers (current_regcache);
+  register_valid = deprecated_grub_regcache_for_register_valid (current_regcache);
+}
+
+void
+regcache_save (struct regcache *regcache)
+{
   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);
-  sizeof_register_valid = ((NUM_REGS + NUM_PSEUDO_REGS)
-			   * sizeof (*register_valid));
-  register_valid = xmalloc (sizeof_register_valid);
-  memset (register_valid, 0, sizeof_register_valid);
+  gdb_assert (current_regcache != NULL && regcache != NULL);
+  gdb_assert (current_regcache->descr->gdbarch == regcache->descr->gdbarch);
+  regcache_cpy (regcache, current_regcache);
+}
+
+void
+regcache_save_no_passthrough (struct regcache *regcache)
+{
+  gdb_assert (current_regcache != NULL && regcache != NULL);
+  gdb_assert (current_regcache->descr->gdbarch == regcache->descr->gdbarch);
+  regcache_cpy_no_passthrough (regcache, current_regcache);
+}
+
+void
+regcache_restore (struct regcache *regcache)
+{
+  int i;
+  gdb_assert (current_regcache != NULL && regcache != NULL);
+  gdb_assert (current_regcache->descr->gdbarch == regcache->descr->gdbarch);
+  regcache_cpy (current_regcache, regcache);
+}
+
+void
+regcache_restore_no_passthrough (struct regcache *regcache)
+{
+  char *regcache_registers;
+  gdb_assert (current_regcache != NULL && regcache != NULL);
+  gdb_assert (current_regcache->descr->gdbarch == regcache->descr->gdbarch);
+  regcache_cpy_no_passthrough (current_regcache, regcache);
 }
 
 void
 _initialize_regcache (void)
 {
+  regcache_descr_handle = register_gdbarch_data (init_regcache_descr,
+						 xfree_regcache_descr);
+  REGISTER_GDBARCH_SWAP (current_regcache);
   register_gdbarch_swap (&registers, sizeof (registers), NULL);
   register_gdbarch_swap (&register_valid, sizeof (register_valid), NULL);
   register_gdbarch_swap (NULL, 0, build_regcache);
Index: regcache.h
===================================================================
RCS file: /cvs/src/src/gdb/regcache.h,v
retrieving revision 1.6
diff -u -r1.6 regcache.h
--- regcache.h	15 Nov 2001 06:43:10 -0000	1.6
+++ regcache.h	20 Jun 2002 01:46:06 -0000
@@ -1,6 +1,7 @@
 /* Cache and manage the values of registers for GDB, the GNU debugger.
-   Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000, 2001
-   Free Software Foundation, Inc.
+
+   Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000,
+   2001, 2002 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -22,11 +23,21 @@
 #ifndef REGCACHE_H
 #define REGCACHE_H
 
+struct regcache;
+struct gdbarch;
+
+extern struct regcache *current_regcache;
+
+void regcache_xfree (struct regcache *regcache);
+struct regcache *regcache_xmalloc (struct gdbarch *gdbarch);
+
 /* 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);
+void regcache_read (struct regcache *regcache, int rawnum, char *buf);
+void regcache_write (struct regcache *regcache, int rawnum, char *buf);
+int regcache_valid_p (struct regcache *regcache, int regnum);
+CORE_ADDR regcache_read_as_address (struct regcache *regcache, int rawnum);
 
 /* Transfer a raw register [0..NUM_REGS) between the regcache and the
    target.  These functions are called by the target in response to a
@@ -46,6 +57,25 @@
    referenced thread. */
 
 extern signed char *register_valid;
+
+/* Save/restore the register cache using the regbuf.  The operation is
+   write through - it is strictly for code that needs to restore the
+   target's registers to a previous state.
+
+   ``no passthrough'' versions do not go through to the target.  They
+   only save values already in the cache.  */
+
+extern void regcache_save (struct regcache *regcache);
+extern void regcache_restore (struct regcache *regcache);
+extern struct regcache *regcache_dup (struct regcache *regcache);
+extern void regcache_save_no_passthrough (struct regcache *regcache);
+extern void regcache_restore_no_passthrough (struct regcache *regcache);
+extern struct regcache *regcache_dup_no_passthrough (struct regcache *regcache);
+extern void regcache_cpy (struct regcache *dest, struct regcache *src);
+extern void regcache_cpy_no_passthrough (struct regcache *dest, struct regcache *src);
+
+extern char *deprecated_grub_regcache_for_registers (struct regcache *);
+extern char *deprecated_grub_regcache_for_register_valid (struct regcache *);
 
 extern int register_cached (int regnum);
 
Index: sh-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/sh-tdep.c,v
retrieving revision 1.63
diff -u -r1.63 sh-tdep.c
--- sh-tdep.c	17 Jun 2002 23:32:33 -0000	1.63
+++ sh-tdep.c	20 Jun 2002 01:46:09 -0000
@@ -3385,9 +3385,9 @@
       /* Build the value in the provided buffer. */ 
       /* Read the real regs for which this one is an alias.  */
       for (portion = 0; portion < 2; portion++)
-	regcache_read (base_regnum + portion, 
-		       temp_buffer
-		       + REGISTER_RAW_SIZE (base_regnum) * portion);
+	regcache_read (current_regcache, base_regnum + portion, 
+		       (temp_buffer
+			+ REGISTER_RAW_SIZE (base_regnum) * portion));
       /* We must pay attention to the endiannes. */
       sh_sh4_register_convert_to_virtual (reg_nr,
 					  REGISTER_VIRTUAL_TYPE (reg_nr),
@@ -3400,7 +3400,7 @@
 
       /* Read the real regs for which this one is an alias.  */
       for (portion = 0; portion < 4; portion++)
-	regcache_read (base_regnum + portion, 
+	regcache_read (current_regcache, base_regnum + portion, 
 		       buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
     }
 }
@@ -3410,7 +3410,7 @@
 {
   if (reg_nr >= 0 && reg_nr < gdbarch_tdep (current_gdbarch)->DR0_REGNUM)
     /* It is a regular register. */
-    regcache_read (reg_nr, buffer);
+    regcache_read (current_regcache, reg_nr, buffer);
   else
     /* It is a pseudo register and we need to construct its value */
     sh_pseudo_register_read (reg_nr, buffer);
@@ -3434,9 +3434,9 @@
       /* DR regs are double precision registers obtained by
 	 concatenating 2 single precision floating point registers. */
       for (portion = 0; portion < 2; portion++)
-	regcache_read (base_regnum + portion, 
-				 temp_buffer
-				 + REGISTER_RAW_SIZE (base_regnum) * portion);
+	regcache_read (current_regcache, base_regnum + portion, 
+		       (temp_buffer
+			+ REGISTER_RAW_SIZE (base_regnum) * portion));
 
       /* We must pay attention to the endiannes. */
       sh_sh64_register_convert_to_virtual (reg_nr, REGISTER_VIRTUAL_TYPE (reg_nr),
@@ -3453,8 +3453,8 @@
       /* FPP regs are pairs of single precision registers obtained by
 	 concatenating 2 single precision floating point registers. */
       for (portion = 0; portion < 2; portion++)
-	regcache_read (base_regnum + portion, 
-				 buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
+	regcache_read (current_regcache, base_regnum + portion, 
+		       buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
     }
 
   else if (reg_nr >= tdep->FV0_REGNUM 
@@ -3466,8 +3466,8 @@
       /* FV regs are vectors of single precision registers obtained by
 	 concatenating 4 single precision floating point registers. */
       for (portion = 0; portion < 4; portion++)
-	regcache_read (base_regnum + portion, 
-				 buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
+	regcache_read (current_regcache, base_regnum + portion, 
+		       buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
     }
 
   /* sh compact pseudo registers. 1-to-1 with a shmedia register */
@@ -3477,7 +3477,7 @@
       base_regnum = sh64_compact_reg_base_num (reg_nr);
 
       /* Build the value in the provided buffer. */ 
-      regcache_read (base_regnum, temp_buffer);
+      regcache_read (current_regcache, base_regnum, temp_buffer);
       if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
 	offset = 4;
       memcpy (buffer, temp_buffer + offset, 4); /* get LOWER 32 bits only????*/
@@ -3491,7 +3491,7 @@
       /* Build the value in the provided buffer. */ 
       /* Floating point registers map 1-1 to the media fp regs,
 	 they have the same size and endienness. */
-      regcache_read (base_regnum, buffer);
+      regcache_read (current_regcache, base_regnum, buffer);
     }
 
   else if (reg_nr >= tdep->DR0_C_REGNUM 
@@ -3502,9 +3502,9 @@
       /* DR_C regs are double precision registers obtained by
 	 concatenating 2 single precision floating point registers. */
       for (portion = 0; portion < 2; portion++)
-	regcache_read (base_regnum + portion, 
-				 temp_buffer
-				 + REGISTER_RAW_SIZE (base_regnum) * portion);
+	regcache_read (current_regcache, base_regnum + portion, 
+		       (temp_buffer
+			+ REGISTER_RAW_SIZE (base_regnum) * portion));
 
       /* We must pay attention to the endiannes. */
       sh_sh64_register_convert_to_virtual (reg_nr, REGISTER_VIRTUAL_TYPE (reg_nr),
@@ -3520,8 +3520,8 @@
       /* FV_C regs are vectors of single precision registers obtained by
 	 concatenating 4 single precision floating point registers. */
       for (portion = 0; portion < 4; portion++)
-	regcache_read (base_regnum + portion, 
-				 buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
+	regcache_read (current_regcache, base_regnum + portion, 
+		       buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
     }
 
   else if (reg_nr == tdep->FPSCR_C_REGNUM)
@@ -3552,11 +3552,11 @@
        */
       /* *INDENT-ON* */
       /* Get FPSCR into a local buffer */
-      regcache_read (fpscr_base_regnum, temp_buffer);
+      regcache_read (current_regcache, fpscr_base_regnum, temp_buffer);
       /* Get value as an int. */
       fpscr_value = extract_unsigned_integer (temp_buffer, 4);
       /* Get SR into a local buffer */
-      regcache_read (sr_base_regnum, temp_buffer);
+      regcache_read (current_regcache, sr_base_regnum, temp_buffer);
       /* Get value as an int. */
       sr_value = extract_unsigned_integer (temp_buffer, 4);
       /* Build the new value. */
@@ -3574,7 +3574,7 @@
 
       /* FPUL_C register is floating point register 32,
 	 same size, same endianness. */
-      regcache_read (base_regnum, buffer);
+      regcache_read (current_regcache, base_regnum, buffer);
     }
 }
 
@@ -3584,7 +3584,7 @@
 
   if (reg_nr >= 0 && reg_nr < gdbarch_tdep (current_gdbarch)->DR0_REGNUM)
     /* It is a regular register. */
-    regcache_read (reg_nr, buffer);
+    regcache_read (current_regcache, reg_nr, buffer);
   else
     /* It is a pseudo register and we need to construct its value */
     sh64_pseudo_register_read (reg_nr, buffer);
@@ -3608,8 +3608,9 @@
 
       /* Write the real regs for which this one is an alias.  */
       for (portion = 0; portion < 2; portion++)
-	regcache_write (base_regnum + portion, 
-			temp_buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
+	regcache_write (current_regcache, base_regnum + portion, 
+			(temp_buffer
+			 + REGISTER_RAW_SIZE (base_regnum) * portion));
     }
   else if (reg_nr >= tdep->FV0_REGNUM
 	   && reg_nr <= tdep->FV_LAST_REGNUM)
@@ -3618,7 +3619,7 @@
 
       /* Write the real regs for which this one is an alias.  */
       for (portion = 0; portion < 4; portion++)
-	regcache_write (base_regnum + portion,
+	regcache_write (current_regcache, base_regnum + portion,
 			buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
     }
 }
@@ -3628,7 +3629,7 @@
 {
   if (reg_nr >= 0 && reg_nr < gdbarch_tdep (current_gdbarch)->DR0_REGNUM)
     /* It is a regular register. */
-    regcache_write (reg_nr, buffer);
+    regcache_write (current_regcache, reg_nr, buffer);
   else
     /* It is a pseudo register and we need to construct its value */
     sh_pseudo_register_write (reg_nr, buffer);
@@ -3653,8 +3654,9 @@
 
       /* Write the real regs for which this one is an alias.  */
       for (portion = 0; portion < 2; portion++)
-	regcache_write (base_regnum + portion, 
-			temp_buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
+	regcache_write (current_regcache, base_regnum + portion, 
+			(temp_buffer
+			 + REGISTER_RAW_SIZE (base_regnum) * portion));
     }
 
   else if (reg_nr >= tdep->FPP0_REGNUM 
@@ -3664,7 +3666,7 @@
 
       /* Write the real regs for which this one is an alias.  */
       for (portion = 0; portion < 2; portion++)
-	regcache_write (base_regnum + portion,
+	regcache_write (current_regcache, base_regnum + portion,
 			buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
     }
 
@@ -3675,7 +3677,7 @@
 
       /* Write the real regs for which this one is an alias.  */
       for (portion = 0; portion < 4; portion++)
-	regcache_write (base_regnum + portion,
+	regcache_write (current_regcache, base_regnum + portion,
 			buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
     }
 
@@ -3693,10 +3695,10 @@
       /* Let's read the value of the base register into a temporary
 	 buffer, so that overwriting the last four bytes with the new
 	 value of the pseudo will leave the upper 4 bytes unchanged. */
-      regcache_read (base_regnum, temp_buffer);
+      regcache_read (current_regcache, base_regnum, temp_buffer);
       /* Write as an 8 byte quantity */
       memcpy (temp_buffer + offset, buffer, 4);
-      regcache_write (base_regnum, temp_buffer);
+      regcache_write (current_regcache, base_regnum, temp_buffer);
     }
 
   /* sh floating point compact pseudo registers. 1-to-1 with a shmedia
@@ -3705,7 +3707,7 @@
 	       && reg_nr <= tdep->FP_LAST_C_REGNUM)
     {
       base_regnum = sh64_compact_reg_base_num (reg_nr);
-      regcache_write (base_regnum, buffer);
+      regcache_write (current_regcache, base_regnum, buffer);
     }
 
   else if (reg_nr >= tdep->DR0_C_REGNUM 
@@ -3718,8 +3720,9 @@
 	  sh_sh64_register_convert_to_raw (REGISTER_VIRTUAL_TYPE (reg_nr), reg_nr,
 					   buffer, temp_buffer);
 
-	  regcache_write (base_regnum + portion,
-			  temp_buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
+	  regcache_write (current_regcache, base_regnum + portion,
+			  (temp_buffer
+			   + REGISTER_RAW_SIZE (base_regnum) * portion));
 	}
     }
 
@@ -3730,7 +3733,7 @@
      
       for (portion = 0; portion < 4; portion++)
 	{
-	  regcache_write (base_regnum + portion,
+	  regcache_write (current_regcache, base_regnum + portion,
 			  buffer + REGISTER_RAW_SIZE (base_regnum) * portion);
 	}
     }
@@ -3773,25 +3776,25 @@
       fpscr_value = fpscr_c_value & fpscr_mask;
       sr_value = (fpscr_value & sr_mask) >> 6;
       
-      regcache_read (fpscr_base_regnum, temp_buffer);
+      regcache_read (current_regcache, fpscr_base_regnum, temp_buffer);
       old_fpscr_value = extract_unsigned_integer (temp_buffer, 4);
       old_fpscr_value &= 0xfffc0002;
       fpscr_value |= old_fpscr_value;
       store_unsigned_integer (temp_buffer, 4, fpscr_value);
-      regcache_write (fpscr_base_regnum, temp_buffer);
+      regcache_write (current_regcache, fpscr_base_regnum, temp_buffer);
       
-      regcache_read (sr_base_regnum, temp_buffer);
+      regcache_read (current_regcache, sr_base_regnum, temp_buffer);
       old_sr_value = extract_unsigned_integer (temp_buffer, 4);
       old_sr_value &= 0xffff8fff;
       sr_value |= old_sr_value;
       store_unsigned_integer (temp_buffer, 4, sr_value);
-      regcache_write (sr_base_regnum, temp_buffer);
+      regcache_write (current_regcache, sr_base_regnum, temp_buffer);
     }
 
   else if (reg_nr == tdep->FPUL_C_REGNUM)
     {
       base_regnum = sh64_compact_reg_base_num (reg_nr);
-      regcache_write (base_regnum, buffer);
+      regcache_write (current_regcache, base_regnum, buffer);
     }
 }
 
@@ -3800,7 +3803,7 @@
 {
   if (reg_nr >= 0 && reg_nr < gdbarch_tdep (current_gdbarch)->DR0_REGNUM)
     /* It is a regular register. */
-    regcache_write (reg_nr, buffer);
+    regcache_write (current_regcache, reg_nr, buffer);
   else
     /* It is a pseudo register and we need to construct its value */
     sh64_pseudo_register_write (reg_nr, buffer);

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