From: Andrew Cagney Date: Thu, 6 Dec 2001 20:49:47 +0000 (+0000) Subject: Expand the regcache so that there is space for pseudo-registers. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=31e9866ea62cc5ec24e9ff633bc9715d7da2b1b0;p=binutils-gdb.git Expand the regcache so that there is space for pseudo-registers. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 9478ccd379a..4ba02574e72 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,20 @@ +2001-12-06 Andrew Cagney + + * regcache.c (store_register, fetch_register): Only use + fetch/store pseudo-register when function is present. Assume + target can handle all registers. + (registers_changed): Simplify invalidate loop. + (registers_fetched): Add comments. + (register_buffer): Add regnum range assertion. Remove code + handling -ve regnum. + (build_regcache): Make space for pseudo-registers when computing + sizeof_registers. Initialize register_offset. + + * gdbarch.sh (FETCH_PSEUDO_REGISTER): Change to a function with + predicate. + (STORE_PSEUDO_REGISTER): Ditto. + * gdbarch.h, gdbarch.c: Re-generate. + 2001-12-06 Jim Blandy * config/s390/nm-linux.h: Watchpoints are either continuable or diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 85ebde7dc1b..83895a4594d 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -667,8 +667,8 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of register_convertible, invalid_p == 0 */ /* Skip verify of register_convert_to_virtual, invalid_p == 0 */ /* Skip verify of register_convert_to_raw, invalid_p == 0 */ - /* Skip verify of fetch_pseudo_register, invalid_p == 0 */ - /* Skip verify of store_pseudo_register, invalid_p == 0 */ + /* Skip verify of fetch_pseudo_register, has predicate */ + /* Skip verify of store_pseudo_register, has predicate */ /* Skip verify of pointer_to_address, invalid_p == 0 */ /* Skip verify of address_to_pointer, invalid_p == 0 */ /* Skip verify of integer_to_address, has predicate */ @@ -3326,6 +3326,12 @@ set_gdbarch_register_convert_to_raw (struct gdbarch *gdbarch, gdbarch->register_convert_to_raw = register_convert_to_raw; } +int +gdbarch_fetch_pseudo_register_p (struct gdbarch *gdbarch) +{ + return gdbarch->fetch_pseudo_register != 0; +} + void gdbarch_fetch_pseudo_register (struct gdbarch *gdbarch, int regnum) { @@ -3344,6 +3350,12 @@ set_gdbarch_fetch_pseudo_register (struct gdbarch *gdbarch, gdbarch->fetch_pseudo_register = fetch_pseudo_register; } +int +gdbarch_store_pseudo_register_p (struct gdbarch *gdbarch) +{ + return gdbarch->store_pseudo_register != 0; +} + void gdbarch_store_pseudo_register (struct gdbarch *gdbarch, int regnum) { diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 52fb9d719d5..22945959eff 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -1170,6 +1170,26 @@ extern void set_gdbarch_register_convert_to_raw (struct gdbarch *gdbarch, gdbarc be updated. Typically it will be defined on a per-architecture basis. */ +#if defined (FETCH_PSEUDO_REGISTER) +/* Legacy for systems yet to multi-arch FETCH_PSEUDO_REGISTER */ +#if !defined (FETCH_PSEUDO_REGISTER_P) +#define FETCH_PSEUDO_REGISTER_P() (1) +#endif +#endif + +/* Default predicate for non- multi-arch targets. */ +#if (!GDB_MULTI_ARCH) && !defined (FETCH_PSEUDO_REGISTER_P) +#define FETCH_PSEUDO_REGISTER_P() (0) +#endif + +extern int gdbarch_fetch_pseudo_register_p (struct gdbarch *gdbarch); +#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (FETCH_PSEUDO_REGISTER_P) +#error "Non multi-arch definition of FETCH_PSEUDO_REGISTER" +#endif +#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) || !defined (FETCH_PSEUDO_REGISTER_P) +#define FETCH_PSEUDO_REGISTER_P() (gdbarch_fetch_pseudo_register_p (current_gdbarch)) +#endif + /* Default (function) for non- multi-arch platforms. */ #if (!GDB_MULTI_ARCH) && !defined (FETCH_PSEUDO_REGISTER) #define FETCH_PSEUDO_REGISTER(regnum) (internal_error (__FILE__, __LINE__, "FETCH_PSEUDO_REGISTER"), 0) @@ -1191,6 +1211,26 @@ extern void set_gdbarch_fetch_pseudo_register (struct gdbarch *gdbarch, gdbarch_ be set or stored. Typically it will be defined on a per-architecture basis. */ +#if defined (STORE_PSEUDO_REGISTER) +/* Legacy for systems yet to multi-arch STORE_PSEUDO_REGISTER */ +#if !defined (STORE_PSEUDO_REGISTER_P) +#define STORE_PSEUDO_REGISTER_P() (1) +#endif +#endif + +/* Default predicate for non- multi-arch targets. */ +#if (!GDB_MULTI_ARCH) && !defined (STORE_PSEUDO_REGISTER_P) +#define STORE_PSEUDO_REGISTER_P() (0) +#endif + +extern int gdbarch_store_pseudo_register_p (struct gdbarch *gdbarch); +#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (STORE_PSEUDO_REGISTER_P) +#error "Non multi-arch definition of STORE_PSEUDO_REGISTER" +#endif +#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) || !defined (STORE_PSEUDO_REGISTER_P) +#define STORE_PSEUDO_REGISTER_P() (gdbarch_store_pseudo_register_p (current_gdbarch)) +#endif + /* Default (function) for non- multi-arch platforms. */ #if (!GDB_MULTI_ARCH) && !defined (STORE_PSEUDO_REGISTER) #define STORE_PSEUDO_REGISTER(regnum) (internal_error (__FILE__, __LINE__, "STORE_PSEUDO_REGISTER"), 0) diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index b77dacb0d12..16b01a5fea3 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -468,11 +468,11 @@ f:2:REGISTER_CONVERT_TO_RAW:void:register_convert_to_raw:struct type *type, int # This function is called when the value of a pseudo-register needs to # be updated. Typically it will be defined on a per-architecture # basis. -f:2:FETCH_PSEUDO_REGISTER:void:fetch_pseudo_register:int regnum:regnum:::0::0 +F:2:FETCH_PSEUDO_REGISTER:void:fetch_pseudo_register:int regnum:regnum: # This function is called when the value of a pseudo-register needs to # be set or stored. Typically it will be defined on a # per-architecture basis. -f:2:STORE_PSEUDO_REGISTER:void:store_pseudo_register:int regnum:regnum:::0::0 +F:2:STORE_PSEUDO_REGISTER:void:store_pseudo_register:int regnum:regnum: # f:2:POINTER_TO_ADDRESS:CORE_ADDR:pointer_to_address:struct type *type, void *buf:type, buf:::unsigned_pointer_to_address::0 f:2:ADDRESS_TO_POINTER:void:address_to_pointer:struct type *type, void *buf, CORE_ADDR addr:type, buf, addr:::unsigned_address_to_pointer::0 diff --git a/gdb/regcache.c b/gdb/regcache.c index ae893454312..9b3d6edcc86 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -93,10 +93,8 @@ register_changed (int regnum) static char * register_buffer (int regnum) { - if (regnum < 0) - return registers; - else - return ®isters[REGISTER_BYTE (regnum)]; + gdb_assert (regnum >= 0 && regnum < (NUM_REGS + NUM_PSEUDO_REGS)); + return ®isters[REGISTER_BYTE (regnum)]; } /* Return whether register REGNUM is a real register. */ @@ -120,10 +118,14 @@ pseudo_register (int regnum) static void fetch_register (int regnum) { - if (real_register (regnum)) - target_fetch_registers (regnum); - else if (pseudo_register (regnum)) + /* NOTE: cagney/2001-12-04: Legacy targets were using fetch/store + pseudo-register as a way of handling registers that needed to be + constructed from one or more raw registers. New targets instead + use gdbarch register read/write. */ + if (FETCH_PSEUDO_REGISTER_P () + && pseudo_register (regnum)) FETCH_PSEUDO_REGISTER (regnum); + target_fetch_registers (regnum); } /* Write register REGNUM cached value to the target. */ @@ -131,10 +133,14 @@ fetch_register (int regnum) static void store_register (int regnum) { - if (real_register (regnum)) - target_store_registers (regnum); - else if (pseudo_register (regnum)) + /* NOTE: cagney/2001-12-04: Legacy targets were using fetch/store + pseudo-register as a way of handling registers that needed to be + constructed from one or more raw registers. New targets instead + use gdbarch register read/write. */ + if (STORE_PSEUDO_REGISTER_P () + && pseudo_register (regnum)) STORE_PSEUDO_REGISTER (regnum); + target_store_registers (regnum); } /* Low level examining and depositing of registers. @@ -162,12 +168,7 @@ registers_changed (void) gdb gives control to the user (ie watchpoints). */ alloca (0); - for (i = 0; i < NUM_REGS; i++) - set_register_cached (i, 0); - - /* Assume that if all the hardware regs have changed, - then so have the pseudo-registers. */ - for (i = NUM_REGS; i < NUM_REGS + NUM_PSEUDO_REGS; i++) + for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++) set_register_cached (i, 0); if (registers_changed_hook) @@ -178,6 +179,13 @@ registers_changed (void) Indicate that all registers have been fetched, so mark them all valid. */ +/* NOTE: cagney/2001-12-04: This function does not set valid on the + pseudo-register range since pseudo registers are always supplied + using supply_register(). */ +/* FIXME: cagney/2001-12-04: This function is DEPRECATED. The target + code was blatting the registers[] array and then calling this. + Since targets should only be using supply_register() the need for + this function/hack is eliminated. */ void registers_fetched (void) @@ -187,7 +195,7 @@ registers_fetched (void) for (i = 0; i < NUM_REGS; i++) set_register_cached (i, 1); /* Do not assume that the pseudo-regs have also been fetched. - Fetching all real regs might not account for all pseudo-regs. */ + Fetching all real regs NEVER accounts for pseudo-regs. */ } /* read_register_bytes and write_register_bytes are generally a *BAD* @@ -758,17 +766,36 @@ reg_flush_command (char *command, int from_tty) printf_filtered ("Register cache flushed.\n"); } +#undef XCALLOC +#define XCALLOC(NR,TYPE) ((TYPE*) xcalloc ((NR), sizeof (TYPE))) static void build_regcache (void) { - /* We allocate some extra slop since we do a lot of memcpy's around - `registers', and failing-soft is better than failing hard. */ - int sizeof_registers = REGISTER_BYTES + /* SLOP */ 256; - int sizeof_register_valid = - (NUM_REGS + NUM_PSEUDO_REGS) * sizeof (*register_valid); + 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); - memset (registers, 0, 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); }