This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[PATCH]: Enable pseudo-registers in GDB.



OK, here is the patch.

The way you use this is:
  1) You define NUM_PSEUDO_REGS to the number of pseudo-registers.
  2) Add names of your pseudo-regs to THE END OF the register_names.
  3) Add the number of bytes of storage that you require for your
     pseudo-registers to REGISTER_BYTES.  Note -- pseudo-regs that
     are just aliases for previously existing regs do not need any
     additional storage.
  4) Add handling for your pseudo-regs to REGISTER_VIRTUAL_TYPE, 
     REGISTER_BYTE, REGISTER_RAW_SIZE, etc.  Note that for an alias
     register, REGISTER_BYTE should return the same offset as the
     real register for which this one is an alias.
  5) Define ARCH_FETCH_PSEUDO_REGISTERS(regno) and
     ARCH_STORE_PSEUDO_REGISTERS(regno) to compute (or whatever)
     the values for your pseudo-registers.  These will probably be
     defined in your tm.h and live in your -tdep.c file.

I will provide an example in a subsequent email.

2000-07-12  Michael Snyder  <msnyder@cleaver.cygnus.com>

        This change adds pseudo-register capability to GDB.
        Pseudo-registers are handled like registers, but they
        don't come from or live on the target.  They may be 
        aliases for an existing register, or they may be computed.
        * defs.h (NUM_PSEUDO_REGISTERS): Define default of zero.
        (ARCH_FETCH_PSEUDO_REGISTERS): Define default of no-op.
        (ARCH_STORE_PSEUDO_REGISTERS): Define default of no-op.
        # regcache.c (registers_changed): Mark pseudo-registers 
        invalid, as well as real registers.
        (registers_fetched): Do not mark pseudo-registers as fetched
        at the same time as other (real) registers.
        (read_register_bytes): Fetch pseudo-registers (if any) from
        the target architecture module instead of from the target.
        (read_register_gen): Ditto.
        (read_register): Ditto.
        (write_register_bytes): Store pseudo-registers (if any) to
        the target architecture module instead of to the target.
        (write_register_gen): Ditto.
        (write_register): Ditto.
        (build_regcache): Allocate enough register_valid space for
        pseudo-registers as well as normal (real) ones.


Index: regcache.c
===================================================================
RCS file: /cvs/src/src/gdb/regcache.c,v
retrieving revision 1.3
diff -p -r1.3 regcache.c
*** regcache.c	2000/07/11 05:42:25	1.3
--- regcache.c	2000/07/12 21:52:50
*************** void
*** 282,288 ****
  registers_changed (void)
  {
    int i;
-   int numregs = ARCH_NUM_REGS;
  
    registers_pid = -1;
  
--- 282,287 ----
*************** registers_changed (void)
*** 293,301 ****
       gdb gives control to the user (ie watchpoints).  */
    alloca (0);
  
!   for (i = 0; i < numregs; i++)
      register_valid[i] = 0;
  
    if (registers_changed_hook)
      registers_changed_hook ();
  }
--- 292,305 ----
       gdb gives control to the user (ie watchpoints).  */
    alloca (0);
  
!   for (i = 0; i < ARCH_NUM_REGS; i++)
      register_valid[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++)
+     register_valid[i] = 0;
+ 
    if (registers_changed_hook)
      registers_changed_hook ();
  }
*************** void
*** 309,318 ****
  registers_fetched (void)
  {
    int i;
-   int numregs = ARCH_NUM_REGS;
  
!   for (i = 0; i < numregs; i++)
      register_valid[i] = 1;
  }
  
  /* read_register_bytes and write_register_bytes are generally a *BAD*
--- 313,323 ----
  registers_fetched (void)
  {
    int i;
  
!   for (i = 0; i < ARCH_NUM_REGS; i++)
      register_valid[i] = 1;
+   /* Do not assume that the pseudo-regs have also been fetched.
+      Fetching all real regs might not account for all pseudo-regs.  */
  }
  
  /* read_register_bytes and write_register_bytes are generally a *BAD*
*************** read_register_bytes (int inregbyte, char
*** 351,357 ****
    /* See if we are trying to read bytes from out-of-date registers.  If so,
       update just those registers.  */
  
!   for (regno = 0; regno < NUM_REGS; regno++)
      {
        int regstart, regend;
  
--- 356,362 ----
    /* See if we are trying to read bytes from out-of-date registers.  If so,
       update just those registers.  */
  
!   for (regno = 0; regno < NUM_REGS + NUM_PSEUDO_REGS; regno++)
      {
        int regstart, regend;
  
*************** read_register_bytes (int inregbyte, char
*** 368,376 ****
  	/* The range the user wants to read doesn't overlap with regno.  */
  	continue;
  
!       /* We've found an invalid register where at least one byte will be read.
           Update it from the target.  */
!       target_fetch_registers (regno);
  
        if (!register_valid[regno])
  	error ("read_register_bytes:  Couldn't update register %d.", regno);
--- 373,384 ----
  	/* The range the user wants to read doesn't overlap with regno.  */
  	continue;
  
!       /* We've found an uncached register where at least one byte will be read.
           Update it from the target.  */
!       if (regno < NUM_REGS)
! 	target_fetch_registers (regno);
!       else if (regno < NUM_PSEUDO_REGS)
! 	ARCH_FETCH_PSEUDO_REGISTERS (regno);
  
        if (!register_valid[regno])
  	error ("read_register_bytes:  Couldn't update register %d.", regno);
*************** read_register_gen (int regno, char *myad
*** 395,401 ****
      }
  
    if (!register_valid[regno])
!     target_fetch_registers (regno);
    memcpy (myaddr, &registers[REGISTER_BYTE (regno)],
  	  REGISTER_RAW_SIZE (regno));
  }
--- 403,414 ----
      }
  
    if (!register_valid[regno])
!     {
!       if (regno < NUM_REGS)
! 	target_fetch_registers (regno);
!       else if (regno < NUM_REGS + NUM_PSEUDO_REGS)
! 	ARCH_FETCH_PSEUDO_REGISTERS (regno);
!     }
    memcpy (myaddr, &registers[REGISTER_BYTE (regno)],
  	  REGISTER_RAW_SIZE (regno));
  }
