* Makefile.tpl: Move .NOEXPORT, MAKEOVERRIDES up. Delete unused
[deliverable/binutils-gdb.git] / gdb / regcache.c
index 136b9466748736253cedcc6d1b63a18bfe76c9ff..5475cf681ef24a6a724c68ecbc94b5c8129b2bba 100644 (file)
@@ -66,6 +66,8 @@ struct regcache_descr
      both raw registers and memory by the architecture methods
      gdbarch_register_read and gdbarch_register_write.  */
   int nr_cooked_registers;
+  long sizeof_cooked_registers;
+  long sizeof_cooked_register_valid_p;
 
   /* Offset and size (in 8 bit bytes), of reach register in the
      register cache.  All registers (including those in the range
@@ -93,20 +95,28 @@ init_legacy_regcache_descr (struct gdbarch *gdbarch,
   gdb_assert (gdbarch != NULL);
 
   /* FIXME: cagney/2002-05-11: Shouldn't be including pseudo-registers
-     in the register buffer.  Unfortunatly some architectures do.  */
+     in the register cache.  Unfortunatly some architectures still
+     rely on this and the pseudo_register_write() method.  */
   descr->nr_raw_registers = descr->nr_cooked_registers;
-  descr->sizeof_raw_register_valid_p = descr->nr_cooked_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_raw_register_valid_p = descr->sizeof_cooked_register_valid_p;
+
+  /* Compute the offset of each register.  Legacy architectures define
+     REGISTER_BYTE() so use that.  */
+  /* FIXME: cagney/2002-11-07: Instead of using REGISTER_BYTE() this
+     code should, as is done in init_regcache_descr(), compute the
+     offets at runtime.  This currently isn't possible as some ISAs
+     define overlapping register regions - see the mess in
+     read_register_bytes() and write_register_bytes() registers.  */
   descr->sizeof_register = XCALLOC (descr->nr_cooked_registers, long);
   descr->register_offset = XCALLOC (descr->nr_cooked_registers, long);
   descr->max_register_size = 0;
   for (i = 0; i < descr->nr_cooked_registers; i++)
     {
+      /* 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.  */
       descr->register_offset[i] = REGISTER_BYTE (i);
       descr->sizeof_register[i] = REGISTER_RAW_SIZE (i);
       if (descr->max_register_size < REGISTER_RAW_SIZE (i))
@@ -115,8 +125,13 @@ init_legacy_regcache_descr (struct gdbarch *gdbarch,
        descr->max_register_size = REGISTER_VIRTUAL_SIZE (i);
     }
 
-  /* Come up with the real size of the registers buffer.  */
-  descr->sizeof_raw_registers = REGISTER_BYTES; /* OK use.  */
+  /* Compute the real size of the register buffer.  Start out by
+     trusting REGISTER_BYTES, but then adjust it upwards should that
+     be found to not be sufficient.  */
+  /* FIXME: cagney/2002-11-05: Instead of using REGISTER_BYTES, this
+     code should, as is done in init_regcache_descr(), compute the
+     total number of register bytes using the accumulated offsets.  */
+  descr->sizeof_cooked_registers = REGISTER_BYTES; /* OK use.  */
   for (i = 0; i < descr->nr_cooked_registers; i++)
     {
       long regend;
@@ -125,15 +140,14 @@ init_legacy_regcache_descr (struct gdbarch *gdbarch,
          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;
+      if (descr->sizeof_cooked_registers < regend)
+       descr->sizeof_cooked_registers = regend;
     }
+  /* FIXME: cagney/2002-05-11: Shouldn't be including pseudo-registers
+     in the register cache.  Unfortunatly some architectures still
+     rely on this and the pseudo_register_write() method.  */
+  descr->sizeof_raw_registers = descr->sizeof_cooked_registers;
 }
 
 static void *
@@ -151,19 +165,27 @@ init_regcache_descr (struct gdbarch *gdbarch)
      directly onto the raw register cache while the pseudo's are
      either mapped onto raw-registers or memory.  */
   descr->nr_cooked_registers = NUM_REGS + NUM_PSEUDO_REGS;
+  descr->sizeof_cooked_register_valid_p = NUM_REGS + NUM_PSEUDO_REGS;
 
   /* Fill in a table of register types.  */
   descr->register_type = XCALLOC (descr->nr_cooked_registers,
                                  struct type *);
   for (i = 0; i < descr->nr_cooked_registers; i++)
     {
-      descr->register_type[i] = REGISTER_VIRTUAL_TYPE (i);
+      if (gdbarch_register_type_p (gdbarch))
+       {
+         gdb_assert (!REGISTER_VIRTUAL_TYPE_P ()); /* OK */
+         descr->register_type[i] = gdbarch_register_type (gdbarch, i);
+       }
+      else
+       descr->register_type[i] = REGISTER_VIRTUAL_TYPE (i); /* OK */
     }
 
   /* If an old style architecture, fill in the remainder of the
      register cache descriptor using the register macros.  */
   if (!gdbarch_pseudo_register_read_p (gdbarch)
-      && !gdbarch_pseudo_register_write_p (gdbarch))
+      && !gdbarch_pseudo_register_write_p (gdbarch)
+      && !gdbarch_register_type_p (gdbarch))
     {
       descr->legacy_p = 1;
       init_legacy_regcache_descr (gdbarch, descr);
@@ -178,12 +200,9 @@ init_regcache_descr (struct gdbarch *gdbarch)
      array.  This pretects GDB from erant code that accesses elements
      of the global register_valid_p[] array in the range [NUM_REGS
      .. NUM_REGS + NUM_PSEUDO_REGS).  */
-  descr->sizeof_raw_register_valid_p = NUM_REGS + NUM_PSEUDO_REGS;
+  descr->sizeof_raw_register_valid_p = descr->sizeof_cooked_register_valid_p;
 
-  /* 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.
+  /* Lay out the register cache.
 
      NOTE: cagney/2002-05-22: Only register_type() is used when
      constructing the register cache.  It is assumed that the
@@ -204,15 +223,16 @@ init_regcache_descr (struct gdbarch *gdbarch)
          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]; */
+    descr->sizeof_cooked_registers = offset;
   }
 
