Merge from gcc:
[deliverable/binutils-gdb.git] / gdb / ppc-linux-nat.c
index b5c5afb393a4d3a8eaba10510687b7d3e495ba95..f1758c88e60edc213cf59a2324ee431b0335be62 100644 (file)
@@ -7,7 +7,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -16,9 +16,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "gdb_string.h"
@@ -144,8 +142,6 @@ struct gdb_evrregset_t
    error.  */
 int have_ptrace_getvrregs = 1;
 
-static CORE_ADDR last_stopped_data_address = 0;
-
 /* Non-zero if our kernel may support the PTRACE_GETEVRREGS and
    PTRACE_SETEVRREGS requests, for reading and writing the SPE
    registers.  Zero if we've tried one of them and gotten an
@@ -188,7 +184,7 @@ ppc_register_u_addr (int regno)
     u_addr = (PT_FPR0 * wordsize) + ((regno - tdep->ppc_fp0_regnum) * 8);
 
   /* UISA special purpose registers: 1 slot each */
-  if (regno == PC_REGNUM)
+  if (regno == gdbarch_pc_regnum (current_gdbarch))
     u_addr = PT_NIP * wordsize;
   if (regno == tdep->ppc_lr_regnum)
     u_addr = PT_LNK * wordsize;
@@ -231,8 +227,9 @@ fetch_altivec_register (struct regcache *regcache, int tid, int regno)
   int ret;
   int offset = 0;
   gdb_vrregset_t regs;
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-  int vrregsize = register_size (current_gdbarch, tdep->ppc_vr0_regnum);
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int vrregsize = register_size (gdbarch, tdep->ppc_vr0_regnum);
 
   ret = ptrace (PTRACE_GETVRREGS, tid, 0, &regs);
   if (ret < 0)
@@ -250,7 +247,7 @@ fetch_altivec_register (struct regcache *regcache, int tid, int regno)
      vector.  VRSAVE is at the end of the array in a 4 bytes slot, so
      there is no need to define an offset for it.  */
   if (regno == (tdep->ppc_vrsave_regnum - 1))
-    offset = vrregsize - register_size (current_gdbarch, tdep->ppc_vrsave_regnum);
+    offset = vrregsize - register_size (gdbarch, tdep->ppc_vrsave_regnum);
   
   regcache_raw_supply (regcache, regno,
                       regs + (regno - tdep->ppc_vr0_regnum) * vrregsize + offset);
@@ -293,15 +290,16 @@ get_spe_registers (int tid, struct gdb_evrregset_t *evrregset)
 static void
 fetch_spe_register (struct regcache *regcache, int tid, int regno)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   struct gdb_evrregset_t evrregs;
 
   gdb_assert (sizeof (evrregs.evr[0])
-              == register_size (current_gdbarch, tdep->ppc_ev0_upper_regnum));
+              == register_size (gdbarch, tdep->ppc_ev0_upper_regnum));
   gdb_assert (sizeof (evrregs.acc)
-              == register_size (current_gdbarch, tdep->ppc_acc_regnum));
+              == register_size (gdbarch, tdep->ppc_acc_regnum));
   gdb_assert (sizeof (evrregs.spefscr)
-              == register_size (current_gdbarch, tdep->ppc_spefscr_regnum));
+              == register_size (gdbarch, tdep->ppc_spefscr_regnum));
 
   get_spe_registers (tid, &evrregs);
 
@@ -331,7 +329,8 @@ fetch_spe_register (struct regcache *regcache, int tid, int regno)
 static void
 fetch_register (struct regcache *regcache, int tid, int regno)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   /* This isn't really an address.  But ptrace thinks of it as one.  */
   CORE_ADDR regaddr = ppc_register_u_addr (regno);
   int bytes_transferred;
