This is the mail archive of the
gdb@sources.redhat.com
mailing list for the GDB project.
Re: [wip/rfc] Handle saved regcache using a regbuf
- From: Andrew Cagney <ac131313 at cygnus dot com>
- To: Andrew Cagney <ac131313 at cygnus dot com>
- Cc: gdb at sources dot redhat dot com
- Date: Wed, 15 May 2002 10:11:15 -0400
- Subject: Re: [wip/rfc] Handle saved regcache using a regbuf
- References: <3CDD7390.10003@cygnus.com>
This version contains the missing regbuf.[hc]
Andrew
? diffs
? new-gdbarch.log
? new-gdbarch.h
? new-gdbarch.c
Index: ChangeLog
===================================================================
RCS file: /cvs/src/src/gdb/ChangeLog,v
retrieving revision 1.2604
diff -r1.2604 ChangeLog
0a1,108
> 2002-05-11 Andrew Cagney <ac131313@redhat.com>
>
> * regcache.c (regcache_restore): New function.
> * regcache.h (regcache_restore): Declare.
>
> * infrun.c (build_infrun): Allocate stop_registers using
> regbuf_xmalloc.
> (_initialize_infrun): Don't call build_infrun.
>
> * Makefile.in (infrun.o): Add dependency on "regbuf.h".
>
> * infrun.c: Include "regbuf.h".
> (struct inferior_status): Change type of stop_registers
> and registers to ``struct regbuf''.
> (xmalloc_inferior_status): Allocate stop_registers and registers
> using regbuf_xmalloc.
> (free_inferior_status): Free registers and stop_registers using
> regbuf_xfree.
> (xmalloc_inferior_status): Delete.
> (save_inferior_status): XMALLOC inf_status directly. Use
> regbuf_dup and regbuf_xmalloc.
> (free_inferior_status): Delete.
> (discard_inferior_status): Free inf_status directly.
> (restore_inferior_status): Free inf_status directly. Restore
> stop_registers by replacing buffer.
> (write_inferior_status_register): Use regbuf_write.
>
> * Makefile.in (infcmd.o): Add $(regbuf_h).
>
> * infcmd.c: Include "regbuf.h".
> (run_stack_dummy): Duplicate the stop_registers.
>
>
> * rs6000-tdep.c (rs6000_extract_struct_value_address): Change type
> of regbuf parameter to ``struct regbuf''.
>
> * Makefile.in (rs6000-tdep.o): Add $(regbuf_h).
>
> * rs6000-tdep.c: Include "regbuf.h".
>
> * infrun.c (normal_stop): Use regcache_save.
>
> * rs6000-tdep.c (rs6000_extract_return_value): Change regbuf type
> to ``struct regbuf''. Use grub_around_regbuf_for_registers.
>
> * inferior.h (stop_registers): Change type to a ``struct regbuf''.
> * infrun.c (stop_registers): Update.
>
> * values.c (value_being_returned): Update.
>
> * infcmd.c (run_stack_dummy): Update.
>
> * gdbarch.sh (EXTRACT_STRUCT_VALUE_ADDRESS): Change type of regbuf
> to ``struct regbuf''.
> (EXTRACT_RETURN_VALUE):
>
> * value.h (value_being_returned): Change regbuf parameter type to
> ``struct retbuf''.
>
> * inferior.h (run_stack_dummy): Change retbuf parameter type to
> ``struct regbuf''.
>
> * valops.c (hand_function_call): Make retbuf a ``struct regbuf''.
>
> * blockframe.c (generic_pop_dummy_frame): Use
> regcache_restore_no_writethrough and regbuf_xfree.
>
> * regcache.c (regcache_restore_no_writethrough): New function.
> (regcache_save): New function.
> * regcache.h (regcache_save): Declare.
> (regcache_restore_no_writethrough): Declare.
>
> * blockframe.c (generic_pop_dummy_frame): Use regbuf_xfree and
> regcache_restore_regbuf.
> (generic_get_saved_register): Use regbuf_read.
>
>
> * blockframe.c: Include "regbuf.h".
> (generic_push_dummy_frame): Use regbuf_xfree and regcache_save.
>
> * frame.h (generic_find_dummy_frame): Change return type to
> ``struct regbuf''.
>
> * Makefile.in (blockframe.o): Add dependency on $(regbuf_h).
>
> * blockframe.c (struct dummy_frame): Replace registers with
> regbuf.
> (generic_find_dummy_frame): Change return type to `struct regbuf',
> return regbuf.
> (generic_read_register_dummy): Rewrite using
> regbuf_read_as_address.
>
> * regcache.c: Include "regbuf.h".
> (_initialize_regcache): Register regcache_regbuf for swapping.
> (regcache_regbuf): Define.
> (build_regcache): Rewrite using regbuf_xmalloc,
> grub_around_regbuf_for_registers and
> grub_around_regbuf_for_register_valid.
>
> * Makefile.in (regcache.o): Add $(regbuf_h).
>
> * defs.h (XCALLOC): Define.
> * regbuf.c, regbuf.c: New files.
> * Makefile.in (SFILES): Add regbuf.c.
> (regbuf_h): Define.
> (COMMON_OBS): Add regbuf.o.
> (regbuf.o): Specify dependencies.
>
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.180
diff -r1.180 Makefile.in
533c533
< findvar.c regcache.c gdbarch.c arch-utils.c gdbtypes.c \
---
> findvar.c regcache.c regbuf.c gdbarch.c arch-utils.c gdbtypes.c \
637a638
> regbuf_h = regbuf.h
718c719
< signals.o \
---
> signals.o regbuf.o \
1292c1293
< $(objfiles_h) $(symfile_h) $(target_h) $(regcache_h)
---
> $(objfiles_h) $(symfile_h) $(target_h) $(regcache_h) $(regbuf_h)
1444c1445,1448
< regcache.o: regcache.c $(defs_h) $(inferior_h) $(target_h) $(regcache_h)
---
> regbuf.o: regbuf.c $(defs_h) $(regbuf_h) gdb_assert.h
>
> regcache.o: regcache.c $(defs_h) $(inferior_h) $(target_h) $(regcache_h) \
> $(regbuf_h)
1656c1660
< $(ui_out_h) $(completer_h)
---
> $(ui_out_h) $(completer_h) $(regbuf_h)
1665,1667c1669,1671
< $(gdbcore_h) $(value_h) \
< $(inferior_h) $(target_h) $(gdbthread_h) $(gdb_string_h) $(event_loop_h) \
< $(event_top_h) $(regcache_h)
---
> $(gdbcore_h) $(value_h) $(inferior_h) $(target_h) $(gdbthread_h) \
> $(gdb_string_h) $(event_loop_h) $(event_top_h) $(regcache_h) \
> $(regbuf_h)
1999c2003,2004
< $(target_h) ppc-tdep.h $(regcache_h) $(value_h) $(parser_defs_h)
---
> $(target_h) ppc-tdep.h $(regcache_h) $(value_h) $(parser_defs_h) \
> $(regbuf_h)
Index: blockframe.c
===================================================================
RCS file: /cvs/src/src/gdb/blockframe.c,v
retrieving revision 1.27
diff -r1.27 blockframe.c
36a37
> #include "regbuf.h"
1072c1073
< char *registers;
---
> struct regbuf *regbuf;
1089c1090
< char *
---
> struct regbuf *
1101c1102
< return dummyframe->registers;
---
> return dummyframe->regbuf;
1134c1135
< char *dummy_regs = generic_find_dummy_frame (pc, fp);
---
> struct regbuf *dummy_regs = generic_find_dummy_frame (pc, fp);
1137,1138c1138
< return extract_address (&dummy_regs[REGISTER_BYTE (regno)],
< REGISTER_RAW_SIZE (regno));
---
> return regbuf_read_as_address (dummy_regs, regno);
1165c1165
< xfree (dummy_frame->registers);
---
> regbuf_xfree (dummy_frame->regbuf);
1173c1173,1174
< dummy_frame->registers = xmalloc (REGISTER_BYTES);
---
> dummy_frame->regbuf = regbuf_xmalloc (current_gdbarch);
> regcache_save (dummy_frame->regbuf);
1179d1179
< read_register_bytes (0, dummy_frame->registers, REGISTER_BYTES);
1227c1227
< write_register_bytes (0, dummy_frame->registers, REGISTER_BYTES);
---
> regcache_restore (dummy_frame->regbuf);
1230c1230
< xfree (dummy_frame->registers);
---
> regbuf_xfree (dummy_frame->regbuf);
1323,1326c1323,1324
< memcpy (raw_buffer,
< generic_find_dummy_frame (frame->pc, frame->frame) +
< REGISTER_BYTE (regnum),
< REGISTER_RAW_SIZE (regnum));
---
> regbuf_read (generic_find_dummy_frame (frame->pc, frame->frame),
> regnum, raw_buffer);
Index: defs.h
===================================================================
RCS file: /cvs/src/src/gdb/defs.h,v
retrieving revision 1.88
diff -r1.88 defs.h
839c839
< /* Utility macro to allocate typed memory. Avoids errors like
---
> /* Utility macros to allocate typed memory. Avoids errors like
842a843
> #define XCALLOC(NR, TYPE) ((TYPE*) xcalloc ((NR), sizeof (TYPE)));
Index: frame.h
===================================================================
RCS file: /cvs/src/src/gdb/frame.h,v
retrieving revision 1.17
diff -r1.17 frame.h
271c271
< extern char *generic_find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp);
---
> extern struct regbuf *generic_find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp);
Index: gdbarch.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.c,v
retrieving revision 1.123
diff -r1.123 gdbarch.c
3680c3680
< gdbarch_extract_return_value (struct gdbarch *gdbarch, struct type *type, char *regbuf, char *valbuf)
---
> gdbarch_extract_return_value (struct gdbarch *gdbarch, struct type *type, struct regbuf *regbuf, char *valbuf)
3827c3827
< gdbarch_extract_struct_value_address (struct gdbarch *gdbarch, char *regbuf)
---
> gdbarch_extract_struct_value_address (struct gdbarch *gdbarch, struct regbuf *regbuf)
Index: gdbarch.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.h,v
retrieving revision 1.91
diff -r1.91 gdbarch.h
48a49
> struct regbuf;
1430,1431c1431,1432
< typedef void (gdbarch_extract_return_value_ftype) (struct type *type, char *regbuf, char *valbuf);
< extern void gdbarch_extract_return_value (struct gdbarch *gdbarch, struct type *type, char *regbuf, char *valbuf);
---
> typedef void (gdbarch_extract_return_value_ftype) (struct type *type, struct regbuf *regbuf, char *valbuf);
> extern void gdbarch_extract_return_value (struct gdbarch *gdbarch, struct type *type, struct regbuf *regbuf, char *valbuf);
1569,1570c1570,1571
< typedef CORE_ADDR (gdbarch_extract_struct_value_address_ftype) (char *regbuf);
< extern CORE_ADDR gdbarch_extract_struct_value_address (struct gdbarch *gdbarch, char *regbuf);
---
> typedef CORE_ADDR (gdbarch_extract_struct_value_address_ftype) (struct regbuf *regbuf);
> extern CORE_ADDR gdbarch_extract_struct_value_address (struct gdbarch *gdbarch, struct regbuf *regbuf);
Index: gdbarch.sh
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.sh,v
retrieving revision 1.134
diff -r1.134 gdbarch.sh
531c531
< f:2:EXTRACT_RETURN_VALUE:void:extract_return_value:struct type *type, char *regbuf, char *valbuf:type, regbuf, valbuf::0:0
---
> f:2:EXTRACT_RETURN_VALUE:void:extract_return_value:struct type *type, struct regbuf *regbuf, char *valbuf:type, regbuf, valbuf::0:0
539c539
< F:2:EXTRACT_STRUCT_VALUE_ADDRESS:CORE_ADDR:extract_struct_value_address:char *regbuf:regbuf:::0
---
> F:2:EXTRACT_STRUCT_VALUE_ADDRESS:CORE_ADDR:extract_struct_value_address:struct regbuf *regbuf:regbuf:::0
764a765
> struct regbuf;
Index: infcmd.c
===================================================================
RCS file: /cvs/src/src/gdb/infcmd.c,v
retrieving revision 1.46
diff -r1.46 infcmd.c
42a43
> #include "regbuf.h"
972c973
< run_stack_dummy (CORE_ADDR addr, char *buffer)
---
> run_stack_dummy (CORE_ADDR addr, struct regbuf **buffer)
1045,1046c1046
<
< memcpy (buffer, stop_registers, REGISTER_BYTES);
---
> *buffer = regbuf_dup (stop_registers);
Index: inferior.h
===================================================================
RCS file: /cvs/src/src/gdb/inferior.h,v
retrieving revision 1.27
diff -r1.27 inferior.h
26a27
> struct regbuf;
156c157
< extern int run_stack_dummy (CORE_ADDR, char *);
---
> extern int run_stack_dummy (CORE_ADDR, struct regbuf **retbuf);
399c400
< extern char *stop_registers;
---
> extern struct regbuf *stop_registers;
Index: infrun.c
===================================================================
RCS file: /cvs/src/src/gdb/infrun.c,v
retrieving revision 1.58
diff -r1.58 infrun.c
44a45
> #include "regbuf.h"
65,68d65
< static struct inferior_status *xmalloc_inferior_status (void);
<
< static void free_inferior_status (struct inferior_status *);
<
344c341
< char *stop_registers;
---
> struct regbuf *stop_registers;
3508c3505
< read_register_bytes (0, stop_registers, REGISTER_BYTES);
---
> regcache_save (stop_registers);
3914c3911
< char *stop_registers;
---
> struct regbuf *stop_registers;
3919c3916
< char *registers;
---
> struct regbuf *registers;
3927,3944d3923
< static struct inferior_status *
< xmalloc_inferior_status (void)
< {
< struct inferior_status *inf_status;
< inf_status = xmalloc (sizeof (struct inferior_status));
< inf_status->stop_registers = xmalloc (REGISTER_BYTES);
< inf_status->registers = xmalloc (REGISTER_BYTES);
< return inf_status;
< }
<
< static void
< free_inferior_status (struct inferior_status *inf_status)
< {
< xfree (inf_status->registers);
< xfree (inf_status->stop_registers);
< xfree (inf_status);
< }
<
3952c3931
< memcpy (&inf_status->registers[REGISTER_BYTE (regno)], buf, size);
---
> regbuf_write (inf_status->registers, regno, buf);
3962c3941
< struct inferior_status *inf_status = xmalloc_inferior_status ();
---
> struct inferior_status *inf_status = XMALLOC (struct inferior_status);
3986,3988c3965,3967
< memcpy (inf_status->stop_registers, stop_registers, REGISTER_BYTES);
<
< read_register_bytes (0, inf_status->registers, REGISTER_BYTES);
---
> inf_status->stop_registers = regbuf_dup (stop_registers);
> inf_status->registers = regbuf_xmalloc (current_gdbarch);
> regcache_save (inf_status->registers);
4052,4053c4031,4033
< /* FIXME: Is the restore of stop_registers always needed */
< memcpy (stop_registers, inf_status->stop_registers, REGISTER_BYTES);
---
> /* FIXME: Is the restore of stop_registers always needed? */
> regbuf_xfree (stop_registers);
> stop_registers = inf_status->stop_registers;
4058c4038,4039
< write_register_bytes (0, inf_status->registers, REGISTER_BYTES);
---
> regcache_restore (inf_status->registers);
> regbuf_xfree (inf_status->registers);
4086c4067
< free_inferior_status (inf_status);
---
> xfree (inf_status);
4106c4087,4089
< free_inferior_status (inf_status);
---
> regbuf_xfree (inf_status->registers);
> regbuf_xfree (inf_status->stop_registers);
> xfree (inf_status);
4197c4180
< stop_registers = xmalloc (REGISTER_BYTES);
---
> stop_registers = regbuf_xmalloc (current_gdbarch);
4206,4207d4188
<
< build_infrun ();
Index: regbuf.c
===================================================================
RCS file: regbuf.c
diff -N regbuf.c
0a1,221
> /* Register buffer sufficient to hold all raw registers
>
> Copyright 2002 Free Software Foundation, Inc.
>
> This file is part of GDB.
>
> Contributed by Red Hat, Inc.
>
> This program is free software; you can redistribute it and/or modify
> it under the terms of the GNU General Public License as published by
> the Free Software Foundation; either version 2 of the License, or
> (at your option) any later version.
>
> This program is distributed in the hope that it will be useful,
> but WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> GNU General Public License for more details.
>
> You should have received a copy of the GNU General Public License
> along with this program; if not, write to the Free Software
> Foundation, Inc., 59 Temple Place - Suite 330,
> Boston, MA 02111-1307, USA. */
>
> #include "defs.h"
> #include "regbuf.h"
> #include "gdb_assert.h"
>
> extern void _initialize_regbuf (void);
>
> /* Per-architecture object describing the layout of a register buffer.
> Computed once when the architecture is created */
>
> struct gdbarch_data *regbuf_data_handle;
>
> struct regbuf_descr
> {
> struct gdbarch *gdbarch;
> /* Size of the register buffer, over-allocate making room for both
> real and pseudo-registers. */
> /* FIXME: cagney/2002-05-11: This over-allocation shouldn't be
> necessary, only some targets store values in the pseudo-register
> section and we want to be sure that GDB won't trash memory. */
> long sizeof_registers;
> /* Total number of registers in the buffer. */
> int nr_registers;
> /* Offset into the register buffer for each register. */
> long *register_offset;
> /* Size, in ``bytes'', of a register. */
> long *sizeof_register;
> };
>
> static struct regbuf_descr *
> regbuf_descr (struct gdbarch *gdbarch)
> {
> int i;
> /* FIXME: cagney/2002-05-11: gdbarch_data() should take that
> ``gdbarch'' as a parameter. */
> struct regbuf_descr *descr = gdbarch_data (/* gdbarch, */
> regbuf_data_handle);
> if (descr != NULL)
> return descr;
>
> descr = XMALLOC (struct regbuf_descr);
> descr->gdbarch = gdbarch;
> /* FIXME: cagney/2002-05-11: Shouldn't be including pseudo-registers
> in the register buffer. Unfortunatly some architectures are
> storing pseudo register values in the raw register buffer. */
> descr->nr_registers = NUM_REGS + NUM_PSEUDO_REGS;
> /* FIXME: cagney/2002-05-11: Instead of using REGISTER_BYTE() this
> should compute, at runtime, an offset table describing where each
> register is in the register table. This currently isn't possible
> because some targets overlap registers, ulgh! */
> descr->register_offset = XCALLOC (descr->nr_registers, long);
> descr->sizeof_register = XCALLOC (descr->nr_registers, long);
> for (i = 0; i < descr->nr_registers; i++)
> {
> descr->register_offset[i] = REGISTER_BYTE (i);
> descr->sizeof_register[i] = REGISTER_RAW_SIZE (i);
> }
> /* Come up with the real size of the registers buffer. */
> descr->sizeof_registers = REGISTER_BYTES; /* OK use. */
> for (i = 0; i < descr->nr_registers; i++)
> {
> long regend;
> /* Keep extending the buffer so that there is always enough
> space for all registers. The comparison is necessary since
> legacy code is free to put registers in random places in the
> buffer separated by holes. Once REGISTER_BYTE() is killed
> this can be greatly simplified. */
> /* FIXME: cagney/2001-12-04: This code shouldn't need to use
> REGISTER_BYTE(). Unfortunatly, legacy code likes to lay the
> buffer out so that certain registers just happen to overlap.
> Ulgh! New targets use gdbarch's register read/write and
> entirely avoid this uglyness. */
> regend = descr->register_offset[i] + descr->sizeof_register[i];
> if (descr->sizeof_registers < regend)
> descr->sizeof_registers = regend;
> }
> set_gdbarch_data (gdbarch, regbuf_data_handle, descr);
> return descr;
> }
>
> static void
> xfree_regbuf (struct gdbarch *gdbarch, void *ptr)
> {
> struct regbuf_descr *descr = ptr;
> if (descr == NULL)
> return;
> xfree (descr->register_offset);
> xfree (descr->sizeof_register);
> xfree (descr);
> }
>
> /* For moment, ``struct regbuf'' is just a character buffer. */
>
> struct regbuf
> {
> struct regbuf_descr *descr;
> char *registers;
> char *valid_p;
> };
>
> struct regbuf *
> regbuf_xmalloc (struct gdbarch *gdbarch)
> {
> struct regbuf_descr *descr = regbuf_descr (gdbarch);
> struct regbuf *regbuf = XMALLOC (struct regbuf);
> regbuf->descr = descr;
> regbuf->registers = xmalloc (descr->sizeof_registers);
> regbuf->valid_p = xmalloc (descr->nr_registers);
> return regbuf;
> }
>
> void
> regbuf_xfree (struct regbuf *regbuf)
> {
> gdb_assert (regbuf != NULL);
> xfree (regbuf->registers);
> xfree (regbuf->valid_p);
> xfree (regbuf);
> }
>
> void
> do_regbuf_xfree (void *buf)
> {
> regbuf_xfree (buf);
> }
>
> struct regbuf *
> regbuf_xmalloc_with_cleanup (struct gdbarch *gdbarch)
> {
> struct regbuf *regbuf = regbuf_xmalloc (gdbarch);
> make_cleanup (do_regbuf_xfree, regbuf);
> return regbuf;
> }
>
> struct regbuf *
> regbuf_dup (struct regbuf *regbuf)
> {
> struct regbuf *newbuf = regbuf_xmalloc (regbuf->descr->gdbarch);
> memcpy (newbuf->registers, regbuf->registers,
> regbuf->descr->sizeof_registers);
> memcpy (newbuf->valid_p, regbuf->valid_p, regbuf->descr->nr_registers);
> return newbuf;
> }
>
> int
> regbuf_valid_p (struct regbuf *regbuf, int regnum)
> {
> gdb_assert (regnum != NULL);
> gdb_assert (regnum >= 0 && regnum < NUM_REGS + NUM_PSEUDO_REGS);
> return regbuf->valid_p[regnum];
> }
>
> void
> regbuf_read (struct regbuf *regbuf, int regnum, void *buf)
> {
> gdb_assert (regbuf != NULL);
> gdb_assert (regnum >= 0 && regnum < regbuf->descr->nr_registers);
> memcpy (buf, regbuf->registers + regbuf->descr->register_offset[regnum],
> regbuf->descr->sizeof_register[regnum]);
> }
>
> void
> regbuf_write (struct regbuf *regbuf, int regnum, const void *buf)
> {
> gdb_assert (regbuf != NULL);
> gdb_assert (regnum >= 0 && regnum < regbuf->descr->nr_registers);
> memcpy (regbuf->registers + regbuf->descr->register_offset[regnum], buf,
> regbuf->descr->sizeof_register[regnum]);
> regbuf->valid_p[regnum] = 1;
> }
>
> CORE_ADDR
> regbuf_read_as_address (struct regbuf *regbuf, int regnum)
> {
> char *buf;
> gdb_assert (regbuf != NULL);
> gdb_assert (regnum >= 0 && regnum < regbuf->descr->nr_registers);
> buf = alloca (regbuf->descr->sizeof_register[regnum]);
> regbuf_read (regbuf, regnum, buf);
> return extract_address (buf, regbuf->descr->sizeof_register[regnum]);
> }
>
> char *
> grub_around_regbuf_for_registers (struct regbuf *regbuf)
> {
> return regbuf->registers;
> }
>
> char *
> grub_around_regbuf_for_register_valid (struct regbuf *regbuf)
> {
> return regbuf->valid_p;
> }
>
> void
> _initialize_regbuf (void)
> {
> regbuf_data_handle = register_gdbarch_data (NULL, xfree_regbuf);
> }
Index: regbuf.h
===================================================================
RCS file: regbuf.h
diff -N regbuf.h
0a1,59
> /* Register buffer sufficient to hold all raw registers
>
> Copyright 2002 Free Software Foundation, Inc.
>
> This file is part of GDB.
>
> Contributed by Red Hat, Inc.
>
> This program is free software; you can redistribute it and/or modify
> it under the terms of the GNU General Public License as published by
> the Free Software Foundation; either version 2 of the License, or
> (at your option) any later version.
>
> This program is distributed in the hope that it will be useful,
> but WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> GNU General Public License for more details.
>
> You should have received a copy of the GNU General Public License
> along with this program; if not, write to the Free Software
> Foundation, Inc., 59 Temple Place - Suite 330,
> Boston, MA 02111-1307, USA. */
>
> #ifndef REGBUF_H
> #define REGBUF_H
>
> struct regbuf;
>
> /* Create/destroy the register buffer. */
>
> extern struct regbuf *regbuf_xmalloc (struct gdbarch *gdbarch);
> extern void regbuf_xfree (struct regbuf *regbuf);
> extern struct regbuf *regbuf_xmalloc_with_cleanup (struct gdbarch *gdbarch);
>
> /* Duplicate a regbuf and all contents. */
>
> extern struct regbuf *regbuf_dup (struct regbuf *regbuf);
>
> /* Is the regbuf entry valid. */
>
> int regbuf_valid_p (struct regbuf *regbuf, int regnum);
>
> /* Access the register buffer. */
>
> extern void regbuf_read (struct regbuf *regbuf, int rawnum, void *buf);
> extern void regbuf_write (struct regbuf *regbuf, int rawnum, const void *buf);
>
> /* Convenience routines for reading/writing registers using an
> internal format. */
>
> extern CORE_ADDR regbuf_read_as_address (struct regbuf *regbuf, int regnum);
>
> /* FIXME: cagney/2002-05-11: This is here simply to prop up the
> `registers' and `register_valid' global arrays. */
>
> extern char *grub_around_regbuf_for_registers (struct regbuf *regbuf);
> extern char *grub_around_regbuf_for_register_valid (struct regbuf *regbuf);
>
> #endif /* REGBUF_H */
Index: regcache.c
===================================================================
RCS file: /cvs/src/src/gdb/regcache.c,v
retrieving revision 1.34
diff -r1.34 regcache.c
28a29
> #include "regbuf.h"
35a37,42
> /* Global structure containing the current regbuf. */
> /* FIXME: cagney/2002-05-11: The two global arrays registers[] and
> register_valid[] currently point into this structure. */
>
> struct regbuf *regcache_regbuf;
>
754,779c761,788
< int i;
< int sizeof_register_valid;
< /* Come up with the real size of the registers buffer. */
< int sizeof_registers = REGISTER_BYTES; /* OK use. */
< for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
< {
< long regend;
< /* Keep extending the buffer so that there is always enough
< space for all registers. The comparison is necessary since
< legacy code is free to put registers in random places in the
< buffer separated by holes. Once REGISTER_BYTE() is killed
< this can be greatly simplified. */
< /* FIXME: cagney/2001-12-04: This code shouldn't need to use
< REGISTER_BYTE(). Unfortunatly, legacy code likes to lay the
< buffer out so that certain registers just happen to overlap.
< Ulgh! New targets use gdbarch's register read/write and
< entirely avoid this uglyness. */
< regend = REGISTER_BYTE (i) + REGISTER_RAW_SIZE (i);
< if (sizeof_registers < regend)
< sizeof_registers = regend;
< }
< registers = xmalloc (sizeof_registers);
< sizeof_register_valid = ((NUM_REGS + NUM_PSEUDO_REGS)
< * sizeof (*register_valid));
< register_valid = xmalloc (sizeof_register_valid);
< memset (register_valid, 0, sizeof_register_valid);
---
> regcache_regbuf = regbuf_xmalloc (current_gdbarch);
> registers = grub_around_regbuf_for_registers (regcache_regbuf);
> register_valid = grub_around_regbuf_for_register_valid (regcache_regbuf);
> }
>
> void
> regcache_save (struct regbuf *regbuf)
> {
> /* FIXME: cagney/2002-05-11: This assumes that the current
> architecture and the regbuf architecture are identical. */
> char *regbuf_registers = grub_around_regbuf_for_registers (regbuf);
> char *regbuf_register_valid = grub_around_regbuf_for_register_valid (regbuf);
> memcpy (regbuf_registers, registers, REGISTER_BYTES);
> memcpy (regbuf_register_valid, register_valid, NUM_REGS + NUM_PSEUDO_REGS);
> }
>
> void
> regcache_restore (struct regbuf *regbuf)
> {
> char *regbuf_registers = grub_around_regbuf_for_registers (regbuf);
> write_register_bytes (0, regbuf_registers, REGISTER_BYTES);
> }
>
> void
> regcache_restore_no_writethrough (struct regbuf *regbuf)
> {
> char *regbuf_registers = grub_around_regbuf_for_registers (regbuf);
> memcpy (registers, regbuf_registers, REGISTER_BYTES);
784a794
> REGISTER_GDBARCH_SWAP (regcache_regbuf);
Index: regcache.h
===================================================================
RCS file: /cvs/src/src/gdb/regcache.h,v
retrieving revision 1.6
diff -r1.6 regcache.h
24a25,26
> struct regbuf;
>
48a51,58
>
> /* 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. */
>
> extern void regcache_save (struct regbuf *regbuf);
> extern void regcache_restore (struct regbuf *regbufx);
> extern void regcache_restore_no_writethrough (struct regbuf *regbufx);
Index: rs6000-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v
retrieving revision 1.63
diff -r1.63 rs6000-tdep.c
48a49,50
> #include "regbuf.h" /* For grub_around_regbuf_for_registers. */
>
1146c1148,1149
< rs6000_extract_return_value (struct type *valtype, char *regbuf, char *valbuf)
---
> rs6000_extract_return_value (struct type *valtype, struct regbuf *regs,
> char *valbuf)
1149a1153
> char *regbuf = grub_around_regbuf_for_registers (regs);
1950c1954
< rs6000_extract_struct_value_address (char *regbuf)
---
> rs6000_extract_struct_value_address (struct regbuf *regs)
1951a1956
> /* FIXME: cagney/2002-05-11: This global variable is just a hack! */
Index: valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.56
diff -r1.56 valops.c
1675c1675
< char *retbuf = (char*) alloca (REGISTER_BYTES);
---
> struct regbuf *retbuf = NULL;
1707c1707
< rc = run_stack_dummy (real_pc + CALL_DUMMY_START_OFFSET, retbuf);
---
> rc = run_stack_dummy (real_pc + CALL_DUMMY_START_OFFSET, &retbuf);
Index: value.h
===================================================================
RCS file: /cvs/src/src/gdb/value.h,v
retrieving revision 1.29
diff -r1.29 value.h
25a26,27
> struct regbuf;
>
412c414,415
< char *retbuf, int struct_return);
---
> struct regbuf *retbuf,
> int struct_return);
Index: values.c
===================================================================
RCS file: /cvs/src/src/gdb/values.c,v
retrieving revision 1.34
diff -r1.34 values.c
1316c1316,1317
< value_being_returned (struct type *valtype, char *retbuf, int struct_return)
---
> value_being_returned (struct type *valtype, struct regbuf *retbuf,
> int struct_return)
Index: mi/ChangeLog
===================================================================
RCS file: /cvs/src/src/gdb/mi/ChangeLog,v
retrieving revision 1.65
diff -r1.65 ChangeLog
0a1,7
> 2002-05-11 Andrew Cagney <ac131313@redhat.com>
>
> * mi-main.c: Include "regbuf.h".
> (old_regs): Change type of old_regs to a regbuf.
> (register_changed_p): Use regbuf_read and regbuf_write.
> (setup_architecture_data): Use regbuf_xmalloc.
>
Index: mi/mi-main.c
===================================================================
RCS file: /cvs/src/src/gdb/mi/mi-main.c,v
retrieving revision 1.29
diff -r1.29 mi-main.c
43a44
> #include "regbuf.h"
58c59
< static char *old_regs;
---
> static struct regbuf *old_regs;
369a371
> char *old_buffer = alloca (MAX_REGISTER_RAW_SIZE);
373,375c375,376
<
< if (memcmp (&old_regs[REGISTER_BYTE (regnum)], raw_buffer,
< REGISTER_RAW_SIZE (regnum)) == 0)
---
> regbuf_read (old_regs, regnum, old_buffer);
> if (memcmp (old_buffer, raw_buffer, REGISTER_RAW_SIZE (regnum)) == 0)
378,382c379,380
< /* Found a changed register. Return 1. */
<
< memcpy (&old_regs[REGISTER_BYTE (regnum)], raw_buffer,
< REGISTER_RAW_SIZE (regnum));
<
---
> /* Found a changed register. Update the buffer and return 1. */
> regbuf_write (old_regs, regnum, raw_buffer);
1476,1478c1474
< /* don't trust REGISTER_BYTES to be zero. */
< old_regs = xmalloc (REGISTER_BYTES + 1);
< memset (old_regs, 0, REGISTER_BYTES + 1);
---
> old_regs = regbuf_xmalloc (current_gdbarch);