Add support for the fpscr register for Power / PowerPC targets.
authorKevin Buettner <kevinb@redhat.com>
Thu, 11 Apr 2002 19:08:56 +0000 (19:08 +0000)
committerKevin Buettner <kevinb@redhat.com>
Thu, 11 Apr 2002 19:08:56 +0000 (19:08 +0000)
gdb/ChangeLog
gdb/ppc-bdm.c
gdb/ppc-linux-nat.c
gdb/ppc-tdep.h
gdb/rs6000-tdep.c

index 9c22f5e..dd24b74 100644 (file)
@@ -1,3 +1,19 @@
+2002-04-11  Kevin Buettner  <kevinb@redhat.com>
+
+       * ppc-tdep.h (struct gdbarch_tdep): Add new field ``ppc_fpscr_regnum''.
+       * ppc-bdm.c (bdm_ppc_fetch_registers, bdm_ppc_store_registers):
+       Add fpscr as an invalid/unfetchable register.
+       * ppc-linux-nat.c (ppc_register_u_addr, store_register)
+       (fetch_ppc_registers, store_ppc_registers, supply_fpregset)
+       (fill_fpregset): Add support for register fpscr.
+       (fetch_ppc_registers, store_ppc_registers, supply_gregset)
+       (fill_gregset): Account for the fact that register ``mq'' might
+       not exist.
+       * rs6000-tdep.c (PPC_UISA_SPRS): Use (unused) slot 70 for fpscr.
+       (registers_power): Add fpscr to register set at slot 71.
+       (rs6000_gdbarch_init): Account for the fact that ``mq'' doesn't
+       exist on most PPC architectures.  Initialize ppc_fpscr_regnum.
+
 2002-04-11  Michael Snyder  <msnyder@redhat.com>
 
        * configure.in: Autoconfiscate _SYSCALL32 define for solaris.
index b2287ea..f20918e 100644 (file)
@@ -201,6 +201,7 @@ bdm_ppc_fetch_registers (int regno)
 
       /* if asking for an invalid register */
       if ((first_regno == gdbarch_tdep (current_gdbarch)->ppc_mq_regnum)
+          || (first_regno == gdbarch_tdep (current_gdbarch)->fpscr_regnum)
          || ((first_regno >= FP0_REGNUM) && (first_regno <= FPLAST_REGNUM)))
        {
 /*          printf("invalid reg request!\n"); */
@@ -289,7 +290,9 @@ bdm_ppc_store_registers (int regno)
 
       /* only attempt to write if it's a valid ppc 8xx register */
       /* (need to avoid FP regs and MQ reg) */
-      if ((i != gdbarch_tdep (current_gdbarch)->ppc_mq_regnum) && ((i < FP0_REGNUM) || (i > FPLAST_REGNUM)))
+      if ((i != gdbarch_tdep (current_gdbarch)->ppc_mq_regnum) 
+          && (i != gdbarch_tdep (current_gdbarch)->ppc_fpscr_regnum) 
+          && ((i < FP0_REGNUM) || (i > FPLAST_REGNUM)))
        {
 /*          printf("write valid reg %d\n", bdm_regno); */
          ocd_write_bdm_registers (bdm_regno, registers + REGISTER_BYTE (i), 4);
index e4bb868..25616c0 100644 (file)
@@ -149,6 +149,8 @@ ppc_register_u_addr (int regno)
     u_addr = PT_MQ * 4;
   if (regno == tdep->ppc_ps_regnum)
     u_addr = PT_MSR * 4;
+  if (regno == tdep->ppc_fpscr_regnum)
+    u_addr = PT_FPSCR * 4;
 
   return u_addr;
 }
@@ -290,8 +292,10 @@ fetch_ppc_registers (int tid)
   int i;
   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
 
-  for (i = 0; i <= tdep->ppc_mq_regnum; i++)
+  for (i = 0; i <= tdep->ppc_fpscr_regnum; i++)
     fetch_register (tid, i);
+  if (tdep->ppc_mq_regnum != -1)
+    fetch_register (tid, tdep->ppc_mq_regnum);
   if (have_ptrace_getvrregs)
     if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
       fetch_altivec_registers (tid);
@@ -376,6 +380,14 @@ store_register (int tid, int regno)
       ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr,
              *(PTRACE_XFER_TYPE *) & buf[i]);
       regaddr += sizeof (PTRACE_XFER_TYPE);
