This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
Re: [rfc] Regcache revamp (vip)
I checked in the attached. Take care!!
Andrew
2001-03-23 Andrew Cagney <ac131313@redhat.com>
* gdbarch.sh (gdbarch_register_read, gdbarch_register_write): Add.
* gdbarch.h, gdbarch.c: Regenerate.
* regcache.h (regcache_read, regcache_write): Declare.
(registers, register_valid, register_buffer): Add note that these
interfaces are deprecated.
* regcache.c: Include "gdb_assert.h".
(legacy_write_register_gen): Rename write_register_gen.
(legacy_read_register_gen): Rename read_register_gen.
(regcache_read, regcache_write): New function.
(read_register_gen, write_register_gen): New function.
(write_register): Simplify. Use write_register_gen.
(read_register): Ditto using read_register_gen.
(read_signed_register): Ditto.
(read_register_bytes): Ditto!!!!
(supply_register): Add note that CLEANUP_REGISTER_VALUE is being
replaced by gdbarch_register_read.
* TODO (GDB 5.2 - Cleanups): Add list of gdbarch methods to
deprecate.
Index: TODO
===================================================================
RCS file: /cvs/src/src/gdb/TODO,v
retrieving revision 1.69
diff -p -r1.69 TODO
*** TODO 2001/03/23 01:14:10 1.69
--- TODO 2001/03/24 01:22:55
*************** Eliminate all warnings for at least one
*** 305,310 ****
--- 305,362 ----
--
+ Deprecate, if not delete, the following:
+
+ register[]
+ register_valid[]
+ register_buffer()
+ REGISTER_BYTE()
+ Replaced by, on the target side
+ supply_register()
+ and on core-gdb side:
+ {read,write}_register_gen()
+ Remote.c will need to use something
+ other than REGISTER_BYTE() and
+ REGISTER_RAW_SIZE() when unpacking
+ [gG] packets.
+
+ STORE_PSEUDO_REGISTER
+ FETCH_PSEUDO_REGISTER
+ Now handed by the methods
+ gdbarch_{read,write}_register()
+ which sits between core GDB and
+ the register cache.
+
+ REGISTER_CONVERTIBLE
+ REGISTER_CONVERT_TO_RAW
+ REGISTER_CONVERT_TO_VIRTUAL
+ I think these three are redundant.
+ gdbarch_register_{read,write} can
+ do any conversion it likes.
+
+ REGISTER_VIRTUAL_SIZE
+ MAX_REGISTER_VIRTUAL_SIZE
+ REGISTER_VIRTUAL_TYPE
+ I think these can be replaced by
+ the pair:
+ FRAME_REGISTER_TYPE(frame, regnum)
+ REGISTER_TYPE(regnum)
+
+ DO_REGISTERS_INFO
+ Replace with
+ FRAME_REGISTER_INFO (frame, ...)
+
+ REGISTER_SIM_REGNO()
+ If nothing else rename this so that
+ how it relates to rawreg and the
+ regnum is clear.
+
+ REGISTER_BYTES
+ The size of the cache can be computed
+ on the fly.
+
+ --
+
Restructure gdb directory tree so that it avoids any 8.3 and 14
filename problems.
Index: gdbarch.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.c,v
retrieving revision 1.54
diff -p -r1.54 gdbarch.c
*** gdbarch.c 2001/02/08 06:03:53 1.54
--- gdbarch.c 2001/03/24 01:22:57
*************** struct gdbarch
*** 149,154 ****
--- 149,156 ----
gdbarch_write_fp_ftype *write_fp;
gdbarch_read_sp_ftype *read_sp;
gdbarch_write_sp_ftype *write_sp;
+ gdbarch_register_read_ftype *register_read;
+ gdbarch_register_write_ftype *register_write;
int num_regs;
int num_pseudo_regs;
int sp_regnum;
*************** struct gdbarch startup_gdbarch =
*** 321,326 ****
--- 323,330 ----
0,
0,
0,
+ 0,
+ 0,
generic_get_saved_register,
0,
0,
*************** verify_gdbarch (struct gdbarch *gdbarch)
*** 512,517 ****
--- 516,523 ----
/* Skip verify of write_fp, invalid_p == 0 */
/* Skip verify of read_sp, invalid_p == 0 */
/* Skip verify of write_sp, invalid_p == 0 */
+ /* Skip verify of register_read, has predicate */
+ /* Skip verify of register_write, has predicate */
if ((GDB_MULTI_ARCH >= 2)
&& (gdbarch->num_regs == -1))
internal_error (__FILE__, __LINE__,
*************** gdbarch_dump (struct gdbarch *gdbarch, s
*** 1534,1539 ****
--- 1540,1553 ----
(long) current_gdbarch->write_sp
/*TARGET_WRITE_SP ()*/);
#endif
+ if (GDB_MULTI_ARCH)
+ fprintf_unfiltered (file,
+ "gdbarch_dump: register_read = 0x%08lx\n",
+ (long) current_gdbarch->register_read);
+ if (GDB_MULTI_ARCH)
+ fprintf_unfiltered (file,
+ "gdbarch_dump: register_write = 0x%08lx\n",
+ (long) current_gdbarch->register_write);
#ifdef NUM_REGS
fprintf_unfiltered (file,
"gdbarch_dump: NUM_REGS = %ld\n",
*************** set_gdbarch_write_sp (struct gdbarch *gd
*** 2449,2454 ****
--- 2463,2516 ----
gdbarch_write_sp_ftype write_sp)
{
gdbarch->write_sp = write_sp;
+ }
+
+ int
+ gdbarch_register_read_p (struct gdbarch *gdbarch)
+ {
+ return gdbarch->register_read != 0;
+ }
+
+ void
+ gdbarch_register_read (struct gdbarch *gdbarch, int regnum, char *buf)
+ {
+ if (gdbarch->register_read == 0)
+ internal_error (__FILE__, __LINE__,
+ "gdbarch: gdbarch_register_read invalid");
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_register_read called\n");
+ gdbarch->register_read (gdbarch, regnum, buf);
+ }
+
+ void
+ set_gdbarch_register_read (struct gdbarch *gdbarch,
+ gdbarch_register_read_ftype register_read)
+ {
+ gdbarch->register_read = register_read;
+ }
+
+ int
+ gdbarch_register_write_p (struct gdbarch *gdbarch)
+ {
+ return gdbarch->register_write != 0;
+ }
+
+ void
+ gdbarch_register_write (struct gdbarch *gdbarch, int regnum, char *buf)
+ {
+ if (gdbarch->register_write == 0)
+ internal_error (__FILE__, __LINE__,
+ "gdbarch: gdbarch_register_write invalid");
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_register_write called\n");
+ gdbarch->register_write (gdbarch, regnum, buf);
+ }
+
+ void
+ set_gdbarch_register_write (struct gdbarch *gdbarch,
+ gdbarch_register_write_ftype register_write)
+ {
+ gdbarch->register_write = register_write;
}
int
Index: gdbarch.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.h,v
retrieving revision 1.44
diff -p -r1.44 gdbarch.h
*** gdbarch.h 2001/03/21 19:47:44 1.44
--- gdbarch.h 2001/03/24 01:22:57
*************** extern void set_gdbarch_write_sp (struct
*** 339,344 ****
--- 339,356 ----
#endif
#endif
+ extern int gdbarch_register_read_p (struct gdbarch *gdbarch);
+
+ typedef void (gdbarch_register_read_ftype) (struct gdbarch *gdbarch, int regnum, char *buf);
+ extern void gdbarch_register_read (struct gdbarch *gdbarch, int regnum, char *buf);
+ extern void set_gdbarch_register_read (struct gdbarch *gdbarch, gdbarch_register_read_ftype *register_read);
+
+ extern int gdbarch_register_write_p (struct gdbarch *gdbarch);
+
+ typedef void (gdbarch_register_write_ftype) (struct gdbarch *gdbarch, int regnum, char *buf);
+ extern void gdbarch_register_write (struct gdbarch *gdbarch, int regnum, char *buf);
+ extern void set_gdbarch_register_write (struct gdbarch *gdbarch, gdbarch_register_write_ftype *register_write);
+
extern int gdbarch_num_regs (struct gdbarch *gdbarch);
extern void set_gdbarch_num_regs (struct gdbarch *gdbarch, int num_regs);
#if GDB_MULTI_ARCH
Index: gdbarch.sh
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.sh,v
retrieving revision 1.57
diff -p -r1.57 gdbarch.sh
*** gdbarch.sh 2001/03/21 19:47:44 1.57
--- gdbarch.sh 2001/03/24 01:23:12
*************** f::TARGET_WRITE_FP:void:write_fp:CORE_AD
*** 383,388 ****
--- 383,391 ----
f::TARGET_READ_SP:CORE_ADDR:read_sp:void:::0:generic_target_read_sp::0
f::TARGET_WRITE_SP:void:write_sp:CORE_ADDR val:val::0:generic_target_write_sp::0
#
+ M:::void:register_read:int regnum, char *buf:regnum, buf:
+ M:::void:register_write:int regnum, char *buf:regnum, buf:
+ #
v:2:NUM_REGS:int:num_regs::::0:-1
# This macro gives the number of pseudo-registers that live in the
# register namespace but do not get fetched or stored on the target.
Index: regcache.c
===================================================================
RCS file: /cvs/src/src/gdb/regcache.c,v
retrieving revision 1.20
diff -p -r1.20 regcache.c
*** regcache.c 2001/03/13 23:31:14 1.20
--- regcache.c 2001/03/24 01:23:13
***************
*** 26,31 ****
--- 26,32 ----
#include "gdbarch.h"
#include "gdbcmd.h"
#include "regcache.h"
+ #include "gdb_assert.h"
/*
* DATA STRUCTURE
*************** registers_fetched (void)
*** 213,266 ****
into memory at MYADDR. */
void
! read_register_bytes (int inregbyte, char *myaddr, int inlen)
{
! int inregend = inregbyte + inlen;
int regnum;
- if (registers_pid != inferior_pid)
- {
- registers_changed ();
- registers_pid = inferior_pid;
- }
-
/* See if we are trying to read bytes from out-of-date registers. If so,
update just those registers. */
for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++)
{
! int regstart, regend;
!
! if (register_cached (regnum))
! continue;
if (REGISTER_NAME (regnum) == NULL || *REGISTER_NAME (regnum) == '\0')
continue;
! regstart = REGISTER_BYTE (regnum);
! regend = regstart + REGISTER_RAW_SIZE (regnum);
! if (regend <= inregbyte || inregend <= regstart)
/* The range the user wants to read doesn't overlap with regnum. */
continue;
! /* We've found an uncached register where at least one byte will be read.
! Update it from the target. */
! fetch_register (regnum);
! if (!register_cached (regnum))
{
! /* Sometimes pseudoregs are never marked valid, so that they
! will be fetched every time (it can be complicated to know
! if a pseudoreg is valid, while "fetching" them can be cheap).
! */
! if (regnum < NUM_REGS)
! error ("read_register_bytes: Couldn't update register %d.", regnum);
}
}
-
- if (myaddr != NULL)
- memcpy (myaddr, register_buffer (-1) + inregbyte, inlen);
}
/* Read register REGNUM into memory at MYADDR, which must be large
--- 214,275 ----
into memory at MYADDR. */
void
! read_register_bytes (int in_start, char *in_buf, int in_len)
{
! int in_end = in_start + in_len;
int regnum;
+ char *reg_buf = alloca (MAX_REGISTER_RAW_SIZE);
/* See if we are trying to read bytes from out-of-date registers. If so,
update just those registers. */
for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++)
{
! int reg_start;
! int reg_end;
! int reg_len;
! int start;
! int end;
! int byte;
if (REGISTER_NAME (regnum) == NULL || *REGISTER_NAME (regnum) == '\0')
continue;
! reg_start = REGISTER_BYTE (regnum);
! reg_len = REGISTER_RAW_SIZE (regnum);
! reg_end = reg_start + reg_len;
! if (reg_end <= in_start || in_end <= reg_start)
/* The range the user wants to read doesn't overlap with regnum. */
continue;
! /* Force the cache to fetch the entire register. */
! read_register_gen (regnum, reg_buf);
! /* Legacy note: This function, for some reason, allows a NULL
! input buffer. If the buffer is NULL, the registers are still
! fetched, just the final transfer is skipped. */
! if (in_buf == NULL)
! continue;
!
! /* start = max (reg_start, in_start) */
! if (reg_start > in_start)
! start = reg_start;
! else
! start = in_start;
!
! /* end = min (reg_end, in_end) */
! if (reg_end < in_end)
! end = reg_end;
! else
! end = in_end;
!
! /* Transfer just the bytes common to both IN_BUF and REG_BUF */
! for (byte = start; byte < end; byte++)
{
! in_buf[byte - in_start] = reg_buf[byte - reg_start];
}
}
}
/* Read register REGNUM into memory at MYADDR, which must be large
*************** read_register_bytes (int inregbyte, char
*** 268,276 ****
register is known to be the size of a CORE_ADDR or smaller,
read_register can be used instead. */
! void
! read_register_gen (int regnum, char *myaddr)
{
if (registers_pid != inferior_pid)
{
registers_changed ();
--- 277,286 ----
register is known to be the size of a CORE_ADDR or smaller,
read_register can be used instead. */
! static void
! legacy_read_register_gen (int regnum, char *myaddr)
{
+ gdb_assert (regnum >= 0 && regnum < (NUM_REGS + NUM_PSEUDO_REGS));
if (registers_pid != inferior_pid)
{
registers_changed ();
*************** read_register_gen (int regnum, char *mya
*** 284,289 ****
--- 294,319 ----
REGISTER_RAW_SIZE (regnum));
}
+ void
+ regcache_read (int rawnum, char *buf)
+ {
+ gdb_assert (rawnum >= 0 && rawnum < NUM_REGS);
+ /* For moment, just use underlying legacy code. Ulgh!!! */
+ legacy_read_register_gen (rawnum, buf);
+ }
+
+ void
+ read_register_gen (int regnum, char *buf)
+ {
+ if (! gdbarch_register_read_p (current_gdbarch))
+ {
+ legacy_read_register_gen (regnum, buf);
+ return;
+ }
+ gdbarch_register_read (current_gdbarch, regnum, buf);
+ }
+
+
/* Write register REGNUM at MYADDR to the target. MYADDR points at
REGISTER_RAW_BYTES(REGNUM), which must be in target byte-order. */
*************** read_register_gen (int regnum, char *mya
*** 292,301 ****
#define CANNOT_STORE_REGISTER(regnum) 0
#endif
! void
! write_register_gen (int regnum, char *myaddr)
{
int size;
/* On the sparc, writing %g0 is a no-op, so we don't even want to
change the registers array if something writes to this register. */
--- 322,332 ----
#define CANNOT_STORE_REGISTER(regnum) 0
#endif
! static void
! legacy_write_register_gen (int regnum, char *myaddr)
{
int size;
+ gdb_assert (regnum >= 0 && regnum < (NUM_REGS + NUM_PSEUDO_REGS));
/* On the sparc, writing %g0 is a no-op, so we don't even want to
change the registers array if something writes to this register. */
*************** write_register_gen (int regnum, char *my
*** 326,331 ****
--- 357,381 ----
store_register (regnum);
}
+ void
+ regcache_write (int rawnum, char *buf)
+ {
+ gdb_assert (rawnum >= 0 && rawnum < NUM_REGS);
+ /* For moment, just use underlying legacy code. Ulgh!!! */
+ legacy_write_register_gen (rawnum, buf);
+ }
+
+ void
+ write_register_gen (int regnum, char *buf)
+ {
+ if (! gdbarch_register_write_p (current_gdbarch))
+ {
+ legacy_write_register_gen (regnum, buf);
+ return;
+ }
+ gdbarch_register_write (current_gdbarch, regnum, buf);
+ }
+
/* Copy INLEN bytes of consecutive data from memory at MYADDR
into registers starting with the MYREGSTART'th byte of register data. */
*************** write_register_bytes (int myregstart, ch
*** 385,401 ****
ULONGEST
read_register (int regnum)
{
! if (registers_pid != inferior_pid)
! {
! registers_changed ();
! registers_pid = inferior_pid;
! }
!
! if (!register_cached (regnum))
! fetch_register (regnum);
!
! return (extract_unsigned_integer (register_buffer (regnum),
! REGISTER_RAW_SIZE (regnum)));
}
ULONGEST
--- 435,443 ----
ULONGEST
read_register (int regnum)
{
! char *buf = alloca (REGISTER_RAW_SIZE (regnum));
! read_register_gen (regnum, buf);
! return (extract_unsigned_integer (buf, REGISTER_RAW_SIZE (regnum)));
}
ULONGEST
*************** read_register_pid (int regnum, int pid)
*** 423,439 ****
LONGEST
read_signed_register (int regnum)
{
! if (registers_pid != inferior_pid)
! {
! registers_changed ();
! registers_pid = inferior_pid;
! }
!
! if (!register_cached (regnum))
! fetch_register (regnum);
!
! return (extract_signed_integer (register_buffer (regnum),
! REGISTER_RAW_SIZE (regnum)));
}
LONGEST
--- 465,473 ----
LONGEST
read_signed_register (int regnum)
{
! void *buf = alloca (REGISTER_RAW_SIZE (regnum));
! read_register_gen (regnum, buf);
! return (extract_signed_integer (buf, REGISTER_RAW_SIZE (regnum)));
}
LONGEST
*************** read_signed_register_pid (int regnum, in
*** 461,498 ****
void
write_register (int regnum, LONGEST val)
{
! PTR buf;
int size;
-
- /* On the sparc, writing %g0 is a no-op, so we don't even want to
- change the registers array if something writes to this register. */
- if (CANNOT_STORE_REGISTER (regnum))
- return;
-
- if (registers_pid != inferior_pid)
- {
- registers_changed ();
- registers_pid = inferior_pid;
- }
-
size = REGISTER_RAW_SIZE (regnum);
buf = alloca (size);
store_signed_integer (buf, size, (LONGEST) val);
!
! /* If we have a valid copy of the register, and new value == old value,
! then don't bother doing the actual store. */
!
! if (register_cached (regnum)
! && memcmp (register_buffer (regnum), buf, size) == 0)
! return;
!
! if (real_register (regnum))
! target_prepare_to_store ();
!
! memcpy (register_buffer (regnum), buf, size);
!
! set_register_cached (regnum, 1);
! store_register (regnum);
}
void
--- 495,506 ----
void
write_register (int regnum, LONGEST val)
{
! void *buf;
int size;
size = REGISTER_RAW_SIZE (regnum);
buf = alloca (size);
store_signed_integer (buf, size, (LONGEST) val);
! write_register_gen (regnum, buf);
}
void
*************** supply_register (int regnum, char *val)
*** 546,551 ****
--- 554,565 ----
/* On some architectures, e.g. HPPA, there are a few stray bits in
some registers, that the rest of the code would like to ignore. */
+
+ /* NOTE: cagney/2001-03-16: The macro CLEAN_UP_REGISTER_VALUE is
+ going to be deprecated. Instead architectures will leave the raw
+ register value as is and instead clean things up as they pass
+ through the method gdbarch_register_read() clean up the
+ values. */
#ifdef CLEAN_UP_REGISTER_VALUE
CLEAN_UP_REGISTER_VALUE (regnum, register_buffer (regnum));
Index: regcache.h
===================================================================
RCS file: /cvs/src/src/gdb/regcache.h,v
retrieving revision 1.3
diff -p -r1.3 regcache.h
*** regcache.h 2001/03/06 08:21:11 1.3
--- regcache.h 2001/03/24 01:23:13
***************
*** 22,34 ****
#ifndef REGCACHE_H
#define REGCACHE_H
! /* Character array containing an image of the inferior programs'
! registers. */
extern char *registers;
! /* Character array containing the current state of each register
! (unavailable<0, invalid=0, valid>0). */
extern signed char *register_valid;
--- 22,41 ----
#ifndef REGCACHE_H
#define REGCACHE_H
! /* Transfer a raw register [0..NUM_REGS) between core-gdb and the
! regcache. */
+ void regcache_read (int rawnum, char *buf);
+ void regcache_write (int rawnum, char *buf);
+
+ /* DEPRECATED: Character array containing an image of the inferior
+ programs' registers for the most recently referenced thread. */
+
extern char *registers;
! /* DEPRECATED: Character array containing the current state of each
! register (unavailable<0, invalid=0, valid>0) for the most recently
! referenced thread. */
extern signed char *register_valid;
*************** extern int register_cached (int regnum);
*** 37,42 ****
--- 44,52 ----
extern void set_register_cached (int regnum, int state);
extern void register_changed (int regnum);
+
+ /* DEPRECATED: Functional interface returning pointer into registers[]
+ array. */
extern char *register_buffer (int regnum);