+  /* 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 = descr->sizeof_cooked_registers;
+
 #if 0
   /* Sanity check.  Confirm that the assumptions about gdbarch are
      true.  The REGCACHE_DESCR_HANDLE is set before doing the checks
@@ -272,6 +292,36 @@ max_register_size (struct gdbarch *gdbarch)
   return descr->max_register_size;
 }
 
+int
+legacy_max_register_raw_size (void)
+{
+  if (DEPRECATED_MAX_REGISTER_RAW_SIZE_P ())
+    return DEPRECATED_MAX_REGISTER_RAW_SIZE;
+  else
+    return max_register_size (current_gdbarch);
+}
+
+int
+legacy_max_register_virtual_size (void)
+{
+  if (DEPRECATED_MAX_REGISTER_VIRTUAL_SIZE_P ())
+    return DEPRECATED_MAX_REGISTER_VIRTUAL_SIZE;
+  else
+    return max_register_size (current_gdbarch);
+}
+
+int
+register_size (struct gdbarch *gdbarch, int regnum)
+{
+  struct regcache_descr *descr = regcache_descr (gdbarch);
+  int size;
+  gdb_assert (regnum >= 0 && regnum < (NUM_REGS + NUM_PSEUDO_REGS));
+  size = descr->sizeof_register[regnum];
+  gdb_assert (size == REGISTER_RAW_SIZE (regnum)); /* OK */
+  gdb_assert (size == REGISTER_RAW_SIZE (regnum)); /* OK */
+  return size;
+}
+
 /* The register cache for storing raw register values.  */
 
 struct regcache
@@ -282,9 +332,13 @@ struct regcache
      register cache can only hold [0 .. NUM_REGS).  */
   char *registers;
   char *register_valid_p;
-  /* If a value isn't in the cache should the corresponding target be
-     queried for a value.  */
-  int passthrough_p;
+  /* Is this a read-only cache?  A read-only cache is used for saving
+     the target's register state (e.g, across an inferior function
+     call or just before forcing a function return).  A read-only
+     cache can only be updated via the methods regcache_dup() and
+     regcache_cpy().  The actual contents are determined by the
+     reggroup_save and reggroup_restore methods.  */
+  int readonly_p;
 };
 
 struct regcache *
@@ -300,7 +354,7 @@ regcache_xmalloc (struct gdbarch *gdbarch)
     = XCALLOC (descr->sizeof_raw_registers, char);
   regcache->register_valid_p
     = XCALLOC (descr->sizeof_raw_register_valid_p, char);