@@ -361,7 +360,7 @@ fetch_register (struct regcache *regcache, int tid, int regno)
 
   if (regaddr == -1)
     {
-      memset (buf, '\0', register_size (current_gdbarch, regno));   /* Supply zeroes */
+      memset (buf, '\0', register_size (gdbarch, regno));   /* Supply zeroes */
       regcache_raw_supply (regcache, regno, buf);
       return;
     }
@@ -370,7 +369,7 @@ fetch_register (struct regcache *regcache, int tid, int regno)
      32-bit platform, 64-bit floating-point registers will require two
      transfers.  */
   for (bytes_transferred = 0;
-       bytes_transferred < register_size (current_gdbarch, regno);
+       bytes_transferred < register_size (gdbarch, regno);
        bytes_transferred += sizeof (long))
     {
       errno = 0;
@@ -381,7 +380,7 @@ fetch_register (struct regcache *regcache, int tid, int regno)
        {
           char message[128];
          sprintf (message, "reading register %s (#%d)", 
-                  REGISTER_NAME (regno), regno);
+                  gdbarch_register_name (gdbarch, regno), regno);
          perror_with_name (message);
        }
     }
@@ -389,34 +388,34 @@ fetch_register (struct regcache *regcache, int tid, int regno)
   /* Now supply the register.  Keep in mind that the regcache's idea
      of the register's size may not be a multiple of sizeof
      (long).  */
-  if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_LITTLE)
+  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
     {
       /* Little-endian values are always found at the left end of the
          bytes transferred.  */
       regcache_raw_supply (regcache, regno, buf);
     }
-  else if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
+  else if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
     {
       /* Big-endian values are found at the right end of the bytes
          transferred.  */
-      size_t padding = (bytes_transferred
-                        - register_size (current_gdbarch, regno));
+      size_t padding = (bytes_transferred - register_size (gdbarch, regno));
       regcache_raw_supply (regcache, regno, buf + padding);
     }
   else 
     internal_error (__FILE__, __LINE__,
                     _("fetch_register: unexpected byte order: %d"),
-                    gdbarch_byte_order (current_gdbarch));
+                    gdbarch_byte_order (gdbarch));
 }
 
 static void
 supply_vrregset (struct regcache *regcache, gdb_vrregset_t *vrregsetp)
 {
   int i;
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   int num_of_vrregs = tdep->ppc_vrsave_regnum - tdep->ppc_vr0_regnum + 1;
-  int vrregsize = register_size (current_gdbarch, tdep->ppc_vr0_regnum);
-  int offset = vrregsize - register_size (current_gdbarch, tdep->ppc_vrsave_regnum);
+  int vrregsize = register_size (gdbarch, tdep->ppc_vr0_regnum);
+  int offset = vrregsize - register_size (gdbarch, tdep->ppc_vrsave_regnum);
 
   for (i = 0; i < num_of_vrregs; i++)
     {
@@ -456,14 +455,15 @@ static void
 fetch_ppc_registers (struct regcache *regcache, int tid)
 {
   int i;
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   for (i = 0; i < ppc_num_gprs; i++)
     fetch_register (regcache, tid, tdep->ppc_gp0_regnum + i);
   if (tdep->ppc_fp0_regnum >= 0)
     for (i = 0; i < ppc_num_fprs; i++)
       fetch_register (regcache, tid, tdep->ppc_fp0_regnum + i);
-  fetch_register (regcache, tid, PC_REGNUM);
+  fetch_register (regcache, tid, gdbarch_pc_regnum (gdbarch));
   if (tdep->ppc_ps_regnum != -1)
     fetch_register (regcache, tid, tdep->ppc_ps_regnum);
   if (tdep->ppc_cr_regnum != -1)
@@ -511,8 +511,9 @@ store_altivec_register (const struct regcache *regcache, int tid, int regno)
   int ret;
   int offset = 0;
   gdb_vrregset_t regs;
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-  int vrregsize = register_size (current_gdbarch, tdep->ppc_vr0_regnum);
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int vrregsize = register_size (gdbarch, tdep->ppc_vr0_regnum);
 
   ret = ptrace (PTRACE_GETVRREGS, tid, 0, &regs);
   if (ret < 0)
@@ -528,7 +529,7 @@ store_altivec_register (const struct regcache *regcache, int tid, int regno)
   /* VSCR is fetched as a 16 bytes quantity, but it is really 4 bytes
      long on the hardware.  */
   if (regno == (tdep->ppc_vrsave_regnum - 1))
-    offset = vrregsize - register_size (current_gdbarch, tdep->ppc_vrsave_regnum);
+    offset = vrregsize - register_size (gdbarch, tdep->ppc_vrsave_regnum);
 
   regcache_raw_collect (regcache, regno,
                        regs + (regno - tdep->ppc_vr0_regnum) * vrregsize + offset);
@@ -573,15 +574,16 @@ set_spe_registers (int tid, struct gdb_evrregset_t *evrregset)
 static void
 store_spe_register (const struct regcache *regcache, int tid, int regno)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   struct gdb_evrregset_t evrregs;
 
   gdb_assert (sizeof (evrregs.evr[0])
-              == register_size (current_gdbarch, tdep->ppc_ev0_upper_regnum));
+              == register_size (gdbarch, tdep->ppc_ev0_upper_regnum));
   gdb_assert (sizeof (evrregs.acc)
-              == register_size (current_gdbarch, tdep->ppc_acc_regnum));
+              == register_size (gdbarch, tdep->ppc_acc_regnum));
   gdb_assert (sizeof (evrregs.spefscr)
-              == register_size (current_gdbarch, tdep->ppc_spefscr_regnum));
+              == register_size (gdbarch, tdep->ppc_spefscr_regnum));
 
   if (regno == -1)
     /* Since we're going to write out every register, the code below
@@ -627,7 +629,8 @@ store_spe_register (const struct regcache *regcache, int tid, int regno)
 static void
 store_register (const struct regcache *regcache, int tid, int regno)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   /* This isn't really an address.  But ptrace thinks of it as one.  */
   CORE_ADDR regaddr = ppc_register_u_addr (regno);
   int i;