+
+      if (errno == EIO 
+          && regno == gdbarch_tdep (current_gdbarch)->ppc_fpscr_regnum)
+       {
+         /* Some older kernel versions don't allow fpscr to be written.  */
+         continue;
+       }
+
       if (errno != 0)
        {
          sprintf (mess, "writing register %s (#%d)", 
@@ -435,8 +447,10 @@ store_ppc_registers (int tid)
   int i;
   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
   
-  for (i = 0; i <= tdep->ppc_mq_regnum; i++)
+  for (i = 0; i <= tdep->ppc_fpscr_regnum; i++)
     store_register (tid, i);
+  if (tdep->ppc_mq_regnum != -1)
+    store_register (tid, tdep->ppc_mq_regnum);
   if (have_ptrace_getvrregs)
     if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
       store_altivec_registers (tid);
@@ -473,7 +487,8 @@ supply_gregset (gdb_gregset_t *gregsetp)
   supply_register (tdep->ppc_cr_regnum, (char *) (regp + PT_CCR));
   supply_register (tdep->ppc_xer_regnum, (char *) (regp + PT_XER));
   supply_register (tdep->ppc_ctr_regnum, (char *) (regp + PT_CTR));
-  supply_register (tdep->ppc_mq_regnum, (char *) (regp + PT_MQ));
+  if (tdep->ppc_mq_regnum != -1)
+    supply_register (tdep->ppc_mq_regnum, (char *) (regp + PT_MQ));
   supply_register (tdep->ppc_ps_regnum, (char *) (regp + PT_MSR));
 }
 
@@ -500,7 +515,8 @@ fill_gregset (gdb_gregset_t *gregsetp, int regno)
     regcache_collect (tdep->ppc_xer_regnum, regp + PT_XER);
   if ((regno == -1) || regno == tdep->ppc_ctr_regnum)
     regcache_collect (tdep->ppc_ctr_regnum, regp + PT_CTR);
-  if ((regno == -1) || regno == tdep->ppc_mq_regnum)
+  if (((regno == -1) || regno == tdep->ppc_mq_regnum)
+      && (tdep->ppc_mq_regnum != -1))
     regcache_collect (tdep->ppc_mq_regnum, regp + PT_MQ);
   if ((regno == -1) || regno == tdep->ppc_ps_regnum)
     regcache_collect (tdep->ppc_ps_regnum, regp + PT_MSR);
@@ -510,9 +526,11 @@ void
 supply_fpregset (gdb_fpregset_t * fpregsetp)
 {
   int regi;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); 
 
   for (regi = 0; regi < 32; regi++)
     supply_register (FP0_REGNUM + regi, (char *) (*fpregsetp + regi));
+  supply_register (tdep->ppc_fpscr_regnum, (char *) (*fpregsetp + 32));
 }
 
 /* Given a pointer to a floating point register set in /proc format
@@ -523,10 +541,13 @@ void
 fill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
 {
   int regi;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); 
   
   for (regi = 0; regi < 32; regi++)
     {
       if ((regno == -1) || (regno == FP0_REGNUM + regi))
        regcache_collect (FP0_REGNUM + regi, (char *) (*fpregsetp + regi));
     }
+  if ((regno == -1) || regno == tdep->ppc_fpscr_regnum)
+    regcache_collect (tdep->ppc_fpscr_regnum, (char *) (*fpregsetp + regi));
 }
index ea4d787..ec64514 100644 (file)
@@ -62,6 +62,8 @@ struct gdbarch_tdep
     int ppc_lr_regnum;         /* Link register */
     int ppc_ctr_regnum;                /* Count register */
     int ppc_xer_regnum;                /* Integer exception register */
+    int ppc_fpscr_regnum;      /* Floating point status and condition
+                                  register */
     int ppc_mq_regnum;         /* Multiply/Divide extension register */
     int ppc_vr0_regnum;                /* First AltiVec register */
     int ppc_vrsave_regnum;     /* Last AltiVec register */
index 4b07b5d..73b2cba 100644 (file)
@@ -2075,7 +2075,7 @@ rs6000_convert_from_func_ptr_addr (CORE_ADDR addr)
 
 /* UISA-level SPRs for PowerPC.  */
 #define PPC_UISA_SPRS \
-  /* 66 */ R4(cr),  R(lr), R(ctr), R4(xer), R0
+  /* 66 */ R4(cr),  R(lr), R(ctr), R4(xer), R4(fpscr)
 
 /* Segment registers, for PowerPC.  */
 #define PPC_SEGMENT_REGS \
@@ -2109,7 +2109,8 @@ rs6000_convert_from_func_ptr_addr (CORE_ADDR addr)
 static const struct reg registers_power[] =
 {
   COMMON_UISA_REGS,
-  /* 66 */ R4(cnd), R(lr), R(cnt), R4(xer), R4(mq)
+  /* 66 */ R4(cnd), R(lr), R(cnt), R4(xer), R4(mq),
+  /* 71 */ R4(fpscr)
 };
 
 /* PowerPC UISA - a PPC processor as viewed by user-level code.  A UISA-only
@@ -2547,8 +2548,11 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->ppc_xer_regnum = 69;
   if (v->mach == bfd_mach_ppc_601)
     tdep->ppc_mq_regnum = 124;
-  else
+  else if (power)
     tdep->ppc_mq_regnum = 70;
+  else
+    tdep->ppc_mq_regnum = -1;
+  tdep->ppc_fpscr_regnum = power ? 71 : 70;
 
   if (v->arch == bfd_arch_powerpc)
     switch (v->mach)