Re-vamp the register code so that a lot more is routed through
{read,write}_register_gen. Hook that function with multi-arch.
This commit is contained in:
parent
cc51ea7952
commit
61a0eb5b8e
7 changed files with 263 additions and 86 deletions
|
@ -1,3 +1,27 @@
|
|||
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.
|
||||
|
||||
2001-03-23 Jim Blandy <jimb@redhat.com>
|
||||
|
||||
* stabsread.c (read_cpp_abbrev): Properly construct the names of
|
||||
|
|
52
gdb/TODO
52
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.
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
@ -2451,6 +2465,54 @@ set_gdbarch_write_sp (struct gdbarch *gdbarch,
|
|||
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
|
||||
gdbarch_num_regs (struct gdbarch *gdbarch)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
178
gdb/regcache.c
178
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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue