[ARC] Add checking for LP_COUNT reg usage, improve error reporting.
[deliverable/binutils-gdb.git] / gdb / regcache.c
index 3ca300831ab7b2f7a35d2bab8e17f799e384b2a0..1fcf93386f7d3d4180ab6dad4f228566563855b2 100644 (file)
@@ -1,7 +1,6 @@
 /* Cache and manage the values of registers for GDB, the GNU debugger.
 
-   Copyright (C) 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000, 2001,
-   2002, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 1986-2016 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "gdbcmd.h"
 #include "regcache.h"
 #include "reggroups.h"
-#include "gdb_assert.h"
-#include "gdb_string.h"
-#include "gdbcmd.h"            /* For maintenanceprintlist.  */
 #include "observer.h"
+#include "remote.h"
+#include "valprint.h"
+#include "regset.h"
 
 /*
  * DATA STRUCTURE
@@ -53,7 +52,7 @@ struct regcache_descr
      cache.  */
   int nr_raw_registers;
   long sizeof_raw_registers;
-  long sizeof_raw_register_valid_p;
+  long sizeof_raw_register_status;
 
   /* The cooked register space.  Each cooked register in the range
      [0..NR_RAW_REGISTERS) is direct-mapped onto the corresponding raw
@@ -63,14 +62,12 @@ struct regcache_descr
      gdbarch_pseudo_register_read and gdbarch_pseudo_register_write.  */
   int nr_cooked_registers;
   long sizeof_cooked_registers;
-  long sizeof_cooked_register_valid_p;
+  long sizeof_cooked_register_status;
 
-  /* Offset and size (in 8 bit bytes), of reach register in the
+  /* Offset and size (in 8 bit bytes), of each register in the
      register cache.  All registers (including those in the range
-     [NR_RAW_REGISTERS .. NR_COOKED_REGISTERS) are given an offset.
-     Assigning all registers an offset makes it possible to keep
-     legacy code, such as that found in read_register_bytes() and
-     write_register_bytes() working.  */
+     [NR_RAW_REGISTERS .. NR_COOKED_REGISTERS) are given an
+     offset.  */
   long *register_offset;
   long *sizeof_register;
 
@@ -94,9 +91,8 @@ init_regcache_descr (struct gdbarch *gdbarch)
      either mapped onto raw-registers or memory.  */
   descr->nr_cooked_registers = gdbarch_num_regs (gdbarch)
                               + gdbarch_num_pseudo_regs (gdbarch);
-  descr->sizeof_cooked_register_valid_p = gdbarch_num_regs (gdbarch)
-                                         + gdbarch_num_pseudo_regs 
-                                             (gdbarch);
+  descr->sizeof_cooked_register_status
+    = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
 
   /* Fill in a table of register types.  */
   descr->register_type
@@ -108,12 +104,7 @@ init_regcache_descr (struct gdbarch *gdbarch)
   /* Construct a strictly RAW register cache.  Don't allow pseudo's
      into the register cache.  */
   descr->nr_raw_registers = gdbarch_num_regs (gdbarch);
-
-  /* FIXME: cagney/2002-08-13: Overallocate the register_valid_p
-     array.  This pretects GDB from erant code that accesses elements
-     of the global register_valid_p[] array in the range 
-     [gdbarch_num_regs .. gdbarch_num_regs + gdbarch_num_pseudo_regs).  */
-  descr->sizeof_raw_register_valid_p = descr->sizeof_cooked_register_valid_p;
+  descr->sizeof_raw_register_status = gdbarch_num_regs (gdbarch);
 
   /* Lay out the register cache.
 
@@ -129,31 +120,35 @@ init_regcache_descr (struct gdbarch *gdbarch)
       = GDBARCH_OBSTACK_CALLOC (gdbarch, descr->nr_cooked_registers, long);
     descr->register_offset
       = GDBARCH_OBSTACK_CALLOC (gdbarch, descr->nr_cooked_registers, long);
-    for (i = 0; i < descr->nr_cooked_registers; i++)
+    for (i = 0; i < descr->nr_raw_registers; i++)
+      {
+       descr->sizeof_register[i] = TYPE_LENGTH (descr->register_type[i]);
+       descr->register_offset[i] = offset;
+       offset += descr->sizeof_register[i];
+       gdb_assert (MAX_REGISTER_SIZE >= descr->sizeof_register[i]);
+      }
+    /* Set the real size of the raw register cache buffer.  */
+    descr->sizeof_raw_registers = offset;
+
+    for (; i < descr->nr_cooked_registers; i++)
       {
        descr->sizeof_register[i] = TYPE_LENGTH (descr->register_type[i]);
        descr->register_offset[i] = offset;
        offset += descr->sizeof_register[i];
        gdb_assert (MAX_REGISTER_SIZE >= descr->sizeof_register[i]);
       }
-    /* Set the real size of the register cache buffer.  */
+    /* Set the real size of the readonly register cache buffer.  */
     descr->sizeof_cooked_registers = offset;
   }
 
-  /* FIXME: cagney/2002-05-22: Should only need to allocate space for
-     the raw registers.  Unfortunately 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;
-
   return descr;
 }
 
 static struct regcache_descr *
 regcache_descr (struct gdbarch *gdbarch)
 {
-  return gdbarch_data (gdbarch, regcache_descr_handle);
+  return (struct regcache_descr *) gdbarch_data (gdbarch,
+                                                regcache_descr_handle);
 }
 
 /* Utility functions returning useful register attributes stored in
@@ -184,6 +179,14 @@ register_size (struct gdbarch *gdbarch, int regnum)
   return size;
 }
 
+/* See common/common-regcache.h.  */
+
+int
+regcache_register_size (const struct regcache *regcache, int n)
+{
+  return register_size (get_regcache_arch (regcache), n);
+}
+
 /* The register cache for storing raw register values.  */
 
 struct regcache
