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