This is the mail archive of the
gdb-patches@sourceware.cygnus.com
mailing list for the GDB project.
[PATCH] Linux/i386 FPU registers fix
- To: gdb-patches at sourceware dot cygnus dot com
- Subject: [PATCH] Linux/i386 FPU registers fix
- From: Mark Kettenis <kettenis at wins dot uva dot nl>
- Date: Mon, 6 Mar 2000 17:15:00 +0100
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
®isters[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, ®isters[REGISTER_BYTE (REGNO)], \
- sizeof (fpregsetp->MEMBER))
+ fpregsetp->MEMBER \
+ = ((fpregsetp->MEMBER & ~0xffff) \
+ | (* (int *) ®isters[REGISTER_BYTE (REGNO)] & 0xffff))
+
+#define fill_register(MEMBER, REGNO) \
+ if (! valid || valid[(REGNO)]) \
+ memcpy (&fpregsetp->MEMBER, ®isters[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