Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 9 Sep 1998 12:16:14 +0200
From:      Martin Cracauer <cracauer@cons.org>
To:        Bruce Evans <bde@zeta.org.au>, cracauer@cons.org, current@FreeBSD.ORG
Subject:   Proposed implementation of trapcodes for SIGFPE
Message-ID:  <19980909121614.A19326@cons.org>
In-Reply-To: <199809010132.LAA14077@godzilla.zeta.org.au>; from Bruce Evans on Tue, Sep 01, 1998 at 11:32:44AM %2B1000
References:  <199809010132.LAA14077@godzilla.zeta.org.au>

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

--sm4nu43k4a2Rpi4c
Content-Type: text/plain; charset=us-ascii

Find appended a proposed implementation of trapcodes for SIGFPE.

It contains a diff against -current, a test program (freebsd-signal.c)
and a program to generate the fpetable (npxvals.c).

This strickly implements the 8 portable FPE_...... values, with
mapping everything that is an illegal access of some kind to
FPE_FLTSUB. Determination of more exact reasons should be part of a
new interface that passes the control and status word to the new
signal handler (SA_SIGINFO).

Questions:
- Does it work on your machine, everyone (especially older ones)?
- The fpetable is rather large, should u_char be used insted of int?
- As npxvals.c shows, the code path to get the values in the table is
  rather short, maybe it is an alternative to run this function instead
  of using a table?

Martin
-- 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Martin Cracauer <cracauer@cons.org> http://www.cons.org/cracauer
  Tel.: (private) +4940 5221829 Fax.: (private) +4940 5228536
  Paper: (private) Waldstrasse 200, 22846 Norderstedt, Germany

--sm4nu43k4a2Rpi4c
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="diff.fpetrapcode"

? conf/WINGS
? conf/WINGS.from-SMP-GENERIC
Index: i386/trap.c
===================================================================
RCS file: /home/CVS-FreeBSD/src/sys/i386/i386/trap.c,v
retrieving revision 1.128
diff -c -r1.128 trap.c
*** trap.c	1998/08/23 10:16:26	1.128
--- trap.c	1998/09/09 00:27:03
***************
*** 328,334 ****
  			break;
  
  		case T_DIVIDE:		/* integer divide fault */
! 			ucode = FPE_INTDIV_TRAP;
  			i = SIGFPE;
  			break;
  
--- 328,334 ----
  			break;
  
  		case T_DIVIDE:		/* integer divide fault */
! 			ucode = FPE_INTDIV;
  			i = SIGFPE;
  			break;
  
***************
*** 350,361 ****
  #endif /* NISA > 0 */
  
  		case T_OFLOW:		/* integer overflow fault */
! 			ucode = FPE_INTOVF_TRAP;
  			i = SIGFPE;
  			break;
  
  		case T_BOUND:		/* bounds check fault */
! 			ucode = FPE_SUBRNG_TRAP;
  			i = SIGFPE;
  			break;
  
--- 350,361 ----
  #endif /* NISA > 0 */
  
  		case T_OFLOW:		/* integer overflow fault */
! 			ucode = FPE_INTOVF;
  			i = SIGFPE;
  			break;
  
  		case T_BOUND:		/* bounds check fault */
! 			ucode = FPE_FLTSUB;
  			i = SIGFPE;
  			break;
  
Index: include/ieeefp.h
===================================================================
RCS file: /home/CVS-FreeBSD/src/sys/i386/include/ieeefp.h,v
retrieving revision 1.5
diff -c -r1.5 ieeefp.h
*** ieeefp.h	1997/02/22 09:34:41	1.5
--- ieeefp.h	1998/09/09 00:27:05
***************
*** 72,77 ****
--- 72,78 ----
  #define FP_X_OFL	0x08	/* overflow */
  #define FP_X_UFL	0x10	/* underflow */
  #define FP_X_IMP	0x20	/* (im)precision */
+ #define FP_X_STK	0x40	/* stack fault */
  
  /*
   * FP registers
Index: include/trap.h
===================================================================
RCS file: /home/CVS-FreeBSD/src/sys/i386/include/trap.h,v
retrieving revision 1.7
diff -c -r1.7 trap.h
*** trap.h	1997/02/22 09:35:19	1.7
--- trap.h	1998/09/09 00:27:05
***************
*** 76,88 ****
  #define	    ILL_ALIGN_FAULT	T_ALIGNFLT
  #define	    ILL_FPOP_FAULT	T_FPOPFLT	/* coprocessor operand fault */
  
