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]

[PATCH] Add support for fpscr for Power / PowerPC targets


I've just committed the patch below.  It adds support for the fpscr
register for Power and PowerPC targets.  I've tested this patch on
GNU/Linux/PPC (native).  

For PowerPC, the fpscr regnum is 70, which was an unused slot.  For
Power, I chose to use the first available slot (71).  The other change
that this patch makes is to make MQ unavailable for all PowerPC
targets except for the 601 processors (which is as it should be).

	* 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.

Index: ppc-bdm.c
===================================================================
RCS file: /cvs/src/src/gdb/ppc-bdm.c,v
retrieving revision 1.12
diff -u -p -r1.12 ppc-bdm.c
--- ppc-bdm.c	9 Dec 2001 21:39:53 -0000	1.12
+++ ppc-bdm.c	11 Apr 2002 08:34:35 -0000
@@ -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: ppc-linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/ppc-linux-nat.c,v
retrieving revision 1.16
diff -u -p -r1.16 ppc-linux-nat.c
--- ppc-linux-nat.c	21 Feb 2002 22:04:46 -0000	1.16
+++ ppc-linux-nat.c	11 Apr 2002 08:34:36 -0000
@@ -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, i
     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: ppc-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/ppc-tdep.h,v
retrieving revision 1.7
diff -u -p -r1.7 ppc-tdep.h
--- ppc-tdep.h	22 Mar 2002 21:58:16 -0000	1.7
+++ ppc-tdep.h	11 Apr 2002 08:34:36 -0000
@@ -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: rs6000-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v
retrieving revision 1.49
diff -u -p -r1.49 rs6000-tdep.c
--- rs6000-tdep.c	9 Apr 2002 02:26:10 -0000	1.49
+++ rs6000-tdep.c	11 Apr 2002 08:34:40 -0000
@@ -2075,7 +2075,7 @@ rs6000_convert_from_func_ptr_addr (CORE_
 
 /* 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_
 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
   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)


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