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