*BSD News Article 8312


Return to BSD News archive

Newsgroups: comp.unix.bsd
Path: sserve!manuel.anu.edu.au!munnari.oz.au!metro!ipso!runxtsa!bde
From: bde@runx.oz.au (Bruce Evans)
Subject: [386BSD] implementation of "info float" for gdb-3.5 (source)
Message-ID: <1992Nov29.103427.22234@runx.oz.au>
Organization: RUNX Un*x Timeshare.  Sydney, Australia.
References: <1992Nov29.092901.21848@runx.oz.au>
Date: Sun, 29 Nov 92 10:34:27 GMT
Lines: 155

The enclosed diffs implement printing of the floating point state for
the version of gdb-3.5 in 386BSD-0.0.  I don't have gdb for 386BSD-0.1
but I've been told that it is also missing this feature.

The changes are small.  Code to read the FP state from the kernel was
#ifdef'ed out, but it essentially works.  Code to change the FP regs
is still #ifdef'ed out.  It is close to working too.  Printing of the
FP regs was broken because hard reg numbers were confused with stack
offsets.

Don't expect examination of the FP state to be of much use for debugging
(user) FP errors.  It won't hurt to look using these changes, but the
kernel has a dozen or so bugs in its FP exception handlers.  E.g.:
1. FP error handling is changed when you look at it using gdb (ptrace,
   really).
2. An FP error may be clobber the FP state.
3. All FP errors may cause a panic, and ptracing through an FP error
   increases the risk.  
4. The emulator does not handle FP errors right, and it does not
   communicate the emulated FP state to the rest of the kernel, so
   "info float" shows garbage.

I may post fixes for the kernel FP bugs (except for emulator bugs and
IRQ13 h/w bugs) in a week or two.

*** /usr/src/usr.bin/gdb/config/i386bsd-dep.c~	Thu Mar 12 04:31:17 1992
--- /usr/src/usr.bin/gdb/config/i386bsd-dep.c	Thu Nov 26 02:49:36 1992
***************
*** 1743,1752 ****
    top = (ep->status >> 11) & 7;
    
!   printf ("regno  tag  msb              lsb  value\n");
    for (fpreg = 7; fpreg >= 0; fpreg--) 
      {
        double val;
        
!       printf ("%s %d: ", fpreg == top ? "=>" : "  ", fpreg);
        
        switch ((ep->tag >> (fpreg * 2)) & 3) 
--- 1743,1758 ----
    top = (ep->status >> 11) & 7;
    
!   printf (" regno     tag  msb              lsb  value\n");
    for (fpreg = 7; fpreg >= 0; fpreg--) 
      {
+       int st_regno;
        double val;
        
!       /* The physical regno `fpreg' is only relevant as an index into the
!        * tag word.  Logical `%st' numbers are required for indexing `p->regs.
!        */
!       st_regno = (fpreg + 8 - top) & 0x7;
! 
!       printf ("%%st(%d) %s ", st_regno, fpreg == top ? "=>" : "  ");
        
        switch ((ep->tag >> (fpreg * 2)) & 3) 
***************
*** 1758,1766 ****
  	}
        for (i = 9; i >= 0; i--)
! 	printf ("%02x", ep->regs[fpreg][i]);
        
!       i387_to_double (ep->regs[fpreg], (char *)&val);
        printf ("  %g\n", val);
      }
    if (ep->r0)
      printf ("warning: reserved0 is 0x%x\n", ep->r0);
--- 1764,1773 ----
  	}
        for (i = 9; i >= 0; i--)
! 	printf ("%02x", ep->regs[st_regno][i]);
        
!       i387_to_double (ep->regs[st_regno], (char *)&val);
        printf ("  %g\n", val);
      }
+ #if 0 /* reserved fields are always 0xffff on 486's */
    if (ep->r0)
      printf ("warning: reserved0 is 0x%x\n", ep->r0);
***************
*** 1771,1776 ****
--- 1778,1789 ----
    if (ep->r3)
      printf ("warning: reserved3 is 0x%x\n", ep->r3);
+ #endif
  }
  
+ #ifdef __386BSD__
+ #define	fpstate		save87
+ #define	U_FPSTATE(u)	u.u_pcb.pcb_savefpu
+ #endif
+ 
  #ifndef U_FPSTATE
  #define U_FPSTATE(u) u.u_fpstate
***************
*** 1781,1785 ****
    struct user u; /* just for address computations */
    int i;
- #ifndef i386b
    /* fpstate defined in <sys/user.h> */
    struct fpstate *fpstatep;
--- 1794,1797 ----
***************
*** 1792,1795 ****
--- 1804,1808 ----
    int skip;
    
+ #ifndef __386BSD__	/* XXX - look at pcb flags */
    uaddr = (char *)&u.u_fpvalid - (char *)&u;
    if (have_inferior_p()) 
***************
*** 1799,1803 ****
        
        rounded_addr = uaddr & -sizeof (int);
!       data = ptrace (3, inferior_pid, rounded_addr, 0);
        mask = 0xff << ((uaddr - rounded_addr) * 8);
        
--- 1812,1816 ----
        
        rounded_addr = uaddr & -sizeof (int);
!       data = ptrace (PT_READ_U, inferior_pid, (caddr_t)rounded_addr, 0);
        mask = 0xff << ((uaddr - rounded_addr) * 8);
        
***************
*** 1818,1821 ****
--- 1831,1835 ----
        return;
      }
+ #endif	/* not __386BSD__ */
    
    uaddr = (char *)&U_FPSTATE(u) - (char *)&u;
***************
*** 1832,1836 ****
        for (i = 0; i < rounded_size; i++) 
  	{
! 	  *ip++ = ptrace (3, inferior_pid, rounded_addr, 0);
  	  rounded_addr += sizeof (int);
  	}
--- 1846,1850 ----
        for (i = 0; i < rounded_size; i++) 
  	{
! 	  *ip++ = ptrace (PT_READ_U, inferior_pid, (caddr_t)rounded_addr, 0);
  	  rounded_addr += sizeof (int);
  	}
***************
*** 1845,1848 ****
--- 1859,1865 ----
      }
    
+ #ifdef __386BSD__
+   print_387_status (0, (struct env387 *)buf);
+ #else
    fpstatep = (struct fpstate *)(buf + skip);
    print_387_status (fpstatep->status, (struct env387 *)fpstatep->state);
-- 
Bruce Evans  (bde@runx.oz.au)