Print this page
11210 libm should be cstyle(1ONBLD) clean
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libm/common/m9x/__fex_hdlr.c
+++ new/usr/src/lib/libm/common/m9x/__fex_hdlr.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
24 24 */
25 +
25 26 /*
26 27 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
27 28 * Use is subject to license terms.
28 29 */
29 30
30 31 #undef lint
31 32 #include <signal.h>
32 33 #include <siginfo.h>
33 34 #include <ucontext.h>
34 35 #include <stdio.h>
35 36 #include <stdlib.h>
36 37 #include <unistd.h>
37 38 #include <thread.h>
38 39 #include <math.h>
39 40 #if defined(__SUNPRO_C)
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
40 41 #include <sunmath.h>
41 42 #endif
42 43 #include <fenv.h>
43 44 #include "fex_handler.h"
44 45 #include "fenv_inlines.h"
45 46
46 47 #if defined(__sparc) && !defined(__sparcv9)
47 48 #include <sys/procfs.h>
48 49 #endif
49 50
50 -/* 2.x signal.h doesn't declare sigemptyset or sigismember
51 - if they're #defined (see sys/signal.h) */
51 +/*
52 + * 2.x signal.h doesn't declare sigemptyset or sigismember
53 + * if they're #define'd (see sys/signal.h)
54 + */
52 55 extern int sigemptyset(sigset_t *);
53 56 extern int sigismember(const sigset_t *, int);
54 57
55 58 /* external globals */
56 -void (*__mt_fex_sync)() = NULL; /* for synchronization with libmtsk */
59 +void (*__mt_fex_sync)() = NULL; /* for synchronization with libmtsk */
57 60 #pragma weak __mt_fex_sync
58 61
59 -void (*__libm_mt_fex_sync)() = NULL; /* new, improved version of above */
62 +void (*__libm_mt_fex_sync)() = NULL; /* new, improved version of above */
60 63 #pragma weak __libm_mt_fex_sync
61 64
62 65 /* private variables */
63 66 static fex_handler_t main_handlers;
64 67 static int handlers_initialized = 0;
65 68 static thread_key_t handlers_key;
66 69 static mutex_t handlers_key_lock = DEFAULTMUTEX;
67 -
68 70 static struct sigaction oact = { 0, SIG_DFL };
69 71 static mutex_t hdlr_lock = DEFAULTMUTEX;
70 72 static int hdlr_installed = 0;
71 73
72 74 /* private const data */
73 75 static const int te_bit[FEX_NUM_EXC] = {
74 - 1 << fp_trap_inexact,
75 - 1 << fp_trap_division,
76 - 1 << fp_trap_underflow,
77 - 1 << fp_trap_overflow,
78 - 1 << fp_trap_invalid,
79 - 1 << fp_trap_invalid,
80 - 1 << fp_trap_invalid,
81 - 1 << fp_trap_invalid,
82 - 1 << fp_trap_invalid,
83 - 1 << fp_trap_invalid,
84 - 1 << fp_trap_invalid,
85 - 1 << fp_trap_invalid
76 + 1 << fp_trap_inexact, 1 << fp_trap_division, 1 << fp_trap_underflow,
77 + 1 << fp_trap_overflow, 1 << fp_trap_invalid, 1 << fp_trap_invalid,
78 + 1 << fp_trap_invalid, 1 << fp_trap_invalid, 1 << fp_trap_invalid,
79 + 1 << fp_trap_invalid, 1 << fp_trap_invalid, 1 << fp_trap_invalid
86 80 };
87 81
88 82 /*
89 -* Return the traps to be enabled given the current handling modes
90 -* and flags
91 -*/
83 + * Return the traps to be enabled given the current handling modes
84 + * and flags
85 + */
92 86 static int
93 87 __fex_te_needed(struct fex_handler_data *thr_handlers, unsigned long fsr)
94 88 {
95 - int i, ex, te;
89 + int i, ex, te;
96 90
97 91 /* set traps for handling modes */
98 92 te = 0;
93 +
99 94 for (i = 0; i < FEX_NUM_EXC; i++)
100 95 if (thr_handlers[i].__mode != FEX_NONSTOP)
101 96 te |= te_bit[i];
102 97
103 98 /* add traps for retrospective diagnostics */
99 +
104 100 if (fex_get_log()) {
105 101 ex = (int)__fenv_get_ex(fsr);
102 +
106 103 if (!(ex & FE_INEXACT))
107 104 te |= (1 << fp_trap_inexact);
105 +
108 106 if (!(ex & FE_UNDERFLOW))
109 107 te |= (1 << fp_trap_underflow);
108 +
110 109 if (!(ex & FE_OVERFLOW))
111 110 te |= (1 << fp_trap_overflow);
111 +
112 112 if (!(ex & FE_DIVBYZERO))
113 113 te |= (1 << fp_trap_division);
114 +
114 115 if (!(ex & FE_INVALID))
115 116 te |= (1 << fp_trap_invalid);
116 117 }
117 118
118 - return te;
119 + return (te);
119 120 }
120 121
121 122 /*
122 -* The following function synchronizes with libmtsk (SPARC only, for now)
123 -*/
123 + * The following function synchronizes with libmtsk (SPARC only, for now)
124 + */
124 125 static void
125 126 __fex_sync_with_libmtsk(int begin, int master)
126 127 {
127 128 static fenv_t master_env;
128 129 static int env_initialized = 0;
129 130 static mutex_t env_lock = DEFAULTMUTEX;
130 131
131 132 if (begin) {
132 133 mutex_lock(&env_lock);
134 +
133 135 if (master) {
134 136 (void) fegetenv(&master_env);
135 137 env_initialized = 1;
136 - }
137 - else if (env_initialized)
138 + } else if (env_initialized) {
138 139 (void) fesetenv(&master_env);
140 + }
141 +
139 142 mutex_unlock(&env_lock);
140 - }
141 - else if (master && fex_get_log())
143 + } else if (master && fex_get_log()) {
142 144 __fex_update_te();
145 + }
143 146 }
144 147
145 148 /*
146 -* The following function may be used for synchronization with any
147 -* internal project that manages multiple threads
148 -*/
149 + * The following function may be used for synchronization with any
150 + * internal project that manages multiple threads
151 + */
149 152 enum __libm_mt_fex_sync_actions {
150 - __libm_mt_fex_start_master = 0,
151 - __libm_mt_fex_start_slave,
152 - __libm_mt_fex_finish_master,
153 - __libm_mt_fex_finish_slave
153 + __libm_mt_fex_start_master = 0, __libm_mt_fex_start_slave,
154 + __libm_mt_fex_finish_master, __libm_mt_fex_finish_slave
154 155 };
155 156
156 157 struct __libm_mt_fex_sync_data {
157 - fenv_t master_env;
158 - int initialized;
159 - mutex_t lock;
158 + fenv_t master_env;
159 + int initialized;
160 + mutex_t lock;
160 161 };
161 162
162 163 static void
163 -__fex_sync_with_threads(enum __libm_mt_fex_sync_actions action,
164 - struct __libm_mt_fex_sync_data *thr_env)
164 +__fex_sync_with_threads(enum __libm_mt_fex_sync_actions action, struct
165 + __libm_mt_fex_sync_data *thr_env)
165 166 {
166 167 switch (action) {
167 168 case __libm_mt_fex_start_master:
168 169 mutex_lock(&thr_env->lock);
169 170 (void) fegetenv(&thr_env->master_env);
170 171 thr_env->initialized = 1;
171 172 mutex_unlock(&thr_env->lock);
172 173 break;
173 174
174 175 case __libm_mt_fex_start_slave:
175 176 mutex_lock(&thr_env->lock);
177 +
176 178 if (thr_env->initialized)
177 179 (void) fesetenv(&thr_env->master_env);
180 +
178 181 mutex_unlock(&thr_env->lock);
179 182 break;
180 183
181 184 case __libm_mt_fex_finish_master:
182 185 #if defined(__x86)
183 186 __fex_update_te();
184 187 #else
185 188 if (fex_get_log())
186 189 __fex_update_te();
187 190 #endif
188 191 break;
189 192
190 193 case __libm_mt_fex_finish_slave:
191 194 #if defined(__x86)
192 - /* clear traps, making all accrued flags visible in status word */
195 + /*
196 + * clear traps, making all accrued flags visible in status
197 + * word
198 + */
193 199 {
194 - unsigned long fsr;
200 + unsigned long fsr;
201 +
195 202 __fenv_getfsr(&fsr);
196 203 __fenv_set_te(fsr, 0);
197 204 __fenv_setfsr(&fsr);
198 205 }
199 206 #endif
200 207 break;
201 208 }
202 209 }
203 210
204 211 #if defined(__sparc)
205 -
206 212 /*
207 -* Code for setting or clearing interval mode on US-III and above.
208 -* This is embedded as data so we don't have to mark the library
209 -* as a v8plusb/v9b object. (I could have just used one entry and
210 -* modified the second word to set the bits I want, but that would
211 -* have required another mutex.)
212 -*/
213 + * Code for setting or clearing interval mode on US-III and above.
214 + * This is embedded as data so we don't have to mark the library
215 + * as a v8plusb/v9b object. (I could have just used one entry and
216 + * modified the second word to set the bits I want, but that would
217 + * have required another mutex.)
218 + */
213 219 static const unsigned int siam[][2] = {
214 - { 0x81c3e008, 0x81b01020 }, /* retl, siam 0 */
215 - { 0x81c3e008, 0x81b01024 }, /* retl, siam 4 */
216 - { 0x81c3e008, 0x81b01025 }, /* retl, siam 5 */
217 - { 0x81c3e008, 0x81b01026 }, /* retl, siam 6 */
218 - { 0x81c3e008, 0x81b01027 } /* retl, siam 7 */
220 + { 0x81c3e008, 0x81b01020 }, /* retl, siam 0 */
221 + { 0x81c3e008, 0x81b01024 }, /* retl, siam 4 */
222 + { 0x81c3e008, 0x81b01025 }, /* retl, siam 5 */
223 + { 0x81c3e008, 0x81b01026 }, /* retl, siam 6 */
224 + { 0x81c3e008, 0x81b01027 } /* retl, siam 7 */
219 225 };
220 226
221 227 /*
222 -* If a handling mode is in effect, apply it; otherwise invoke the
223 -* saved handler
224 -*/
228 + * If a handling mode is in effect, apply it; otherwise invoke the
229 + * saved handler
230 + */
225 231 static void
226 232 __fex_hdlr(int sig, siginfo_t *sip, ucontext_t *uap)
227 233 {
228 - struct fex_handler_data *thr_handlers;
229 - struct sigaction act;
230 - void (*handler)(), (*siamp)();
231 - int mode, i;
232 - enum fex_exception e;
233 - fex_info_t info;
234 - unsigned long fsr, tmpfsr, addr;
235 - unsigned int gsr;
234 + struct fex_handler_data *thr_handlers;
235 + struct sigaction act;
236 +
237 + void (*handler)(), (*siamp)();
238 +
239 + int mode, i;
240 + enum fex_exception e;
241 + fex_info_t info;
242 + unsigned long fsr, tmpfsr, addr;
243 + unsigned int gsr;
236 244
237 245 /* determine which exception occurred */
238 246 switch (sip->si_code) {
239 247 case FPE_FLTDIV:
240 248 e = fex_division;
241 249 break;
242 250 case FPE_FLTOVF:
243 251 e = fex_overflow;
244 252 break;
245 253 case FPE_FLTUND:
246 254 e = fex_underflow;
247 255 break;
248 256 case FPE_FLTRES:
249 257 e = fex_inexact;
250 258 break;
251 259 case FPE_FLTINV:
260 +
252 261 if ((int)(e = __fex_get_invalid_type(sip, uap)) < 0)
253 262 goto not_ieee;
263 +
254 264 break;
255 265 default:
256 266 /* not an IEEE exception */
257 267 goto not_ieee;
258 268 }
259 269
260 270 /* get the handling mode */
261 271 mode = FEX_NOHANDLER;
262 272 handler = oact.sa_handler; /* for log; just looking, no need to lock */
263 273 thr_handlers = __fex_get_thr_handlers();
274 +
264 275 if (thr_handlers && thr_handlers[(int)e].__mode != FEX_NOHANDLER) {
265 276 mode = thr_handlers[(int)e].__mode;
266 277 handler = thr_handlers[(int)e].__handler;
267 278 }
268 279
269 280 /* make an entry in the log of retro. diag. if need be */
270 281 i = ((int)uap->uc_mcontext.fpregs.fpu_fsr >> 5) & 0x1f;
271 282 __fex_mklog(uap, (char *)sip->si_addr, i, e, mode, (void *)handler);
272 283
273 284 /* handle the exception based on the mode */
274 - if (mode == FEX_NOHANDLER)
285 + if (mode == FEX_NOHANDLER) {
275 286 goto not_ieee;
276 - else if (mode == FEX_ABORT)
287 + } else if (mode == FEX_ABORT) {
277 288 abort();
278 - else if (mode == FEX_SIGNAL) {
289 + } else if (mode == FEX_SIGNAL) {
279 290 handler(sig, sip, uap);
280 291 return;
281 292 }
282 293
283 294 /* custom or nonstop mode; disable traps and clear flags */
284 295 __fenv_getfsr(&fsr);
285 296 __fenv_set_te(fsr, 0);
286 297 __fenv_set_ex(fsr, 0);
287 298
288 - /* if interval mode was set, clear it, then substitute the
289 - interval rounding direction and clear ns mode in the fsr */
299 + /*
300 + * if interval mode was set, clear it, then substitute the interval
301 + * rounding direction and clear ns mode in the fsr
302 + */
290 303 #ifdef __sparcv9
291 304 gsr = uap->uc_mcontext.asrs[3];
292 305 #else
293 306 gsr = 0;
307 +
294 308 if (uap->uc_mcontext.xrs.xrs_id == XRS_ID)
295 - gsr = (*(unsigned long long*)((prxregset_t*)uap->uc_mcontext.
296 - xrs.xrs_ptr)->pr_un.pr_v8p.pr_filler);
309 + gsr = (*(unsigned long long *)
310 + ((prxregset_t *)uap->uc_mcontext.xrs.xrs_ptr)->pr_un.
311 + pr_v8p.pr_filler);
297 312 #endif
298 313 gsr = (gsr >> 25) & 7;
314 +
299 315 if (gsr & 4) {
300 - siamp = (void (*)()) siam[0];
316 + siamp = (void (*)())siam[0];
301 317 siamp();
302 318 tmpfsr = fsr;
303 319 fsr = (fsr & ~0xc0400000ul) | ((gsr & 3) << 30);
304 320 }
321 +
305 322 __fenv_setfsr(&fsr);
306 323
307 324 /* decode the operation */
308 325 __fex_get_op(sip, uap, &info);
309 326
310 327 /* if a custom mode handler is installed, invoke it */
311 328 if (mode == FEX_CUSTOM) {
312 329 /* if we got here from feraiseexcept, pass dummy info */
313 330 addr = (unsigned long)sip->si_addr;
314 - if (addr >= (unsigned long)feraiseexcept &&
315 - addr < (unsigned long)fetestexcept) {
331 +
332 + if (addr >= (unsigned long)feraiseexcept && addr < (unsigned
333 + long)fetestexcept) {
316 334 info.op = fex_other;
317 335 info.op1.type = info.op2.type = info.res.type =
318 336 fex_nodata;
319 337 }
320 338
321 - /* restore interval mode if it was set, and put the original
322 - rounding direction and ns mode back in the fsr */
339 + /*
340 + * restore interval mode if it was set, and put the original
341 + * rounding direction and ns mode back in the fsr
342 + */
323 343 if (gsr & 4) {
324 344 __fenv_setfsr(&tmpfsr);
325 - siamp = (void (*)()) siam[1 + (gsr & 3)];
345 + siamp = (void (*)())siam[1 + (gsr & 3)];
326 346 siamp();
327 347 }
328 348
329 349 handler(1 << (int)e, &info);
330 350
331 351 /* restore modes in case the user's handler changed them */
332 352 if (gsr & 4) {
333 - siamp = (void (*)()) siam[0];
353 + siamp = (void (*)())siam[0];
334 354 siamp();
335 355 }
356 +
336 357 __fenv_setfsr(&fsr);
337 358 }
338 359
339 360 /* stuff the result */
340 361 __fex_st_result(sip, uap, &info);
341 362
342 363 /* "or" in any exception flags and update traps */
343 364 fsr = uap->uc_mcontext.fpregs.fpu_fsr;
344 365 fsr |= ((info.flags & 0x1f) << 5);
345 366 i = __fex_te_needed(thr_handlers, fsr);
346 367 __fenv_set_te(fsr, i);
347 368 uap->uc_mcontext.fpregs.fpu_fsr = fsr;
348 369 return;
349 370
350 371 not_ieee:
351 372 /* revert to the saved handler (if any) */
352 373 mutex_lock(&hdlr_lock);
353 374 act = oact;
354 375 mutex_unlock(&hdlr_lock);
376 +
355 377 switch ((unsigned long)act.sa_handler) {
356 378 case (unsigned long)SIG_DFL:
357 379 /* simulate trap with no handler installed */
358 380 sigaction(SIGFPE, &act, NULL);
359 381 kill(getpid(), SIGFPE);
360 382 break;
361 383 #if !defined(__lint)
362 384 case (unsigned long)SIG_IGN:
363 385 break;
364 386 #endif
365 387 default:
366 388 act.sa_handler(sig, sip, uap);
367 389 }
368 390 }
369 -
370 391 #elif defined(__x86)
371 -
372 392 #if defined(__amd64)
373 -#define test_sse_hw 1
393 +#define test_sse_hw 1
374 394 #else
375 395 extern int _sse_hw;
376 -#define test_sse_hw _sse_hw
396 +
397 +#define test_sse_hw _sse_hw
377 398 #endif
378 399
379 400 #if !defined(REG_PC)
380 -#define REG_PC EIP
401 +#define REG_PC EIP
381 402 #endif
382 403
383 404 /*
384 -* If a handling mode is in effect, apply it; otherwise invoke the
385 -* saved handler
386 -*/
405 + * If a handling mode is in effect, apply it; otherwise invoke the
406 + * saved handler
407 + */
387 408 static void
388 409 __fex_hdlr(int sig, siginfo_t *sip, ucontext_t *uap)
389 410 {
390 - struct fex_handler_data *thr_handlers;
391 - struct sigaction act;
392 - void (*handler)() = NULL, (*simd_handler[4])();
393 - int mode, simd_mode[4], i, len, accrued, *ap;
394 - unsigned int cwsw, oldcwsw, mxcsr, oldmxcsr;
395 - enum fex_exception e, simd_e[4];
396 - fex_info_t info, simd_info[4];
397 - unsigned long addr;
398 - siginfo_t osip = *sip;
399 - sseinst_t inst;
411 + struct fex_handler_data *thr_handlers;
412 + struct sigaction act;
413 +
414 + void (*handler)() = NULL, (*simd_handler[4])();
415 +
416 + int mode, simd_mode[4], i, len, accrued, *ap;
417 + unsigned int cwsw, oldcwsw, mxcsr, oldmxcsr;
418 + enum fex_exception e, simd_e[4];
419 + fex_info_t info, simd_info[4];
420 + unsigned long addr;
421 + siginfo_t osip = *sip;
422 + sseinst_t inst;
400 423
401 424 /* check for an exception caused by an SSE instruction */
402 425 if (!(uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.status & 0x80)) {
403 426 len = __fex_parse_sse(uap, &inst);
427 +
404 428 if (len == 0)
405 429 goto not_ieee;
406 430
407 431 /* disable all traps and clear flags */
408 432 __fenv_getcwsw(&oldcwsw);
409 433 cwsw = (oldcwsw & ~0x3f) | 0x003f0000;
410 434 __fenv_setcwsw(&cwsw);
411 435 __fenv_getmxcsr(&oldmxcsr);
412 436 mxcsr = (oldmxcsr & ~0x3f) | 0x1f80;
413 437 __fenv_setmxcsr(&mxcsr);
414 438
415 439 if ((int)inst.op & SIMD) {
416 440 __fex_get_simd_op(uap, &inst, simd_e, simd_info);
417 441
418 442 thr_handlers = __fex_get_thr_handlers();
419 443 addr = (unsigned long)uap->uc_mcontext.gregs[REG_PC];
420 - accrued = uap->uc_mcontext.fpregs.fp_reg_set.
421 - fpchip_state.mxcsr;
444 + accrued =
445 + uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.
446 + mxcsr;
422 447
423 448 e = (enum fex_exception)-1;
424 449 mode = FEX_NONSTOP;
450 +
425 451 for (i = 0; i < 4; i++) {
426 452 if ((int)simd_e[i] < 0)
427 453 continue;
428 454
429 455 e = simd_e[i];
430 456 simd_mode[i] = FEX_NOHANDLER;
431 457 simd_handler[i] = oact.sa_handler;
458 +
432 459 if (thr_handlers &&
433 460 thr_handlers[(int)e].__mode !=
434 461 FEX_NOHANDLER) {
435 462 simd_mode[i] =
436 463 thr_handlers[(int)e].__mode;
437 464 simd_handler[i] =
438 465 thr_handlers[(int)e].__handler;
439 466 }
467 +
440 468 accrued &= ~te_bit[(int)e];
469 +
441 470 switch (simd_mode[i]) {
442 471 case FEX_ABORT:
443 472 mode = FEX_ABORT;
444 473 break;
445 474 case FEX_SIGNAL:
475 +
446 476 if (mode != FEX_ABORT)
447 477 mode = FEX_SIGNAL;
478 +
448 479 handler = simd_handler[i];
449 480 break;
450 481 case FEX_NOHANDLER:
482 +
451 483 if (mode != FEX_ABORT && mode !=
452 484 FEX_SIGNAL)
453 485 mode = FEX_NOHANDLER;
486 +
454 487 break;
455 488 }
456 489 }
490 +
457 491 if (e == (enum fex_exception)-1) {
458 492 __fenv_setcwsw(&oldcwsw);
459 493 __fenv_setmxcsr(&oldmxcsr);
460 494 goto not_ieee;
461 495 }
462 - accrued |= uap->uc_mcontext.fpregs.fp_reg_set.
463 - fpchip_state.status;
496 +
497 + accrued |=
498 + uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.
499 + status;
464 500 ap = __fex_accrued();
465 501 accrued |= *ap;
466 502 accrued &= 0x3d;
467 503
468 504 for (i = 0; i < 4; i++) {
469 505 if ((int)simd_e[i] < 0)
470 506 continue;
471 507
472 508 __fex_mklog(uap, (char *)addr, accrued,
473 509 simd_e[i], simd_mode[i],
474 510 (void *)simd_handler[i]);
475 511 }
476 512
477 513 if (mode == FEX_NOHANDLER) {
478 514 __fenv_setcwsw(&oldcwsw);
479 515 __fenv_setmxcsr(&oldmxcsr);
480 516 goto not_ieee;
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
481 517 } else if (mode == FEX_ABORT) {
482 518 abort();
483 519 } else if (mode == FEX_SIGNAL) {
484 520 __fenv_setcwsw(&oldcwsw);
485 521 __fenv_setmxcsr(&oldmxcsr);
486 522 handler(sig, &osip, uap);
487 523 return;
488 524 }
489 525
490 526 *ap = 0;
527 +
491 528 for (i = 0; i < 4; i++) {
492 529 if ((int)simd_e[i] < 0)
493 530 continue;
494 531
495 532 if (simd_mode[i] == FEX_CUSTOM) {
496 533 handler(1 << (int)simd_e[i],
497 534 &simd_info[i]);
498 535 __fenv_setcwsw(&cwsw);
499 536 __fenv_setmxcsr(&mxcsr);
500 537 }
501 538 }
502 539
503 540 __fex_st_simd_result(uap, &inst, simd_e, simd_info);
541 +
504 542 for (i = 0; i < 4; i++) {
505 543 if ((int)simd_e[i] < 0)
506 544 continue;
507 545
508 546 accrued |= simd_info[i].flags;
509 547 }
510 548
511 549 if ((int)inst.op & INTREG) {
512 550 /* set MMX mode */
513 551 #if defined(__amd64)
514 - uap->uc_mcontext.fpregs.fp_reg_set.
515 - fpchip_state.sw &= ~0x3800;
516 - uap->uc_mcontext.fpregs.fp_reg_set.
517 - fpchip_state.fctw = 0;
552 + uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.
553 + sw &= ~0x3800;
554 + uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.
555 + fctw = 0;
518 556 #else
519 - uap->uc_mcontext.fpregs.fp_reg_set.
520 - fpchip_state.state[1] &= ~0x3800;
521 - uap->uc_mcontext.fpregs.fp_reg_set.
522 - fpchip_state.state[2] = 0;
557 + uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.
558 + state[1] &= ~0x3800;
559 + uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.
560 + state[2] = 0;
523 561 #endif
524 562 }
525 563 } else {
526 564 e = __fex_get_sse_op(uap, &inst, &info);
565 +
527 566 if ((int)e < 0) {
528 567 __fenv_setcwsw(&oldcwsw);
529 568 __fenv_setmxcsr(&oldmxcsr);
530 569 goto not_ieee;
531 570 }
532 571
533 572 mode = FEX_NOHANDLER;
534 573 handler = oact.sa_handler;
535 574 thr_handlers = __fex_get_thr_handlers();
575 +
536 576 if (thr_handlers && thr_handlers[(int)e].__mode !=
537 577 FEX_NOHANDLER) {
538 578 mode = thr_handlers[(int)e].__mode;
539 579 handler = thr_handlers[(int)e].__handler;
540 580 }
541 581
542 582 addr = (unsigned long)uap->uc_mcontext.gregs[REG_PC];
543 - accrued = uap->uc_mcontext.fpregs.fp_reg_set.
544 - fpchip_state.mxcsr & ~te_bit[(int)e];
545 - accrued |= uap->uc_mcontext.fpregs.fp_reg_set.
546 - fpchip_state.status;
583 + accrued =
584 + uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.
585 + mxcsr & ~te_bit[(int)e];
586 + accrued |=
587 + uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.
588 + status;
547 589 ap = __fex_accrued();
548 590 accrued |= *ap;
549 591 accrued &= 0x3d;
550 592 __fex_mklog(uap, (char *)addr, accrued, e, mode,
551 593 (void *)handler);
552 594
553 595 if (mode == FEX_NOHANDLER) {
554 596 __fenv_setcwsw(&oldcwsw);
555 597 __fenv_setmxcsr(&oldmxcsr);
556 598 goto not_ieee;
557 599 } else if (mode == FEX_ABORT) {
558 600 abort();
559 601 } else if (mode == FEX_SIGNAL) {
560 602 __fenv_setcwsw(&oldcwsw);
561 603 __fenv_setmxcsr(&oldmxcsr);
562 604 handler(sig, &osip, uap);
563 605 return;
564 606 } else if (mode == FEX_CUSTOM) {
565 607 *ap = 0;
608 +
566 609 if (addr >= (unsigned long)feraiseexcept &&
567 610 addr < (unsigned long)fetestexcept) {
568 611 info.op = fex_other;
569 612 info.op1.type = info.op2.type =
570 613 info.res.type = fex_nodata;
571 614 }
615 +
572 616 handler(1 << (int)e, &info);
573 617 __fenv_setcwsw(&cwsw);
574 618 __fenv_setmxcsr(&mxcsr);
575 619 }
576 620
577 621 __fex_st_sse_result(uap, &inst, e, &info);
578 622 accrued |= info.flags;
579 623
580 624 #if defined(__amd64)
581 625 /*
582 626 * In 64-bit mode, the 32-bit convert-to-integer
583 627 * instructions zero the upper 32 bits of the
584 628 * destination. (We do this here and not in
585 629 * __fex_st_sse_result because __fex_st_sse_result
586 630 * can be called from __fex_st_simd_result, too.)
587 631 */
588 632 if (inst.op == cvtss2si || inst.op == cvttss2si ||
589 633 inst.op == cvtsd2si || inst.op == cvttsd2si)
590 634 inst.op1->i[1] = 0;
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
591 635 #endif
592 636 }
593 637
594 638 /* advance the pc past the SSE instruction */
595 639 uap->uc_mcontext.gregs[REG_PC] += len;
596 640 goto update_state;
597 641 }
598 642
599 643 /* determine which exception occurred */
600 644 __fex_get_x86_exc(sip, uap);
645 +
601 646 switch (sip->si_code) {
602 647 case FPE_FLTDIV:
603 648 e = fex_division;
604 649 break;
605 650 case FPE_FLTOVF:
606 651 e = fex_overflow;
607 652 break;
608 653 case FPE_FLTUND:
609 654 e = fex_underflow;
610 655 break;
611 656 case FPE_FLTRES:
612 657 e = fex_inexact;
613 658 break;
614 659 case FPE_FLTINV:
660 +
615 661 if ((int)(e = __fex_get_invalid_type(sip, uap)) < 0)
616 662 goto not_ieee;
663 +
617 664 break;
618 665 default:
619 666 /* not an IEEE exception */
620 667 goto not_ieee;
621 668 }
622 669
623 670 /* get the handling mode */
624 671 mode = FEX_NOHANDLER;
625 672 handler = oact.sa_handler; /* for log; just looking, no need to lock */
626 673 thr_handlers = __fex_get_thr_handlers();
674 +
627 675 if (thr_handlers && thr_handlers[(int)e].__mode != FEX_NOHANDLER) {
628 676 mode = thr_handlers[(int)e].__mode;
629 677 handler = thr_handlers[(int)e].__handler;
630 678 }
631 679
632 680 /* make an entry in the log of retro. diag. if need be */
633 681 #if defined(__amd64)
634 - addr = (unsigned long)uap->uc_mcontext.fpregs.fp_reg_set.
635 - fpchip_state.rip;
682 + addr = (unsigned
683 + long)uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.rip;
636 684 #else
637 - addr = (unsigned long)uap->uc_mcontext.fpregs.fp_reg_set.
638 - fpchip_state.state[3];
685 + addr = (unsigned
686 + long)uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[3];
639 687 #endif
640 - accrued = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.status &
688 + accrued = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.status &
641 689 ~te_bit[(int)e];
690 +
642 691 if (test_sse_hw)
643 - accrued |= uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.
644 - mxcsr;
692 + accrued |=
693 + uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.mxcsr;
694 +
645 695 ap = __fex_accrued();
646 696 accrued |= *ap;
647 697 accrued &= 0x3d;
648 698 __fex_mklog(uap, (char *)addr, accrued, e, mode, (void *)handler);
649 699
650 700 /* handle the exception based on the mode */
651 - if (mode == FEX_NOHANDLER)
701 + if (mode == FEX_NOHANDLER) {
652 702 goto not_ieee;
653 - else if (mode == FEX_ABORT)
703 + } else if (mode == FEX_ABORT) {
654 704 abort();
655 - else if (mode == FEX_SIGNAL) {
705 + } else if (mode == FEX_SIGNAL) {
656 706 handler(sig, &osip, uap);
657 707 return;
658 708 }
659 709
660 710 /* disable all traps and clear flags */
661 711 __fenv_getcwsw(&cwsw);
662 712 cwsw = (cwsw & ~0x3f) | 0x003f0000;
663 713 __fenv_setcwsw(&cwsw);
714 +
664 715 if (test_sse_hw) {
665 716 __fenv_getmxcsr(&mxcsr);
666 717 mxcsr = (mxcsr & ~0x3f) | 0x1f80;
667 718 __fenv_setmxcsr(&mxcsr);
668 719 }
720 +
669 721 *ap = 0;
670 722
671 723 /* decode the operation */
672 724 __fex_get_op(sip, uap, &info);
673 725
674 726 /* if a custom mode handler is installed, invoke it */
675 727 if (mode == FEX_CUSTOM) {
676 728 /* if we got here from feraiseexcept, pass dummy info */
677 - if (addr >= (unsigned long)feraiseexcept &&
678 - addr < (unsigned long)fetestexcept) {
729 + if (addr >= (unsigned long)feraiseexcept && addr < (unsigned
730 + long)fetestexcept) {
679 731 info.op = fex_other;
680 732 info.op1.type = info.op2.type = info.res.type =
681 733 fex_nodata;
682 734 }
683 735
684 736 handler(1 << (int)e, &info);
685 737
686 738 /* restore modes in case the user's handler changed them */
687 739 __fenv_setcwsw(&cwsw);
740 +
688 741 if (test_sse_hw)
689 742 __fenv_setmxcsr(&mxcsr);
690 743 }
691 744
692 745 /* stuff the result */
693 746 __fex_st_result(sip, uap, &info);
694 747 accrued |= info.flags;
695 748
696 749 update_state:
697 750 accrued &= 0x3d;
698 751 i = __fex_te_needed(thr_handlers, accrued);
699 752 *ap = accrued & i;
700 753 #if defined(__amd64)
701 754 uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw &= ~0x3d;
702 755 uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw |= (accrued & ~i);
703 756 uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.cw |= 0x3d;
704 757 uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.cw &= ~i;
705 758 #else
706 759 uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[1] &= ~0x3d;
707 - uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[1] |=
708 - (accrued & ~i);
760 + uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[1] |= (accrued &
761 + ~i);
709 762 uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[0] |= 0x3d;
710 763 uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[0] &= ~i;
711 764 #endif
765 +
712 766 if (test_sse_hw) {
713 767 uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.mxcsr &= ~0x3d;
714 768 uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.mxcsr |=
715 769 0x1e80 | (accrued & ~i);
716 - uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.mxcsr &=
717 - ~(i << 7);
770 + uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.mxcsr &= ~(i <<
771 + 7);
718 772 }
773 +
719 774 return;
720 775
721 776 not_ieee:
722 777 /* revert to the saved handler (if any) */
723 778 mutex_lock(&hdlr_lock);
724 779 act = oact;
725 780 mutex_unlock(&hdlr_lock);
781 +
726 782 switch ((unsigned long)act.sa_handler) {
727 783 case (unsigned long)SIG_DFL:
728 784 /* simulate trap with no handler installed */
729 785 sigaction(SIGFPE, &act, NULL);
730 786 kill(getpid(), SIGFPE);
731 787 break;
732 788 #if !defined(__lint)
733 789 case (unsigned long)SIG_IGN:
734 790 break;
735 791 #endif
736 792 default:
737 793 act.sa_handler(sig, &osip, uap);
738 794 }
739 795 }
740 -
741 796 #else
742 797 #error Unknown architecture
743 798 #endif
744 799
745 800 /*
746 -* Return a pointer to the thread-specific handler data, and
747 -* initialize it if necessary
748 -*/
801 + * Return a pointer to the thread-specific handler data, and
802 + * initialize it if necessary
803 + */
749 804 struct fex_handler_data *
750 805 __fex_get_thr_handlers()
751 806 {
752 - struct fex_handler_data *ptr;
753 - unsigned long fsr;
754 - int i, te;
807 + struct fex_handler_data *ptr;
808 + unsigned long fsr;
809 + int i, te;
755 810
756 811 if (thr_main()) {
757 812 if (!handlers_initialized) {
758 - /* initialize to FEX_NOHANDLER if trap is enabled,
759 - FEX_NONSTOP if trap is disabled */
813 + /*
814 + * initialize to FEX_NOHANDLER if trap is enabled,
815 + * FEX_NONSTOP if trap is disabled
816 + */
760 817 __fenv_getfsr(&fsr);
761 818 te = (int)__fenv_get_te(fsr);
819 +
762 820 for (i = 0; i < FEX_NUM_EXC; i++)
763 - main_handlers[i].__mode =
764 - ((te & te_bit[i])? FEX_NOHANDLER : FEX_NONSTOP);
821 + main_handlers[i].__mode = ((te & te_bit[i]) ?
822 + FEX_NOHANDLER : FEX_NONSTOP);
823 +
765 824 handlers_initialized = 1;
766 825 }
767 - return main_handlers;
768 - }
769 - else {
826 +
827 + return (main_handlers);
828 + } else {
770 829 ptr = NULL;
771 830 mutex_lock(&handlers_key_lock);
831 +
772 832 if (thr_getspecific(handlers_key, (void **)&ptr) != 0 &&
773 - thr_keycreate(&handlers_key, free) != 0) {
833 + thr_keycreate(&handlers_key, free) != 0) {
774 834 mutex_unlock(&handlers_key_lock);
775 - return NULL;
835 + return (NULL);
776 836 }
837 +
777 838 mutex_unlock(&handlers_key_lock);
839 +
778 840 if (!ptr) {
779 - if ((ptr = (struct fex_handler_data *)
780 - malloc(sizeof(fex_handler_t))) == NULL) {
781 - return NULL;
782 - }
841 + if ((ptr = malloc(sizeof (fex_handler_t))) == NULL)
842 + return (NULL);
843 +
783 844 if (thr_setspecific(handlers_key, (void *)ptr) != 0) {
784 - (void)free(ptr);
785 - return NULL;
845 + (void) free(ptr);
846 + return (NULL);
786 847 }
787 - /* initialize to FEX_NOHANDLER if trap is enabled,
788 - FEX_NONSTOP if trap is disabled */
848 +
849 + /*
850 + * initialize to FEX_NOHANDLER if trap is enabled,
851 + * FEX_NONSTOP if trap is disabled
852 + */
789 853 __fenv_getfsr(&fsr);
790 854 te = (int)__fenv_get_te(fsr);
855 +
791 856 for (i = 0; i < FEX_NUM_EXC; i++)
792 - ptr[i].__mode = ((te & te_bit[i])? FEX_NOHANDLER : FEX_NONSTOP);
857 + ptr[i].__mode = ((te & te_bit[i]) ?
858 + FEX_NOHANDLER : FEX_NONSTOP);
793 859 }
794 - return ptr;
860 +
861 + return (ptr);
795 862 }
796 863 }
797 864
798 865 /*
799 -* Update the trap enable bits according to the selected modes
800 -*/
866 + * Update the trap enable bits according to the selected modes
867 + */
801 868 void
802 869 __fex_update_te()
803 870 {
804 - struct fex_handler_data *thr_handlers;
805 - struct sigaction act, tmpact;
806 - sigset_t blocked;
807 - unsigned long fsr;
808 - int te;
871 + struct fex_handler_data *thr_handlers;
872 + struct sigaction act, tmpact;
873 + sigset_t blocked;
874 + unsigned long fsr;
875 + int te;
809 876
810 877 /* determine which traps are needed */
811 878 thr_handlers = __fex_get_thr_handlers();
812 879 __fenv_getfsr(&fsr);
813 880 te = __fex_te_needed(thr_handlers, fsr);
814 881
815 882 /* install __fex_hdlr as necessary */
816 883 if (!hdlr_installed && te) {
817 884 act.sa_handler = __fex_hdlr;
818 885 sigemptyset(&act.sa_mask);
819 886 act.sa_flags = SA_SIGINFO;
820 887 sigaction(SIGFPE, &act, &tmpact);
821 - if (tmpact.sa_handler != __fex_hdlr)
822 - {
888 +
889 + if (tmpact.sa_handler != __fex_hdlr) {
823 890 mutex_lock(&hdlr_lock);
824 891 oact = tmpact;
825 892 mutex_unlock(&hdlr_lock);
826 893 }
894 +
827 895 hdlr_installed = 1;
828 896 }
829 897
830 898 /* set the new trap enable bits (only if SIGFPE is not blocked) */
831 - if (sigprocmask(0, NULL, &blocked) == 0 &&
832 - !sigismember(&blocked, SIGFPE)) {
899 + if (sigprocmask(0, NULL, &blocked) == 0 && !sigismember(&blocked,
900 + SIGFPE)) {
833 901 __fenv_set_te(fsr, te);
834 902 __fenv_setfsr(&fsr);
835 903 }
836 904
837 905 /* synchronize with libmtsk */
838 906 __mt_fex_sync = __fex_sync_with_libmtsk;
839 907
840 908 /* synchronize with other projects */
841 909 __libm_mt_fex_sync = __fex_sync_with_threads;
842 910 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX