diff options
Diffstat (limited to 'gdb/regcache.c')
-rw-r--r-- | gdb/regcache.c | 116 |
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) { |