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