struct value *
 get_return_value (struct value *function, struct type *value_type)
 {
-  regcache stop_regs (regcache::readonly, *get_current_regcache ());
-  struct gdbarch *gdbarch = stop_regs.arch ();
+  regcache *stop_regs = get_current_regcache ();
+  struct gdbarch *gdbarch = stop_regs->arch ();
   struct value *value;
 
   value_type = check_typedef (value_type);
     case RETURN_VALUE_ABI_RETURNS_ADDRESS:
     case RETURN_VALUE_ABI_PRESERVES_ADDRESS:
       value = allocate_value (value_type);
-      gdbarch_return_value (gdbarch, function, value_type, &stop_regs,
+      gdbarch_return_value (gdbarch, function, value_type, stop_regs,
                            value_contents_raw (value), NULL);
       break;
     case RETURN_VALUE_STRUCT_CONVENTION:
 
   return regcache_cooked_read (regcache, regnum, buf);
 }
 
-regcache::regcache (readonly_t, const regcache &src)
-  : regcache (src.arch (), nullptr, true)
-{
-  gdb_assert (!src.m_readonly_p);
-  save (do_cooked_read, (void *) &src);
-}
-
 readonly_detached_regcache::readonly_detached_regcache (const regcache &src)
   : readonly_detached_regcache (src.arch (), do_cooked_read, (void *) &src)
 {
   const bool m_dump_pseudo;
 };
 
+/* Dump from reg_buffer, used when there is no thread or
+   registers.  */
+
+class register_dump_reg_buffer : public register_dump, reg_buffer
+{
+public:
+  register_dump_reg_buffer (gdbarch *gdbarch, bool dump_pseudo)
+    : register_dump (gdbarch), reg_buffer (gdbarch, dump_pseudo)
+  {
+  }
+
+protected:
+  void dump_reg (ui_file *file, int regnum) override
+  {
+    if (regnum < 0)
+      {
+       if (m_has_pseudo)
+         fprintf_unfiltered (file, "Cooked value");
+       else
+         fprintf_unfiltered (file, "Raw value");
+      }
+    else
+      {
+       if (regnum < gdbarch_num_regs (m_gdbarch) || m_has_pseudo)
+         {
+           auto size = register_size (m_gdbarch, regnum);
+
+           if (size == 0)
+             return;
+
+           auto status = get_register_status (regnum);
+
+           gdb_assert (status != REG_VALID);
+
+           if (status == REG_UNKNOWN)
+             fprintf_unfiltered (file, "<invalid>");
+           else
+             fprintf_unfiltered (file, "<unavailable>");
+         }
+       else
+         {
+           /* Just print "<cooked>" for pseudo register when
+              regcache_dump_raw.  */
+           fprintf_unfiltered (file, "<cooked>");
+         }
+      }
+  }
+};
+
 /* For "maint print registers".  */
 
 class register_dump_none : public register_dump
     case regcache_dump_raw:
     case regcache_dump_cooked:
       {
-       regcache *reg;
+       auto dump_pseudo = (what_to_dump == regcache_dump_cooked);
 
        if (target_has_registers)
-         reg = get_current_regcache ();
+         dump.reset (new register_dump_regcache (get_current_regcache (),
+                                                 dump_pseudo));
        else
          {
            /* For the benefit of "maint print registers" & co when
               debugging an executable, allow dumping a regcache even when
               there is no thread selected / no registers.  */
-           reg = new regcache (target_gdbarch ());
-           regs.reset (reg);
+           dump.reset (new register_dump_reg_buffer (target_gdbarch (),
+                                                     dump_pseudo));
          }
-
-       auto dump_pseudo = (what_to_dump == regcache_dump_cooked);
-
-       dump.reset (new register_dump_regcache (reg, dump_pseudo));
       }
       break;
     }
       mock_target.reset ();
     }
 
-  regcache readonly (regcache::readonly, readwrite);
+  readonly_detached_regcache readonly (readwrite);
 
   /* GDB may go to target layer to fetch all registers and memory for
      readonly regcache.  */