*************** write_register_gen (int regno, char *mya
*** 433,445 ****
        && memcmp (&registers[REGISTER_BYTE (regno)], myaddr, size) == 0)
      return;
  
!   target_prepare_to_store ();
  
    memcpy (&registers[REGISTER_BYTE (regno)], myaddr, size);
  
    register_valid[regno] = 1;
  
!   target_store_registers (regno);
  }
  
  /* Copy INLEN bytes of consecutive data from memory at MYADDR
--- 446,462 ----
        && memcmp (&registers[REGISTER_BYTE (regno)], myaddr, size) == 0)
      return;
  
!   if (regno < NUM_REGS)
!     target_prepare_to_store ();
  
    memcpy (&registers[REGISTER_BYTE (regno)], myaddr, size);
  
    register_valid[regno] = 1;
  
!   if (regno < NUM_REGS)
!     target_store_registers (regno);
!   else if (regno < NUM_REGS + NUM_PSEUDO_REGS)
!     ARCH_STORE_PSEUDO_REGISTERS (regno);
  }
  
  /* Copy INLEN bytes of consecutive data from memory at MYADDR
*************** write_register_bytes (int myregstart, ch
*** 458,464 ****
       nice things like handling threads, and avoiding updates when the
       new and old contents are the same.  */
  
!   for (regno = 0; regno < NUM_REGS; regno++)
      {
        int regstart, regend;
  
--- 475,481 ----
       nice things like handling threads, and avoiding updates when the
       new and old contents are the same.  */
  
!   for (regno = 0; regno < NUM_REGS + NUM_PSEUDO_REGS; regno++)
      {
        int regstart, regend;
  
*************** write_register_bytes (int myregstart, ch
*** 490,496 ****
  		  myaddr + (overlapstart - myregstart),
  		  overlapend - overlapstart);
  
! 	  target_store_registers (regno);
  	}
      }
  }
--- 507,516 ----
  		  myaddr + (overlapstart - myregstart),
  		  overlapend - overlapstart);
  
! 	  if (regno < NUM_REGS)
! 	    target_store_registers (regno);
! 	  else if (regno < NUM_REGS + NUM_PSEUDO_REGS)
! 	    ARCH_STORE_PSEUDO_REGISTERS (regno);
  	}
      }
  }
*************** read_register (int regno)
*** 509,515 ****
      }
  
    if (!register_valid[regno])
!     target_fetch_registers (regno);
  
    return (extract_unsigned_integer (&registers[REGISTER_BYTE (regno)],
  				    REGISTER_RAW_SIZE (regno)));
--- 529,540 ----
      }
  
    if (!register_valid[regno])
!     {
!       if (regno < NUM_REGS)
! 	target_fetch_registers (regno);
!       else if (regno < NUM_PSEUDO_REGS)
! 	ARCH_FETCH_PSEUDO_REGISTERS (regno);
!     }
  
    return (extract_unsigned_integer (&registers[REGISTER_BYTE (regno)],
  				    REGISTER_RAW_SIZE (regno)));
*************** write_register (int regno, LONGEST val)
*** 604,616 ****
        && memcmp (&registers[REGISTER_BYTE (regno)], buf, size) == 0)
      return;
  
!   target_prepare_to_store ();
  
    memcpy (&registers[REGISTER_BYTE (regno)], buf, size);
  
    register_valid[regno] = 1;
  
!   target_store_registers (regno);
  }
  
  void
--- 629,645 ----
        && memcmp (&registers[REGISTER_BYTE (regno)], buf, size) == 0)
      return;
  
!   if (regno < NUM_REGS)
!     target_prepare_to_store ();
  
    memcpy (&registers[REGISTER_BYTE (regno)], buf, size);
  
    register_valid[regno] = 1;
  
!   if (regno < NUM_REGS)
!     target_store_registers (regno);
!   else if (regno < NUM_REGS + NUM_PSEUDO_REGS)
!     ARCH_STORE_PSEUDO_REGISTERS (regno);
  }
  
  void
*************** build_regcache (void)
*** 859,865 ****
    /* 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 * sizeof (*register_valid);
    registers = xmalloc (sizeof_registers);
    memset (registers, 0, sizeof_registers);
    register_valid = xmalloc (sizeof_register_valid);
--- 888,895 ----
    /* 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);
    registers = xmalloc (sizeof_registers);
    memset (registers, 0, sizeof_registers);
    register_valid = xmalloc (sizeof_register_valid);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]