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:
Andrew Cagney 2001-03-24 01:26:09 +00:00
parent cc51ea7952
commit 61a0eb5b8e
7 changed files with 263 additions and 86 deletions

View file

@ -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

View file

@ -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.

View file

@ -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)
{

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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);