! /* codes for SIGFPE/ARITHTRAP */
  #define	    FPE_INTOVF_TRAP	0x1	/* integer overflow */
  #define	    FPE_INTDIV_TRAP	0x2	/* integer divide by zero */
  #define	    FPE_FLTDIV_TRAP	0x3	/* floating/decimal divide by zero */
  #define	    FPE_FLTOVF_TRAP	0x4	/* floating overflow */
  #define	    FPE_FLTUND_TRAP	0x5	/* floating underflow */
! #define	    FPE_FPU_NP_TRAP	0x6	/* floating point unit not present */
  #define	    FPE_SUBRNG_TRAP	0x7	/* subrange out of bounds */
  
  /* codes for SIGBUS */
--- 76,104 ----
  #define	    ILL_ALIGN_FAULT	T_ALIGNFLT
  #define	    ILL_FPOP_FAULT	T_FPOPFLT	/* coprocessor operand fault */
  
! /* 
!  * codes for SIGFPE/ARITHTRAP 
!  *
!  */
! /* portable macros */
! #define FPE_INTDIV	1	/* integer divide by zero */
! #define FPE_INTOVF	2	/* integer overflow */
! #define FPE_FLTDIV	3	/* floating point divide by zero */
! #define FPE_FLTOVF	4	/* floating point overflow */
! #define FPE_FLTUND	5	/* floating point underflow */
! #define FPE_FLTRES	6	/* floating point inexact result */
! #define FPE_FLTINV	7	/* invalid floating point operation */
! #define FPE_FLTSUB	8	/* subscript out of range */
! 
! /* old FreeBSD macros, deprecated */
  #define	    FPE_INTOVF_TRAP	0x1	/* integer overflow */
  #define	    FPE_INTDIV_TRAP	0x2	/* integer divide by zero */
  #define	    FPE_FLTDIV_TRAP	0x3	/* floating/decimal divide by zero */
  #define	    FPE_FLTOVF_TRAP	0x4	/* floating overflow */
  #define	    FPE_FLTUND_TRAP	0x5	/* floating underflow */
! #define	    FPE_FPU_NP_TRAP	0x6	/* floating point unit not present 
! 					 * - won't happen in practice
! 					 */
  #define	    FPE_SUBRNG_TRAP	0x7	/* subrange out of bounds */
  
  /* codes for SIGBUS */
Index: isa/npx.c
===================================================================
RCS file: /home/CVS-FreeBSD/src/sys/i386/isa/npx.c,v
retrieving revision 1.61
diff -c -r1.61 npx.c
*** npx.c	1998/06/21 18:02:39	1.61
--- npx.c	1998/09/09 00:27:07
***************
*** 474,479 ****
--- 474,637 ----
  #endif
  }
  
