This is the mail archive of the gdb-patches@sourceware.cygnus.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]

[PATCH] Linux/i386 FPU registers fix


FYI,

I checked in the attached patch.  It makes sure that GDB ignores the
reserved bits in the FPU state.

Mark


2000-03-06  Mark Kettenis  <kettenis@gnu.org>

	* i386-linux-nat.c (supply_fpregset): Mask off the reserved bits
	in *FPREGSETP.
	(convert_to_fpregset): Don't touch the reserved bits in *FPREGSETP.


Index: i386-linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-linux-nat.c,v
retrieving revision 1.3
diff -u -p -r1.3 i386-linux-nat.c
--- i386-linux-nat.c	2000/03/05 22:57:05	1.3
+++ i386-linux-nat.c	2000/03/06 16:04:44
@@ -393,28 +393,33 @@ void 
 supply_fpregset (elf_fpregset_t *fpregsetp)
 {
   int reg;
+  long l;
 
   /* Supply the floating-point registers.  */
   for (reg = 0; reg < 8; reg++)
     supply_register (FP0_REGNUM + reg, FPREG_ADDR (fpregsetp, reg));
 
-  supply_register (FCTRL_REGNUM, (char *) &fpregsetp->cwd);
-  supply_register (FSTAT_REGNUM, (char *) &fpregsetp->swd);
-  supply_register (FTAG_REGNUM,  (char *) &fpregsetp->twd);
+  /* We have to mask off the reserved bits in *FPREGSETP before
+     storing the values in GDB's register file.  */
+#define supply(REGNO, MEMBER)                                           \
+  l = fpregsetp->MEMBER & 0xffff;                                       \
+  supply_register (REGNO, (char *) &l)
+
+  supply (FCTRL_REGNUM, cwd);
+  supply (FSTAT_REGNUM, swd);
+  supply (FTAG_REGNUM, twd);
   supply_register (FCOFF_REGNUM, (char *) &fpregsetp->fip);
-  supply_register (FDS_REGNUM,   (char *) &fpregsetp->fos);
+  supply (FDS_REGNUM, fos);
   supply_register (FDOFF_REGNUM, (char *) &fpregsetp->foo);
-  
-  /* Extract the code segment and opcode from the  "fcs" member.  */
-  {
-    long l;
+
+#undef supply
 
-    l = fpregsetp->fcs & 0xffff;
-    supply_register (FCS_REGNUM, (char *) &l);
+  /* Extract the code segment and opcode from the  "fcs" member.  */
+  l = fpregsetp->fcs & 0xffff;
+  supply_register (FCS_REGNUM, (char *) &l);
 
-    l = (fpregsetp->fcs >> 16) & ((1 << 11) - 1);
-    supply_register (FOP_REGNUM, (char *) &l);
-  }
+  l = (fpregsetp->fcs >> 16) & ((1 << 11) - 1);
+  supply_register (FOP_REGNUM, (char *) &l);
 }
 
 /* Convert the valid floating-point register values in GDB's register
@@ -434,19 +439,28 @@ convert_to_fpregset (elf_fpregset_t *fpr
 	      &registers[REGISTER_BYTE (FP0_REGNUM + reg)],
 	      REGISTER_RAW_SIZE(FP0_REGNUM + reg));
 
+  /* We're not supposed to touch the reserved bits in *FPREGSETP.  */
+
 #define fill(MEMBER, REGNO)						\
   if (! valid || valid[(REGNO)])					\
-    memcpy (&fpregsetp->MEMBER, &registers[REGISTER_BYTE (REGNO)],	\
-	    sizeof (fpregsetp->MEMBER))
+    fpregsetp->MEMBER                                                   \
+      = ((fpregsetp->MEMBER & ~0xffff)                                  \
+         | (* (int *) &registers[REGISTER_BYTE (REGNO)] & 0xffff))
+
+#define fill_register(MEMBER, REGNO)                                    \
+  if (! valid || valid[(REGNO)])                                        \
+    memcpy (&fpregsetp->MEMBER, &registers[REGISTER_BYTE (REGNO)],      \
+            sizeof (fpregsetp->MEMBER))
 
   fill (cwd, FCTRL_REGNUM);
   fill (swd, FSTAT_REGNUM);
   fill (twd, FTAG_REGNUM);
-  fill (fip, FCOFF_REGNUM);
+  fill_register (fip, FCOFF_REGNUM);
   fill (foo, FDOFF_REGNUM);
-  fill (fos, FDS_REGNUM);
+  fill_register (fos, FDS_REGNUM);
 
 #undef fill
+#undef fill_register
 
   if (! valid || valid[FCS_REGNUM])
     fpregsetp->fcs

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