@@ -198,11 +201,8 @@ struct regcache
      full [0 .. gdbarch_num_regs + gdbarch_num_pseudo_regs) while a read/write
      register cache can only hold [0 .. gdbarch_num_regs).  */
   gdb_byte *registers;
-  /* Register cache status:
-     register_valid_p[REG] == 0 if REG value is not in the cache
-                            > 0 if REG value is in the cache
-                            < 0 if REG value is permanently unavailable */
-  signed char *register_valid_p;
+  /* Register cache status.  */
+  signed char *register_status;
   /* 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
@@ -215,40 +215,57 @@ struct regcache
   ptid_t ptid;
 };
 
-struct regcache *
-regcache_xmalloc (struct gdbarch *gdbarch, struct address_space *aspace)
+static struct regcache *
+regcache_xmalloc_1 (struct gdbarch *gdbarch, struct address_space *aspace,
+                   int readonly_p)
 {
   struct regcache_descr *descr;
   struct regcache *regcache;
 
   gdb_assert (gdbarch != NULL);
   descr = regcache_descr (gdbarch);
-  regcache = XMALLOC (struct regcache);
+  regcache = XNEW (struct regcache);
   regcache->descr = descr;
-  regcache->registers
-    = XCALLOC (descr->sizeof_raw_registers, gdb_byte);
-  regcache->register_valid_p
-    = XCALLOC (descr->sizeof_raw_register_valid_p, gdb_byte);
+  regcache->readonly_p = readonly_p;
+  if (readonly_p)
+    {
+      regcache->registers
+       = XCNEWVEC (gdb_byte, descr->sizeof_cooked_registers);
+      regcache->register_status
+       = XCNEWVEC (signed char, descr->sizeof_cooked_register_status);
+    }
+  else
+    {
+      regcache->registers
+       = XCNEWVEC (gdb_byte, descr->sizeof_raw_registers);
+      regcache->register_status
+       = XCNEWVEC (signed char, descr->sizeof_raw_register_status);
+    }
   regcache->aspace = aspace;
-  regcache->readonly_p = 1;
   regcache->ptid = minus_one_ptid;
   return regcache;
 }
 
+struct regcache *
+regcache_xmalloc (struct gdbarch *gdbarch, struct address_space *aspace)
+{
+  return regcache_xmalloc_1 (gdbarch, aspace, 1);
+}
+
 void
 regcache_xfree (struct regcache *regcache)
 {
   if (regcache == NULL)
     return;
   xfree (regcache->registers);
-  xfree (regcache->register_valid_p);
+  xfree (regcache->register_status);
   xfree (regcache);
 }
 
 static void
 do_regcache_xfree (void *data)
 {
-  regcache_xfree (data);
+  regcache_xfree ((struct regcache *) data);
 }
 
 struct cleanup *
@@ -257,6 +274,32 @@ make_cleanup_regcache_xfree (struct regcache *regcache)
   return make_cleanup (do_regcache_xfree, regcache);
 }
 
+/* Cleanup routines for invalidating a register.  */
+
+struct register_to_invalidate
+{
+  struct regcache *regcache;
+  int regnum;
+};
+
+static void
+do_regcache_invalidate (void *data)
+{
+  struct register_to_invalidate *reg = (struct register_to_invalidate *) data;
+
+  regcache_invalidate (reg->regcache, reg->regnum);
+}
+
+static struct cleanup *
+make_cleanup_regcache_invalidate (struct regcache *regcache, int regnum)
+{
+  struct register_to_invalidate* reg = XNEW (struct register_to_invalidate);
+
+  reg->regcache = regcache;
+  reg->regnum = regnum;
+  return make_cleanup_dtor (do_regcache_invalidate, (void *) reg, xfree);
+}
+
 /* Return REGCACHE's architecture.  */
 
 struct gdbarch *
@@ -293,8 +336,8 @@ regcache_save (struct regcache *dst, regcache_cooked_read_ftype *cooked_read,
   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);
+  memset (dst->register_status, 0,
+         dst->descr->sizeof_cooked_register_status);
   /* Copy over any registers (identified by their membership in the
      save_reggroup) and mark them as valid.  The full [0 .. gdbarch_num_regs +
      gdbarch_num_pseudo_regs) range is checked since some architectures need
@@ -303,19 +346,24 @@ regcache_save (struct regcache *dst, regcache_cooked_read_ftype *cooked_read,
     {
       if (gdbarch_register_reggroup_p (gdbarch, regnum, save_reggroup))
        {
-         int valid = cooked_read (src, regnum, buf);
+         enum register_status status = cooked_read (src, regnum, buf);
 
-         if (valid)
+         if (status == REG_VALID)
+           memcpy (register_buffer (dst, regnum), buf,
+                   register_size (gdbarch, regnum));
+         else
            {
-             memcpy (register_buffer (dst, regnum), buf,
+             gdb_assert (status != REG_UNKNOWN);
+
+             memset (register_buffer (dst, regnum), 0,
                      register_size (gdbarch, regnum));
-             dst->register_valid_p[regnum] = 1;
            }
+         dst->register_status[regnum] = status;
        }
     }
 }
 
-void
+static void
 regcache_restore (struct regcache *dst,
                  regcache_cooked_read_ftype *cooked_read,
                  void *cooked_read_context)
@@ -335,28 +383,25 @@ regcache_restore (struct regcache *dst,
     {
       if (gdbarch_register_reggroup_p (gdbarch, regnum, restore_reggroup))
        {
-         int valid = cooked_read (cooked_read_context, regnum, buf);
+         enum register_status status;
 
-         if (valid)
+         status = cooked_read (cooked_read_context, regnum, buf);
+         if (status == REG_VALID)
            regcache_cooked_write (dst, regnum, buf);
        }
     }
 }
 
-static int
+static enum register_status
 do_cooked_read (void *src, int regnum, gdb_byte *buf)
 {
-  struct regcache *regcache = src;
+  struct regcache *regcache = (struct regcache *) src;
 
-  if (!regcache->register_valid_p[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;
+  return regcache_cooked_read (regcache, regnum, buf);
 }
 
+static void regcache_cpy_no_passthrough (struct regcache *dst,
+                                        struct regcache *src);
 
 void
 regcache_cpy (struct regcache *dst, struct regcache *src)
@@ -374,19 +419,26 @@ regcache_cpy (struct regcache *dst, struct regcache *src)
     regcache_cpy_no_passthrough (dst, src);
 }
 
-void
+/* Copy/duplicate the contents of a register cache.  Unlike regcache_cpy,
+   which is pass-through, this does not go through to the target.
+   Only values values already in the cache are transferred.  The SRC and DST
+   buffers must not overlap.  */
+
+static void
 regcache_cpy_no_passthrough (struct regcache *dst, struct regcache *src)
 {
   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 completely invalid.  */
-  gdb_assert (dst->readonly_p);
-
-  memcpy (dst->registers, src->registers, dst->descr->sizeof_raw_registers);
-  memcpy (dst->register_valid_p, src->register_valid_p,
-         dst->descr->sizeof_raw_register_valid_p);
+     move of data into a thread's regcache.  Doing this would be silly
+     - it would mean that regcache->register_status would be
+     completely invalid.  */
+  gdb_assert (dst->readonly_p && src->readonly_p);
+
+  memcpy (dst->registers, src->registers,
+         dst->descr->sizeof_cooked_registers);
+  memcpy (dst->register_status, src->register_status,
+         dst->descr->sizeof_cooked_register_status);
 }
 
 struct regcache *