@@ -652,18 +655,16 @@ store_register (const struct regcache *regcache, int tid, int regno)
      idea of the register's size may not be a multiple of sizeof
      (long).  */
   memset (buf, 0, sizeof buf);
-  bytes_to_transfer = align_up (register_size (current_gdbarch, regno),
-                                sizeof (long));
-  if (TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
+  bytes_to_transfer = align_up (register_size (gdbarch, regno), sizeof (long));
+  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
     {
       /* Little-endian values always sit at the left end of the buffer.  */
       regcache_raw_collect (regcache, regno, buf);
     }
-  else if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+  else if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
     {
       /* Big-endian values sit at the right end of the buffer.  */
-      size_t padding = (bytes_to_transfer
-                        - register_size (current_gdbarch, regno));
+      size_t padding = (bytes_to_transfer - register_size (gdbarch, regno));
       regcache_raw_collect (regcache, regno, buf + padding);
     }
 
@@ -685,7 +686,7 @@ store_register (const struct regcache *regcache, int tid, int regno)
        {
           char message[128];
          sprintf (message, "writing register %s (#%d)", 
-                  REGISTER_NAME (regno), regno);
+                  gdbarch_register_name (gdbarch, regno), regno);
          perror_with_name (message);
        }
     }
@@ -695,10 +696,11 @@ static void
 fill_vrregset (const struct regcache *regcache, gdb_vrregset_t *vrregsetp)
 {
   int i;
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   int num_of_vrregs = tdep->ppc_vrsave_regnum - tdep->ppc_vr0_regnum + 1;
-  int vrregsize = register_size (current_gdbarch, tdep->ppc_vr0_regnum);
-  int offset = vrregsize - register_size (current_gdbarch, tdep->ppc_vrsave_regnum);
+  int vrregsize = register_size (gdbarch, tdep->ppc_vr0_regnum);
+  int offset = vrregsize - register_size (gdbarch, tdep->ppc_vrsave_regnum);
 
   for (i = 0; i < num_of_vrregs; i++)
     {
@@ -740,14 +742,15 @@ static void
 store_ppc_registers (const struct regcache *regcache, int tid)
 {
   int i;
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   
   for (i = 0; i < ppc_num_gprs; i++)
     store_register (regcache, tid, tdep->ppc_gp0_regnum + i);
   if (tdep->ppc_fp0_regnum >= 0)
     for (i = 0; i < ppc_num_fprs; i++)
       store_register (regcache, tid, tdep->ppc_fp0_regnum + i);
-  store_register (regcache, tid, PC_REGNUM);
+  store_register (regcache, tid, gdbarch_pc_regnum (gdbarch));
   if (tdep->ppc_ps_regnum != -1)
     store_register (regcache, tid, tdep->ppc_ps_regnum);
   if (tdep->ppc_cr_regnum != -1)
@@ -807,13 +810,16 @@ ppc_linux_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
   return 1;
 }
 
+/* The cached DABR value, to install in new threads.  */
+static long saved_dabr_value;
+
 /* Set a watchpoint of type TYPE at address ADDR.  */
 static int
 ppc_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw)
 {
-  int tid;
+  struct lwp_info *lp;
+  ptid_t ptid;
   long dabr_value;
-  ptid_t ptid = inferior_ptid;
 
   dabr_value = addr & ~7;
   switch (rw)
@@ -832,61 +838,57 @@ ppc_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw)
       break;
     }
 
