[rfc] Regcache revamp (vip)

Andrew Cagney ac131313@cygnus.com
Fri Mar 23 17:26:00 GMT 2001


I checked in the attached.  Take care!!

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

Index: TODO
===================================================================
RCS file: /cvs/src/src/gdb/TODO,v
retrieving revision 1.69
diff -p -r1.69 TODO
*** TODO	2001/03/23 01:14:10	1.69
--- TODO	2001/03/24 01:22:55
*************** Eliminate all warnings for at least one 
*** 305,310 ****
--- 305,362 ----
  
  --
  
+ 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.
  
Index: gdbarch.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.c,v
retrieving revision 1.54
diff -p -r1.54 gdbarch.c
*** gdbarch.c	2001/02/08 06:03:53	1.54
--- gdbarch.c	2001/03/24 01:22:57
*************** struct gdbarch
*** 149,154 ****
--- 149,156 ----
    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;
*************** struct gdbarch startup_gdbarch =
*** 321,326 ****
--- 323,330 ----
    0,
    0,
    0,
+   0,
+   0,
    generic_get_saved_register,
    0,
    0,
*************** verify_gdbarch (struct gdbarch *gdbarch)
*** 512,517 ****
--- 516,523 ----
    /* 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__,
*************** gdbarch_dump (struct gdbarch *gdbarch, s
*** 1534,1539 ****
--- 1540,1553 ----
                          (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",
*************** set_gdbarch_write_sp (struct gdbarch *gd
*** 2449,2454 ****
--- 2463,2516 ----
                        gdbarch_write_sp_ftype write_sp)
  {
    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
Index: gdbarch.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.h,v
retrieving revision 1.44
diff -p -r1.44 gdbarch.h
*** gdbarch.h	2001/03/21 19:47:44	1.44
--- gdbarch.h	2001/03/24 01:22:57
*************** extern void set_gdbarch_write_sp (struct
*** 339,344 ****
--- 339,356 ----
  #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
Index: gdbarch.sh
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.sh,v
retrieving revision 1.57
diff -p -r1.57 gdbarch.sh
*** gdbarch.sh	2001/03/21 19:47:44	1.57
--- gdbarch.sh	2001/03/24 01:23:12
*************** f::TARGET_WRITE_FP:void:write_fp:CORE_AD
*** 383,388 ****
--- 383,391 ----
  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.
Index: regcache.c
===================================================================
RCS file: /cvs/src/src/gdb/regcache.c,v
retrieving revision 1.20
diff -p -r1.20 regcache.c
*** regcache.c	2001/03/13 23:31:14	1.20
--- regcache.c	2001/03/24 01:23:13
***************
*** 26,31 ****
--- 26,32 ----
  #include "gdbarch.h"
  #include "gdbcmd.h"
  #include "regcache.h"
+ #include "gdb_assert.h"
  
  /*
   * DATA STRUCTURE
*************** registers_fetched (void)
*** 213,266 ****
     into memory at MYADDR.  */
  
  void
