Skip site navigation (1)Skip section navigation (2)
Date:      12 Apr 95 12:55:20+0200
From:      "Georg-W. Koltermann" <gwk@racer.dkrz.d400.de>
To:        bde@zeta.org.au
Cc:        bugs@FreeBSD.org, nate@sneezy.sri.com, smace@metal-mail.neosoft.com
Subject:   Re: 80387 hangs system at divide by zero
Message-ID:  <9504121055.AA08106@racer.dkrz.de>
References:  <message from Bruce Evans on Sat>, <8 Apr 1995 22:56:47 %2B1000>

next in thread | previous in thread | raw e-mail | index | archive | help
Hi Bruce,

thanks for explaining in long what's wrong with my '387 setup.  Also
thanks to the others telling me ULSI '387s are broke (especially to
Nate who is from Montana...  :) .

Well, I did some more testing last night.

Bruce Evans wrote:
> Some buggy i387 (in)compatibles and/or motherboards are reported to lock
> up the whole system (interrupts stop working; I think this is an i387
> bug); others are reported to only stop IRQ13 working (I think this is
> a motherboard problem).  FreeBSD makes no attempt to handle either
> problem.  Linux handles the second problem using a timeout, so an i387
> error only wastes an average of 1/2 a clock tick.

If I generate an overflow or divide by zero on MS-DOG(tm), the result
prints out as "infinity".  I tried with Symantec C++ 6.11 as well as
gcc 2.6.3 (the EMX port).  Both environments mask off all exceptions
by default.  If I enable exceptions, the program will hang just as
with FreeBSD.  In case of gcc/MS-DOG I can ctrl-break out of the hang,
but the system gets somewhat instable--the next invocation of the gcc
compiler will hang irreversibly.

With Linux [Slackware 2.1 binaries with a 1.1.78 kernel, gcc 2.5.8]
both overflow and divide by zero are reported as floating point
exception.  Linux can handle it!  When I mask off exceptions, results
are printed as infinity just as with MS-DOG.

On FreeBSD overflow and divide by zero hang my system irreversibly.
Can't even switch consoles, or CTRL-ALT-DEL, only reset will help.

> Actually it should be possible to use the chip in IEEE mode (with all
> exceptions masked).  This should be the default mode, and probably will
> be in FreeBSD-2.1.

Yup, when I mask off exceptions on FreeBSD my test program works and
prints the results as infinity.  I only get a warning when the program
terminates stating that it terminated with pending exceptions (or
something to that effect).

Is there a way that I can mask off exceptions globally for every
program on my system?  Or would you think there is a chance that
FreeBSD gets as good as coping with my hardware as Linux?  I have
already tried to compare FreeBSD and Linux sources, the parts that do
exception handling.  Not much luck though.  As the German saying goes:
"I couln't find the forest because there were so many trees".

Georg-W. Koltermann, gwk@cray.com

P.S.: For the curious I will append my test program here.  Yes, it's a
      quick and dirty one...
----------------------------------------------------------------------
#include <stdio.h>
#if linux
# include <fpu_control.h>
#endif
#if __FreeBSD__
# include <machine/floatingpoint.h>
#endif

static void
divide (double divisor)
{
  double dividend = 42.0;

  printf ("%g / %g = %g\n", dividend, divisor, dividend / divisor);
}

int
main (int argc, char *argv [])
{
#if linux
  unsigned control = 0;
#define	fnstcw(addr)		__asm("fnstcw %0" : : "m" (*(addr)))
  fnstcw (&control);
  printf ("fpu_control = 0x%x\n", control);
  __setfpucw (control & ~0xd);
  sleep (1);
  fnstcw (&control);
  printf ("fpu_control now 0x%x\n", control);
#elif __FreeBSD__
#define	fldcw(addr)		__asm("fldcw %0" : : "m" (*(addr)))
  /* previous #define stolen from npx.c--why is it missing from
     floatingpoint.h ?? */
  unsigned control = 0;
  setvbuf (stdout, NULL, _IONBF, 0);
  __fnstcw (&control);
  printf ("x387 control word: 0x%x\n", control);
  control &= ~0xd;
  fldcw (&control);
  __fnstcw (&control);
  printf ("x387 control word now: 0x%x\n", control);
#else /* MS-DOG */
  printf ("x387 control word: 0x%x\n", _control87 (0x0, 0xd));
  printf ("x387 control word now: 0x%x\n", _control87 (0, 0));
#endif
  divide (7.0);
  divide (3e-308);
  divide (0.0);

  return 0;
}




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?9504121055.AA08106>