From 705998783980188784ae6d5d293ac80b39988049 Mon Sep 17 00:00:00 2001 From: Andrew Cagney Date: Sat, 24 Mar 2001 01:26:09 +0000 Subject: [PATCH] Re-vamp the register code so that a lot more is routed through {read,write}_register_gen. Hook that function with multi-arch. --- gdb/ChangeLog | 24 ++++++++ gdb/TODO | 52 +++++++++++++++++ gdb/gdbarch.c | 62 ++++++++++++++++++++ gdb/gdbarch.h | 12 ++++ gdb/gdbarch.sh | 3 + gdb/regcache.c | 178 +++++++++++++++++++++++++++++++-------------------------- gdb/regcache.h | 18 ++++-- 7 files changed, 263 insertions(+), 86 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 6f7cbda9a1..8ab4e59f1e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,27 @@ +2001-03-23 Andrew Cagney + + * 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. + 2001-03-23 Jim Blandy * stabsread.c (read_cpp_abbrev): Properly construct the names of diff --git a/gdb/TODO b/gdb/TODO index 55f6084cb8..a74005559b 100644 --- a/gdb/TODO +++ b/gdb/TODO @@ -305,6 +305,58 @@ Eliminate all warnings for at least one host/target for the flags: -- +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. diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 4ff794c23b..8145d99a75 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -149,6 +149,8 @@ struct gdbarch 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; @@ -321,6 +323,8 @@ struct gdbarch startup_gdbarch = 0, 0, 0, + 0, + 0, generic_get_saved_register, 0, 0, @@ -512,6 +516,8 @@ verify_gdbarch (struct gdbarch *gdbarch) /* 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__, @@ -1534,6 +1540,14 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) (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", @@ -2452,6 +2466,54 @@ set_gdbarch_write_sp (struct gdbarch *gdbarch, } 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 gdbarch_num_regs (struct gdbarch *gdbarch) { if (gdbarch->num_regs == -1) diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index f5b1b44005..a9f0e158f9 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -339,6 +339,18 @@ extern void set_gdbarch_write_sp (struct gdbarch *gdbarch, gdbarch_write_sp_ftyp #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 diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index a4ad4cca74..ac6d3e971d 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -383,6 +383,9 @@ f::TARGET_WRITE_FP:void:write_fp:CORE_ADDR val:val::0:generic_target_write_fp::0 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. diff --git a/gdb/regcache.c b/gdb/regcache.c index 7b462dedcc..5128c1e6fd 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -26,6 +26,7 @@ #include "gdbarch.h" #include "gdbcmd.h" #include "regcache.h" +#include "gdb_assert.h" /* * DATA STRUCTURE @@ -213,54 +214,62 @@ registers_fetched (void) into memory at MYADDR. */ void -read_register_bytes (int inregbyte, char *myaddr, int inlen) +read_register_bytes (int in_start, char *in_buf, int in_len) { - int inregend = inregbyte + inlen; + int in_end = in_start + in_len; int regnum; - - if (registers_pid != inferior_pid) - { - registers_changed (); - registers_pid = inferior_pid; - } + 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 regstart, regend; - - if (register_cached (regnum)) - continue; + 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; - regstart = REGISTER_BYTE (regnum); - regend = regstart + REGISTER_RAW_SIZE (regnum); + reg_start = REGISTER_BYTE (regnum); + reg_len = REGISTER_RAW_SIZE (regnum); + reg_end = reg_start + reg_len; - if (regend <= inregbyte || inregend <= regstart) + if (reg_end <= in_start || in_end <= reg_start) /* 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); + /* Force the cache to fetch the entire register. */ + read_register_gen (regnum, reg_buf); - if (!register_cached (regnum)) + /* 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++) { - /* 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); + in_buf[byte - in_start] = reg_buf[byte - reg_start]; } } - - if (myaddr != NULL) - memcpy (myaddr, register_buffer (-1) + inregbyte, inlen); } /* Read register REGNUM into memory at MYADDR, which must be large @@ -268,9 +277,10 @@ read_register_bytes (int inregbyte, char *myaddr, int inlen) 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) +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 (); @@ -284,6 +294,26 @@ read_register_gen (int regnum, char *myaddr) 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. */ @@ -292,10 +322,11 @@ read_register_gen (int regnum, char *myaddr) #define CANNOT_STORE_REGISTER(regnum) 0 #endif -void -write_register_gen (int regnum, char *myaddr) +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. */ @@ -326,6 +357,25 @@ write_register_gen (int regnum, char *myaddr) 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. */ @@ -385,17 +435,9 @@ write_register_bytes (int myregstart, char *myaddr, int inlen) 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))); + char *buf = alloca (REGISTER_RAW_SIZE (regnum)); + read_register_gen (regnum, buf); + return (extract_unsigned_integer (buf, REGISTER_RAW_SIZE (regnum))); } ULONGEST @@ -423,17 +465,9 @@ read_register_pid (int regnum, int pid) 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))); + void *buf = alloca (REGISTER_RAW_SIZE (regnum)); + read_register_gen (regnum, buf); + return (extract_signed_integer (buf, REGISTER_RAW_SIZE (regnum))); } LONGEST @@ -461,38 +495,12 @@ read_signed_register_pid (int regnum, int pid) void write_register (int regnum, LONGEST val) { - PTR buf; + void *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); + write_register_gen (regnum, buf); } void @@ -547,6 +555,12 @@ supply_register (int regnum, char *val) /* 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)); #endif diff --git a/gdb/regcache.h b/gdb/regcache.h index cb5754ba61..dbffb5792e 100644 --- a/gdb/regcache.h +++ b/gdb/regcache.h @@ -22,13 +22,20 @@ #ifndef REGCACHE_H #define REGCACHE_H -/* Character array containing an image of the inferior programs' - registers. */ +/* 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; -/* Character array containing the current state of each register - (unavailable<0, invalid=0, valid>0). */ +/* 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; @@ -38,6 +45,9 @@ 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); extern void registers_changed (void); -- 2.11.0