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]
Other format: [Raw text]

RFA 3/3: adapt native to new E500 regcache layout


2004-06-30  Jim Blandy  <jimb@redhat.com>

	Adapt PPC E500 native support to the new raw regcache layout.
	* ppc-linux-nat.c (struct gdb_evrregset_t): Doc fixes.
	(read_spliced_spe_reg, write_spliced_spe_reg): Deleted.
	(fetch_spe_register, store_spe_register): Handle fetching/storing
	all the SPE registers at once, if regno == -1.  These now take
	over the job of fetch_spe_registers and store_spe_registers.
	(fetch_spe_registers, store_spe_registers): Deleted.
	(fetch_ppc_registers, store_ppc_registers): Fetch/store gprs
	unconditionally; they're always raw.  Fetch/store SPE upper half
	registers, if present, instead of ev registers.
	(fetch_register, store_register): Remove sanity checks: gprs are
	never pseudo-registers now, so we never need to even mention any
	registers that are ever pseudoregisters.

diff -crp -x '*~' -x '.#*' -x CVS gdb/ppc-linux-nat.c gdb/ppc-linux-nat.c
*** gdb/ppc-linux-nat.c	2004-06-16 15:30:33.000000000 -0500
--- gdb/ppc-linux-nat.c	2004-06-22 12:40:45.000000000 -0500
*************** typedef char gdb_vrregset_t[SIZEOF_VRREG
*** 123,134 ****
     some SPE-specific registers.
  
     GDB itself continues to claim the general-purpose registers are 32
!    bits long; the full 64-bit registers are called 'ev0' -- 'ev31'.
!    The ev registers are raw registers, and the GPR's are pseudo-
!    registers mapped onto their lower halves.  This means that reading
!    and writing ev registers involves a mix of regset-at-once
!    PTRACE_{GET,SET}EVRREGS calls and register-at-a-time
!    PTRACE_{PEEK,POKE}USR calls.
  
     This is the structure filled in by PTRACE_GETEVRREGS and written to
     the inferior's registers by PTRACE_SETEVRREGS.  */
--- 123,132 ----
     some SPE-specific registers.
  
     GDB itself continues to claim the general-purpose registers are 32
!    bits long.  It has unnamed raw registers that hold the upper halves
!    of the gprs, and the the full 64-bit SIMD views of the registers,
!    'ev0' -- 'ev31', are pseudo-registers that splice the top and
!    bottom halves together.
  
     This is the structure filled in by PTRACE_GETEVRREGS and written to
     the inferior's registers by PTRACE_SETEVRREGS.  */
*************** get_spe_registers (int tid, struct gdb_e
*** 283,387 ****
    memset (evrregset, 0, sizeof (*evrregset));
  }
  
! /* Assuming TID refers to an SPE process, store the full 64-bit value
!    of TID's ev register EV_REGNUM in DEST, getting the high bits from
!    EVRREGS and the low bits from the kernel via ptrace.  */
! static void
! read_spliced_spe_reg (int tid, int ev_regnum,
!                       struct gdb_evrregset_t *evrregs,
!                       char *dest)
! {
!   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
! 
!   /* Make sure we're trying to read an EV register; that's all we
!      handle.  */
!   gdb_assert (tdep->ppc_ev0_regnum <= ev_regnum
!               && ev_regnum <= tdep->ppc_ev31_regnum);
! 
!   /* Make sure the sizes for the splicing add up.  */
!   gdb_assert (sizeof (evrregs->evr[0]) + sizeof (PTRACE_XFER_TYPE)
!               == register_size (current_gdbarch, ev_regnum));
! 
!   {
!     /* The index of ev_regnum in evrregs->evr[].  */
!     int ev_index = ev_regnum - tdep->ppc_ev0_regnum;
! 
!     /* The number of the corresponding general-purpose register, which
!        holds the lower 32 bits of the EV register.  */
!     int gpr_regnum = tdep->ppc_gp0_regnum + ev_index;
! 
!     /* The offset of gpr_regnum in the process's uarea.  */
!     CORE_ADDR gpr_uoffset = ppc_register_u_addr (gpr_regnum);
! 
!     /* The low word of the EV register's value.  */
!     PTRACE_XFER_TYPE low_word;
! 
!     /* The PTRACE_PEEKUSR / PT_READ_U ptrace requests need to be able
!        to return arbitrary register values, so they can't return -1 to
!        indicate an error.  So we clear errno, and then check it after
!        the call.  */
!     errno = 0;
!     low_word = ptrace (PT_READ_U, tid, (PTRACE_ARG3_TYPE) gpr_uoffset, 0);
!   
!     if (errno != 0)
!       {
!         char message[128];
!         sprintf (message, "reading register %s (#%d)",
!                  REGISTER_NAME (ev_regnum), ev_regnum);
!         perror_with_name (message);
!       }
! 
!     if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
!       {
!         memcpy (dest, &evrregs->evr[ev_index],
!                 sizeof (evrregs->evr[ev_index]));
!         * (PTRACE_XFER_TYPE *) (dest + sizeof (evrregs->evr[ev_index]))
!           = low_word;
!       }
!     else if (TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
!       {
!         * (PTRACE_XFER_TYPE *) dest = low_word;
!         memcpy (dest + sizeof (PTRACE_XFER_TYPE),
!                 &evrregs->evr[ev_index], sizeof (evrregs->evr[ev_index]));
!       }
!     else
!       gdb_assert (0);
!   }
! }
! 
! 
! /* On SPE machines, supply the full value of the SPE register REGNO
!    from TID.  This handles ev0 -- ev31 and acc, which are 64 bits
!    long, and spefscr, which is 32 bits long.  */
  static void
  fetch_spe_register (int tid, int regno)
  {
    struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
    struct gdb_evrregset_t evrregs;
  
    get_spe_registers (tid, &evrregs);
  
!   if (tdep->ppc_ev0_regnum <= regno
!       && regno <= tdep->ppc_ev31_regnum)
!     {
!       char buf[MAX_REGISTER_SIZE];
!       read_spliced_spe_reg (tid, regno, &evrregs, buf);
!       supply_register (regno, buf);
!     }
!   else if (regno == tdep->ppc_acc_regnum)
!     {
!       gdb_assert (sizeof (evrregs.acc)
!                   == register_size (current_gdbarch, regno));
!       supply_register (regno, &evrregs.acc);
!     }
!   else if (regno == tdep->ppc_spefscr_regnum)
      {
!       gdb_assert (sizeof (evrregs.spefscr)
!                   == register_size (current_gdbarch, regno));
!       supply_register (regno, &evrregs.spefscr);
      }
!   else
!     gdb_assert (0);
  }
  
  static void
--- 281,323 ----
    memset (evrregset, 0, sizeof (*evrregset));
  }
  
! /* Supply values from TID for SPE-specific raw registers: the upper
!    halves of the GPRs, the accumulator, and the spefscr.  REGNO must
!    be the number of an upper half register, acc, spefscr, or -1 to
!    supply the values of all registers.  */
  static void
  fetch_spe_register (int tid, int regno)
  {
    struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
    struct gdb_evrregset_t evrregs;
  
+   gdb_assert (sizeof (evrregs.evr[0])
+               == register_size (current_gdbarch, tdep->ppc_ev0_upper_regnum));
+   gdb_assert (sizeof (evrregs.acc)
+               == register_size (current_gdbarch, tdep->ppc_acc_regnum));
+   gdb_assert (sizeof (evrregs.spefscr)
+               == register_size (current_gdbarch, tdep->ppc_spefscr_regnum));
+ 
    get_spe_registers (tid, &evrregs);
  
!   if (regno == -1)
      {
!       int i;
! 
!       for (i = 0; i < ppc_num_gprs; i++)
!         supply_register (tdep->ppc_ev0_upper_regnum + i, &evrregs.evr[i]);
      }
!   else if (tdep->ppc_ev0_upper_regnum <= regno
!            && regno <= tdep->ppc_ev0_upper_regnum + ppc_num_gprs)
!     supply_register (regno, &evrregs.evr[regno - tdep->ppc_ev0_upper_regnum]);
! 
!   if (regno == -1
!       || regno == tdep->ppc_acc_regnum)
!     supply_register (regno, &evrregs.acc);
! 
!   if (regno == -1
!       || regno == tdep->ppc_spefscr_regnum)
!     supply_register (regno, &evrregs.spefscr);
  }
  
  static void
*************** fetch_register (int tid, int regno)
*** 394,405 ****
    unsigned int offset;         /* Offset of registers within the u area. */
    char buf[MAX_REGISTER_SIZE];
  
-   /* Sanity check: this function should only be called to fetch raw
-      registers' values, never pseudoregisters' values.  */
-   if (tdep->ppc_gp0_regnum <= regno
-       && regno < tdep->ppc_gp0_regnum + ppc_num_gprs)
-     gdb_assert (! tdep->ppc_gprs_pseudo_p);
- 
    if (altivec_register_p (regno))
      {
        /* If this is the first time through, or if it is not the first
--- 330,335 ----
*************** fetch_altivec_registers (int tid)
*** 511,551 ****
    supply_vrregset (&regs);
  }
  
- /* On SPE machines, fetch the full 64 bits of all the general-purpose
-    registers, as well as the SPE-specific registers 'acc' and
-    'spefscr'.  */
- static void
- fetch_spe_registers (int tid)
- {
-   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-   struct gdb_evrregset_t evrregs;
-   int i;
- 
-   get_spe_registers (tid, &evrregs);
- 
-   /* Splice and supply each of the EV registers.  */
-   for (i = 0; i < ppc_num_gprs; i++)
-     {
-       char buf[MAX_REGISTER_SIZE];
- 
-       read_spliced_spe_reg (tid, tdep->ppc_ev0_regnum + i, &evrregs, buf);
-       supply_register (tdep->ppc_ev0_regnum + i, buf);
-     }
- 
-   /* Supply the SPE-specific registers.  */
-   supply_register (tdep->ppc_acc_regnum, &evrregs.acc);
-   supply_register (tdep->ppc_spefscr_regnum, &evrregs.spefscr);
- }
- 
  static void 
  fetch_ppc_registers (int tid)
  {
    int i;
    struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
  
!   if (! tdep->ppc_gprs_pseudo_p)
!     for (i = 0; i < ppc_num_gprs; i++)
!       fetch_register (tid, tdep->ppc_gp0_regnum + i);
    if (tdep->ppc_fp0_regnum >= 0)
      for (i = 0; i < ppc_num_fprs; i++)
        fetch_register (tid, tdep->ppc_fp0_regnum + i);
--- 441,454 ----
    supply_vrregset (&regs);
  }
  
  static void 
  fetch_ppc_registers (int tid)
  {
    int i;
    struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
  
!   for (i = 0; i < ppc_num_gprs; i++)
!     fetch_register (tid, tdep->ppc_gp0_regnum + i);
    if (tdep->ppc_fp0_regnum >= 0)
      for (i = 0; i < ppc_num_fprs; i++)
        fetch_register (tid, tdep->ppc_fp0_regnum + i);
*************** fetch_ppc_registers (int tid)
*** 567,574 ****
    if (have_ptrace_getvrregs)
      if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
        fetch_altivec_registers (tid);
!   if (tdep->ppc_ev0_regnum >= 0)
!     fetch_spe_registers (tid);
  }
  
  /* Fetch registers from the child process.  Fetch all registers if
--- 470,477 ----
    if (have_ptrace_getvrregs)
      if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
        fetch_altivec_registers (tid);
!   if (tdep->ppc_ev0_upper_regnum >= 0)
!     fetch_spe_register (tid, -1);
  }
  
  /* Fetch registers from the child process.  Fetch all registers if
*************** set_spe_registers (int tid, struct gdb_e
*** 653,754 ****
      }
  }
  
! /* Store the bytes at SRC as the contents of TID's EV register EV_REGNUM.
!    Write the less significant word to TID using ptrace, and copy the
!    more significant word to the appropriate slot in EVRREGS.  */
! static void
! write_spliced_spe_reg (int tid, int ev_regnum,
!                        struct gdb_evrregset_t *evrregs,
!                        char *src)
! {
!   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
! 
!   /* Make sure we're trying to write an EV register; that's all we
!      handle.  */
!   gdb_assert (tdep->ppc_ev0_regnum <= ev_regnum
!               && ev_regnum <= tdep->ppc_ev31_regnum);
! 
!   /* Make sure the sizes for the splicing add up.  */
!   gdb_assert (sizeof (evrregs->evr[0]) + sizeof (PTRACE_XFER_TYPE)
!               == register_size (current_gdbarch, ev_regnum));
! 
!   {
!     int ev_index = ev_regnum - tdep->ppc_ev0_regnum;
! 
!     /* The number of the corresponding general-purpose register, which
!        holds the lower 32 bits of the EV register.  */
!     int gpr_regnum = tdep->ppc_gp0_regnum + ev_index;
! 
!     /* The offset of gpr_regnum in the process's uarea.  */
!     CORE_ADDR gpr_uoffset = ppc_register_u_addr (gpr_regnum);
! 
!     /* The PTRACE_POKEUSR / PT_WRITE_U ptrace requests need to be able
!        to return arbitrary register values, so they can't return -1 to
!        indicate an error.  So we clear errno, and check it again
!        afterwards.  */
!     errno = 0;
! 
!     if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
!       {
!         memcpy (&evrregs->evr[ev_index], src, sizeof (evrregs->evr[ev_index]));
!         ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) gpr_uoffset,
!                 * (PTRACE_XFER_TYPE *) (src + sizeof (evrregs->evr[0])));
!       }
!     else if (TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
!       {
!         ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) gpr_uoffset,
!                 * (PTRACE_XFER_TYPE *) src);
!         memcpy (&evrregs->evr[ev_index], src + sizeof (PTRACE_XFER_TYPE),
!                 sizeof (evrregs->evr[ev_index]));
!       }
!     else 
!       gdb_assert (0);
! 
!     if (errno != 0)
!       {
!         char message[128];
!         sprintf (message, "writing register %s (#%d)", 
!                  REGISTER_NAME (ev_regnum), ev_regnum);
!         perror_with_name (message);
!       }
!   }
! }
! 
! /* Write GDB's value for the SPE register REGNO to TID.  */
  static void
  store_spe_register (int tid, int regno)
  {
    struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
    struct gdb_evrregset_t evrregs;
  
!   /* We can only read and write the entire EVR register set at a time,
!      so to write just a single register, we do a read-modify-write
!      maneuver.  */
!   get_spe_registers (tid, &evrregs);
  
!   if (tdep->ppc_ev0_regnum >= 0
!       && tdep->ppc_ev0_regnum <= regno && regno <= tdep->ppc_ev31_regnum)
!     {
!       char buf[MAX_REGISTER_SIZE];
!       regcache_collect (regno, buf);
!       write_spliced_spe_reg (tid, regno, &evrregs, buf);
!     }
!   else if (tdep->ppc_acc_regnum >= 0
!            && regno == tdep->ppc_acc_regnum)
!     {
!       gdb_assert (sizeof (evrregs.acc)
!                   == register_size (current_gdbarch, regno));
!       regcache_collect (regno, &evrregs.acc);
!     }
!   else if (tdep->ppc_spefscr_regnum >= 0
!            && regno == tdep->ppc_spefscr_regnum)
!     {
!       gdb_assert (sizeof (evrregs.spefscr)
!                   == register_size (current_gdbarch, regno));
!       regcache_collect (regno, &evrregs.spefscr);
!     }
    else
!     gdb_assert (0);
  
    /* Write back the modified register set.  */
    set_spe_registers (tid, &evrregs);
--- 556,609 ----
      }
  }
  
