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