From d805fddaada440a5a54601622162f37309dd6692 Mon Sep 17 00:00:00 2001 From: Andrew Cagney Date: Fri, 17 May 2002 15:06:31 +0000 Subject: introduce regcache_move. Fix cases where normal vs no_passthroug copies didn't reflect the old code. --- gdb/ChangeLog | 30 +++++++++++++++++-- gdb/blockframe.c | 2 +- gdb/infcmd.c | 2 +- gdb/infrun.c | 8 ++--- gdb/regcache.c | 91 +++++++++++++++++++++++++++++++++++++++++++------------- gdb/regcache.h | 11 +++++-- 6 files changed, 114 insertions(+), 30 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 11bcf3d77f7..742d060137a 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,31 @@ -2002-05-16 Andrew Cagney - +2002-05-17 Andrew Cagney + +*** FIXME: the regcache_desc should contain max_register_size. + + * regcache.c (regcache_move): New function. + (regcache_save): Rewrite, handle pre and post + gdbarch_register_read_p with regcache_move. + (regcache_dup): Ditto + (regcache_dup_no_passthrough): Ditto ditto. + (regcache_save_no_passthrough): Ditto ditto. + (regcache_restore): Ditto ditto. + (regcache_restore_no_passthrough): Ditto ditto. + * regcache.h: Upate + + * infrun.c (save_inferior_status): Use regcache_dup_no_passthrough + instead of regcache_dup. Use regcache dup instead of + regcache_xmalloc, regcache_save. Revert white space change. + + * infcmd.c (run_stack_dummy): Use regcache_dup_no_passthrough not + regcache_dup. + + * blockframe.c (generic_push_dummy_frame): Re-order regcache_save + call to so that the patch is better. + + * regcache.c (regcache_save_no_passthrough): New function. + (regcache_dup_no_passthrough): Ditto. + (regcache_restore_no_passthrough): Rename to + regcache_restore_no_writethrough. * blockframe.c, regbuf.c, rs6000-tdep.c: Include "regcache.h". diff --git a/gdb/blockframe.c b/gdb/blockframe.c index 477a8a3e2f5..78b31eff438 100644 --- a/gdb/blockframe.c +++ b/gdb/blockframe.c @@ -1170,12 +1170,12 @@ generic_push_dummy_frame (void) dummy_frame = xmalloc (sizeof (struct dummy_frame)); dummy_frame->regcache = regcache_xmalloc (current_gdbarch); - regcache_save (dummy_frame->regcache); dummy_frame->pc = read_pc (); dummy_frame->sp = read_sp (); dummy_frame->top = dummy_frame->sp; dummy_frame->fp = fp; + regcache_save (dummy_frame->regcache); dummy_frame->next = dummy_frame_stack; dummy_frame_stack = dummy_frame; } diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 14bb00bda49..ae5d5253902 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -1043,7 +1043,7 @@ run_stack_dummy (CORE_ADDR addr, struct regcache **buffer) return 2; /* On normal return, the stack dummy has been popped already. */ - *buffer = regcache_dup (stop_registers); + *buffer = regcache_dup_no_passthrough (stop_registers); return 0; } diff --git a/gdb/infrun.c b/gdb/infrun.c index b46779160ed..409fede4d1d 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -3961,9 +3961,9 @@ save_inferior_status (int restore_stack_info) inf_status->restore_stack_info = restore_stack_info; inf_status->proceed_to_finish = proceed_to_finish; - inf_status->stop_registers = regcache_dup (stop_registers); - inf_status->registers = regcache_xmalloc (current_gdbarch); - regcache_save (inf_status->registers); + inf_status->stop_registers = regcache_dup_no_passthrough (stop_registers); + + inf_status->registers = regcache_dup (current_regcache); record_selected_frame (&(inf_status->selected_frame_address), &(inf_status->selected_level)); @@ -4027,7 +4027,7 @@ restore_inferior_status (struct inferior_status *inf_status) breakpoint_proceeded = inf_status->breakpoint_proceeded; proceed_to_finish = inf_status->proceed_to_finish; - /* FIXME: Is the restore of stop_registers always needed? */ + /* FIXME: Is the restore of stop_registers always needed. */ regcache_xfree (stop_registers); stop_registers = inf_status->stop_registers; diff --git a/gdb/regcache.c b/gdb/regcache.c index 38f611c63c2..3c9617658e0 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -182,16 +182,65 @@ regcache_xmalloc_with_cleanup (struct gdbarch *gdbarch) return regcache; } +void +regcache_move (struct regcache *dst, struct regcache *src) +{ + int i; + char *buf = alloca (MAX_REGISTER_RAW_SIZE); + gdb_assert (src != NULL && dst != NULL); + gdb_assert (src->descr->gdbarch == dst->descr->gdbarch); + /* FIXME: cagney/2002-05-17: To say this bit is bad is being polite. + It keeps the existing code working where things rely on going + through the register cache. */ + if (src == current_regcache + && !gdbarch_register_read_p (src->descr->gdbarch)) + { + /* ULGH!!!! Old way. Use REGISTER bytes and let code below + untangle fetch. */ + read_register_bytes (0, dst->registers, REGISTER_BYTES); + return; + } + for (i = 0; i < current_regcache->descr->nr_registers; i++) + { + /* Should we worry about the valid bit here? */ + regcache_read (src, i, buf); + regcache_write (dst, i, buf); + } +} + +void +regcache_move_no_passthrough (struct regcache *dst, struct regcache *src) +{ + int i; + gdb_assert (src != NULL && dst != NULL); + gdb_assert (src->descr->gdbarch == dst->descr->gdbarch); + /* NOTE: cagney/2002-05-17: Don't let the caller do a no-passthrough + move of data into the current_regcache(). Doing this would be + silly - it would mean that valid_p would be completly invalid. */ + gdb_assert (dst != current_regcache); + memcpy (dst->registers, src->registers, + dst->descr->sizeof_registers); + memcpy (dst->register_valid_p, src->register_valid_p, + dst->descr->sizeof_register_valid_p); +} + struct regcache * -regcache_dup (struct regcache *regcache) +regcache_dup (struct regcache *src) { struct regcache *newbuf; gdb_assert (current_regcache != NULL); - newbuf = regcache_xmalloc (regcache->descr->gdbarch); - memcpy (newbuf->registers, regcache->registers, - regcache->descr->sizeof_registers); - memcpy (newbuf->register_valid_p, regcache->register_valid_p, - regcache->descr->sizeof_register_valid_p); + newbuf = regcache_xmalloc (src->descr->gdbarch); + regcache_move (newbuf, src); + return newbuf; +} + +struct regcache * +regcache_dup_no_passthrough (struct regcache *src) +{ + struct regcache *newbuf; + gdb_assert (current_regcache != NULL); + newbuf = regcache_xmalloc (src->descr->gdbarch); + regcache_move_no_passthrough (newbuf, src); return newbuf; } @@ -982,36 +1031,38 @@ build_regcache (void) void regcache_save (struct regcache *regcache) { + int i; + char *buf = alloca (MAX_REGISTER_RAW_SIZE); gdb_assert (current_regcache != NULL && regcache != NULL); gdb_assert (current_regcache->descr->gdbarch == regcache->descr->gdbarch); - memcpy (grub_around_regcache_for_registers (regcache), - grub_around_regcache_for_registers (current_regcache), - regcache->descr->sizeof_registers); - memcpy (grub_around_regcache_for_register_valid (regcache), - grub_around_regcache_for_register_valid (current_regcache), - regcache->descr->sizeof_register_valid_p); + regcache_move (regcache, current_regcache); +} + +void +regcache_save_no_passthrough (struct regcache *regcache) +{ + gdb_assert (current_regcache != NULL && regcache != NULL); + gdb_assert (current_regcache->descr->gdbarch == regcache->descr->gdbarch); + regcache_move_no_passthrough (regcache, current_regcache); } void regcache_restore (struct regcache *regcache) { - char *regcache_registers; + int i; + char *buf = alloca (MAX_REGISTER_RAW_SIZE); gdb_assert (current_regcache != NULL && regcache != NULL); gdb_assert (current_regcache->descr->gdbarch == regcache->descr->gdbarch); - regcache_registers = grub_around_regcache_for_registers (regcache); - /* NOTE: cagney, this should be regcache->sizeof_registers but, - again, things are screwed as it might copy pseudo registers. */ - write_register_bytes (0, regcache_registers, REGISTER_BYTES); + regcache_move (current_regcache, regcache); } void -regcache_restore_no_writethrough (struct regcache *regcache) +regcache_restore_no_passthrough (struct regcache *regcache) { char *regcache_registers; gdb_assert (current_regcache != NULL && regcache != NULL); gdb_assert (current_regcache->descr->gdbarch == regcache->descr->gdbarch); - regcache_registers = grub_around_regcache_for_registers (regcache); - memcpy (registers, regcache_registers, REGISTER_BYTES); + regcache_move_no_passthrough (current_regcache, regcache); } void diff --git a/gdb/regcache.h b/gdb/regcache.h index 8a209d80553..931393527fc 100644 --- a/gdb/regcache.h +++ b/gdb/regcache.h @@ -59,12 +59,19 @@ extern signed char *register_valid; /* Save/restore the register cache using the regbuf. The operation is write through - it is strictly for code that needs to restore the - target's registers to a previous state. */ + target's registers to a previous state. + + ``no passthrough'' versions do not go through to the target. They + only save values already in the cache. */ extern void regcache_save (struct regcache *regcache); extern void regcache_restore (struct regcache *regcache); -extern void regcache_restore_no_writethrough (struct regcache *regcache); extern struct regcache *regcache_dup (struct regcache *regcache); +extern void regcache_save_no_passthrough (struct regcache *regcache); +extern void regcache_restore_no_passthrough (struct regcache *regcache); +extern struct regcache *regcache_dup_no_passthrough (struct regcache *regcache); +extern void regcache_move (struct regcache *dest, struct regcache *src); +extern void regcache_move_no_passthrough (struct regcache *dest, struct regcache *src); extern char *grub_around_regcache_for_registers (struct regcache *); extern char *grub_around_regcache_for_register_valid (struct regcache *); -- cgit v1.2.1