-  regcache->passthrough_p = 0;
+  regcache->readonly_p = 1;
   return regcache;
 }
 
@@ -334,6 +388,80 @@ register_buffer (struct regcache *regcache, int regnum)
   return regcache->registers + regcache->descr->register_offset[regnum];
 }
 
+void
+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 DST should be `read-only', if it wasn't then the save would
+     end up trying to write the register values back out to the
+     target.  */
+  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.  */
+  for (regnum = 0; regnum < dst->descr->nr_cooked_registers; regnum++)
+    {
+      if (gdbarch_register_reggroup_p (gdbarch, regnum, save_reggroup))
+       {
+         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,
+                 regcache_cooked_read_ftype *cooked_read,
+                 void *src)
+{
+  struct gdbarch *gdbarch = dst->descr->gdbarch;
+  void *buf = alloca (max_register_size (gdbarch));
+  int regnum;
+  /* The dst had better not be read-only.  If it is, the `restore'
+     doesn't make much sense.  */
+  gdb_assert (!dst->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 < dst->descr->nr_cooked_registers; regnum++)
+    {
+      if (gdbarch_register_reggroup_p (gdbarch, regnum, restore_reggroup))
+       {
+         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)
 {
@@ -342,33 +470,13 @@ regcache_cpy (struct regcache *dst, struct regcache *src)
   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->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->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_raw_read (src, i, buf);
-      regcache_raw_write (dst, i, buf);
-    }
+  gdb_assert (src->readonly_p || dst->readonly_p);
+  if (!src->readonly_p)
+    regcache_save (dst, do_cooked_read, src);
+  else if (!dst->readonly_p)
+    regcache_restore (dst, do_cooked_read, src);
+  else
+    regcache_cpy_no_passthrough (dst, src);
 }
 
 void
@@ -438,7 +546,7 @@ struct regcache *current_regcache;
 
 /* REGISTERS contains the cached register values (in target byte order). */
 
-char *registers;
+char *deprecated_registers;
 
 /* DEPRECATED_REGISTER_VALID is 0 if the register needs to be fetched,
                      1 if it has been fetched, and
@@ -547,29 +655,29 @@ deprecated_registers_fetched (void)
      Fetching all real regs NEVER accounts for pseudo-regs.  */
 }
 
-/* read_register_bytes and write_register_bytes are generally a *BAD*
-   idea.  They are inefficient because they need to check for partial
-   updates, which can only be done by scanning through all of the
-   registers and seeing if the bytes that are being read/written fall
-   inside of an invalid register.  [The main reason this is necessary
-   is that register sizes can vary, so a simple index won't suffice.]
-   It is far better to call read_register_gen and write_register_gen
-   if you want to get at the raw register contents, as it only takes a
-   regnum as an argument, and therefore can't do a partial register
-   update.
+/* deprecated_read_register_bytes and deprecated_write_register_bytes
+   are generally a *BAD* idea.  They are inefficient because they need
+   to check for partial updates, which can only be done by scanning
+   through all of the registers and seeing if the bytes that are being
+   read/written fall inside of an invalid register.  [The main reason
+   this is necessary is that register sizes can vary, so a simple
+   index won't suffice.]  It is far better to call read_register_gen
+   and write_register_gen if you want to get at the raw register
+   contents, as it only takes a regnum as an argument, and therefore
+   can't do a partial register update.
 
    Prior to the recent fixes to check for partial updates, both read
-   and write_register_bytes always checked to see if any registers
-   were stale, and then called target_fetch_registers (-1) to update
-   the whole set.  This caused really slowed things down for remote
-   targets.  */
+   and deprecated_write_register_bytes always checked to see if any
+   registers were stale, and then called target_fetch_registers (-1)
+   to update the whole set.  This caused really slowed things down for
+   remote targets.  */
 
 /* Copy INLEN bytes of consecutive data from registers
    starting with the INREGBYTE'th byte of register data
    into memory at MYADDR.  */
 
 void
