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
_sigfpe_master(sig,code,scp,addr)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
_enable_sigfpe_master()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
_test_sigfpe_master()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
sigfpe(code,hdl)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