+ /* 
+  * Table with FPE_ values for every possible combination of exception bits.
+  * The precedence is based upon Intel Document "Numerical Applications",
+  * Chapter "Special Computational Situations". That means when the user
+  * process enter with more than one unmasked exceptions bit (can be
+  * when it modified the control word), we through away bits as would the
+  * FPU if one instruction would cause more than one exception to be raised.
+  *
+  * Precisly, it is:
+  * 1) Invalid operation (FP_X_INV)
+  * 1a) Stack underflow
+  * 1b) Stack overflow
+  * 1c) Operand of unsupported format
+  * 1d) SNaN operand.
+  * 2) QNaN operand (not an exception, irrelavant here)
+  * 3) Any other invalid-operation not mentioned above or zero divide
+  *    (FP_X_INV, FP_X_DZ)
+  * 4) Denormal operand (FP_X_DNML)
+  * 5) Numeric over/underflow (FP_X_OFL, FP_X_UFL)
+  * 6) Inexact result (FP_X_IMP)
+  */
+ static int fpetable[128] = {
+ 	0,
+ 	FPE_FLTINV, /*  1 - INV */
+ 	FPE_FLTUND, /*  2 - DNML */
+ 	FPE_FLTINV, /*  3 - INV | DNML */
+ 	FPE_FLTDIV, /*  4 - DZ */
+ 	FPE_FLTINV, /*  5 - INV | DZ */
+ 	FPE_FLTDIV, /*  6 - DNML | DZ */
+ 	FPE_FLTINV, /*  7 - INV | DNML | DZ */
+ 	FPE_FLTOVF, /*  8 - OFL */
+ 	FPE_FLTINV, /*  9 - INV | OFL */
+ 	FPE_FLTUND, /*  A - DNML | OFL */
+ 	FPE_FLTINV, /*  B - INV | DNML | OFL */
+ 	FPE_FLTDIV, /*  C - DZ | OFL */
+ 	FPE_FLTINV, /*  D - INV | DZ | OFL */
+ 	FPE_FLTDIV, /*  E - DNML | DZ | OFL */
+ 	FPE_FLTINV, /*  F - INV | DNML | DZ | OFL */
+ 	FPE_FLTUND, /* 10 - UFL */
+ 	FPE_FLTINV, /* 11 - INV | UFL */
+ 	FPE_FLTUND, /* 12 - DNML | UFL */
+ 	FPE_FLTINV, /* 13 - INV | DNML | UFL */
+ 	FPE_FLTDIV, /* 14 - DZ | UFL */
+ 	FPE_FLTINV, /* 15 - INV | DZ | UFL */
+ 	FPE_FLTDIV, /* 16 - DNML | DZ | UFL */
+ 	FPE_FLTINV, /* 17 - INV | DNML | DZ | UFL */
+ 	FPE_FLTOVF, /* 18 - OFL | UFL */
+ 	FPE_FLTINV, /* 19 - INV | OFL | UFL */
+ 	FPE_FLTUND, /* 1A - DNML | OFL | UFL */
+ 	FPE_FLTINV, /* 1B - INV | DNML | OFL | UFL */
+ 	FPE_FLTDIV, /* 1C - DZ | OFL | UFL */
+ 	FPE_FLTINV, /* 1D - INV | DZ | OFL | UFL */
+ 	FPE_FLTDIV, /* 1E - DNML | DZ | OFL | UFL */
+ 	FPE_FLTINV, /* 1F - INV | DNML | DZ | OFL | UFL */
+ 	FPE_FLTRES, /* 20 - IMP */
+ 	FPE_FLTINV, /* 21 - INV | IMP */
+ 	FPE_FLTUND, /* 22 - DNML | IMP */
+ 	FPE_FLTINV, /* 23 - INV | DNML | IMP */
+ 	FPE_FLTDIV, /* 24 - DZ | IMP */
+ 	FPE_FLTINV, /* 25 - INV | DZ | IMP */
+ 	FPE_FLTDIV, /* 26 - DNML | DZ | IMP */
+ 	FPE_FLTINV, /* 27 - INV | DNML | DZ | IMP */
+ 	FPE_FLTOVF, /* 28 - OFL | IMP */
+ 	FPE_FLTINV, /* 29 - INV | OFL | IMP */
+ 	FPE_FLTUND, /* 2A - DNML | OFL | IMP */
+ 	FPE_FLTINV, /* 2B - INV | DNML | OFL | IMP */
+ 	FPE_FLTDIV, /* 2C - DZ | OFL | IMP */
+ 	FPE_FLTINV, /* 2D - INV | DZ | OFL | IMP */
+ 	FPE_FLTDIV, /* 2E - DNML | DZ | OFL | IMP */
+ 	FPE_FLTINV, /* 2F - INV | DNML | DZ | OFL | IMP */
+ 	FPE_FLTUND, /* 30 - UFL | IMP */
+ 	FPE_FLTINV, /* 31 - INV | UFL | IMP */
+ 	FPE_FLTUND, /* 32 - DNML | UFL | IMP */
+ 	FPE_FLTINV, /* 33 - INV | DNML | UFL | IMP */
+ 	FPE_FLTDIV, /* 34 - DZ | UFL | IMP */
+ 	FPE_FLTINV, /* 35 - INV | DZ | UFL | IMP */
+ 	FPE_FLTDIV, /* 36 - DNML | DZ | UFL | IMP */
+ 	FPE_FLTINV, /* 37 - INV | DNML | DZ | UFL | IMP */
+ 	FPE_FLTOVF, /* 38 - OFL | UFL | IMP */
+ 	FPE_FLTINV, /* 39 - INV | OFL | UFL | IMP */
+ 	FPE_FLTUND, /* 3A - DNML | OFL | UFL | IMP */
+ 	FPE_FLTINV, /* 3B - INV | DNML | OFL | UFL | IMP */
+ 	FPE_FLTDIV, /* 3C - DZ | OFL | UFL | IMP */
+ 	FPE_FLTINV, /* 3D - INV | DZ | OFL | UFL | IMP */
+ 	FPE_FLTDIV, /* 3E - DNML | DZ | OFL | UFL | IMP */
+ 	FPE_FLTINV, /* 3F - INV | DNML | DZ | OFL | UFL | IMP */
+ 	FPE_FLTSUB, /* 40 - STK */
+ 	FPE_FLTSUB, /* 41 - INV | STK */
+ 	FPE_FLTUND, /* 42 - DNML | STK */
+ 	FPE_FLTSUB, /* 43 - INV | DNML | STK */
+ 	FPE_FLTDIV, /* 44 - DZ | STK */
+ 	FPE_FLTSUB, /* 45 - INV | DZ | STK */
+ 	FPE_FLTDIV, /* 46 - DNML | DZ | STK */
+ 	FPE_FLTSUB, /* 47 - INV | DNML | DZ | STK */
+ 	FPE_FLTOVF, /* 48 - OFL | STK */
+ 	FPE_FLTSUB, /* 49 - INV | OFL | STK */
+ 	FPE_FLTUND, /* 4A - DNML | OFL | STK */
+ 	FPE_FLTSUB, /* 4B - INV | DNML | OFL | STK */
+ 	FPE_FLTDIV, /* 4C - DZ | OFL | STK */
+ 	FPE_FLTSUB, /* 4D - INV | DZ | OFL | STK */
+ 	FPE_FLTDIV, /* 4E - DNML | DZ | OFL | STK */
+ 	FPE_FLTSUB, /* 4F - INV | DNML | DZ | OFL | STK */
+ 	FPE_FLTUND, /* 50 - UFL | STK */
+ 	FPE_FLTSUB, /* 51 - INV | UFL | STK */
+ 	FPE_FLTUND, /* 52 - DNML | UFL | STK */
+ 	FPE_FLTSUB, /* 53 - INV | DNML | UFL | STK */
+ 	FPE_FLTDIV, /* 54 - DZ | UFL | STK */
+ 	FPE_FLTSUB, /* 55 - INV | DZ | UFL | STK */
+ 	FPE_FLTDIV, /* 56 - DNML | DZ | UFL | STK */
+ 	FPE_FLTSUB, /* 57 - INV | DNML | DZ | UFL | STK */
+ 	FPE_FLTOVF, /* 58 - OFL | UFL | STK */
+ 	FPE_FLTSUB, /* 59 - INV | OFL | UFL | STK */
+ 	FPE_FLTUND, /* 5A - DNML | OFL | UFL | STK */
+ 	FPE_FLTSUB, /* 5B - INV | DNML | OFL | UFL | STK */
+ 	FPE_FLTDIV, /* 5C - DZ | OFL | UFL | STK */
+ 	FPE_FLTSUB, /* 5D - INV | DZ | OFL | UFL | STK */
+ 	FPE_FLTDIV, /* 5E - DNML | DZ | OFL | UFL | STK */
+ 	FPE_FLTSUB, /* 5F - INV | DNML | DZ | OFL | UFL | STK */
+ 	FPE_FLTRES, /* 60 - IMP | STK */
+ 	FPE_FLTSUB, /* 61 - INV | IMP | STK */
+ 	FPE_FLTUND, /* 62 - DNML | IMP | STK */
+ 	FPE_FLTSUB, /* 63 - INV | DNML | IMP | STK */
+ 	FPE_FLTDIV, /* 64 - DZ | IMP | STK */
+ 	FPE_FLTSUB, /* 65 - INV | DZ | IMP | STK */
+ 	FPE_FLTDIV, /* 66 - DNML | DZ | IMP | STK */
+ 	FPE_FLTSUB, /* 67 - INV | DNML | DZ | IMP | STK */
+ 	FPE_FLTOVF, /* 68 - OFL | IMP | STK */
+ 	FPE_FLTSUB, /* 69 - INV | OFL | IMP | STK */
+ 	FPE_FLTUND, /* 6A - DNML | OFL | IMP | STK */
+ 	FPE_FLTSUB, /* 6B - INV | DNML | OFL | IMP | STK */
+ 	FPE_FLTDIV, /* 6C - DZ | OFL | IMP | STK */
+ 	FPE_FLTSUB, /* 6D - INV | DZ | OFL | IMP | STK */
+ 	FPE_FLTDIV, /* 6E - DNML | DZ | OFL | IMP | STK */
+ 	FPE_FLTSUB, /* 6F - INV | DNML | DZ | OFL | IMP | STK */
+ 	FPE_FLTUND, /* 70 - UFL | IMP | STK */
+ 	FPE_FLTSUB, /* 71 - INV | UFL | IMP | STK */
+ 	FPE_FLTUND, /* 72 - DNML | UFL | IMP | STK */
+ 	FPE_FLTSUB, /* 73 - INV | DNML | UFL | IMP | STK */
+ 	FPE_FLTDIV, /* 74 - DZ | UFL | IMP | STK */
+ 	FPE_FLTSUB, /* 75 - INV | DZ | UFL | IMP | STK */
+ 	FPE_FLTDIV, /* 76 - DNML | DZ | UFL | IMP | STK */
+ 	FPE_FLTSUB, /* 77 - INV | DNML | DZ | UFL | IMP | STK */
+ 	FPE_FLTOVF, /* 78 - OFL | UFL | IMP | STK */
+ 	FPE_FLTSUB, /* 79 - INV | OFL | UFL | IMP | STK */
+ 	FPE_FLTUND, /* 7A - DNML | OFL | UFL | IMP | STK */
+ 	FPE_FLTSUB, /* 7B - INV | DNML | OFL | UFL | IMP | STK */
+ 	FPE_FLTDIV, /* 7C - DZ | OFL | UFL | IMP | STK */
+ 	FPE_FLTSUB, /* 7D - INV | DZ | OFL | UFL | IMP | STK */
+ 	FPE_FLTDIV, /* 7E - DNML | DZ | OFL | UFL | IMP | STK */
+ 	FPE_FLTSUB, /* 7F - INV | DNML | DZ | OFL | UFL | IMP | STK */
+ };
+ 
+ /*
+  * Return the right FPE_ value (from trap.h) based on current control and
+  * status word.
+  */
+ #define ENCODE(_sw, _cw) (fpetable[_sw & ~_cw & 0x3f | _sw & 0x40])
+ 
  /*
   * Preserve the FP status word, clear FP exceptions, then generate a SIGFPE.
   *
***************
*** 500,505 ****
--- 658,664 ----
  	int unit;
  {
  	int code;
+ 	u_long cw;
  	struct intrframe *frame;
  
  	if (npxproc == NULL || !npx_exists) {
***************
*** 515,520 ****
--- 674,680 ----
  
  	outb(0xf0, 0);
  	fnstsw(&curpcb->pcb_savefpu.sv_ex_sw);
+ 	fnstcw(&cw);
  	fnclex();
  
  	/*
***************
*** 534,548 ****
  		 * just before it is used).
  		 */
  		curproc->p_md.md_regs = (struct trapframe *)&frame->if_es;