-read_register_bytes (int in_start, char *in_buf, int in_len)
+deprecated_read_register_bytes (int in_start, char *in_buf, int in_len)
 {
   int in_end = in_start + in_len;
   int regnum;
@@ -606,7 +714,7 @@ read_register_bytes (int in_start, char *in_buf, int in_len)
        /* FIXME: cagney/2001-08-18: This is just silly.  It defeats
            the entire register read/write flow of control.  Must
            resist temptation to return 0xdeadbeef.  */
-       memcpy (reg_buf, registers + reg_start, reg_len);
+       memcpy (reg_buf, &deprecated_registers[reg_start], reg_len);
 
       /* Legacy note: This function, for some reason, allows a NULL
          input buffer.  If the buffer is NULL, the registers are still
@@ -662,7 +770,7 @@ regcache_raw_read (struct regcache *regcache, int regnum, void *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)
+      && !regcache->readonly_p)
     {
       gdb_assert (regcache == current_regcache);
       /* For moment, just use underlying legacy code.  Ulgh!!! This
@@ -675,7 +783,7 @@ regcache_raw_read (struct regcache *regcache, int regnum, void *buf)
      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)
+  if (!regcache->readonly_p)
     {
       gdb_assert (regcache == current_regcache);
       if (! ptid_equal (registers_ptid, inferior_ptid))
@@ -759,6 +867,12 @@ regcache_cooked_read (struct regcache *regcache, int regnum, void *buf)
   gdb_assert (regnum < regcache->descr->nr_cooked_registers);
   if (regnum < regcache->descr->nr_raw_registers)
     regcache_raw_read (regcache, regnum, buf);
+  else if (regcache->readonly_p
+          && regnum < regcache->descr->nr_cooked_registers
+          && regcache->register_valid_p[regnum])
+    /* Read-only register cache, perhaphs the cooked value was cached?  */
+    memcpy (buf, register_buffer (regcache, regnum),
+           regcache->descr->sizeof_register[regnum]);
   else
     gdbarch_pseudo_register_read (regcache->descr->gdbarch, regcache,
                                  regnum, buf);
@@ -835,9 +949,9 @@ regcache_raw_write (struct regcache *regcache, int regnum, const void *buf)
 {
   gdb_assert (regcache != NULL && buf != NULL);
   gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
+  gdb_assert (!regcache->readonly_p);
 
-  if (regcache->passthrough_p
-      && regcache->descr->legacy_p)
+  if (regcache->descr->legacy_p)
     {
       /* For moment, just use underlying legacy code.  Ulgh!!! This
         silently and very indirectly updates the regcache's buffers
@@ -852,16 +966,6 @@ regcache_raw_write (struct regcache *regcache, int regnum, const void *buf)
   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 (register_buffer (regcache, regnum), buf,
-             regcache->descr->sizeof_register[regnum]);
-      regcache->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))
@@ -913,7 +1017,7 @@ regcache_cooked_write (struct regcache *regcache, int regnum, const void *buf)
    into registers starting with the MYREGSTART'th byte of register data.  */
 
 void
-write_register_bytes (int myregstart, char *myaddr, int inlen)
+deprecated_write_register_bytes (int myregstart, char *myaddr, int inlen)
 {
   int myregend = myregstart + inlen;
   int regnum;
@@ -953,7 +1057,7 @@ write_register_bytes (int myregstart, char *myaddr, int inlen)
             Update it from the target before scribbling on it.  */
          deprecated_read_register_gen (regnum, regbuf);
 
-         memcpy (registers + overlapstart,
+         memcpy (&deprecated_registers[overlapstart],
                  myaddr + (overlapstart - myregstart),
                  overlapend - overlapstart);
 
@@ -1365,8 +1469,8 @@ static void
 build_regcache (void)
 {
   current_regcache = regcache_xmalloc (current_gdbarch);
-  current_regcache->passthrough_p = 1;
-  registers = deprecated_grub_regcache_for_registers (current_regcache);
+  current_regcache->readonly_p = 0;
+  deprecated_registers = deprecated_grub_regcache_for_registers (current_regcache);
   deprecated_register_valid = deprecated_grub_regcache_for_register_valid (current_regcache);
 }
 
@@ -1648,7 +1752,7 @@ _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 (&deprecated_registers, sizeof (deprecated_registers), NULL);
   register_gdbarch_swap (&deprecated_register_valid, sizeof (deprecated_register_valid), NULL);
   register_gdbarch_swap (NULL, 0, build_regcache);
 
This page took 0.041087 seconds and 4 git commands to generate.