! /* Write GDB's value for the SPE-specific raw register REGNO to TID.
!    If REGNO is -1, write the values of all the SPE-specific
!    registers.  */
  static void
  store_spe_register (int tid, int regno)
  {
    struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
    struct gdb_evrregset_t evrregs;
  
!   gdb_assert (sizeof (evrregs.evr[0])
!               == register_size (current_gdbarch, tdep->ppc_ev0_upper_regnum));
!   gdb_assert (sizeof (evrregs.acc)
!               == register_size (current_gdbarch, tdep->ppc_acc_regnum));
!   gdb_assert (sizeof (evrregs.spefscr)
!               == register_size (current_gdbarch, tdep->ppc_spefscr_regnum));
  
!   if (regno == -1)
!     /* Since we're going to write out every register, the code below
!        should store to every field of evrregs; if that doesn't happen,
!        make it obvious by initializing it with suspicious values.  */
!     memset (&evrregs, 42, sizeof (evrregs));
    else
!     /* We can only read and write the entire EVR register set at a
!        time, so to write just a single register, we do a
!        read-modify-write maneuver.  */
!     get_spe_registers (tid, &evrregs);
! 
!   if (regno == -1)
!     {
!       int i;
! 
!       for (i = 0; i < ppc_num_gprs; i++)
!         regcache_raw_collect (current_regcache,
!                               tdep->ppc_ev0_upper_regnum + i,
!                               &evrregs.evr[i]);
!     }
!   else if (tdep->ppc_ev0_upper_regnum <= regno
!            && regno < tdep->ppc_ev0_upper_regnum + ppc_num_gprs)
!     regcache_raw_collect (current_regcache, regno,
!                           &evrregs.evr[regno - tdep->ppc_ev0_upper_regnum]);
! 
!   if (regno == -1
!       || regno == tdep->ppc_acc_regnum)
!     regcache_raw_collect (current_regcache, regno, &evrregs.acc);
! 
!   if (regno == -1
!       || regno == tdep->ppc_spefscr_regnum)
!     regcache_raw_collect (current_regcache, regno, &evrregs.spefscr);
  
    /* Write back the modified register set.  */
    set_spe_registers (tid, &evrregs);
*************** store_register (int tid, int regno)
*** 764,775 ****
    size_t bytes_to_transfer;
    char buf[MAX_REGISTER_SIZE];
  
-   /* Sanity check: this function should only be called to store raw
-      registers' values, never pseudoregisters' values.  */
-   if (tdep->ppc_gp0_regnum <= regno
-       && regno < tdep->ppc_gp0_regnum + ppc_num_gprs)
-     gdb_assert (! tdep->ppc_gprs_pseudo_p);
- 
    if (altivec_register_p (regno))
      {
        store_altivec_register (tid, regno);
--- 619,624 ----
*************** store_altivec_registers (int tid)
*** 872,915 ****
  }
  
  static void
- store_spe_registers (tid)
- {
-   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-   struct gdb_evrregset_t evrregs;
-   int i;
- 
-   /* The code below should store to every field of evrregs; if that
-      doesn't happen, make it obvious by initializing it with
-      suspicious values.  */
-   memset (&evrregs, 42, sizeof (evrregs));
- 
-   for (i = 0; i < ppc_num_gprs; i++)
-     {
-       char buf[MAX_REGISTER_SIZE];
- 
-       regcache_collect (tdep->ppc_ev0_regnum + i, buf);
-       write_spliced_spe_reg (tid, tdep->ppc_ev0_regnum + i, &evrregs, buf);
-     }
- 
-   gdb_assert (sizeof (evrregs.acc)
-               == register_size (current_gdbarch, tdep->ppc_acc_regnum));
-   regcache_collect (tdep->ppc_acc_regnum, &evrregs.acc);
-   gdb_assert (sizeof (evrregs.spefscr)
-               == register_size (current_gdbarch, tdep->ppc_spefscr_regnum));
-   regcache_collect (tdep->ppc_acc_regnum, &evrregs.spefscr);
- 
-   set_spe_registers (tid, &evrregs);
- }
- 
- static void
  store_ppc_registers (int tid)
  {
    int i;
    struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
    
!   if (! tdep->ppc_gprs_pseudo_p)
!     for (i = 0; i < ppc_num_gprs; i++)
!       store_register (tid, tdep->ppc_gp0_regnum + i);
    if (tdep->ppc_fp0_regnum >= 0)
      for (i = 0; i < ppc_num_fprs; i++)
        store_register (tid, tdep->ppc_fp0_regnum + i);
--- 721,733 ----
  }
  
  static void
  store_ppc_registers (int tid)
  {
    int i;
    struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
    
!   for (i = 0; i < ppc_num_gprs; i++)
!     store_register (tid, tdep->ppc_gp0_regnum + i);
    if (tdep->ppc_fp0_regnum >= 0)
      for (i = 0; i < ppc_num_fprs; i++)
        store_register (tid, tdep->ppc_fp0_regnum + i);
*************** store_ppc_registers (int tid)
*** 931,938 ****
    if (have_ptrace_getvrregs)
      if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
        store_altivec_registers (tid);
!   if (tdep->ppc_ev0_regnum >= 0)
!     store_spe_registers (tid);
  }
  
  void
--- 749,756 ----
    if (have_ptrace_getvrregs)
      if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
        store_altivec_registers (tid);
!   if (tdep->ppc_ev0_upper_regnum >= 0)
!     store_spe_register (tid, -1);
  }
  
  void


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