-  tid = TIDGET (ptid);
-  if (tid == 0)
-    tid = PIDGET (ptid);
+  saved_dabr_value = dabr_value;
+
+  ALL_LWPS (lp, ptid)
+    if (ptrace (PTRACE_SET_DEBUGREG, TIDGET (ptid), 0, saved_dabr_value) < 0)
+      return -1;
 
-  return ptrace (PTRACE_SET_DEBUGREG, tid, 0, dabr_value);
+  return 0;
 }
 
 static int
 ppc_linux_remove_watchpoint (CORE_ADDR addr, int len, int rw)
 {
-  int tid;
-  ptid_t ptid = inferior_ptid;
-
-  tid = TIDGET (ptid);
-  if (tid == 0)
-    tid = PIDGET (ptid);
-
-  return ptrace (PTRACE_SET_DEBUGREG, tid, 0, 0);
+  struct lwp_info *lp;
+  ptid_t ptid;
+  long dabr_value = 0;
+
+  saved_dabr_value = 0;
+  ALL_LWPS (lp, ptid)
+    if (ptrace (PTRACE_SET_DEBUGREG, TIDGET (ptid), 0, saved_dabr_value) < 0)
+      return -1;
+  return 0;
 }
 
-static int
-ppc_linux_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
+static void
+ppc_linux_new_thread (ptid_t ptid)
 {
-  if (last_stopped_data_address)
-    {
-      *addr_p = last_stopped_data_address;
-      last_stopped_data_address = 0;
-      return 1;
-    }
-  return 0;
+  ptrace (PTRACE_SET_DEBUGREG, TIDGET (ptid), 0, saved_dabr_value);
 }
 
 static int