@@ -399,18 +451,8 @@ regcache_dup (struct regcache *src)
   return newbuf;
 }
 
-struct regcache *
-regcache_dup_no_passthrough (struct regcache *src)
-{
-  struct regcache *newbuf;
-
-  newbuf = regcache_xmalloc (src->descr->gdbarch, get_regcache_aspace (src));
-  regcache_cpy_no_passthrough (newbuf, src);
-  return newbuf;
-}
-
-int
-regcache_valid_p (const struct regcache *regcache, int regnum)
+enum register_status
+regcache_register_status (const struct regcache *regcache, int regnum)
 {
   gdb_assert (regcache != NULL);
   gdb_assert (regnum >= 0);
@@ -419,7 +461,7 @@ regcache_valid_p (const struct regcache *regcache, int regnum)
   else
     gdb_assert (regnum < regcache->descr->nr_raw_registers);
 
-  return regcache->register_valid_p[regnum];
+  return (enum register_status) regcache->register_status[regnum];
 }
 
 void
@@ -429,7 +471,7 @@ regcache_invalidate (struct regcache *regcache, int regnum)
   gdb_assert (regnum >= 0);
   gdb_assert (!regcache->readonly_p);
   gdb_assert (regnum < regcache->descr->nr_raw_registers);
-  regcache->register_valid_p[regnum] = 0;
+  regcache->register_status[regnum] = REG_UNKNOWN;
 }
 
 
@@ -449,7 +491,8 @@ struct regcache_list
 static struct regcache_list *current_regcache;
 
 struct regcache *
-get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch)
+get_thread_arch_aspace_regcache (ptid_t ptid, struct gdbarch *gdbarch,
+                                struct address_space *aspace)
 {
   struct regcache_list *list;
   struct regcache *new_regcache;
@@ -459,13 +502,10 @@ get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch)
        && get_regcache_arch (list->regcache) == gdbarch)
       return list->regcache;
 
-  new_regcache = regcache_xmalloc (gdbarch,
-                                  target_thread_address_space (ptid));
-  new_regcache->readonly_p = 0;
+  new_regcache = regcache_xmalloc_1 (gdbarch, aspace, 0);
   new_regcache->ptid = ptid;
-  gdb_assert (new_regcache->aspace != NULL);
 
-  list = xmalloc (sizeof (struct regcache_list));
+  list = XNEW (struct regcache_list);
   list->regcache = new_regcache;
   list->next = current_regcache;
   current_regcache = list;
@@ -473,6 +513,24 @@ get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch)
   return new_regcache;
 }
 
+struct regcache *
+get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch)
+{
+  struct address_space *aspace;
+
+  /* For the benefit of "maint print registers" & co when debugging an
+     executable, allow dumping the regcache even when there is no
+     thread selected (target_thread_address_space internal-errors if
+     no address space is found).  Note that normal user commands will
+     fail higher up on the call stack due to no
+     target_has_registers.  */
+  aspace = (ptid_equal (null_ptid, ptid)
+           ? NULL
+           : target_thread_address_space (ptid));
+
+  return get_thread_arch_aspace_regcache  (ptid, gdbarch, aspace);
+}
+
 static ptid_t current_thread_ptid;
 static struct gdbarch *current_thread_arch;
 
@@ -494,6 +552,13 @@ get_current_regcache (void)
   return get_thread_regcache (inferior_ptid);
 }
 
+/* See common/common-regcache.h.  */
+
+struct regcache *
+get_thread_regcache_for_ptid (ptid_t ptid)
+{
+  return get_thread_regcache (ptid);
+}
 
 /* Observer for the target_changed event.  */
 
@@ -550,13 +615,24 @@ registers_changed_ptid (ptid_t ptid)
       list = *list_link;
     }
 
-  current_regcache = NULL;
+  if (ptid_match (current_thread_ptid, ptid))
+    {
+      current_thread_ptid = null_ptid;
+      current_thread_arch = NULL;
+    }
 
-  current_thread_ptid = null_ptid;
-  current_thread_arch = NULL;
+  if (ptid_match (inferior_ptid, ptid))
+    {
+      /* We just deleted the regcache of the current thread.  Need to
+        forget about any frames we have cached, too.  */
+      reinit_frame_cache ();
+    }
+}
 
