Simplify regcache_restore
[deliverable/binutils-gdb.git] / gdb / regcache.c
index 5ee31fb20df6adcaa67a1ff3bc0c4e6e052087aa..41c23a59875c53f2a99dda87cf5e1c3bbee7f846 100644 (file)
@@ -1,6 +1,6 @@
 /* Cache and manage the values of registers for GDB, the GNU debugger.
 
-   Copyright (C) 1986-2015 Free Software Foundation, Inc.
+   Copyright (C) 1986-2017 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -215,6 +215,16 @@ struct regcache
   ptid_t ptid;
 };
 
+/* See regcache.h.  */
+
+ptid_t
+regcache_get_ptid (const struct regcache *regcache)
+{
+  gdb_assert (!ptid_equal (regcache->ptid, minus_one_ptid));
+
+  return regcache->ptid;
+}
+
 static struct regcache *
 regcache_xmalloc_1 (struct gdbarch *gdbarch, struct address_space *aspace,
                    int readonly_p)
@@ -364,17 +374,15 @@ regcache_save (struct regcache *dst, regcache_cooked_read_ftype *cooked_read,
 }
 
 static void
-regcache_restore (struct regcache *dst,
-                 regcache_cooked_read_ftype *cooked_read,
-                 void *cooked_read_context)
+regcache_restore (struct regcache *dst, struct regcache *src)
 {
   struct gdbarch *gdbarch = dst->descr->gdbarch;
-  gdb_byte buf[MAX_REGISTER_SIZE];
   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);
