xref: /onnv-gate/usr/src/lib/libbc/libc/gen/common/sigfpe.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
23*0Sstevel@tonic-gate 
24*0Sstevel@tonic-gate /*
25*0Sstevel@tonic-gate  * Copyright (c) 1987 by Sun Microsystems, Inc.
26*0Sstevel@tonic-gate  */
27*0Sstevel@tonic-gate 
28*0Sstevel@tonic-gate /* Swap handler for SIGFPE codes.	 */
29*0Sstevel@tonic-gate 
30*0Sstevel@tonic-gate #include <errno.h>
31*0Sstevel@tonic-gate #include <signal.h>
32*0Sstevel@tonic-gate #include <floatingpoint.h>
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate #ifndef FPE_INTDIV_TRAP
35*0Sstevel@tonic-gate #define     FPE_INTDIV_TRAP     0x14	/* integer divide by zero */
36*0Sstevel@tonic-gate #endif
37*0Sstevel@tonic-gate #ifndef FPE_CHKINST_TRAP
38*0Sstevel@tonic-gate #define     FPE_CHKINST_TRAP    0x18	/* CHK [CHK2] instruction */
39*0Sstevel@tonic-gate #endif
40*0Sstevel@tonic-gate #ifndef FPE_TRAPV_TRAP
41*0Sstevel@tonic-gate #define     FPE_TRAPV_TRAP      0x1c	/* TRAPV [cpTRAPcc TRAPcc] instr */
42*0Sstevel@tonic-gate #endif
43*0Sstevel@tonic-gate #ifndef FPE_FLTBSUN_TRAP
44*0Sstevel@tonic-gate #define     FPE_FLTBSUN_TRAP    0xc0	/* [branch or set on unordered cond] */
45*0Sstevel@tonic-gate #endif
46*0Sstevel@tonic-gate #ifndef FPE_FLTINEX_TRAP
47*0Sstevel@tonic-gate #define     FPE_FLTINEX_TRAP    0xc4	/* [floating inexact result] */
48*0Sstevel@tonic-gate #endif
49*0Sstevel@tonic-gate #ifndef FPE_FLTDIV_TRAP
50*0Sstevel@tonic-gate #define     FPE_FLTDIV_TRAP     0xc8	/* [floating divide by zero] */
51*0Sstevel@tonic-gate #endif
52*0Sstevel@tonic-gate #ifndef FPE_FLTUND_TRAP
53*0Sstevel@tonic-gate #define     FPE_FLTUND_TRAP     0xcc	/* [floating underflow] */
54*0Sstevel@tonic-gate #endif
55*0Sstevel@tonic-gate #ifndef FPE_FLTOPERR_TRAP
56*0Sstevel@tonic-gate #define     FPE_FLTOPERR_TRAP   0xd0	/* [floating operand error] */
57*0Sstevel@tonic-gate #endif
58*0Sstevel@tonic-gate #ifndef FPE_FLTOVF_TRAP
59*0Sstevel@tonic-gate #define     FPE_FLTOVF_TRAP     0xd4	/* [floating overflow] */
60*0Sstevel@tonic-gate #endif
61*0Sstevel@tonic-gate #ifndef FPE_FLTNAN_TRAP
62*0Sstevel@tonic-gate #define     FPE_FLTNAN_TRAP     0xd8	/* [floating Not-A-Number] */
63*0Sstevel@tonic-gate #endif
64*0Sstevel@tonic-gate #ifndef FPE_FPA_ENABLE
65*0Sstevel@tonic-gate #define     FPE_FPA_ENABLE      0x400	/* [FPA not enabled] */
66*0Sstevel@tonic-gate #endif
67*0Sstevel@tonic-gate #ifndef FPE_FPA_ERROR
68*0Sstevel@tonic-gate #define     FPE_FPA_ERROR       0x404	/* [FPA arithmetic exception] */
69*0Sstevel@tonic-gate #endif
70*0Sstevel@tonic-gate 
71*0Sstevel@tonic-gate #define N_SIGFPE_CODE 13
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate /* Array of SIGFPE codes. */
74*0Sstevel@tonic-gate 
75*0Sstevel@tonic-gate static sigfpe_code_type sigfpe_codes[N_SIGFPE_CODE] = {
76*0Sstevel@tonic-gate 						       FPE_INTDIV_TRAP,
77*0Sstevel@tonic-gate 						       FPE_CHKINST_TRAP,
78*0Sstevel@tonic-gate 						       FPE_TRAPV_TRAP,
79*0Sstevel@tonic-gate 						       FPE_FLTBSUN_TRAP,
80*0Sstevel@tonic-gate 						       FPE_FLTINEX_TRAP,
81*0Sstevel@tonic-gate 						       FPE_FLTDIV_TRAP,
82*0Sstevel@tonic-gate 						       FPE_FLTUND_TRAP,
83*0Sstevel@tonic-gate 						       FPE_FLTOPERR_TRAP,
84*0Sstevel@tonic-gate 						       FPE_FLTOVF_TRAP,
85*0Sstevel@tonic-gate 						       FPE_FLTNAN_TRAP,
86*0Sstevel@tonic-gate 						       FPE_FPA_ENABLE,
87*0Sstevel@tonic-gate 						       FPE_FPA_ERROR,
88*0Sstevel@tonic-gate 						       0};
89*0Sstevel@tonic-gate 
90*0Sstevel@tonic-gate /* Array of handlers. */
91*0Sstevel@tonic-gate 
92*0Sstevel@tonic-gate static sigfpe_handler_type sigfpe_handlers[N_SIGFPE_CODE];
93*0Sstevel@tonic-gate 
94*0Sstevel@tonic-gate static int      _sigfpe_master_enabled;
95*0Sstevel@tonic-gate /* Originally zero, set to 1 by _enable_sigfpe_master. */
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate void
_sigfpe_master(sig,code,scp,addr)98*0Sstevel@tonic-gate _sigfpe_master(sig, code, scp, addr)
99*0Sstevel@tonic-gate 	int             sig;
100*0Sstevel@tonic-gate 	sigfpe_code_type code;
101*0Sstevel@tonic-gate 	struct sigcontext *scp;
102*0Sstevel@tonic-gate 	char *addr;
103*0Sstevel@tonic-gate {
104*0Sstevel@tonic-gate 	int             i;
105*0Sstevel@tonic-gate 	enum fp_exception_type exception;
106*0Sstevel@tonic-gate 
107*0Sstevel@tonic-gate 	for (i = 0; (i < N_SIGFPE_CODE) && (code != sigfpe_codes[i]); i++);
108*0Sstevel@tonic-gate 	/* Find index of handler. */
109*0Sstevel@tonic-gate 	if (i >= N_SIGFPE_CODE)
110*0Sstevel@tonic-gate 		i = N_SIGFPE_CODE - 1;
111*0Sstevel@tonic-gate 	switch ((unsigned int)sigfpe_handlers[i]) {
112*0Sstevel@tonic-gate 	case (unsigned int)SIGFPE_DEFAULT:
113*0Sstevel@tonic-gate 		switch (code) {
114*0Sstevel@tonic-gate 		case FPE_FLTBSUN_TRAP:
115*0Sstevel@tonic-gate 		case FPE_FLTOPERR_TRAP:
116*0Sstevel@tonic-gate 		case FPE_FLTNAN_TRAP:
117*0Sstevel@tonic-gate 			exception = fp_invalid;
118*0Sstevel@tonic-gate 			goto ieee;
119*0Sstevel@tonic-gate 		case FPE_FLTINEX_TRAP:
120*0Sstevel@tonic-gate 			exception = fp_inexact;
121*0Sstevel@tonic-gate 			goto ieee;
122*0Sstevel@tonic-gate 		case FPE_FLTDIV_TRAP:
123*0Sstevel@tonic-gate 			exception = fp_division;
124*0Sstevel@tonic-gate 			goto ieee;
125*0Sstevel@tonic-gate 		case FPE_FLTUND_TRAP:
126*0Sstevel@tonic-gate 			exception = fp_underflow;
127*0Sstevel@tonic-gate 			goto ieee;
128*0Sstevel@tonic-gate 		case FPE_FLTOVF_TRAP:
129*0Sstevel@tonic-gate 			exception = fp_overflow;
130*0Sstevel@tonic-gate 			goto ieee;
131*0Sstevel@tonic-gate 		default:	/* The common default treatment is to abort. */
132*0Sstevel@tonic-gate 			break;
133*0Sstevel@tonic-gate 		}
134*0Sstevel@tonic-gate 	case (unsigned int)SIGFPE_ABORT:
135*0Sstevel@tonic-gate 		abort();
136*0Sstevel@tonic-gate 	case (unsigned int)SIGFPE_IGNORE:
137*0Sstevel@tonic-gate 		return;
138*0Sstevel@tonic-gate 	default:		/* User-defined not SIGFPE_DEFAULT or
139*0Sstevel@tonic-gate 				 * SIGFPE_ABORT. */
140*0Sstevel@tonic-gate 		(sigfpe_handlers[i]) (sig, code, scp, addr);
141*0Sstevel@tonic-gate 		return;
142*0Sstevel@tonic-gate 	}
143*0Sstevel@tonic-gate ieee:
144*0Sstevel@tonic-gate 	switch ((unsigned int)ieee_handlers[(int) exception]) {
145*0Sstevel@tonic-gate 	case (unsigned int)SIGFPE_DEFAULT:
146*0Sstevel@tonic-gate 					/* Error condition but ignore it. */
147*0Sstevel@tonic-gate 	case (unsigned int)SIGFPE_IGNORE:
148*0Sstevel@tonic-gate 					/* Error condition but ignore it. */
149*0Sstevel@tonic-gate 		return;
150*0Sstevel@tonic-gate 	case (unsigned int)SIGFPE_ABORT:
151*0Sstevel@tonic-gate 		abort();
152*0Sstevel@tonic-gate 	default:
153*0Sstevel@tonic-gate 		(ieee_handlers[(int) exception]) (sig, code, scp, addr);
154*0Sstevel@tonic-gate 		return;
155*0Sstevel@tonic-gate 	}
156*0Sstevel@tonic-gate }
157*0Sstevel@tonic-gate 
158*0Sstevel@tonic-gate int
_enable_sigfpe_master()159*0Sstevel@tonic-gate _enable_sigfpe_master()
160*0Sstevel@tonic-gate {
161*0Sstevel@tonic-gate 	/* Enable the sigfpe master handler always.	 */
162*0Sstevel@tonic-gate 	struct sigvec   newsigvec, oldsigvec;
163*0Sstevel@tonic-gate 
164*0Sstevel@tonic-gate 	newsigvec.sv_handler = _sigfpe_master;
165*0Sstevel@tonic-gate 	newsigvec.sv_mask = 0;
166*0Sstevel@tonic-gate 	newsigvec.sv_onstack = 0;
167*0Sstevel@tonic-gate 	_sigfpe_master_enabled = 1;
168*0Sstevel@tonic-gate 	return sigvec(SIGFPE, &newsigvec, &oldsigvec);
169*0Sstevel@tonic-gate }
170*0Sstevel@tonic-gate 
171*0Sstevel@tonic-gate int
_test_sigfpe_master()172*0Sstevel@tonic-gate _test_sigfpe_master()
173*0Sstevel@tonic-gate {
174*0Sstevel@tonic-gate 	/*
175*0Sstevel@tonic-gate 	 * Enable the sigfpe master handler if it's never been enabled
176*0Sstevel@tonic-gate 	 * before.
177*0Sstevel@tonic-gate 	 */
178*0Sstevel@tonic-gate 
179*0Sstevel@tonic-gate 	if (_sigfpe_master_enabled == 0)
180*0Sstevel@tonic-gate 		return _enable_sigfpe_master();
181*0Sstevel@tonic-gate 	else
182*0Sstevel@tonic-gate 		return _sigfpe_master_enabled;
183*0Sstevel@tonic-gate }
184*0Sstevel@tonic-gate 
185*0Sstevel@tonic-gate sigfpe_handler_type
sigfpe(code,hdl)186*0Sstevel@tonic-gate sigfpe(code, hdl)
187*0Sstevel@tonic-gate 	sigfpe_code_type code;
188*0Sstevel@tonic-gate 	sigfpe_handler_type hdl;
189*0Sstevel@tonic-gate {
190*0Sstevel@tonic-gate 	sigfpe_handler_type oldhdl;
191*0Sstevel@tonic-gate 	int             i;
192*0Sstevel@tonic-gate 
193*0Sstevel@tonic-gate 	_test_sigfpe_master();
194*0Sstevel@tonic-gate 	for (i = 0; (i < N_SIGFPE_CODE) && (code != sigfpe_codes[i]); i++);
195*0Sstevel@tonic-gate 	/* Find index of handler. */
196*0Sstevel@tonic-gate 	if (i >= N_SIGFPE_CODE) {
197*0Sstevel@tonic-gate 		errno = EINVAL;
198*0Sstevel@tonic-gate 		return (sigfpe_handler_type) BADSIG;/* Not 0 or SIGFPE code */
199*0Sstevel@tonic-gate 	}
200*0Sstevel@tonic-gate 	oldhdl = sigfpe_handlers[i];
201*0Sstevel@tonic-gate 	sigfpe_handlers[i] = hdl;
202*0Sstevel@tonic-gate 	return oldhdl;
203*0Sstevel@tonic-gate }
204