-  /* Need to forget about any frames we have cached, too.  */
-  reinit_frame_cache ();
+void
+registers_changed (void)
+{
+  registers_changed_ptid (minus_one_ptid);
 
   /* Force cleanup of any alloca areas if using C alloca instead of
      a builtin alloca.  This particular call is used to clean up
@@ -566,13 +642,7 @@ registers_changed_ptid (ptid_t ptid)
   alloca (0);
 }
 
-void
-registers_changed (void)
-{
-  registers_changed_ptid (minus_one_ptid);
-}
-
-void
+enum register_status
 regcache_raw_read (struct regcache *regcache, int regnum, gdb_byte *buf)
 {
   gdb_assert (regcache != NULL && buf != NULL);
@@ -581,68 +651,78 @@ regcache_raw_read (struct regcache *regcache, int regnum, gdb_byte *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->readonly_p)
+  if (!regcache->readonly_p
+      && regcache_register_status (regcache, regnum) == REG_UNKNOWN)
     {
-      if (!regcache_valid_p (regcache, regnum))
-       {
-         struct cleanup *old_chain = save_inferior_ptid ();
+      struct cleanup *old_chain = save_inferior_ptid ();
 
-         inferior_ptid = regcache->ptid;
-         target_fetch_registers (regcache, regnum);
-         do_cleanups (old_chain);
-       }
-#if 0
-      /* FIXME: cagney/2004-08-07: At present a number of targets
-        forget (or didn't know that they needed) to set this leading to
-        panics.  Also is the problem that targets need to indicate
-        that a register is in one of the possible states: valid,
-        undefined, unknown.  The last of which isn't yet
-        possible.  */
-      gdb_assert (regcache_valid_p (regcache, regnum));
-#endif
+      inferior_ptid = regcache->ptid;
+      target_fetch_registers (regcache, regnum);
+      do_cleanups (old_chain);
+
+      /* A number of targets can't access the whole set of raw
+        registers (because the debug API provides no means to get at
+        them).  */
+      if (regcache->register_status[regnum] == REG_UNKNOWN)
+       regcache->register_status[regnum] = REG_UNAVAILABLE;
     }
-  /* Copy the value directly into the register cache.  */
-  memcpy (buf, register_buffer (regcache, regnum),
-         regcache->descr->sizeof_register[regnum]);
+
+  if (regcache->register_status[regnum] != REG_VALID)
+    memset (buf, 0, regcache->descr->sizeof_register[regnum]);
+  else
+    memcpy (buf, register_buffer (regcache, regnum),
+           regcache->descr->sizeof_register[regnum]);
+
+  return (enum register_status) regcache->register_status[regnum];
 }
 
-void
+enum register_status
 regcache_raw_read_signed (struct regcache *regcache, int regnum, LONGEST *val)
 {
   gdb_byte *buf;
+  enum register_status status;
 
   gdb_assert (regcache != NULL);
   gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
-  buf = alloca (regcache->descr->sizeof_register[regnum]);
-  regcache_raw_read (regcache, regnum, buf);
-  (*val) = extract_signed_integer
-            (buf, regcache->descr->sizeof_register[regnum],
-             gdbarch_byte_order (regcache->descr->gdbarch));
+  buf = (gdb_byte *) alloca (regcache->descr->sizeof_register[regnum]);
+  status = regcache_raw_read (regcache, regnum, buf);
+  if (status == REG_VALID)
+    *val = extract_signed_integer
+      (buf, regcache->descr->sizeof_register[regnum],
+       gdbarch_byte_order (regcache->descr->gdbarch));
+  else
+    *val = 0;
+  return status;
 }
 