+  gdb_assert (src->readonly_p);
   /* Copy over any registers, being careful to only restore those that
      were both saved and need to be restored.  The full [0 .. gdbarch_num_regs
      + gdbarch_num_pseudo_regs) range is checked since some architectures need
@@ -383,11 +391,8 @@ regcache_restore (struct regcache *dst,
     {
       if (gdbarch_register_reggroup_p (gdbarch, regnum, restore_reggroup))
        {
-         enum register_status status;
-
-         status = cooked_read (cooked_read_context, regnum, buf);
-         if (status == REG_VALID)
-           regcache_cooked_write (dst, regnum, buf);
+         if (src->register_status[regnum] == REG_VALID)
+           regcache_cooked_write (dst, regnum, register_buffer (src, regnum));
        }
     }
 }
@@ -414,7 +419,7 @@ regcache_cpy (struct regcache *dst, struct regcache *src)
   if (!src->readonly_p)
     regcache_save (dst, do_cooked_read, src);
   else if (!dst->readonly_p)
-    regcache_restore (dst, do_cooked_read, src);
+    regcache_restore (dst, src);
   else
     regcache_cpy_no_passthrough (dst, src);
 }
@@ -642,23 +647,21 @@ registers_changed (void)
   alloca (0);
 }
 
-enum register_status
-regcache_raw_read (struct regcache *regcache, int regnum, gdb_byte *buf)
+void
+regcache_raw_update (struct regcache *regcache, int regnum)
 {
-  gdb_assert (regcache != NULL && buf != NULL);
+  gdb_assert (regcache != NULL);
   gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
+
   /* 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->readonly_p
       && regcache_register_status (regcache, regnum) == REG_UNKNOWN)
     {
-      struct cleanup *old_chain = save_inferior_ptid ();
-
-      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
@@ -666,6 +669,13 @@ regcache_raw_read (struct regcache *regcache, int regnum, gdb_byte *buf)
       if (regcache->register_status[regnum] == REG_UNKNOWN)
        regcache->register_status[regnum] = REG_UNAVAILABLE;
     }
+}
+
+enum register_status
+regcache_raw_read (struct regcache *regcache, int regnum, gdb_byte *buf)
+{
+  gdb_assert (buf != NULL);
+  regcache_raw_update (regcache, regnum);
 
   if (regcache->register_status[regnum] != REG_VALID)
     memset (buf, 0, regcache->descr->sizeof_register[regnum]);
@@ -742,6 +752,19 @@ regcache_raw_write_unsigned (struct regcache *regcache, int regnum,
   regcache_raw_write (regcache, regnum, buf);
 }
 
+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)
 {
@@ -890,12 +913,22 @@ regcache_cooked_write_unsigned (struct regcache *regcache, int regnum,
   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 *chain_before_save_inferior;
-  struct cleanup *chain_before_invalidate_register;
+  struct cleanup *old_chain;
 
   gdb_assert (regcache != NULL && buf != NULL);
   gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
@@ -913,26 +946,18 @@ regcache_raw_write (struct regcache *regcache, int regnum,
                  regcache->descr->sizeof_register[regnum]) == 0))
     return;
 
-  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_status[regnum] = REG_VALID;
+  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);
+  old_chain = make_cleanup_regcache_invalidate (regcache, regnum);
 
   target_store_registers (regcache, regnum);
 
   /* 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);
+  discard_cleanups (old_chain);
 }
 
 void
@@ -966,7 +991,8 @@ regcache_xfer_part (struct regcache *regcache, int regnum,
                                   const gdb_byte *buf))
 {
   struct regcache_descr *descr = regcache->descr;
-  gdb_byte reg[MAX_REGISTER_SIZE];
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  gdb_byte *reg = (gdb_byte *) alloca (register_size (gdbarch, regnum));
 
   gdb_assert (offset >= 0 && offset <= descr->sizeof_register[regnum]);
   gdb_assert (len >= 0 && offset + len <= descr->sizeof_register[regnum]);
@@ -1227,6 +1253,41 @@ regcache_write_pc (struct regcache *regcache, CORE_ADDR pc)
   reinit_frame_cache ();
 }
 
+void
+regcache_debug_print_register (const char *func, struct regcache *regcache,
+                              int regno)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+
+  fprintf_unfiltered (gdb_stdlog, "%s ", func);
+  if (regno >= 0 && regno < gdbarch_num_regs (gdbarch)
+      && gdbarch_register_name (gdbarch, regno) != NULL
+      && gdbarch_register_name (gdbarch, regno)[0] != '\0')
+    fprintf_unfiltered (gdb_stdlog, "(%s)",
+                       gdbarch_register_name (gdbarch, regno));
+  else
+    fprintf_unfiltered (gdb_stdlog, "(%d)", regno);
+  if (regno >= 0 && regno < gdbarch_num_regs (gdbarch))
+    {
+      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+      int size = register_size (gdbarch, regno);
+      gdb_byte *buf = register_buffer (regcache, regno);
+
+      fprintf_unfiltered (gdb_stdlog, " = ");
+      for (int i = 0; i < size; i++)
+       {
+         fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]);
+       }
+      if (size <= sizeof (LONGEST))
+       {
+         ULONGEST val = extract_unsigned_integer (buf, size, byte_order);
+
+         fprintf_unfiltered (gdb_stdlog, " %s %s",
+                             core_addr_to_string_nz (val), plongest (val));
+       }
+    }
+  fprintf_unfiltered (gdb_stdlog, "\n");
+}
 
 static void
 reg_flush_command (char *command, int from_tty)
@@ -1475,14 +1536,11 @@ regcache_print (char *args, enum regcache_dump_what what_to_dump)
     regcache_dump (get_current_regcache (), gdb_stdout, what_to_dump);
   else
     {
-      struct cleanup *cleanups;
-      struct ui_file *file = gdb_fopen (args, "w");
+      stdio_file file;
 
-      if (file == NULL)
+      if (!file.open (args, "w"))
        perror_with_name (_("maintenance print architecture"));
-      cleanups = make_cleanup_ui_file_delete (file);
-      regcache_dump (get_current_regcache (), file, what_to_dump);
-      do_cleanups (cleanups);
+      regcache_dump (get_current_regcache (), &file, what_to_dump);
     }
 }
 
This page took 0.028257 seconds and 4 git commands to generate.