! read_register_bytes (int inregbyte, char *myaddr, int inlen)
  {
!   int inregend = inregbyte + inlen;
    int regnum;
  
-   if (registers_pid != inferior_pid)
-     {
-       registers_changed ();
-       registers_pid = inferior_pid;
-     }
- 
    /* 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;
  
        if (REGISTER_NAME (regnum) == NULL || *REGISTER_NAME (regnum) == '\0')
  	continue;
  
!       regstart = REGISTER_BYTE (regnum);
!       regend = regstart + REGISTER_RAW_SIZE (regnum);
  
!       if (regend <= inregbyte || inregend <= regstart)
  	/* 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);
  
!       if (!register_cached (regnum))
  	{
! 	  /* 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);
  	}
      }
- 
-   if (myaddr != NULL)
-     memcpy (myaddr, register_buffer (-1) + inregbyte, inlen);
  }
  
  /* Read register REGNUM into memory at MYADDR, which must be large
--- 214,275 ----
     into memory at MYADDR.  */
  
  void
! read_register_bytes (int in_start, char *in_buf, int in_len)
  {
!   int in_end = in_start + in_len;
    int regnum;
+   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 reg_start;
!       int reg_end;
!       int reg_len;
!       int start;
!       int end;
!       int byte;
  
        if (REGISTER_NAME (regnum) == NULL || *REGISTER_NAME (regnum) == '\0')
  	continue;
  
!       reg_start = REGISTER_BYTE (regnum);
!       reg_len = REGISTER_RAW_SIZE (regnum);
!       reg_end = reg_start + reg_len;
  
!       if (reg_end <= in_start || in_end <= reg_start)
  	/* The range the user wants to read doesn't overlap with regnum.  */
  	continue;
  
!       /* Force the cache to fetch the entire register. */
!       read_register_gen (regnum, reg_buf);
  
!       /* 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++)
  	{
! 	  in_buf[byte - in_start] = reg_buf[byte - reg_start];
  	}
      }
  }
  
  /* Read register REGNUM into memory at MYADDR, which must be large
*************** read_register_bytes (int inregbyte, char
*** 268,276 ****
     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)
  {
    if (registers_pid != inferior_pid)
      {
        registers_changed ();
--- 277,286 ----
     register is known to be the size of a CORE_ADDR or smaller,
     read_register can be used instead.  */
  
! 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 ();
*************** read_register_gen (int regnum, char *mya
*** 284,289 ****
--- 294,319 ----
  	  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.  */
  
*************** read_register_gen (int regnum, char *mya
*** 292,301 ****
  #define CANNOT_STORE_REGISTER(regnum) 0
  #endif
  
! void
! write_register_gen (int regnum, char *myaddr)
  {
    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.  */
--- 322,332 ----
  #define CANNOT_STORE_REGISTER(regnum) 0
  #endif
  
! 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.  */
*************** write_register_gen (int regnum, char *my
*** 326,331 ****
--- 357,381 ----
    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.  */
  
*************** write_register_bytes (int myregstart, ch
*** 385,401 ****
  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)));
  }
  
  ULONGEST
--- 435,443 ----
  ULONGEST
  read_register (int regnum)
  {
!   char *buf = alloca (REGISTER_RAW_SIZE (regnum));
!   read_register_gen (regnum, buf);
!   return (extract_unsigned_integer (buf, REGISTER_RAW_SIZE (regnum)));
  }
  
  ULONGEST
*************** read_register_pid (int regnum, int pid)
*** 423,439 ****
  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)));
  }
  
  LONGEST
--- 465,473 ----
  LONGEST
  read_signed_register (int regnum)
  {
!   void *buf = alloca (REGISTER_RAW_SIZE (regnum));
!   read_register_gen (regnum, buf);
!   return (extract_signed_integer (buf, REGISTER_RAW_SIZE (regnum)));
  }
  
  LONGEST
*************** read_signed_register_pid (int regnum, in
*** 461,498 ****
  void
  write_register (int regnum, LONGEST val)
  {
!   PTR 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);
  }
  
  void
--- 495,506 ----
  void
  write_register (int regnum, LONGEST val)
  {
!   void *buf;
    int size;
    size = REGISTER_RAW_SIZE (regnum);
    buf = alloca (size);
    store_signed_integer (buf, size, (LONGEST) val);
!   write_register_gen (regnum, buf);
  }
  
  void
*************** supply_register (int regnum, char *val)
*** 546,551 ****
--- 554,565 ----
  
    /* 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));
Index: regcache.h
===================================================================
RCS file: /cvs/src/src/gdb/regcache.h,v
retrieving revision 1.3
diff -p -r1.3 regcache.h
*** regcache.h	2001/03/06 08:21:11	1.3
--- regcache.h	2001/03/24 01:23:13
***************
*** 22,34 ****
  #ifndef REGCACHE_H
  #define REGCACHE_H
  
! /* Character array containing an image of the inferior programs'
!    registers. */
  
  extern char *registers;
  
! /* Character array containing the current state of each register
!    (unavailable<0, invalid=0, valid>0). */
  
  extern signed char *register_valid;
  
--- 22,41 ----
  #ifndef REGCACHE_H
  #define REGCACHE_H
  
! /* 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;
  
! /* 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;
  
*************** extern int register_cached (int regnum);
*** 37,42 ****
--- 44,52 ----
  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);
  


More information about the Gdb-patches mailing list