-void
+enum register_status
 regcache_raw_read_unsigned (struct regcache *regcache, int regnum,
                            ULONGEST *val)
 {
   gdb_byte *buf;
+  enum register_status status;
 
   gdb_assert (regcache != NULL);
   gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
-  buf = alloca (regcache->descr->sizeof_register[regnum]);
-  regcache_raw_read (regcache, regnum, buf);
-  (*val) = extract_unsigned_integer
-            (buf, regcache->descr->sizeof_register[regnum],
-             gdbarch_byte_order (regcache->descr->gdbarch));
+  buf = (gdb_byte *) alloca (regcache->descr->sizeof_register[regnum]);
+  status = regcache_raw_read (regcache, regnum, buf);
+  if (status == REG_VALID)
+    *val = extract_unsigned_integer
+      (buf, regcache->descr->sizeof_register[regnum],
+       gdbarch_byte_order (regcache->descr->gdbarch));
+  else
+    *val = 0;
+  return status;
 }
 
 void
 regcache_raw_write_signed (struct regcache *regcache, int regnum, LONGEST val)
 {
-  void *buf;
+  gdb_byte *buf;
 
   gdb_assert (regcache != NULL);
   gdb_assert (regnum >=0 && regnum < regcache->descr->nr_raw_registers);
-  buf = alloca (regcache->descr->sizeof_register[regnum]);
+  buf = (gdb_byte *) alloca (regcache->descr->sizeof_register[regnum]);
   store_signed_integer (buf, regcache->descr->sizeof_register[regnum],
                        gdbarch_byte_order (regcache->descr->gdbarch), val);
   regcache_raw_write (regcache, regnum, buf);
@@ -652,73 +732,158 @@ void
 regcache_raw_write_unsigned (struct regcache *regcache, int regnum,
                             ULONGEST val)
 {
-  void *buf;
+  gdb_byte *buf;
 
   gdb_assert (regcache != NULL);
   gdb_assert (regnum >=0 && regnum < regcache->descr->nr_raw_registers);
-  buf = alloca (regcache->descr->sizeof_register[regnum]);
+  buf = (gdb_byte *) alloca (regcache->descr->sizeof_register[regnum]);
   store_unsigned_integer (buf, regcache->descr->sizeof_register[regnum],
                          gdbarch_byte_order (regcache->descr->gdbarch), val);
   regcache_raw_write (regcache, regnum, buf);
 }
 
-void
+LONGEST
+regcache_raw_get_signed (struct regcache *regcache, int regnum)
+{
+  LONGEST value;
+  enum register_status status;
+
+  status = regcache_raw_read_signed (regcache, regnum, &value);
+  if (status == REG_UNAVAILABLE)
+    throw_error (NOT_AVAILABLE_ERROR,
+                _("Register %d is not available"), regnum);
+  return value;
+}
+
+enum register_status
 regcache_cooked_read (struct regcache *regcache, int regnum, gdb_byte *buf)
 {
   gdb_assert (regnum >= 0);
   gdb_assert (regnum < regcache->descr->nr_cooked_registers);
   if (regnum < regcache->descr->nr_raw_registers)
-    regcache_raw_read (regcache, regnum, buf);
+    return 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, perhaps the cooked value was cached?  */
-    memcpy (buf, register_buffer (regcache, regnum),
-           regcache->descr->sizeof_register[regnum]);
+          && regcache->register_status[regnum] != REG_UNKNOWN)
+    {
+      /* Read-only register cache, perhaps the cooked value was
+        cached?  */
+      if (regcache->register_status[regnum] == REG_VALID)
+       memcpy (buf, register_buffer (regcache, regnum),
+               regcache->descr->sizeof_register[regnum]);
+      else
+       memset (buf, 0, regcache->descr->sizeof_register[regnum]);
+
+      return (enum register_status) regcache->register_status[regnum];
+    }
+  else if (gdbarch_pseudo_register_read_value_p (regcache->descr->gdbarch))
+    {
+      struct value *mark, *computed;
+      enum register_status result = REG_VALID;
+
+      mark = value_mark ();
+
+      computed = gdbarch_pseudo_register_read_value (regcache->descr->gdbarch,
+                                                    regcache, regnum);
+      if (value_entirely_available (computed))
+       memcpy (buf, value_contents_raw (computed),
+               regcache->descr->sizeof_register[regnum]);
+      else
+       {
+         memset (buf, 0, regcache->descr->sizeof_register[regnum]);
+         result = REG_UNAVAILABLE;
+       }
+
+      value_free_to_mark (mark);
+
+      return result;
+    }
   else
-    gdbarch_pseudo_register_read (regcache->descr->gdbarch, regcache,
-                                 regnum, buf);
+    return gdbarch_pseudo_register_read (regcache->descr->gdbarch, regcache,
+                                        regnum, buf);
 }
 
-void
+struct value *
+regcache_cooked_read_value (struct regcache *regcache, int regnum)
+{
+  gdb_assert (regnum >= 0);
+  gdb_assert (regnum < regcache->descr->nr_cooked_registers);
+
+  if (regnum < regcache->descr->nr_raw_registers
+      || (regcache->readonly_p
+         && regcache->register_status[regnum] != REG_UNKNOWN)
+      || !gdbarch_pseudo_register_read_value_p (regcache->descr->gdbarch))
+    {
+      struct value *result;
+
+      result = allocate_value (register_type (regcache->descr->gdbarch,
+                                             regnum));
+      VALUE_LVAL (result) = lval_register;
+      VALUE_REGNUM (result) = regnum;
+
+      /* It is more efficient in general to do this delegation in this
+        direction than in the other one, even though the value-based
+        API is preferred.  */
+      if (regcache_cooked_read (regcache, regnum,
+                               value_contents_raw (result)) == REG_UNAVAILABLE)
+       mark_value_bytes_unavailable (result, 0,
+                                     TYPE_LENGTH (value_type (result)));
+
+      return result;
+    }
+  else
+    return gdbarch_pseudo_register_read_value (regcache->descr->gdbarch,
+                                              regcache, regnum);
+}
+
+enum register_status
 regcache_cooked_read_signed (struct regcache *regcache, int regnum,
                             LONGEST *val)
 {
+  enum register_status status;
   gdb_byte *buf;
 
   gdb_assert (regcache != NULL);
   gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_cooked_registers);
-  buf = alloca (regcache->descr->sizeof_register[regnum]);
-  regcache_cooked_read (regcache, regnum, buf);
-  (*val) = extract_signed_integer
-            (buf, regcache->descr->sizeof_register[regnum],
-             gdbarch_byte_order (regcache->descr->gdbarch));
+  buf = (gdb_byte *) alloca (regcache->descr->sizeof_register[regnum]);
+  status = regcache_cooked_read (regcache, regnum, buf);
+  if (status == REG_VALID)
+    *val = extract_signed_integer
+      (buf, regcache->descr->sizeof_register[regnum],
+       gdbarch_byte_order (regcache->descr->gdbarch));
+  else
+    *val = 0;
+  return status;
 }
 
-void
+enum register_status
 regcache_cooked_read_unsigned (struct regcache *regcache, int regnum,
                               ULONGEST *val)
 {
+  enum register_status status;
   gdb_byte *buf;
 
   gdb_assert (regcache != NULL);
   gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_cooked_registers);
