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]

Re: [PATCH]: Enable pseudo-registers in GDB.


Argh.  "defs.h" should be "inferior.h".
The diffs for inferior.h are appended below.


Michael Snyder wrote:
> 
> 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.
>         * inferior.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);

diff -p -r1.7 -r1.8
*** inferior.h  2000/06/04 13:46:37     1.7
--- inferior.h  2000/07/12 22:01:17     1.8
*************** extern void write_inferior_status_regist
*** 52,61 ****
  
  /* This macro gives the number of registers actually in use by the
     inferior.  This may be less than the total number of registers,
!    perhaps depending on the actual CPU in use or program being run. 
*/
  
  #ifndef ARCH_NUM_REGS
  #define ARCH_NUM_REGS NUM_REGS
  #endif
  
  extern void set_sigint_trap (void);
--- 52,85 ----
  
  /* This macro gives the number of registers actually in use by the
     inferior.  This may be less than the total number of registers,
!    perhaps depending on the actual CPU in use or program being run.  
!    FIXME: This could be replaced by the new MULTI_ARCH capability.  */
  
  #ifndef ARCH_NUM_REGS
  #define ARCH_NUM_REGS NUM_REGS
+ #endif
+ 
+ /* This macro gives the number of pseudo-registers that live in the
+    register namespace but do not get fetched or stored on the target.
+    These pseudo-registers may be aliases for other registers, 
+    combinations of other registers, or they may be computed by GDB. 
+    FIXME: move into gdbarch.[ch] */
+ #ifndef NUM_PSEUDO_REGS
+ #define NUM_PSEUDO_REGS 0
+ #endif
+ 
+ /* This function is called when the value of a pseudo-register needs
+    to be updated.  Typically it will be defined on a per-architecture
+    basis.  FIXME: move into gdbarch.[ch].  */
+ #ifndef ARCH_FETCH_PSEUDO_REGISTERS
+ #define ARCH_FETCH_PSEUDO_REGISTERS(REGNUM) /* no-op */
+ #endif
+ 
+ /* This function is called when the value of a pseudo-register needs
+    to be set or stored.  Typically it will be defined on a
per-architecture
+    basis.  FIXME: move into gdbarch.[ch].  */
+ #ifndef ARCH_STORE_PSEUDO_REGISTERS
+ #define ARCH_STORE_PSEUDO_REGISTERS(REGNUM) /* no-op */
  #endif
  
  extern void set_sigint_trap (void);

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