2021-10-11 18:20:23 -03:00

125 lines
3.4 KiB
C

#ifndef lint
static char sccsid[] = "@(#)ieee_handler.c 1.1 92/07/30 SMI";
#endif
/*
* Copyright (c) 1987 by Sun Microsystems, Inc.
*/
#include <floatingpoint.h>
#include "libm.h"
#define divbyz (1<<(int)fp_division)
#define unflow (1<<(int)fp_underflow)
#define ovflow (1<<(int)fp_overflow)
#define iexact (1<<(int)fp_inexact)
#define ivalid (1<<(int)fp_invalid)
#define allexc (divbyz|unflow|ovflow|iexact|ivalid)
#define comexc (divbyz|ovflow|ivalid)
extern _swapTE(); /* _swapTE(ex) exchanges ex with the current
* exception trap enable bits. Here ex is an integer
* where each bit corresponds to an
* exception trap enable status flag (0 off,1 on).
* (cf. enum fp_exception_type in <sys/ieeefp.h>)
*/
int ieee_handler(action,exception,hdl)
char *action, *exception;
sigfpe_handler_type hdl;
{
char a,e;
int ex;
int default_or_ignore;
a = action[0];
e = exception[0];
switch(a) {
case 'g':
switch(e) {
case 'd': ex = (int) fp_division; break;
case 'u': ex = (int) fp_underflow; break;
case 'o': ex = (int) fp_overflow; break;
case 'i': e = exception[2];
if(e=='v') ex = (int)fp_invalid; else
if(e=='e') ex = (int)fp_inexact;
else {return (int) SIGFPE_DEFAULT;}
break;
default:
return (int) SIGFPE_DEFAULT;
}
return (int) ieee_handlers[ex ];
case 's':
default_or_ignore = (hdl == SIGFPE_DEFAULT) |
(hdl == SIGFPE_IGNORE) ;
if (!default_or_ignore) _test_sigfpe_master();
/* Make sure master SIGFPE handler
is enabled. */
ex = _swapTE(0);
if (ex < 0) return 1; /* action not available */
switch(e) {
case 'd':
if(default_or_ignore) ex &= (~ divbyz);
else ex |= divbyz;
ieee_handlers[(int)fp_division] = hdl; break;
case 'u':
if(default_or_ignore) ex &= (~ unflow);
else ex |= unflow;
ieee_handlers[(int)fp_underflow] = hdl; break;
case 'o':
if(default_or_ignore) ex &= (~ ovflow);
else ex |= ovflow;
ieee_handlers[(int)fp_overflow] = hdl; break;
case 'a':
if(default_or_ignore) ex &= (~ allexc);
else ex |= allexc;
ieee_handlers[(int)fp_inexact] = hdl;
ieee_handlers[(int)fp_underflow] = hdl;
ieee_handlers[(int)fp_invalid] = hdl;
ieee_handlers[(int)fp_division] = hdl;
ieee_handlers[(int)fp_overflow] = hdl; break;
case 'c':
if(default_or_ignore) ex &= (~ comexc);
else ex |= comexc;
ieee_handlers[(int)fp_invalid] = hdl;
ieee_handlers[(int)fp_division] = hdl;
ieee_handlers[(int)fp_overflow] = hdl; break;
case 'i':
e = exception[2];
if(e=='v') {
if(default_or_ignore) ex &= (~ ivalid);
else ex |= ivalid;
ieee_handlers[(int)fp_invalid] = hdl; break;
} else if(e=='e') {
if(default_or_ignore) ex &= (~ iexact);
else ex |= iexact;
ieee_handlers[(int)fp_inexact] = hdl; break;
}
default:
return 1; /* action not available */
}
if(ex!=0) _swapTE(ex);
return 0;
case 'c':
ex = _swapTE(0);
if (ex < 0) return 0; /* action not available */
switch(e) {
case 'a': ex &= (~ allexc); return 0;
case 'd': ex &= (~ divbyz); break;
case 'u': ex &= (~ unflow); break;
case 'o': ex &= (~ ovflow); break;
case 'c': ex &= (~ comexc); break;
case 'i': e=exception[2];
if(e=='v') ex &= (~ ivalid); else
if(e=='e') ex &= (~ iexact);
break;
}
if(ex!=0) _swapTE(ex);
return 0;
default:
return 1; /* action not available */
}
}