-  buf = alloca (regcache->descr->sizeof_register[regnum]);
-  regcache_cooked_read (regcache, regnum, buf);
-  (*val) = extract_unsigned_integer
-            (buf, regcache->descr->sizeof_register[regnum],
-             gdbarch_byte_order (regcache->descr->gdbarch));
+  buf = (gdb_byte *) alloca (regcache->descr->sizeof_register[regnum]);
+  status = regcache_cooked_read (regcache, regnum, buf);
+  if (status == REG_VALID)
+    *val = extract_unsigned_integer
+      (buf, regcache->descr->sizeof_register[regnum],
+       gdbarch_byte_order (regcache->descr->gdbarch));
+  else
+    *val = 0;
+  return status;
 }
 
 void
 regcache_cooked_write_signed (struct regcache *regcache, int regnum,
                              LONGEST val)
 {
-  void *buf;
+  gdb_byte *buf;
 
   gdb_assert (regcache != NULL);
   gdb_assert (regnum >=0 && regnum < regcache->descr->nr_cooked_registers);
-  buf = alloca (regcache->descr->sizeof_register[regnum]);
+  buf = (gdb_byte *) alloca (regcache->descr->sizeof_register[regnum]);
   store_signed_integer (buf, regcache->descr->sizeof_register[regnum],
                        gdbarch_byte_order (regcache->descr->gdbarch), val);
   regcache_cooked_write (regcache, regnum, buf);
@@ -728,21 +893,33 @@ void
 regcache_cooked_write_unsigned (struct regcache *regcache, int regnum,
                                ULONGEST val)
 {
-  void *buf;
+  gdb_byte *buf;
 
   gdb_assert (regcache != NULL);
   gdb_assert (regnum >=0 && regnum < regcache->descr->nr_cooked_registers);
-  buf = alloca (regcache->descr->sizeof_register[regnum]);
+  buf = (gdb_byte *) alloca (regcache->descr->sizeof_register[regnum]);
   store_unsigned_integer (buf, regcache->descr->sizeof_register[regnum],
                          gdbarch_byte_order (regcache->descr->gdbarch), val);
   regcache_cooked_write (regcache, regnum, buf);
 }
 
+/* See regcache.h.  */
+
+void
+regcache_raw_set_cached_value (struct regcache *regcache, int regnum,
+                              const gdb_byte *buf)
+{
+  memcpy (register_buffer (regcache, regnum), buf,
+         regcache->descr->sizeof_register[regnum]);
+  regcache->register_status[regnum] = REG_VALID;
+}
+
 void
 regcache_raw_write (struct regcache *regcache, int regnum,
                    const gdb_byte *buf)
 {
-  struct cleanup *old_chain;
+  struct cleanup *chain_before_save_inferior;
+  struct cleanup *chain_before_invalidate_register;
 
   gdb_assert (regcache != NULL && buf != NULL);
   gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
@@ -755,21 +932,29 @@ regcache_raw_write (struct regcache *regcache, int regnum,
 
   /* 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)
+  if (regcache_register_status (regcache, regnum) == REG_VALID
       && (memcmp (register_buffer (regcache, regnum), buf,
                  regcache->descr->sizeof_register[regnum]) == 0))
     return;
 
-  old_chain = save_inferior_ptid ();
+  chain_before_save_inferior = save_inferior_ptid ();
   inferior_ptid = regcache->ptid;
 
   target_prepare_to_store (regcache);
-  memcpy (register_buffer (regcache, regnum), buf,
-         regcache->descr->sizeof_register[regnum]);
-  regcache->register_valid_p[regnum] = 1;
+  regcache_raw_set_cached_value (regcache, regnum, buf);
+
+  /* Register a cleanup function for invalidating the register after it is
+     written, in case of a failure.  */
+  chain_before_invalidate_register
+    = make_cleanup_regcache_invalidate (regcache, regnum);
+
   target_store_registers (regcache, regnum);
 
-  do_cleanups (old_chain);
+  /* The target did not throw an error so we can discard invalidating the
+     register and restore the cleanup chain to what it was.  */
+  discard_cleanups (chain_before_invalidate_register);
+
+  do_cleanups (chain_before_save_inferior);
 }
 
 void
@@ -793,11 +978,12 @@ typedef void (regcache_read_ftype) (struct regcache *regcache, int regnum,
 typedef void (regcache_write_ftype) (struct regcache *regcache, int regnum,
                                     const void *buf);
 
-static void
+static enum register_status
 regcache_xfer_part (struct regcache *regcache, int regnum,
                    int offset, int len, void *in, const void *out,
-                   void (*read) (struct regcache *regcache, int regnum,
-                                 gdb_byte *buf),
+                   enum register_status (*read) (struct regcache *regcache,
+                                                 int regnum,
+                                                 gdb_byte *buf),
                    void (*write) (struct regcache *regcache, int regnum,
                                   const gdb_byte *buf))
 {
@@ -808,14 +994,18 @@ regcache_xfer_part (struct regcache *regcache, int regnum,
   gdb_assert (len >= 0 && offset + len <= descr->sizeof_register[regnum]);
   /* Something to do?  */
   if (offset + len == 0)
-    return;
+    return REG_VALID;
   /* Read (when needed) ...  */
   if (in != NULL
       || offset > 0
       || offset + len < descr->sizeof_register[regnum])
     {
+      enum register_status status;
+
       gdb_assert (read != NULL);
-      read (regcache, regnum, reg);
+      status = read (regcache, regnum, reg);
+      if (status != REG_VALID)
+       return status;
     }
   /* ... modify ...  */
   if (in != NULL)
@@ -828,17 +1018,19 @@ regcache_xfer_part (struct regcache *regcache, int regnum,
       gdb_assert (write != NULL);
       write (regcache, regnum, reg);
     }
+
+  return REG_VALID;
 }
 
-void
+enum register_status
 regcache_raw_read_part (struct regcache *regcache, int regnum,
                        int offset, int len, gdb_byte *buf)
 {
   struct regcache_descr *descr = regcache->descr;
 
   gdb_assert (regnum >= 0 && regnum < descr->nr_raw_registers);
-  regcache_xfer_part (regcache, regnum, offset, len, buf, NULL,
-                     regcache_raw_read, regcache_raw_write);
+  return regcache_xfer_part (regcache, regnum, offset, len, buf, NULL,
+                            regcache_raw_read, regcache_raw_write);
 }
 
 void
@@ -852,15 +1044,15 @@ regcache_raw_write_part (struct regcache *regcache, int regnum,
                      regcache_raw_read, regcache_raw_write);
 }
 
-void
+enum register_status
 regcache_cooked_read_part (struct regcache *regcache, int regnum,
                           int offset, int len, gdb_byte *buf)
 {
   struct regcache_descr *descr = regcache->descr;
 
   gdb_assert (regnum >= 0 && regnum < descr->nr_cooked_registers);
-  regcache_xfer_part (regcache, regnum, offset, len, buf, NULL,
-                     regcache_cooked_read, regcache_cooked_write);
+  return regcache_xfer_part (regcache, regnum, offset, len, buf, NULL,
+                            regcache_cooked_read, regcache_cooked_write);
 }
 
 void
@@ -890,12 +1082,18 @@ regcache_raw_supply (struct regcache *regcache, int regnum, const void *buf)
   size = regcache->descr->sizeof_register[regnum];
 
   if (buf)
-    memcpy (regbuf, buf, size);
+    {
+      memcpy (regbuf, buf, size);
+      regcache->register_status[regnum] = REG_VALID;
+    }
   else
-    memset (regbuf, 0, size);
-
-  /* Mark the register as cached.  */
-  regcache->register_valid_p[regnum] = 1;
+    {
+      /* This memset not strictly necessary, but better than garbage
+        in case the register value manages to escape somewhere (due
+        to a bug, no less).  */
+      memset (regbuf, 0, size);
+      regcache->register_status[regnum] = REG_UNAVAILABLE;
+    }
 }
 
 /* Collect register REGNUM from REGCACHE and store its contents in BUF.  */
@@ -914,6 +1112,94 @@ regcache_raw_collect (const struct regcache *regcache, int regnum, void *buf)
   memcpy (buf, regbuf, size);
 }
 
+/* Transfer a single or all registers belonging to a certain register
+   set to or from a buffer.  This is the main worker function for
+   regcache_supply_regset and regcache_collect_regset.  */
+
+static void
+regcache_transfer_regset (const struct regset *regset,
+                         const struct regcache *regcache,
+                         struct regcache *out_regcache,
+                         int regnum, const void *in_buf,
+                         void *out_buf, size_t size)
+{
+  const struct regcache_map_entry *map;
+  int offs = 0, count;
+
+  for (map = (const struct regcache_map_entry *) regset->regmap;
+       (count = map->count) != 0;
+       map++)
+    {
+      int regno = map->regno;
+      int slot_size = map->size;
+
+      if (slot_size == 0 && regno != REGCACHE_MAP_SKIP)
+       slot_size = regcache->descr->sizeof_register[regno];
+
+      if (regno == REGCACHE_MAP_SKIP
+         || (regnum != -1
+             && (regnum < regno || regnum >= regno + count)))
+         offs += count * slot_size;
+
+      else if (regnum == -1)
+       for (; count--; regno++, offs += slot_size)
+         {
+           if (offs + slot_size > size)
+             break;
+
+           if (out_buf)
+             regcache_raw_collect (regcache, regno,
+                                   (gdb_byte *) out_buf + offs);
+           else
+             regcache_raw_supply (out_regcache, regno, in_buf
+                                  ? (const gdb_byte *) in_buf + offs
+                                  : NULL);
+         }
+      else
+       {
+         /* Transfer a single register and return.  */
+         offs += (regnum - regno) * slot_size;
+         if (offs + slot_size > size)
+           return;
+
+         if (out_buf)
+           regcache_raw_collect (regcache, regnum,
+                                 (gdb_byte *) out_buf + offs);
+         else
+           regcache_raw_supply (out_regcache, regnum, in_buf
+                                ? (const gdb_byte *) in_buf + offs
+                                : NULL);
+         return;
+       }
+    }
+}
+
+/* Supply register REGNUM from BUF to REGCACHE, using the register map
+   in REGSET.  If REGNUM is -1, do this for all registers in REGSET.
+   If BUF is NULL, set the register(s) to "unavailable" status. */
+
+void
+regcache_supply_regset (const struct regset *regset,
+                       struct regcache *regcache,
+                       int regnum, const void *buf, size_t size)
+{
+  regcache_transfer_regset (regset, regcache, regcache, regnum,
+                           buf, NULL, size);
+}
+
+/* Collect register REGNUM from REGCACHE to BUF, using the register
+   map in REGSET.  If REGNUM is -1, do this for all registers in
+   REGSET.  */
+
+void
+regcache_collect_regset (const struct regset *regset,
+                        const struct regcache *regcache,
+                        int regnum, void *buf, size_t size)
+{
+  regcache_transfer_regset (regset, regcache, NULL, regnum,
+                           NULL, buf, size);
+}
+
 
 /* Special handling for register PC.  */
 
@@ -931,9 +1217,11 @@ regcache_read_pc (struct regcache *regcache)
     {
       ULONGEST raw_val;
 
-      regcache_cooked_read_unsigned (regcache,
-                                    gdbarch_pc_regnum (gdbarch),
-                                    &raw_val);
+      if (regcache_cooked_read_unsigned (regcache,
+                                        gdbarch_pc_regnum (gdbarch),
+                                        &raw_val) == REG_UNAVAILABLE)
+       throw_error (NOT_AVAILABLE_ERROR, _("PC register is not available"));
+
       pc_val = gdbarch_addr_bits_remove (gdbarch, raw_val);
     }
   else
@@ -971,31 +1259,11 @@ reg_flush_command (char *command, int from_tty)
     printf_filtered (_("Register cache flushed.\n"));
 }
 