-ppc_linux_stopped_by_watchpoint (void)
+ppc_linux_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
 {
-  int tid;
-  struct siginfo siginfo;
-  ptid_t ptid = inferior_ptid;
-  CORE_ADDR *addr_p;
-
-  tid = TIDGET(ptid);
-  if (tid == 0)
-    tid = PIDGET (ptid);
+  struct siginfo *siginfo_p;
 
-  errno = 0;
-  ptrace (PTRACE_GETSIGINFO, tid, (PTRACE_TYPE_ARG3) 0, &siginfo);
+  siginfo_p = linux_nat_get_siginfo (inferior_ptid);
 
-  if (errno != 0 || siginfo.si_signo != SIGTRAP ||
-      (siginfo.si_code & 0xffff) != 0x0004)
+  if (siginfo_p->si_signo != SIGTRAP
+      || (siginfo_p->si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
     return 0;
 
-  last_stopped_data_address = (uintptr_t) siginfo.si_addr;
+  *addr_p = (CORE_ADDR) (uintptr_t) siginfo_p->si_addr;
   return 1;
 }
 
+static int
+ppc_linux_stopped_by_watchpoint (void)
+{
+  CORE_ADDR addr;
+  return ppc_linux_stopped_data_address (&current_target, &addr);
+}
+
 static void
 ppc_linux_store_inferior_registers (struct regcache *regcache, int regno)
 {
@@ -903,100 +905,75 @@ ppc_linux_store_inferior_registers (struct regcache *regcache, int regno)
     store_ppc_registers (regcache, tid);
 }
 
+/* Functions for transferring registers between a gregset_t or fpregset_t
+   (see sys/ucontext.h) and gdb's regcache.  The word size is that used
+   by the ptrace interface, not the current program's ABI.  eg. If a
+   powerpc64-linux gdb is being used to debug a powerpc32-linux app, we
+   read or write 64-bit gregsets.  This is to suit the host libthread_db.  */
+
 void
 supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
 {
-  /* NOTE: cagney/2003-11-25: This is the word size used by the ptrace
-     interface, and not the wordsize of the program's ABI.  */
-  int wordsize = sizeof (long);
-  ppc_linux_supply_gregset (regcache, -1, gregsetp,
-                           sizeof (gdb_gregset_t), wordsize);
-}
+  const struct regset *regset = ppc_linux_gregset (sizeof (long));
 
-static void
-right_fill_reg (const struct regcache *regcache, int regnum, void *reg)
-{
-  /* NOTE: cagney/2003-11-25: This is the word size used by the ptrace
-     interface, and not the wordsize of the program's ABI.  */
-  int wordsize = sizeof (long);
-  /* Right fill the register.  */
-  regcache_raw_collect (regcache, regnum,
-                       ((bfd_byte *) reg
-                        + wordsize
-                        - register_size (current_gdbarch, regnum)));
+  ppc_supply_gregset (regset, regcache, -1, gregsetp, sizeof (*gregsetp));
 }
 
 void
 fill_gregset (const struct regcache *regcache,
              gdb_gregset_t *gregsetp, int regno)
 {
-  int regi;
-  elf_greg_t *regp = (elf_greg_t *) gregsetp;
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); 
-  const int elf_ngreg = 48;
-
-
-  /* Start with zeros.  */
-  memset (regp, 0, elf_ngreg * sizeof (*regp));
-
-  for (regi = 0; regi < ppc_num_gprs; regi++)
-    {
-      if ((regno == -1) || regno == tdep->ppc_gp0_regnum + regi)
-       right_fill_reg (regcache, tdep->ppc_gp0_regnum + regi,
-                       (regp + PT_R0 + regi));
-    }
+  const struct regset *regset = ppc_linux_gregset (sizeof (long));
 
-  if ((regno == -1) || regno == PC_REGNUM)
-    right_fill_reg (regcache, PC_REGNUM, regp + PT_NIP);
-  if ((regno == -1) || regno == tdep->ppc_lr_regnum)
-    right_fill_reg (regcache, tdep->ppc_lr_regnum, regp + PT_LNK);
-  if ((regno == -1) || regno == tdep->ppc_cr_regnum)
-    regcache_raw_collect (regcache, tdep->ppc_cr_regnum,
-                         regp + PT_CCR);
-  if ((regno == -1) || regno == tdep->ppc_xer_regnum)
-    regcache_raw_collect (regcache, tdep->ppc_xer_regnum,
-                         regp + PT_XER);
-  if ((regno == -1) || regno == tdep->ppc_ctr_regnum)
-    right_fill_reg (regcache, tdep->ppc_ctr_regnum, regp + PT_CTR);
-#ifdef PT_MQ
-  if (((regno == -1) || regno == tdep->ppc_mq_regnum)
-      && (tdep->ppc_mq_regnum != -1))
-    right_fill_reg (regcache, tdep->ppc_mq_regnum, regp + PT_MQ);
-#endif
-  if ((regno == -1) || regno == tdep->ppc_ps_regnum)
-    right_fill_reg (regcache, tdep->ppc_ps_regnum, regp + PT_MSR);
+  if (regno == -1)
+    memset (gregsetp, 0, sizeof (*gregsetp));
+  ppc_collect_gregset (regset, regcache, regno, gregsetp, sizeof (*gregsetp));
 }
 
 void
 supply_fpregset (struct regcache *regcache, const gdb_fpregset_t * fpregsetp)
 {
-  ppc_linux_supply_fpregset (NULL, regcache, -1, fpregsetp,
-                            sizeof (gdb_fpregset_t));
+  const struct regset *regset = ppc_linux_fpregset ();
+
+  ppc_supply_fpregset (regset, regcache, -1,
+                      fpregsetp, sizeof (*fpregsetp));
 }
 
-/* Given a pointer to a floating point register set in /proc format
-   (fpregset_t *), update the register specified by REGNO from gdb's
-   idea of the current floating point register set.  If REGNO is -1,
-   update them all.  */
 void
 fill_fpregset (const struct regcache *regcache,
               gdb_fpregset_t *fpregsetp, int regno)
 {
-  int regi;
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); 
-  bfd_byte *fpp = (void *) fpregsetp;
-  
-  if (ppc_floating_point_unit_p (current_gdbarch))
+  const struct regset *regset = ppc_linux_fpregset ();
+
+  ppc_collect_fpregset (regset, regcache, regno,
+                       fpregsetp, sizeof (*fpregsetp));
+}
+
+static const struct target_desc *
+ppc_linux_read_description (struct target_ops *ops)
+{
+  if (have_ptrace_getsetevrregs)
     {
-      for (regi = 0; regi < ppc_num_fprs; regi++)
+      struct gdb_evrregset_t evrregset;
+      int tid = TIDGET (inferior_ptid);
+
+      if (tid == 0)
+       tid = PIDGET (inferior_ptid);
+
+      if (ptrace (PTRACE_GETEVRREGS, tid, 0, &evrregset) >= 0)
+        return tdesc_powerpc_e500;
+      else
         {
-          if ((regno == -1) || (regno == tdep->ppc_fp0_regnum + regi))
-            regcache_raw_collect (regcache, tdep->ppc_fp0_regnum + regi,
-                                 fpp + 8 * regi);
-        }
-      if (regno == -1 || regno == tdep->ppc_fpscr_regnum)
-        right_fill_reg (regcache, tdep->ppc_fpscr_regnum, (fpp + 8 * 32));
+          /* EIO means that the PTRACE_GETEVRREGS request isn't supported.  */
+          if (errno == EIO)
+           return NULL;
+         else
+            /* Anything else needs to be reported.  */
+            perror_with_name (_("Unable to fetch SPE registers"));
+       }
     }
+
+  return NULL;
 }
 
 void _initialize_ppc_linux_nat (void);
@@ -1021,6 +998,9 @@ _initialize_ppc_linux_nat (void)
   t->to_stopped_by_watchpoint = ppc_linux_stopped_by_watchpoint;
   t->to_stopped_data_address = ppc_linux_stopped_data_address;
 
+  t->to_read_description = ppc_linux_read_description;
+
   /* Register the target.  */
   linux_nat_add_target (t);
+  linux_nat_set_new_thread (t, ppc_linux_new_thread);
 }
This page took 0.030903 seconds and 4 git commands to generate.