- #ifdef notyet
  		/*
  		 * Encode the appropriate code for detailed information on
  		 * this exception.
  		 */
! 		code = XXX_ENCODE(curpcb->pcb_savefpu.sv_ex_sw);
! #else
! 		code = 0;	/* XXX */
! #endif
  		trapsignal(curproc, SIGFPE, code);
  	} else {
  		/*
--- 694,704 ----
  		 * just before it is used).
  		 */
  		curproc->p_md.md_regs = (struct trapframe *)&frame->if_es;
  		/*
  		 * Encode the appropriate code for detailed information on
  		 * this exception.
  		 */
! 		code = ENCODE(curpcb->pcb_savefpu.sv_ex_sw, cw);
  		trapsignal(curproc, SIGFPE, code);
  	} else {
  		/*

--sm4nu43k4a2Rpi4c
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="npxvals.c"

#include <stdio.h>
#include <machine/ieeefp.h>

#if 0
#define FPE_INTDIV	1	/* integer divide by zero */
#define FPE_INTOVF	2	/* integer overflow */
#define FPE_FLTDIV	3	/* floating point divide by zero */
#define FPE_FLTOVF	4	/* floating point overflow */
#define FPE_FLTUND	5	/* floating point underflow */
#define FPE_FLTRES	6	/* floating point inexact result */
#define FPE_FLTINV	7	/* invalid floating point operation */
#define FPE_FLTSUB	8	/* subscript out of range, not used on FreeBSD */

#define FP_X_INV        0x01	/* invalid operation */
#define FP_X_DNML       0x02	/* denormal */
#define FP_X_DZ         0x04	/* zero divide */
#define FP_X_OFL        0x08	/* overflow */
#define FP_X_UFL        0x10	/* underflow */
#define FP_X_IMP        0x20	/* (im)precision */
#endif

char *names[] = {
  "INV",
  "DNML",
  "DZ",
  "OFL",
  "UFL",
  "IMP",
  "STK"
};

/*
 * 1) Invalid operation (FP_X_INV)
 * 1a) Stack underflow
 * 1b) Stack overflow
 * 1c) Operand of unsupported format
 * 1d) SNaN operand.
 * 2) QNaN operand (not an exception, irrelavant here)
 * 3) Any other invalid-operation not mentioned above or zero divide
 *    (FP_X_INV)
 * 4) Denormal operand (FP_X_DNML)
 * 5) Numeric over/underflow (FP_X_OFL, FP_X_UFL)
 * 6) Inexact result (FP_X_IMP)
 */

int
main(void)
{
  int i,j;
  int first;
  /* OK, los gehts */

  for (i = 1; i < 128 ; i++) {
    printf("\t");
    if (i & FP_X_INV) {
      if (i & FP_X_STK)
	printf("FPE_FLTSUB");
      else
	printf("FPE_FLTINV");
      goto done;
    }
    if (i & FP_X_DZ) {
      printf("FPE_FLTDIV");
      goto done;
    }
    if (i & FP_X_DNML) {
      printf("FPE_FLTUND");
      goto done;
    }
    if (i & FP_X_OFL) {
      printf("FPE_FLTOVF");
      goto done;
    }
    if (i & FP_X_UFL) {
      printf("FPE_FLTUND");
      goto done;
    }
    if (i & FP_X_IMP) {
      printf("FPE_FLTRES");
      goto done;
    }
    if (i & FP_X_STK) {/* Can't happen */
      printf("FPE_FLTSUB");
      goto done;
    }

  done:

    printf(", /* %2X - ", i);
    first = 1;
    for ( j=0; j<7 ; j++) {
      if (i & (1<<j)) {
	if (!first)
	  printf(" | ");
	first = 0;
	printf("%s", names[j]);
      }
    }
    printf(" */\n");

  }

  return 0;
}

--sm4nu43k4a2Rpi4c
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="freebsd-signal.c"

#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/types.h>
#include <unistd.h>

#include <math.h>

#include <float.h>
#include <floatingpoint.h>

volatile static sig_atomic_t sig_fpe_was_here = 0;
volatile static int sig_sig;
volatile static int sig_code;
static struct sigcontext sig_context;
static jmp_buf jmpbuf;

static int 
handler(int sig, int code, struct sigcontext *scp)
{
#if 0
#define TMP "FPE handler\n"
  write(2,TMP,sizeof(TMP)-1);
#undef TMP
#endif
  sig_fpe_was_here++;
  sig_sig = sig;
  sig_code = code;
  memcpy(&sig_context, scp, sizeof(*scp));
  longjmp(jmpbuf,1);

  return sig;
}

static const char *
codestring(int code)
{
  switch (code) {
  case FPE_INTDIV: return "FPE_INTDIV";
  case FPE_INTOVF: return "FPE_INTOVF";
  case FPE_FLTDIV: return "FPE_FLTDIV";
  case FPE_FLTOVF: return "FPE_FLTOVF";
  case FPE_FLTUND: return "FPE_FLTUND";
  case FPE_FLTRES: return "FPE_FLTRES";
  case FPE_FLTINV: return "FPE_FLTINV";
  case FPE_FLTSUB: return "FPE_FLTSUB";
  default: return "Unknwon code";
  }
}

#if 0
static double 
deopt(double d)
{
  return d;
}
#endif

static double
l_idiv(double p1, double p2)
{
  return (double)((int)p1 / (int)p2);
}

static double
l_fadd(double p1, double p2)
{
  return p1 + p2;
}

static double
l_fmul(double p1, double p2)
{
  return p1 * p2;
}

static double
l_fdiv(double p1, double p2)
{
  return p1 / p2;
}

static double
l_fsub(double p1, double p2)
{
  return p1 - p2;
}

static double
l_sin(double p1, double p2)
{
  return sin(p1);
}

static double
l_sqrt(double p1, double p2)
{
  return sqrt(p1);
}

static double
l_stkofl(double p1, double p2)
{
  asm("fldz");
  asm("fldz");
  asm("fldz");
  asm("fldz");
  asm("fldz");
  asm("fldz");
  asm("fldz");
  asm("fldz");
  return p1 + p2;
}

static double
l_stkufl(double p1, double p2)
{
  asm("fdivp %st(0)");
  return p1 + p2;
}

typedef double (test_f_t)(double, double);

struct funcpair {
  test_f_t *func;
  const double p1;
  const double p2;
  const char *const descr;
} const funcs[] = {
  {l_stkofl, 0.0,     0.0,     "stack oflow  "},
  {l_stkufl, 0.0,     0.0,     "stack uflow  "},
  {l_idiv,   0.0,     0.0,     "int 0/0      "},
  {l_idiv,   1.0,     0.0,     "int 1/0      "},
  {l_fdiv,   0.0,     0.0,     "dbl 0/0      "},
  {l_fdiv,   1.0,     0.0,     "dbl 1/0      "},
  {l_fdiv,   DBL_MIN, DBL_MIN, "dbl MIN/MIN  "},
  {l_fdiv,   DBL_MIN, 2.0,     "dbl MIN/2    "},
  {l_fsub,   DBL_MIN, DBL_MIN, "dbl MIN-MIN  "},
  {l_fmul,   DBL_MAX, 2.0,     "dbl 2*MAX    "},
  {l_fmul,   DBL_MAX, DBL_MAX, "dbl MAX*MAX  "},
  {l_fadd,   DBL_MAX, DBL_MAX, "dbl MAX+MAX  "},
  {l_sin,    10.0,    0.0,     "dbl sin(10.0)"},
  {l_sqrt,   -1.0,    0.0,     "dbl sqrt(-1) "},
  {NULL, NULL}
};

#define forcefpe() asm("wait")

static void 
dotests(void)
{
  const struct funcpair *volatile it;
  double res;

  it = funcs;
  while (it->func) {
    fprintf(stderr, "Function '%s'", it->descr);
    if (setjmp(jmpbuf) == 0) {
      res = it->func(it->p1, it->p2);
      forcefpe();
      fprintf(stderr, " survived, res: %g", res);
    }
    else {
      if (sig_fpe_was_here != 1) {
	fprintf(stderr,"Strange, %d exceptions after jongjmp\n"
		, sig_fpe_was_here);
	exit(2);
      }
      sig_fpe_was_here = 0;
      fprintf(stderr, " signal %d, code %-20s (%2d)"
	      , sig_sig
	      , codestring(sig_code)
	      , sig_code
	      );
    }
    fputc('\n', stderr);
    it++;
  }
}

int 
main(int argc, char *argv[])
{
  int oldmask;
  
  fprintf(stderr,"Round: %x, Precision: %x\n", fpgetround(), fpgetprec());

  oldmask = fpgetmask();
  signal(SIGFPE,(__sighandler_t *)handler);

  fprintf(stderr,"Testing with all exceptions enabled\n");
  fpsetmask(FP_X_INV|FP_X_DNML|FP_X_DZ|FP_X_OFL|FP_X_UFL|FP_X_IMP);
  dotests();

  fprintf(stderr,"Testing with all exceptions except precision loss\n");
  fpsetmask(FP_X_INV|FP_X_DNML|FP_X_DZ|FP_X_OFL|FP_X_UFL);
  dotests();

  fprintf(stderr,"Testing with exceptions disabled\n");
  fpsetmask(0L);
  dotests();

  fprintf(stderr,"Round: %x, Precision: %x\n", fpgetround(), fpgetprec());

  return 0;
}

--sm4nu43k4a2Rpi4c--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message



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