redundant information - if the PC is constructed from two
registers then those registers and not the PC lives in the raw
cache. */
- int nr_raw_registers;
long sizeof_raw_registers;
- 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
gdbarch_pseudo_register_read and gdbarch_pseudo_register_write. */
int nr_cooked_registers;
long sizeof_cooked_registers;
- long sizeof_cooked_register_status;
/* Offset and size (in 8 bit bytes), of each register in the
register cache. All registers (including those in the range
either mapped onto raw-registers or memory. */
descr->nr_cooked_registers = 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
/* Construct a strictly RAW register cache. Don't allow pseudo's
into the register cache. */
- descr->nr_raw_registers = gdbarch_num_regs (gdbarch);
- descr->sizeof_raw_register_status = gdbarch_num_regs (gdbarch);
/* Lay out the register cache.
= 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_raw_registers; i++)
+ for (i = 0; i < gdbarch_num_regs (gdbarch); i++)
{
descr->sizeof_register[i] = TYPE_LENGTH (descr->register_type[i]);
descr->register_offset[i] = offset;
int
regcache_register_size (const struct regcache *regcache, int n)
{
- return register_size (get_regcache_arch (regcache), n);
+ return register_size (regcache->arch (), n);
}
-regcache::regcache (gdbarch *gdbarch, address_space *aspace_,
+regcache::regcache (gdbarch *gdbarch, const address_space *aspace_,
bool readonly_p_)
: m_aspace (aspace_), m_readonly_p (readonly_p_)
{
{
m_registers = XCNEWVEC (gdb_byte, m_descr->sizeof_cooked_registers);
m_register_status = XCNEWVEC (signed char,
- m_descr->sizeof_cooked_register_status);
+ m_descr->nr_cooked_registers);
}
else
{
m_registers = XCNEWVEC (gdb_byte, m_descr->sizeof_raw_registers);
- m_register_status = XCNEWVEC (signed char,
- m_descr->sizeof_raw_register_status);
+ m_register_status = XCNEWVEC (signed char, gdbarch_num_regs (gdbarch));
}
m_ptid = minus_one_ptid;
}
}
regcache::regcache (readonly_t, const regcache &src)
- : regcache (src.arch (), src.aspace (), true)
+ : regcache (src.arch (), nullptr, true)
{
gdb_assert (!src.m_readonly_p);
save (do_cooked_read, (void *) &src);
return regcache->ptid ();
}
-void
-regcache_xfree (struct regcache *regcache)
-{
- if (regcache == NULL)
- return;
-
- delete regcache;
-}
-
-static void
-do_regcache_xfree (void *data)
-{
- regcache_xfree ((struct regcache *) data);
-}
-
-struct cleanup *
-make_cleanup_regcache_xfree (struct regcache *regcache)
-{
- return make_cleanup (do_regcache_xfree, regcache);
-}
-
-/* Cleanup routines for invalidating a register. */
+/* Cleanup class for invalidating a register. */
-struct register_to_invalidate
+class regcache_invalidator
{
- struct regcache *regcache;
- int regnum;
-};
-
-static void
-do_regcache_invalidate (void *data)
-{
- struct register_to_invalidate *reg = (struct register_to_invalidate *) data;
+public:
- regcache_invalidate (reg->regcache, reg->regnum);
-}
+ regcache_invalidator (struct regcache *regcache, int regnum)
+ : m_regcache (regcache),
+ m_regnum (regnum)
+ {
+ }
-static struct cleanup *
-make_cleanup_regcache_invalidate (struct regcache *regcache, int regnum)
-{
- struct register_to_invalidate* reg = XNEW (struct register_to_invalidate);
+ ~regcache_invalidator ()
+ {
+ if (m_regcache != nullptr)
+ regcache_invalidate (m_regcache, m_regnum);
+ }
- reg->regcache = regcache;
- reg->regnum = regnum;
- return make_cleanup_dtor (do_regcache_invalidate, (void *) reg, xfree);
-}
+ DISABLE_COPY_AND_ASSIGN (regcache_invalidator);
-/* Return REGCACHE's architecture. */
+ void release ()
+ {
+ m_regcache = nullptr;
+ }
-struct gdbarch *
-get_regcache_arch (const struct regcache *regcache)
-{
- return regcache->arch ();
-}
+private:
-struct address_space *
-get_regcache_aspace (const struct regcache *regcache)
-{
- return regcache->aspace ();
-}
+ struct regcache *m_regcache;
+ int m_regnum;
+};
/* Return a pointer to register REGNUM's buffer cache. */
gdb_assert (m_readonly_p);
/* Clear the dest. */
memset (m_registers, 0, m_descr->sizeof_cooked_registers);
- memset (m_register_status, 0, m_descr->sizeof_cooked_register_status);
+ memset (m_register_status, 0, m_descr->nr_cooked_registers);
/* 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
if (m_readonly_p)
gdb_assert (regnum < m_descr->nr_cooked_registers);
else
- gdb_assert (regnum < m_descr->nr_raw_registers);
+ gdb_assert (regnum < num_raw_registers ());
return (enum register_status) m_register_status[regnum];
}
void
regcache::invalidate (int regnum)
{
- gdb_assert (regnum >= 0);
gdb_assert (!m_readonly_p);
- gdb_assert (regnum < m_descr->nr_raw_registers);
+ assert_regnum (regnum);
m_register_status[regnum] = REG_UNKNOWN;
}
+void
+regcache::assert_regnum (int regnum) const
+{
+ gdb_assert (regnum >= 0 && regnum < gdbarch_num_regs (arch ()));
+}
+
/* Global structure containing the current regcache. */
/* NOTE: this is a write-through cache. There is no "dirty" bit for
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));
+ address_space *aspace = target_thread_address_space (ptid);
return get_thread_arch_aspace_regcache (ptid, gdbarch, aspace);
}
void
regcache::raw_update (int regnum)
{
- gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
+ assert_regnum (regnum);
/* Make certain that the register cache is up-to-date with respect
to the current thread. This switching shouldn't be necessary
gdb_byte *buf;
enum register_status status;
- gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
+ assert_regnum (regnum);
buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
status = raw_read (regnum, buf);
if (status == REG_VALID)
{
gdb_byte *buf;
- gdb_assert (regnum >=0 && regnum < m_descr->nr_raw_registers);
+ assert_regnum (regnum);
buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
store_integer (buf, m_descr->sizeof_register[regnum],
gdbarch_byte_order (m_descr->gdbarch), val);
{
gdb_assert (regnum >= 0);
gdb_assert (regnum < m_descr->nr_cooked_registers);
- if (regnum < m_descr->nr_raw_registers)
+ if (regnum < num_raw_registers ())
return raw_read (regnum, buf);
else if (m_readonly_p
&& m_register_status[regnum] != REG_UNKNOWN)
gdb_assert (regnum >= 0);
gdb_assert (regnum < m_descr->nr_cooked_registers);
- if (regnum < m_descr->nr_raw_registers
+ if (regnum < num_raw_registers ()
|| (m_readonly_p && m_register_status[regnum] != REG_UNKNOWN)
|| !gdbarch_pseudo_register_read_value_p (m_descr->gdbarch))
{
void
regcache::raw_write (int regnum, const gdb_byte *buf)
{
- struct cleanup *old_chain;
gdb_assert (buf != NULL);
- gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
+ assert_regnum (regnum);
gdb_assert (!m_readonly_p);
/* On the sparc, writing %g0 is a no-op, so we don't even want to
target_prepare_to_store (this);
raw_set_cached_value (regnum, buf);
- /* Register a cleanup function for invalidating the register after it is
- written, in case of a failure. */
- old_chain = make_cleanup_regcache_invalidate (this, regnum);
+ /* Invalidate the register after it is written, in case of a
+ failure. */
+ regcache_invalidator invalidator (this, regnum);
target_store_registers (this, 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 (old_chain);
+ /* The target did not throw an error so we can discard invalidating
+ the register. */
+ invalidator.release ();
}
void
{
gdb_assert (regnum >= 0);
gdb_assert (regnum < m_descr->nr_cooked_registers);
- if (regnum < m_descr->nr_raw_registers)
+ if (regnum < num_raw_registers ())
raw_write (regnum, buf);
else
gdbarch_pseudo_register_write (m_descr->gdbarch, this,
enum register_status
regcache::xfer_part (int regnum, int offset, int len, void *in,
- const void *out,
- enum register_status (*read) (struct regcache *regcache,
- int regnum,
- gdb_byte *buf),
- void (*write) (struct regcache *regcache, int regnum,
- const gdb_byte *buf))
+ const void *out, bool is_raw)
{
struct gdbarch *gdbarch = arch ();
gdb_byte *reg = (gdb_byte *) alloca (register_size (gdbarch, regnum));
{
enum register_status status;
- gdb_assert (read != NULL);
- status = read (this, regnum, reg);
+ if (is_raw)
+ status = raw_read (regnum, reg);
+ else
+ status = cooked_read (regnum, reg);
if (status != REG_VALID)
return status;
}
/* ... write (when needed). */
if (out != NULL)
{
- gdb_assert (write != NULL);
- write (this, regnum, reg);
+ if (is_raw)
+ raw_write (regnum, reg);
+ else
+ cooked_write (regnum, reg);
}
return REG_VALID;
enum register_status
regcache::raw_read_part (int regnum, int offset, int len, gdb_byte *buf)
{
- gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
- return xfer_part (regnum, offset, len, buf, NULL,
- regcache_raw_read, regcache_raw_write);
+ assert_regnum (regnum);
+ return xfer_part (regnum, offset, len, buf, NULL, true);
}
void
regcache::raw_write_part (int regnum, int offset, int len,
const gdb_byte *buf)
{
- gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
- xfer_part (regnum, offset, len, NULL, buf, regcache_raw_read,
- regcache_raw_write);
+ assert_regnum (regnum);
+ xfer_part (regnum, offset, len, NULL, buf, true);
}
enum register_status
regcache::cooked_read_part (int regnum, int offset, int len, gdb_byte *buf)
{
gdb_assert (regnum >= 0 && regnum < m_descr->nr_cooked_registers);
- return xfer_part (regnum, offset, len, buf, NULL,
- regcache_cooked_read, regcache_cooked_write);
+ return xfer_part (regnum, offset, len, buf, NULL, false);
}
void
const gdb_byte *buf)
{
gdb_assert (regnum >= 0 && regnum < m_descr->nr_cooked_registers);
- xfer_part (regnum, offset, len, NULL, buf,
- regcache_cooked_read, regcache_cooked_write);
+ xfer_part (regnum, offset, len, NULL, buf, false);
}
/* Supply register REGNUM, whose contents are stored in BUF, to REGCACHE. */
void *regbuf;
size_t size;
- gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
+ assert_regnum (regnum);
gdb_assert (!m_readonly_p);
regbuf = register_buffer (regnum);
gdb_byte *regbuf;
size_t regsize;
- gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
+ assert_regnum (regnum);
gdb_assert (!m_readonly_p);
regbuf = register_buffer (regnum);
void *regbuf;
size_t size;
- gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
+ assert_regnum (regnum);
gdb_assert (!m_readonly_p);
regbuf = register_buffer (regnum);
size_t size;
gdb_assert (buf != NULL);
- gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
+ assert_regnum (regnum);
regbuf = register_buffer (regnum);
size = m_descr->sizeof_register[regnum];
const gdb_byte *regbuf;
size_t regsize;
- gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
+ assert_regnum (regnum);
regbuf = register_buffer (regnum);
regsize = m_descr->sizeof_register[regnum];
CORE_ADDR
regcache_read_pc (struct regcache *regcache)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
CORE_ADDR pc_val;
void
regcache_write_pc (struct regcache *regcache, CORE_ADDR pc)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
if (gdbarch_write_pc_p (gdbarch))
gdbarch_write_pc (gdbarch, regcache, pc);
reinit_frame_cache ();
}
+int
+regcache::num_raw_registers () const
+{
+ return gdbarch_num_regs (arch ());
+}
+
void
regcache::debug_print_register (const char *func, int regno)
{
}
static void
-reg_flush_command (char *command, int from_tty)
+reg_flush_command (const char *command, int from_tty)
{
/* Force-flush the register cache. */
registers_changed ();
void
regcache::dump (ui_file *file, enum regcache_dump_what what_to_dump)
{
- struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
struct gdbarch *gdbarch = m_descr->gdbarch;
int regnum;
int footnote_nr = 0;
int footnote_register_type_name_null = 0;
long register_offset = 0;
-#if 0
- fprintf_unfiltered (file, "nr_raw_registers %d\n",
- m_descr->nr_raw_registers);
- fprintf_unfiltered (file, "nr_cooked_registers %d\n",
- m_descr->nr_cooked_registers);
- fprintf_unfiltered (file, "sizeof_raw_registers %ld\n",
- m_descr->sizeof_raw_registers);
- fprintf_unfiltered (file, "sizeof_raw_register_status %ld\n",
- m_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",
- gdbarch_num_pseudo_regs (gdbarch));
-#endif
-
gdb_assert (m_descr->nr_cooked_registers
== (gdbarch_num_regs (gdbarch)
+ gdbarch_num_pseudo_regs (gdbarch)));
/* Type. */
{
const char *t;
+ std::string name_holder;
if (regnum < 0)
t = "Type";
t = TYPE_NAME (register_type (arch (), regnum));
if (t == NULL)
{
- char *n;
-
if (!footnote_register_type_name_null)
footnote_register_type_name_null = ++footnote_nr;
- n = xstrprintf ("*%d", footnote_register_type_name_null);
- make_cleanup (xfree, n);
- t = n;
+ name_holder = string_printf ("*%d",
+ footnote_register_type_name_null);
+ t = name_holder.c_str ();
}
/* Chop a leading builtin_type. */
if (startswith (t, blt))
{
if (regnum < 0)
fprintf_unfiltered (file, "Raw value");
- else if (regnum >= m_descr->nr_raw_registers)
+ else if (regnum >= num_raw_registers ())
fprintf_unfiltered (file, "<cooked>");
else if (get_register_status (regnum) == REG_UNKNOWN)
fprintf_unfiltered (file, "<invalid>");
enum register_status status;
struct value *value = NULL;
- if (regnum < m_descr->nr_raw_registers)
+ if (regnum < num_raw_registers ())
{
raw_update (regnum);
status = get_register_status (regnum);
{
fprintf_unfiltered (file, "Rmt Nr g/G Offset");
}
- else if (regnum < m_descr->nr_raw_registers)
+ else if (regnum < num_raw_registers ())
{
int pnum, poffset;
fprintf_unfiltered (file,
"*%d: Register type's name NULL.\n",
footnote_register_type_name_null);
- do_cleanups (cleanups);
}
static void
-regcache_print (char *args, enum regcache_dump_what what_to_dump)
+regcache_print (const char *args, enum regcache_dump_what what_to_dump)
{
+ /* Where to send output. */
+ stdio_file file;
+ ui_file *out;
+
if (args == NULL)
- get_current_regcache ()->dump (gdb_stdout, what_to_dump);
+ out = gdb_stdout;
else
{
- stdio_file file;
-
if (!file.open (args, "w"))
perror_with_name (_("maintenance print architecture"));
- get_current_regcache ()->dump (&file, what_to_dump);
+ out = &file;
+ }
+
+ if (target_has_registers)
+ get_current_regcache ()->dump (out, what_to_dump);
+ 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. */
+ regcache dummy_regs (target_gdbarch ());
+ dummy_regs.dump (out, what_to_dump);
}
}
static void
-maintenance_print_registers (char *args, int from_tty)
+maintenance_print_registers (const char *args, int from_tty)
{
regcache_print (args, regcache_dump_none);
}
static void
-maintenance_print_raw_registers (char *args, int from_tty)
+maintenance_print_raw_registers (const char *args, int from_tty)
{
regcache_print (args, regcache_dump_raw);
}
static void
-maintenance_print_cooked_registers (char *args, int from_tty)
+maintenance_print_cooked_registers (const char *args, int from_tty)
{
regcache_print (args, regcache_dump_cooked);
}
static void
-maintenance_print_register_groups (char *args, int from_tty)
+maintenance_print_register_groups (const char *args, int from_tty)
{
regcache_print (args, regcache_dump_groups);
}
static void
-maintenance_print_remote_registers (char *args, int from_tty)
+maintenance_print_remote_registers (const char *args, int from_tty)
{
regcache_print (args, regcache_dump_remote);
}