aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cagney <cagney@redhat.com>2001-03-24 01:26:09 +0000
committerAndrew Cagney <cagney@redhat.com>2001-03-24 01:26:09 +0000
commit61a0eb5b8e81215b3d3d7be207315572af3fe8a8 (patch)
tree965ae3b93b17a55427bf619b9d5d3178453bcbdf
parentcc51ea7952632d60e3d95071c3e0b2f1ab2d5da1 (diff)
downloadbinutils-61a0eb5b8e81215b3d3d7be207315572af3fe8a8.zip
binutils-61a0eb5b8e81215b3d3d7be207315572af3fe8a8.tar.gz
binutils-61a0eb5b8e81215b3d3d7be207315572af3fe8a8.tar.bz2
Re-vamp the register code so that a lot more is routed through
{read,write}_register_gen. Hook that function with multi-arch.
-rw-r--r--gdb/ChangeLog24
-rw-r--r--gdb/TODO52
-rw-r--r--gdb/gdbarch.c62
-rw-r--r--gdb/gdbarch.h12
-rwxr-xr-xgdb/gdbarch.sh3
-rw-r--r--gdb/regcache.c178
-rw-r--r--gdb/regcache.h18
7 files changed, 263 insertions, 86 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 6f7cbda..8ab4e59 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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
diff --git a/gdb/TODO b/gdb/TODO
index 55f6084..a740055 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 4ff794c..8145d99 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 f5b1b44..a9f0e15 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 a4ad4cc..ac6d3e9 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 7b462de..5128c1e 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 cb5754b..dbffb57 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);