-static void
-dump_endian_bytes (struct ui_file *file, enum bfd_endian endian,
-                  const unsigned char *buf, long len)
-{
-  int i;
-
-  switch (endian)
-    {
-    case BFD_ENDIAN_BIG:
-      for (i = 0; i < len; i++)
-       fprintf_unfiltered (file, "%02x", buf[i]);
-      break;
-    case BFD_ENDIAN_LITTLE:
-      for (i = len - 1; i >= 0; i--)
-       fprintf_unfiltered (file, "%02x", buf[i]);
-      break;
-    default:
-      internal_error (__FILE__, __LINE__, _("Bad switch"));
-    }
-}
-
 enum regcache_dump_what
 {
   regcache_dump_none, regcache_dump_raw,
-  regcache_dump_cooked, regcache_dump_groups
+  regcache_dump_cooked, regcache_dump_groups,
+  regcache_dump_remote
 };
 
 static void
@@ -1010,7 +1278,7 @@ regcache_dump (struct regcache *regcache, struct ui_file *file,
   int footnote_register_offset = 0;
   int footnote_register_type_name_null = 0;
   long register_offset = 0;
-  unsigned char buf[MAX_REGISTER_SIZE];
+  gdb_byte buf[MAX_REGISTER_SIZE];
 
 #if 0
   fprintf_unfiltered (file, "nr_raw_registers %d\n",
@@ -1019,8 +1287,8 @@ regcache_dump (struct regcache *regcache, struct ui_file *file,
                      regcache->descr->nr_cooked_registers);
   fprintf_unfiltered (file, "sizeof_raw_registers %ld\n",
                      regcache->descr->sizeof_raw_registers);
-  fprintf_unfiltered (file, "sizeof_raw_register_valid_p %ld\n",
-                     regcache->descr->sizeof_raw_register_valid_p);
+  fprintf_unfiltered (file, "sizeof_raw_register_status %ld\n",
+                     regcache->descr->sizeof_raw_register_status);
   fprintf_unfiltered (file, "gdbarch_num_regs %d\n", 
                      gdbarch_num_regs (gdbarch));
   fprintf_unfiltered (file, "gdbarch_num_pseudo_regs %d\n",
@@ -1115,7 +1383,7 @@ regcache_dump (struct regcache *regcache, struct ui_file *file,
                t = n;
              }
            /* Chop a leading builtin_type.  */
-           if (strncmp (t, blt, strlen (blt)) == 0)
+           if (startswith (t, blt))
              t += strlen (blt);
          }
        fprintf_unfiltered (file, " %-15s", t);
@@ -1131,15 +1399,16 @@ regcache_dump (struct regcache *regcache, struct ui_file *file,
            fprintf_unfiltered (file, "Raw value");
          else if (regnum >= regcache->descr->nr_raw_registers)
            fprintf_unfiltered (file, "<cooked>");
-         else if (!regcache_valid_p (regcache, regnum))
+         else if (regcache_register_status (regcache, regnum) == REG_UNKNOWN)
            fprintf_unfiltered (file, "<invalid>");
+         else if (regcache_register_status (regcache, regnum) == REG_UNAVAILABLE)
+           fprintf_unfiltered (file, "<unavailable>");
          else
            {
              regcache_raw_read (regcache, regnum, buf);
-             fprintf_unfiltered (file, "0x");
-             dump_endian_bytes (file,
-                                gdbarch_byte_order (gdbarch), buf,
-                                regcache->descr->sizeof_register[regnum]);
+             print_hex_chars (file, buf,
+                              regcache->descr->sizeof_register[regnum],
+                              gdbarch_byte_order (gdbarch));
            }
        }
 
@@ -1150,11 +1419,17 @@ regcache_dump (struct regcache *regcache, struct ui_file *file,
            fprintf_unfiltered (file, "Cooked value");
          else
            {
-             regcache_cooked_read (regcache, regnum, buf);
-             fprintf_unfiltered (file, "0x");
-             dump_endian_bytes (file,
-                                gdbarch_byte_order (gdbarch), buf,
-                                regcache->descr->sizeof_register[regnum]);
+             enum register_status status;
+
+             status = regcache_cooked_read (regcache, regnum, buf);
+             if (status == REG_UNKNOWN)
+               fprintf_unfiltered (file, "<invalid>");
+             else if (status == REG_UNAVAILABLE)
+               fprintf_unfiltered (file, "<unavailable>");
+             else
+               print_hex_chars (file, buf,
+                                regcache->descr->sizeof_register[regnum],
+                                gdbarch_byte_order (gdbarch));
            }
        }
 
@@ -1182,6 +1457,23 @@ regcache_dump (struct regcache *regcache, struct ui_file *file,
            }
        }
 
+      /* Remote packet configuration.  */
+      if (what_to_dump == regcache_dump_remote)
+       {
+         if (regnum < 0)
+           {
+             fprintf_unfiltered (file, "Rmt Nr  g/G Offset");
+           }
+         else if (regnum < regcache->descr->nr_raw_registers)
+           {
+             int pnum, poffset;
+
+             if (remote_register_number_and_offset (get_regcache_arch (regcache), regnum,
+                                                    &pnum, &poffset))
+               fprintf_unfiltered (file, "%7d %11d", pnum, poffset);
+           }
+       }
+
       fprintf_unfiltered (file, "\n");
     }
 
@@ -1240,6 +1532,12 @@ maintenance_print_register_groups (char *args, int from_tty)
   regcache_print (args, regcache_dump_groups);
 }
 
+static void
+maintenance_print_remote_registers (char *args, int from_tty)
+{
+  regcache_print (args, regcache_dump_remote);
+}
+
 extern initialize_file_ftype _initialize_regcache; /* -Wmissing-prototype */
 
 void
@@ -1273,5 +1571,11 @@ _initialize_regcache (void)
             "including each register's group.\n"
             "Takes an optional file parameter."),
           &maintenanceprintlist);
+  add_cmd ("remote-registers", class_maintenance,
+          maintenance_print_remote_registers, _("\
+Print the internal register configuration including each register's\n\
+remote register number and buffer offset in the g/G packets.\n\
+Takes an optional file parameter."),
+          &maintenanceprintlist);
 
 }
This page took 0.064119 seconds and 4 git commands to generate.