aboutsummaryrefslogtreecommitdiff
path: root/gdb/regcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/regcache.c')
-rw-r--r--gdb/regcache.c116
1 files changed, 77 insertions, 39 deletions
diff --git a/gdb/regcache.c b/gdb/regcache.c
index 3f2be7b..70af06f 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -389,59 +389,79 @@ register_buffer (struct regcache *regcache, int regnum)
}
void
-regcache_save (struct regcache *dst, struct regcache *src)
+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 SRC and DST register caches had better belong to the same
- architecture. */
- gdb_assert (src->descr->gdbarch == dst->descr->gdbarch);
/* The DST should be `read-only', if it wasn't then the save would
- end up trying to write the register values out through to the
+ end up trying to write the register values back out to the
target. */
- gdb_assert (!src->readonly_p);
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. */
+ 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))
{
- regcache_cooked_read (src, regnum, register_buffer (dst, regnum));
- dst->register_valid_p[regnum] = 1;
+ 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, struct regcache *src)
+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;
- gdb_assert (src->descr->gdbarch == dst->descr->gdbarch);
+ /* 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
- .. 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 < src->descr->nr_cooked_registers; regnum++)
+ 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)
- && src->register_valid_p[regnum])
+ if (gdbarch_register_reggroup_p (gdbarch, regnum, restore_reggroup))
{
- regcache_cooked_write (dst, regnum, register_buffer (src, regnum));
+ 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)
{
@@ -452,9 +472,9 @@ regcache_cpy (struct regcache *dst, struct regcache *src)
gdb_assert (src != dst);
gdb_assert (src->readonly_p || dst->readonly_p);
if (!src->readonly_p)
- regcache_save (dst, src);
+ regcache_save (dst, do_cooked_read, src);
else if (!dst->readonly_p)
- regcache_restore (dst, src);
+ regcache_restore (dst, do_cooked_read, src);
else
regcache_cpy_no_passthrough (dst, src);
}
@@ -864,7 +884,7 @@ regcache_cooked_read_signed (struct regcache *regcache, int regnum,
{
char *buf;
gdb_assert (regcache != NULL);
- gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
+ 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,
@@ -877,13 +897,37 @@ regcache_cooked_read_unsigned (struct regcache *regcache, int regnum,
{
char *buf;
gdb_assert (regcache != NULL);
- gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
+ 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]);
}
+void
+regcache_cooked_write_signed (struct regcache *regcache, int regnum,
+ LONGEST val)
+{
+ void *buf;
+ gdb_assert (regcache != NULL);
+ gdb_assert (regnum >=0 && regnum < regcache->descr->nr_cooked_registers);
+ buf = alloca (regcache->descr->sizeof_register[regnum]);
+ store_signed_integer (buf, regcache->descr->sizeof_register[regnum], val);
+ regcache_cooked_write (regcache, regnum, buf);
+}
+
+void
+regcache_cooked_write_unsigned (struct regcache *regcache, int regnum,
+ ULONGEST val)
+{
+ void *buf;
+ gdb_assert (regcache != NULL);
+ gdb_assert (regnum >=0 && regnum < regcache->descr->nr_cooked_registers);
+ buf = alloca (regcache->descr->sizeof_register[regnum]);
+ store_unsigned_integer (buf, regcache->descr->sizeof_register[regnum], val);
+ regcache_cooked_write (regcache, regnum, buf);
+}
+
/* Write register REGNUM at MYADDR to the target. MYADDR points at
REGISTER_RAW_BYTES(REGNUM), which must be in target byte-order. */
@@ -1284,16 +1328,16 @@ regcache_collect (int regnum, void *buf)
}
-/* read_pc, write_pc, read_sp, write_sp, read_fp, etc. Special
- handling for registers PC, SP, and FP. */
+/* read_pc, write_pc, read_sp, read_fp, etc. Special handling for
+ registers PC, SP, and FP. */
/* NOTE: cagney/2001-02-18: The functions generic_target_read_pc(),
read_pc_pid(), read_pc(), generic_target_write_pc(),
write_pc_pid(), write_pc(), generic_target_read_sp(), read_sp(),
- generic_target_write_sp(), write_sp(), generic_target_read_fp() and
- read_fp(), will eventually be moved out of the reg-cache into
- either frame.[hc] or to the multi-arch framework. The are not part
- of the raw register cache. */
+ generic_target_write_sp(), generic_target_read_fp() and read_fp(),
+ will eventually be moved out of the reg-cache into either
+ frame.[hc] or to the multi-arch framework. The are not part of the
+ raw register cache. */
/* This routine is getting awfully cluttered with #if's. It's probably
time to turn this into READ_PC and define it in the tm.h file.
@@ -1412,12 +1456,6 @@ generic_target_write_sp (CORE_ADDR val)
"generic_target_write_sp");
}
-void
-write_sp (CORE_ADDR val)
-{
- TARGET_WRITE_SP (val);
-}
-
CORE_ADDR
generic_target_read_fp (void)
{