Print this page
11210 libm should be cstyle(1ONBLD) clean

*** 20,29 **** --- 20,30 ---- */ /* * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ + /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */
*** 49,91 **** /* * The following variable lives in libc on Solaris 10, where it * gets set to a nonzero value at startup time on systems with SSE. */ extern int _sse_hw; #define test_sse_hw _sse_hw #endif static int accrued = 0; static thread_key_t accrued_key; static mutex_t accrued_key_lock = DEFAULTMUTEX; - int * __fex_accrued() { int *p; ! if (thr_main()) ! return &accrued; ! else { p = NULL; mutex_lock(&accrued_key_lock); if (thr_getspecific(accrued_key, (void **)&p) != 0 && thr_keycreate(&accrued_key, free) != 0) { mutex_unlock(&accrued_key_lock); ! return NULL; } mutex_unlock(&accrued_key_lock); if (!p) { ! if ((p = (int*) malloc(sizeof(int))) == NULL) ! return NULL; if (thr_setspecific(accrued_key, (void *)p) != 0) { ! (void)free(p); ! return NULL; } *p = 0; } ! return p; } } void __fenv_getfsr(unsigned long *fsr) --- 50,98 ---- /* * The following variable lives in libc on Solaris 10, where it * gets set to a nonzero value at startup time on systems with SSE. */ extern int _sse_hw; + #define test_sse_hw _sse_hw #endif static int accrued = 0; static thread_key_t accrued_key; static mutex_t accrued_key_lock = DEFAULTMUTEX; int * __fex_accrued() { int *p; ! if (thr_main()) { ! return (&accrued); ! } else { p = NULL; mutex_lock(&accrued_key_lock); + if (thr_getspecific(accrued_key, (void **)&p) != 0 && thr_keycreate(&accrued_key, free) != 0) { mutex_unlock(&accrued_key_lock); ! return (NULL); } + mutex_unlock(&accrued_key_lock); + if (!p) { ! if ((p = (int *)malloc(sizeof (int))) == NULL) ! return (NULL); ! if (thr_setspecific(accrued_key, (void *)p) != 0) { ! (void) free(p); ! return (NULL); } + *p = 0; } ! ! return (p); } } void __fenv_getfsr(unsigned long *fsr)
*** 93,108 **** unsigned int cwsw, mxcsr; __fenv_getcwsw(&cwsw); /* clear reserved bits for no particularly good reason */ cwsw &= ~0xe0c00000u; if (test_sse_hw) { ! /* pick up exception flags (excluding denormal operand ! flag) from mxcsr */ __fenv_getmxcsr(&mxcsr); cwsw |= (mxcsr & 0x3d); } cwsw |= *__fex_accrued(); *fsr = cwsw ^ 0x003f0000u; } void --- 100,119 ---- unsigned int cwsw, mxcsr; __fenv_getcwsw(&cwsw); /* clear reserved bits for no particularly good reason */ cwsw &= ~0xe0c00000u; + if (test_sse_hw) { ! /* ! * pick up exception flags (excluding denormal operand flag) ! * from mxcsr ! */ __fenv_getmxcsr(&mxcsr); cwsw |= (mxcsr & 0x3d); } + cwsw |= *__fex_accrued(); *fsr = cwsw ^ 0x003f0000u; } void
*** 114,131 **** /* save accrued exception flags corresponding to enabled exceptions */ cwsw = (unsigned int)*fsr; te = __fenv_get_te(cwsw); *__fex_accrued() = cwsw & te; cwsw = (cwsw & ~te) ^ 0x003f0000; if (test_sse_hw) { ! /* propagate rounding direction, masks, and exception flags ! (excluding denormal operand mask and flag) to mxcsr */ __fenv_getmxcsr(&mxcsr); ! mxcsr = (mxcsr & ~0x7ebd) | ((cwsw >> 13) & 0x6000) | ! ((cwsw >> 9) & 0x1e80) | (cwsw & 0x3d); __fenv_setmxcsr(&mxcsr); } __fenv_setcwsw(&cwsw); } /* Offsets into the fp environment save area (assumes 32-bit protected mode) */ #define CW 0 /* control word */ --- 125,146 ---- /* save accrued exception flags corresponding to enabled exceptions */ cwsw = (unsigned int)*fsr; te = __fenv_get_te(cwsw); *__fex_accrued() = cwsw & te; cwsw = (cwsw & ~te) ^ 0x003f0000; + if (test_sse_hw) { ! /* ! * propagate rounding direction, masks, and exception flags ! * (excluding denormal operand mask and flag) to mxcsr ! */ __fenv_getmxcsr(&mxcsr); ! mxcsr = (mxcsr & ~0x7ebd) | ((cwsw >> 13) & 0x6000) | ((cwsw >> ! 9) & 0x1e80) | (cwsw & 0x3d); __fenv_setmxcsr(&mxcsr); } + __fenv_setcwsw(&cwsw); } /* Offsets into the fp environment save area (assumes 32-bit protected mode) */ #define CW 0 /* control word */
*** 135,152 **** #define OP 4 /* opcode */ #define EA 5 /* operand address */ /* macro for accessing fp registers in the save area */ #if defined(__amd64) ! #define fpreg(u,x) *(long double *)(10*(x)+(char*)&(u)->uc_mcontext.fpregs.fp_reg_set.fpchip_state.st) #else ! #define fpreg(u,x) *(long double *)(10*(x)+(char*)&(u)->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[7]) #endif /* ! * Fix sip->si_code; the Solaris x86 kernel can get it wrong ! */ void __fex_get_x86_exc(siginfo_t *sip, ucontext_t *uap) { unsigned sw, cw; --- 150,169 ---- #define OP 4 /* opcode */ #define EA 5 /* operand address */ /* macro for accessing fp registers in the save area */ #if defined(__amd64) ! #define fpreg(u, x) *(long double *)(10 * (x) + \ ! (char *)&(u)->uc_mcontext.fpregs.fp_reg_set.fpchip_state.st) #else ! #define fpreg(u, x) *(long double *)(10 * (x) + \ ! (char *)&(u)->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[7]) #endif /* ! * Fix sip->si_code; the Solaris x86 kernel can get it wrong ! */ void __fex_get_x86_exc(siginfo_t *sip, ucontext_t *uap) { unsigned sw, cw;
*** 154,166 **** #if defined(__amd64) cw = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.cw; #else cw = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[CW]; #endif if ((sw & FE_INVALID) && !(cw & (1 << fp_trap_invalid))) /* store 0 for stack fault, FPE_FLTINV for IEEE invalid op */ ! sip->si_code = ((sw & 0x40)? 0 : FPE_FLTINV); else if ((sw & FE_DIVBYZERO) && !(cw & (1 << fp_trap_division))) sip->si_code = FPE_FLTDIV; else if ((sw & FE_OVERFLOW) && !(cw & (1 << fp_trap_overflow))) sip->si_code = FPE_FLTOVF; else if ((sw & FE_UNDERFLOW) && !(cw & (1 << fp_trap_underflow))) --- 171,184 ---- #if defined(__amd64) cw = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.cw; #else cw = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[CW]; #endif + if ((sw & FE_INVALID) && !(cw & (1 << fp_trap_invalid))) /* store 0 for stack fault, FPE_FLTINV for IEEE invalid op */ ! sip->si_code = ((sw & 0x40) ? 0 : FPE_FLTINV); else if ((sw & FE_DIVBYZERO) && !(cw & (1 << fp_trap_division))) sip->si_code = FPE_FLTDIV; else if ((sw & FE_OVERFLOW) && !(cw & (1 << fp_trap_overflow))) sip->si_code = FPE_FLTOVF; else if ((sw & FE_UNDERFLOW) && !(cw & (1 << fp_trap_underflow)))
*** 172,241 **** } static enum fp_class_type my_fp_classf(float *x) { ! int i = *(int*)x & ~0x80000000; if (i < 0x7f800000) { if (i < 0x00800000) ! return ((i == 0)? fp_zero : fp_subnormal); ! return fp_normal; } - else if (i == 0x7f800000) - return fp_infinity; - else if (i & 0x400000) - return fp_quiet; - else - return fp_signaling; } static enum fp_class_type my_fp_class(double *x) { ! int i = *(1+(int*)x) & ~0x80000000; if (i < 0x7ff00000) { if (i < 0x00100000) ! return (((i | *(int*)x) == 0)? fp_zero : fp_subnormal); ! return fp_normal; } - else if (i == 0x7ff00000 && *(int*)x == 0) - return fp_infinity; - else if (i & 0x80000) - return fp_quiet; - else - return fp_signaling; } static enum fp_class_type my_fp_classl(long double *x) { ! int i = *(2+(int*)x) & 0x7fff; if (i < 0x7fff) { if (i < 1) { ! if (*(1+(int*)x) < 0) return fp_normal; /* pseudo-denormal */ ! return (((*(1+(int*)x) | *(int*)x) == 0)? ! fp_zero : fp_subnormal); ! } ! return ((*(1+(int*)x) < 0)? fp_normal : ! (enum fp_class_type) -1); /* unsupported format */ ! } ! else if (*(1+(int*)x) == 0x80000000 && *(int*)x == 0) ! return fp_infinity; ! else if (*(1+(unsigned*)x) >= 0xc0000000) ! return fp_quiet; ! else if (*(1+(int*)x) < 0) ! return fp_signaling; ! else ! return (enum fp_class_type) -1; /* unsupported format */ } /* ! * Determine which type of invalid operation exception occurred ! */ enum fex_exception __fex_get_invalid_type(siginfo_t *sip, ucontext_t *uap) { unsigned op; unsigned long ea; --- 190,265 ---- } static enum fp_class_type my_fp_classf(float *x) { ! int i = *(int *)x & ~0x80000000; if (i < 0x7f800000) { if (i < 0x00800000) ! return ((i == 0) ? fp_zero : fp_subnormal); ! ! return (fp_normal); ! } else if (i == 0x7f800000) { ! return (fp_infinity); ! } else if (i & 0x400000) { ! return (fp_quiet); ! } else { ! return (fp_signaling); } } static enum fp_class_type my_fp_class(double *x) { ! int i = *(1 + (int *)x) & ~0x80000000; if (i < 0x7ff00000) { if (i < 0x00100000) ! return (((i | *(int *)x) == 0) ? fp_zero : ! fp_subnormal); ! ! return (fp_normal); ! } else if (i == 0x7ff00000 && *(int *)x == 0) { ! return (fp_infinity); ! } else if (i & 0x80000) { ! return (fp_quiet); ! } else { ! return (fp_signaling); } } static enum fp_class_type my_fp_classl(long double *x) { ! int i = *(2 + (int *)x) & 0x7fff; if (i < 0x7fff) { if (i < 1) { ! if (*(1 + (int *)x) < 0) ! return (fp_normal); /* pseudo-denormal */ ! ! return (((*(1 + (int *)x) | *(int *)x) == 0) ? fp_zero : ! fp_subnormal); ! } ! ! return ((*(1 + (int *)x) < 0) ? fp_normal : ! (enum fp_class_type)-1); /* unsupported format */ ! } else if (*(1 + (int *)x) == 0x80000000 && *(int *)x == 0) { ! return (fp_infinity); ! } else if (*(1 + (unsigned *)x) >= 0xc0000000) { ! return (fp_quiet); ! } else if (*(1 + (int *)x) < 0) { ! return (fp_signaling); ! } else { ! return ((enum fp_class_type)-1); /* unsupported format */ ! } } /* ! * Determine which type of invalid operation exception occurred ! */ enum fex_exception __fex_get_invalid_type(siginfo_t *sip, ucontext_t *uap) { unsigned op; unsigned long ea;
*** 248,326 **** #else op = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[OP] >> 16; ea = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[EA]; #endif ! /* if the instruction is fld, the source must be snan (it can't be ! an unsupported format, since fldt doesn't raise any exceptions) */ switch (op & 0x7f8) { case 0x100: case 0x140: case 0x180: case 0x500: case 0x540: case 0x580: ! return fex_inv_snan; } /* otherwise st is one of the operands; see if it's snan */ t1 = my_fp_classl(&fpreg(uap, 0)); if (t1 == fp_signaling) ! return fex_inv_snan; ! else if (t1 == (enum fp_class_type) -1) ! return (enum fex_exception) -1; /* determine the class of the second operand if there is one */ t2 = fp_normal; switch (op & 0x7e0) { case 0x600: case 0x620: case 0x640: case 0x660: case 0x680: case 0x6a0: /* short memory operand */ if (!ea) ! return (enum fex_exception) -1; if (*(short *)ea == 0) t2 = fp_zero; break; case 0x200: case 0x220: case 0x240: case 0x260: case 0x280: case 0x2a0: /* int memory operand */ if (!ea) ! return (enum fex_exception) -1; if (*(int *)ea == 0) t2 = fp_zero; break; case 0x000: case 0x020: case 0x040: case 0x060: case 0x080: case 0x0a0: /* single precision memory operand */ if (!ea) ! return (enum fex_exception) -1; t2 = my_fp_classf((float *)ea); break; case 0x400: case 0x420: case 0x440: case 0x460: case 0x480: case 0x4a0: /* double precision memory operand */ if (!ea) ! return (enum fex_exception) -1; t2 = my_fp_class((double *)ea); break; case 0x0c0: case 0x0e0: --- 272,364 ---- #else op = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[OP] >> 16; ea = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[EA]; #endif ! /* ! * if the instruction is fld, the source must be snan (it can't be ! * an unsupported format, since fldt doesn't raise any exceptions) ! */ switch (op & 0x7f8) { case 0x100: case 0x140: case 0x180: case 0x500: case 0x540: case 0x580: ! return (fex_inv_snan); } /* otherwise st is one of the operands; see if it's snan */ t1 = my_fp_classl(&fpreg(uap, 0)); + if (t1 == fp_signaling) ! return (fex_inv_snan); ! else if (t1 == (enum fp_class_type)-1) ! return ((enum fex_exception)-1); /* determine the class of the second operand if there is one */ t2 = fp_normal; + switch (op & 0x7e0) { case 0x600: case 0x620: case 0x640: case 0x660: case 0x680: case 0x6a0: + /* short memory operand */ if (!ea) ! return ((enum fex_exception)-1); ! if (*(short *)ea == 0) t2 = fp_zero; + break; case 0x200: case 0x220: case 0x240: case 0x260: case 0x280: case 0x2a0: + /* int memory operand */ if (!ea) ! return ((enum fex_exception)-1); ! if (*(int *)ea == 0) t2 = fp_zero; + break; case 0x000: case 0x020: case 0x040: case 0x060: case 0x080: case 0x0a0: + /* single precision memory operand */ if (!ea) ! return ((enum fex_exception)-1); ! t2 = my_fp_classf((float *)ea); break; case 0x400: case 0x420: case 0x440: case 0x460: case 0x480: case 0x4a0: + /* double precision memory operand */ if (!ea) ! return ((enum fex_exception)-1); ! t2 = my_fp_class((double *)ea); break; case 0x0c0: case 0x0e0:
*** 329,338 **** --- 367,377 ---- case 0x4e0: case 0x5e0: case 0x6c0: case 0x6e0: case 0x7e0: + /* register operand determined by opcode */ switch (op & 0x7f8) { case 0x3e0: case 0x3f8: case 0x5f0:
*** 343,356 **** --- 382,397 ---- break; default: t2 = my_fp_classl(&fpreg(uap, op & 7)); } + break; case 0x1e0: case 0x2e0: + /* special forms */ switch (op) { case 0x1f1: /* fyl2x */ case 0x1f3: /* fpatan */ case 0x1f5: /* fprem1 */
*** 359,376 **** case 0x1fd: /* fscale */ case 0x2e9: /* fucompp */ t2 = my_fp_classl(&fpreg(uap, 1)); break; } break; } /* see if the second op is snan */ if (t2 == fp_signaling) ! return fex_inv_snan; ! else if (t2 == (enum fp_class_type) -1) ! return (enum fex_exception) -1; /* determine the type of operation */ switch (op & 0x7f8) { case 0x000: case 0x020: --- 400,418 ---- case 0x1fd: /* fscale */ case 0x2e9: /* fucompp */ t2 = my_fp_classl(&fpreg(uap, 1)); break; } + break; } /* see if the second op is snan */ if (t2 == fp_signaling) ! return (fex_inv_snan); ! else if (t2 == (enum fp_class_type)-1) ! return ((enum fex_exception)-1); /* determine the type of operation */ switch (op & 0x7f8) { case 0x000: case 0x020:
*** 397,409 **** case 0x4e0: case 0x4e8: case 0x6c0: case 0x6e0: case 0x6e8: /* fadd, fsub, fsubr */ if (t1 == fp_infinity && t2 == fp_infinity) ! return fex_inv_isi; break; case 0x008: case 0x048: case 0x088: --- 439,453 ---- case 0x4e0: case 0x4e8: case 0x6c0: case 0x6e0: case 0x6e8: + /* fadd, fsub, fsubr */ if (t1 == fp_infinity && t2 == fp_infinity) ! return (fex_inv_isi); ! break; case 0x008: case 0x048: case 0x088:
*** 417,430 **** case 0x4c8: case 0x608: case 0x648: case 0x688: case 0x6c8: /* fmul */ if ((t1 == fp_zero && t2 == fp_infinity) || (t2 == fp_zero && t1 == fp_infinity)) ! return fex_inv_zmi; break; case 0x030: case 0x038: case 0x070: --- 461,476 ---- case 0x4c8: case 0x608: case 0x648: case 0x688: case 0x6c8: + /* fmul */ if ((t1 == fp_zero && t2 == fp_infinity) || (t2 == fp_zero && t1 == fp_infinity)) ! return (fex_inv_zmi); ! break; case 0x030: case 0x038: case 0x070:
*** 453,473 **** case 0x678: case 0x6b0: case 0x6b8: case 0x6f0: case 0x6f8: /* fdiv */ if (t1 == fp_zero && t2 == fp_zero) ! return fex_inv_zdz; else if (t1 == fp_infinity && t2 == fp_infinity) ! return fex_inv_idi; break; case 0x1f0: case 0x1f8: /* fsqrt, other special ops */ ! return fex_inv_sqrt; case 0x010: case 0x018: case 0x050: case 0x058: --- 499,521 ---- case 0x678: case 0x6b0: case 0x6b8: case 0x6f0: case 0x6f8: + /* fdiv */ if (t1 == fp_zero && t2 == fp_zero) ! return (fex_inv_zdz); else if (t1 == fp_infinity && t2 == fp_infinity) ! return (fex_inv_idi); ! break; case 0x1f0: case 0x1f8: /* fsqrt, other special ops */ ! return (fex_inv_sqrt); case 0x010: case 0x018: case 0x050: case 0x058:
*** 500,518 **** case 0x690: case 0x698: case 0x6d0: case 0x6d8: case 0x7f0: /* fcom */ if (t1 == fp_quiet || t2 == fp_quiet) ! return fex_inv_cmp; break; case 0x1e0: /* ftst */ if (op == 0x1e4 && t1 == fp_quiet) ! return fex_inv_cmp; break; case 0x310: case 0x318: case 0x350: --- 548,570 ---- case 0x690: case 0x698: case 0x6d0: case 0x6d8: case 0x7f0: + /* fcom */ if (t1 == fp_quiet || t2 == fp_quiet) ! return (fex_inv_cmp); ! break; case 0x1e0: + /* ftst */ if (op == 0x1e4 && t1 == fp_quiet) ! return (fex_inv_cmp); ! break; case 0x310: case 0x318: case 0x350:
*** 530,551 **** case 0x790: case 0x798: case 0x7b0: case 0x7b8: /* fist, fbst */ ! return fex_inv_int; } ! return (enum fex_exception) -1; } /* scale factors for exponent unwrapping */ static const long double - two12288 = 1.139165225263043370845938579315932009e+3699l, /* 2^12288 */ - twom12288 = 8.778357852076208839765066529179033145e-3700l, /* 2^-12288 */ twom12288mulp = 8.778357852076208839289190796475222545e-3700l; - /* (")*(1-2^-64) */ /* inline templates */ extern long double f2xm1(long double); extern long double fyl2x(long double, long double); extern long double fptan(long double); --- 582,607 ---- case 0x790: case 0x798: case 0x7b0: case 0x7b8: /* fist, fbst */ ! return (fex_inv_int); } ! return ((enum fex_exception)-1); } /* scale factors for exponent unwrapping */ + /* 2^12288 */ + static const long double + two12288 = 1.139165225263043370845938579315932009e+3699l; + /* 2^-12288 */ + static const long double + twom12288 = 8.778357852076208839765066529179033145e-3700l; + /* (")*(1-2^-64) */ static const long double twom12288mulp = 8.778357852076208839289190796475222545e-3700l; /* inline templates */ extern long double f2xm1(long double); extern long double fyl2x(long double, long double); extern long double fptan(long double);
*** 560,572 **** extern long double fscale(long double, long double); extern long double fsin(long double); extern long double fcos(long double); /* ! * Get the operands, generate the default untrapped result with ! * exceptions, and set a code indicating the type of operation ! */ void __fex_get_op(siginfo_t *sip, ucontext_t *uap, fex_info_t *info) { fex_numeric_t t; long double op2v, x; --- 616,628 ---- extern long double fscale(long double, long double); extern long double fsin(long double); extern long double fcos(long double); /* ! * Get the operands, generate the default untrapped result with ! * exceptions, and set a code indicating the type of operation ! */ void __fex_get_op(siginfo_t *sip, ucontext_t *uap, fex_info_t *info) { fex_numeric_t t; long double op2v, x;
*** 583,730 **** #else op = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[OP] >> 16; ea = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[EA]; #endif ! /* initialize res to the default untrapped result and ex to the ! corresponding flags (assume trapping is disabled and flags ! are clear) */ /* single operand instructions */ info->op = fex_cnvt; info->op2.type = fex_nodata; switch (op & 0x7f8) { /* load instructions */ case 0x100: case 0x140: case 0x180: if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = info->res.type = fex_nodata; info->flags = 0; return; } info->op1.type = fex_float; info->op1.val.f = *(float *)ea; info->res.type = fex_ldouble; ! info->res.val.q = (long double) info->op1.val.f; goto done; case 0x500: case 0x540: case 0x580: if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = info->res.type = fex_nodata; info->flags = 0; return; } info->op1.type = fex_double; info->op1.val.d = *(double *)ea; info->res.type = fex_ldouble; ! info->res.val.q = (long double) info->op1.val.d; goto done; /* store instructions */ case 0x110: case 0x118: case 0x150: case 0x158: case 0x190: case 0x198: info->res.type = fex_float; if (ex == FPE_FLTRES && (op & 8) != 0) { /* inexact, stack popped */ if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = info->res.type = fex_nodata; info->flags = 0; return; } info->op1.type = fex_nodata; info->res.val.f = *(float *)ea; info->flags = FE_INEXACT; return; } info->op1.type = fex_ldouble; info->op1.val.q = fpreg(uap, 0); ! info->res.val.f = (float) info->op1.val.q; goto done; case 0x310: case 0x318: case 0x350: case 0x358: case 0x390: case 0x398: info->res.type = fex_int; if (ex == FPE_FLTRES && (op & 8) != 0) { /* inexact, stack popped */ if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = info->res.type = fex_nodata; info->flags = 0; return; } info->op1.type = fex_nodata; info->res.val.i = *(int *)ea; info->flags = FE_INEXACT; return; } info->op1.type = fex_ldouble; info->op1.val.q = fpreg(uap, 0); ! info->res.val.i = (int) info->op1.val.q; goto done; case 0x510: case 0x518: case 0x550: case 0x558: case 0x590: case 0x598: info->res.type = fex_double; if (ex == FPE_FLTRES && (op & 8) != 0) { /* inexact, stack popped */ if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = info->res.type = fex_nodata; info->flags = 0; return; } info->op1.type = fex_nodata; info->res.val.d = *(double *)ea; info->flags = FE_INEXACT; return; } info->op1.type = fex_ldouble; info->op1.val.q = fpreg(uap, 0); ! info->res.val.d = (double) info->op1.val.q; goto done; case 0x710: case 0x718: case 0x750: case 0x758: case 0x790: case 0x798: info->res.type = fex_int; if (ex == FPE_FLTRES && (op & 8) != 0) { /* inexact, stack popped */ if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = info->res.type = fex_nodata; info->flags = 0; return; } info->op1.type = fex_nodata; info->res.val.i = *(short *)ea; info->flags = FE_INEXACT; return; } info->op1.type = fex_ldouble; info->op1.val.q = fpreg(uap, 0); ! info->res.val.i = (short) info->op1.val.q; goto done; case 0x730: case 0x770: case 0x7b0: --- 639,811 ---- #else op = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[OP] >> 16; ea = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[EA]; #endif ! /* ! * initialize res to the default untrapped result and ex to the ! * corresponding flags (assume trapping is disabled and flags are ! * clear) ! */ /* single operand instructions */ info->op = fex_cnvt; info->op2.type = fex_nodata; + switch (op & 0x7f8) { /* load instructions */ case 0x100: case 0x140: case 0x180: + if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = info->res.type = ! fex_nodata; info->flags = 0; return; } + info->op1.type = fex_float; info->op1.val.f = *(float *)ea; info->res.type = fex_ldouble; ! info->res.val.q = (long double)info->op1.val.f; goto done; case 0x500: case 0x540: case 0x580: + if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = info->res.type = ! fex_nodata; info->flags = 0; return; } + info->op1.type = fex_double; info->op1.val.d = *(double *)ea; info->res.type = fex_ldouble; ! info->res.val.q = (long double)info->op1.val.d; goto done; /* store instructions */ case 0x110: case 0x118: case 0x150: case 0x158: case 0x190: case 0x198: info->res.type = fex_float; + if (ex == FPE_FLTRES && (op & 8) != 0) { /* inexact, stack popped */ if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = ! info->res.type = fex_nodata; info->flags = 0; return; } + info->op1.type = fex_nodata; info->res.val.f = *(float *)ea; info->flags = FE_INEXACT; return; } + info->op1.type = fex_ldouble; info->op1.val.q = fpreg(uap, 0); ! info->res.val.f = (float)info->op1.val.q; goto done; case 0x310: case 0x318: case 0x350: case 0x358: case 0x390: case 0x398: info->res.type = fex_int; + if (ex == FPE_FLTRES && (op & 8) != 0) { /* inexact, stack popped */ if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = ! info->res.type = fex_nodata; info->flags = 0; return; } + info->op1.type = fex_nodata; info->res.val.i = *(int *)ea; info->flags = FE_INEXACT; return; } + info->op1.type = fex_ldouble; info->op1.val.q = fpreg(uap, 0); ! info->res.val.i = (int)info->op1.val.q; goto done; case 0x510: case 0x518: case 0x550: case 0x558: case 0x590: case 0x598: info->res.type = fex_double; + if (ex == FPE_FLTRES && (op & 8) != 0) { /* inexact, stack popped */ if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = ! info->res.type = fex_nodata; info->flags = 0; return; } + info->op1.type = fex_nodata; info->res.val.d = *(double *)ea; info->flags = FE_INEXACT; return; } + info->op1.type = fex_ldouble; info->op1.val.q = fpreg(uap, 0); ! info->res.val.d = (double)info->op1.val.q; goto done; case 0x710: case 0x718: case 0x750: case 0x758: case 0x790: case 0x798: info->res.type = fex_int; + if (ex == FPE_FLTRES && (op & 8) != 0) { /* inexact, stack popped */ if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = ! info->res.type = fex_nodata; info->flags = 0; return; } + info->op1.type = fex_nodata; info->res.val.i = *(short *)ea; info->flags = FE_INEXACT; return; } + info->op1.type = fex_ldouble; info->op1.val.q = fpreg(uap, 0); ! info->res.val.i = (short)info->op1.val.q; goto done; case 0x730: case 0x770: case 0x7b0:
*** 736,774 **** case 0x738: case 0x778: case 0x7b8: info->res.type = fex_llong; if (ex == FPE_FLTRES) { /* inexact, stack popped */ if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = info->res.type = fex_nodata; info->flags = 0; return; } info->op1.type = fex_nodata; info->res.val.l = *(long long *)ea; info->flags = FE_INEXACT; return; } info->op1.type = fex_ldouble; info->op1.val.q = fpreg(uap, 0); ! info->res.val.l = (long long) info->op1.val.q; goto done; } ! /* all other ops (except compares) have destinations on the stack ! so overflow, underflow, and inexact will stomp their operands */ if (ex == FPE_FLTOVF || ex == FPE_FLTUND || ex == FPE_FLTRES) { /* find the trapped result */ info->op1.type = info->op2.type = fex_nodata; info->res.type = fex_ldouble; switch (op & 0x7f8) { case 0x1f0: /* fptan pushes 1.0 afterward, so result is in st(1) */ ! info->res.val.q = ((op == 0x1f2)? fpreg(uap, 1) : fpreg(uap, 0)); break; case 0x4c0: case 0x4c8: --- 817,862 ---- case 0x738: case 0x778: case 0x7b8: info->res.type = fex_llong; + if (ex == FPE_FLTRES) { /* inexact, stack popped */ if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = ! info->res.type = fex_nodata; info->flags = 0; return; } + info->op1.type = fex_nodata; info->res.val.l = *(long long *)ea; info->flags = FE_INEXACT; return; } + info->op1.type = fex_ldouble; info->op1.val.q = fpreg(uap, 0); ! info->res.val.l = (long long)info->op1.val.q; goto done; } ! /* ! * all other ops (except compares) have destinations on the stack so ! * overflow, underflow, and inexact will stomp their operands ! */ if (ex == FPE_FLTOVF || ex == FPE_FLTUND || ex == FPE_FLTRES) { /* find the trapped result */ info->op1.type = info->op2.type = fex_nodata; info->res.type = fex_ldouble; + switch (op & 0x7f8) { case 0x1f0: /* fptan pushes 1.0 afterward, so result is in st(1) */ ! info->res.val.q = ((op == 0x1f2) ? fpreg(uap, 1) : fpreg(uap, 0)); break; case 0x4c0: case 0x4c8:
*** 795,827 **** /* reconstruct default untrapped result */ if (ex == FPE_FLTOVF) { /* generate an overflow with the sign of the result */ x = two12288; ! *(4+(short*)&x) |= (*(4+(short*)&info->res.val.q) & 0x8000); info->res.val.q = x * two12288; info->flags = FE_OVERFLOW | FE_INEXACT; __fenv_getcwsw(&cwsw); cwsw &= ~FE_ALL_EXCEPT; __fenv_setcwsw(&cwsw); ! } ! else if (ex == FPE_FLTUND) { ! /* undo the scaling; we can't distinguish a chopped result ! from an exact one without futzing around to trap all in- ! exact exceptions so as to keep the flag clear, so we just ! punt */ if (sw & 0x200) /* result was rounded up */ ! info->res.val.q = (info->res.val.q * twom12288) * twom12288mulp; else ! info->res.val.q = (info->res.val.q * twom12288) * twom12288; __fenv_getcwsw(&cwsw); info->flags = (cwsw & FE_INEXACT) | FE_UNDERFLOW; cwsw &= ~FE_ALL_EXCEPT; __fenv_setcwsw(&cwsw); ! } ! else info->flags = FE_INEXACT; /* determine the operation code */ switch (op) { case 0x1f0: /* f2xm1 */ case 0x1f1: /* fyl2x */ --- 883,920 ---- /* reconstruct default untrapped result */ if (ex == FPE_FLTOVF) { /* generate an overflow with the sign of the result */ x = two12288; ! *(4 + (short *)&x) |= (*(4 + ! (short *)&info->res.val.q) & 0x8000); info->res.val.q = x * two12288; info->flags = FE_OVERFLOW | FE_INEXACT; __fenv_getcwsw(&cwsw); cwsw &= ~FE_ALL_EXCEPT; __fenv_setcwsw(&cwsw); ! } else if (ex == FPE_FLTUND) { ! /* ! * undo the scaling; we can't distinguish a chopped ! * result from an exact one without futzing around to ! * trap all in- exact exceptions so as to keep the ! * flag clear, so we just punt ! */ if (sw & 0x200) /* result was rounded up */ ! info->res.val.q = (info->res.val.q * ! twom12288) * twom12288mulp; else ! info->res.val.q = (info->res.val.q * ! twom12288) * twom12288; ! __fenv_getcwsw(&cwsw); info->flags = (cwsw & FE_INEXACT) | FE_UNDERFLOW; cwsw &= ~FE_ALL_EXCEPT; __fenv_setcwsw(&cwsw); ! } else { info->flags = FE_INEXACT; + } /* determine the operation code */ switch (op) { case 0x1f0: /* f2xm1 */ case 0x1f1: /* fyl2x */
*** 842,851 **** --- 935,945 ---- info->op = fex_sqrt; return; } info->op = fex_other; + switch (op & 0x7c0) { case 0x000: case 0x040: case 0x080: case 0x0c0:
*** 858,867 **** --- 952,962 ---- case 0x4c0: case 0x600: case 0x640: case 0x680: case 0x6c0: + switch (op & 0x38) { case 0x00: info->op = fex_add; break;
*** 878,899 **** case 0x38: info->op = fex_div; break; } } return; } ! /* for other exceptions, the operands are preserved, so we can ! just emulate the operation with traps disabled */ /* one operand is always in st */ info->op1.type = fex_ldouble; info->op1.val.q = fpreg(uap, 0); /* oddball instructions */ info->op = fex_other; switch (op) { case 0x1e4: /* ftst */ info->op = fex_cmp; info->op2.type = fex_ldouble; info->op2.val.q = 0.0l; --- 973,998 ---- case 0x38: info->op = fex_div; break; } } + return; } ! /* ! * for other exceptions, the operands are preserved, so we can just ! * emulate the operation with traps disabled ! */ /* one operand is always in st */ info->op1.type = fex_ldouble; info->op1.val.q = fpreg(uap, 0); /* oddball instructions */ info->op = fex_other; + switch (op) { case 0x1e4: /* ftst */ info->op = fex_cmp; info->op2.type = fex_ldouble; info->op2.val.q = 0.0l;
*** 1014,1073 **** info->res.type = fex_nodata; c = (info->op1.val.q < info->op2.val.q); goto done; } ! /* all other instructions come in groups of the form ! fadd, fmul, fcom, fcomp, fsub, fsubr, fdiv, fdivr */ /* get the second operand */ switch (op & 0x7c0) { case 0x000: case 0x040: case 0x080: if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = info->res.type = fex_nodata; info->flags = 0; return; } info->op2.type = fex_float; info->op2.val.f = *(float *)ea; ! op2v = (long double) info->op2.val.f; break; case 0x0c0: info->op2.type = fex_ldouble; op2v = info->op2.val.q = fpreg(uap, op & 7); break; case 0x200: case 0x240: case 0x280: if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = info->res.type = fex_nodata; info->flags = 0; return; } info->op2.type = fex_int; info->op2.val.i = *(int *)ea; ! op2v = (long double) info->op2.val.i; break; case 0x400: case 0x440: case 0x480: if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = info->res.type = fex_nodata; info->flags = 0; return; } info->op2.type = fex_double; info->op2.val.d = *(double *)ea; ! op2v = (long double) info->op2.val.d; break; case 0x4c0: case 0x6c0: info->op2.type = fex_ldouble; --- 1113,1183 ---- info->res.type = fex_nodata; c = (info->op1.val.q < info->op2.val.q); goto done; } ! /* ! * all other instructions come in groups of the form ! * fadd, fmul, fcom, fcomp, fsub, fsubr, fdiv, fdivr ! */ /* get the second operand */ switch (op & 0x7c0) { case 0x000: case 0x040: case 0x080: + if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = info->res.type = ! fex_nodata; info->flags = 0; return; } + info->op2.type = fex_float; info->op2.val.f = *(float *)ea; ! op2v = (long double)info->op2.val.f; break; case 0x0c0: info->op2.type = fex_ldouble; op2v = info->op2.val.q = fpreg(uap, op & 7); break; case 0x200: case 0x240: case 0x280: + if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = info->res.type = ! fex_nodata; info->flags = 0; return; } + info->op2.type = fex_int; info->op2.val.i = *(int *)ea; ! op2v = (long double)info->op2.val.i; break; case 0x400: case 0x440: case 0x480: + if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = info->res.type = ! fex_nodata; info->flags = 0; return; } + info->op2.type = fex_double; info->op2.val.d = *(double *)ea; ! op2v = (long double)info->op2.val.d; break; case 0x4c0: case 0x6c0: info->op2.type = fex_ldouble;
*** 1079,1097 **** break; case 0x600: case 0x640: case 0x680: if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = info->res.type = fex_nodata; info->flags = 0; return; } info->op2.type = fex_int; info->op2.val.i = *(short *)ea; ! op2v = (long double) info->op2.val.i; break; default: info->op = fex_other; info->op1.type = info->op2.type = info->res.type = fex_nodata; --- 1189,1210 ---- break; case 0x600: case 0x640: case 0x680: + if (!ea) { info->op = fex_other; ! info->op1.type = info->op2.type = info->res.type = ! fex_nodata; info->flags = 0; return; } + info->op2.type = fex_int; info->op2.val.i = *(short *)ea; ! op2v = (long double)info->op2.val.i; break; default: info->op = fex_other; info->op1.type = info->op2.type = info->res.type = fex_nodata;
*** 1099,1108 **** --- 1212,1222 ---- return; } /* distinguish different operations in the group */ info->res.type = fex_ldouble; + switch (op & 0x38) { case 0x00: info->op = fex_add; info->res.val.q = info->op1.val.q + op2v; break;
*** 1158,1168 **** cwsw &= ~FE_ALL_EXCEPT; __fenv_setcwsw(&cwsw); } /* pop the saved stack */ ! static void pop(ucontext_t *uap) { unsigned top; fpreg(uap, 0) = fpreg(uap, 1); fpreg(uap, 1) = fpreg(uap, 2); --- 1272,1283 ---- cwsw &= ~FE_ALL_EXCEPT; __fenv_setcwsw(&cwsw); } /* pop the saved stack */ ! static void ! pop(ucontext_t *uap) { unsigned top; fpreg(uap, 0) = fpreg(uap, 1); fpreg(uap, 1) = fpreg(uap, 2);
*** 1170,1199 **** fpreg(uap, 3) = fpreg(uap, 4); fpreg(uap, 4) = fpreg(uap, 5); fpreg(uap, 5) = fpreg(uap, 6); fpreg(uap, 6) = fpreg(uap, 7); #if defined(__amd64) ! top = (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw >> 10) ! & 0xe; uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.fctw |= (3 << top); top = (top + 2) & 0xe; uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw = ! (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw & ~0x3800) ! | (top << 10); #else ! top = (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] >> 10) ! & 0xe; uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[TW] |= (3 << top); top = (top + 2) & 0xe; uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] = ! (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] & ~0x3800) ! | (top << 10); #endif } /* push x onto the saved stack */ ! static void push(long double x, ucontext_t *uap) { unsigned top; fpreg(uap, 7) = fpreg(uap, 6); fpreg(uap, 6) = fpreg(uap, 5); --- 1285,1314 ---- fpreg(uap, 3) = fpreg(uap, 4); fpreg(uap, 4) = fpreg(uap, 5); fpreg(uap, 5) = fpreg(uap, 6); fpreg(uap, 6) = fpreg(uap, 7); #if defined(__amd64) ! top = (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw >> 10) & 0xe; uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.fctw |= (3 << top); top = (top + 2) & 0xe; uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw = ! (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw & ~0x3800) | ! (top << 10); #else ! top = (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] >> ! 10) & 0xe; uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[TW] |= (3 << top); top = (top + 2) & 0xe; uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] = ! (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] & ! ~0x3800) | (top << 10); #endif } /* push x onto the saved stack */ ! static void ! push(long double x, ucontext_t *uap) { unsigned top; fpreg(uap, 7) = fpreg(uap, 6); fpreg(uap, 6) = fpreg(uap, 5);
*** 1202,1259 **** fpreg(uap, 3) = fpreg(uap, 2); fpreg(uap, 2) = fpreg(uap, 1); fpreg(uap, 1) = fpreg(uap, 0); fpreg(uap, 0) = x; #if defined(__amd64) ! top = (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw >> 10) ! & 0xe; top = (top - 2) & 0xe; uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.fctw &= ~(3 << top); uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw = ! (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw & ~0x3800) ! | (top << 10); #else ! top = (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] >> 10) ! & 0xe; top = (top - 2) & 0xe; ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[TW] &= ~(3 << top); uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] = ! (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] & ~0x3800) ! | (top << 10); #endif } /* scale factors for exponent wrapping */ ! static const float ! fun = 7.922816251e+28f, /* 2^96 */ fov = 1.262177448e-29f; /* 2^-96 */ ! static const double ! dun = 1.552518092300708935e+231, /* 2^768 */ dov = 6.441148769597133308e-232; /* 2^-768 */ /* ! * Store the specified result; if no result is given but the exception ! * is underflow or overflow, use the default trapped result ! */ void __fex_st_result(siginfo_t *sip, ucontext_t *uap, fex_info_t *info) { fex_numeric_t r; unsigned long ex, op, ea, stack; /* get the exception type, opcode, and data address */ ex = sip->si_code; #if defined(__amd64) op = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.fop >> 16; ! ea = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.rdp; /*???*/ #else op = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[OP] >> 16; ea = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[EA]; #endif ! /* if the instruction is a compare, set the condition codes ! to unordered and update the stack */ switch (op & 0x7f8) { case 0x010: case 0x050: case 0x090: case 0x0d0: --- 1317,1374 ---- fpreg(uap, 3) = fpreg(uap, 2); fpreg(uap, 2) = fpreg(uap, 1); fpreg(uap, 1) = fpreg(uap, 0); fpreg(uap, 0) = x; #if defined(__amd64) ! top = (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw >> 10) & 0xe; top = (top - 2) & 0xe; uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.fctw &= ~(3 << top); uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw = ! (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw & ~0x3800) | ! (top << 10); #else ! top = (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] >> ! 10) & 0xe; top = (top - 2) & 0xe; ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[TW] &= ~(3 << ! top); uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] = ! (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] & ! ~0x3800) | (top << 10); #endif } /* scale factors for exponent wrapping */ ! static const float fun = 7.922816251e+28f, /* 2^96 */ fov = 1.262177448e-29f; /* 2^-96 */ ! static const double dun = 1.552518092300708935e+231, /* 2^768 */ dov = 6.441148769597133308e-232; /* 2^-768 */ /* ! * Store the specified result; if no result is given but the exception ! * is underflow or overflow, use the default trapped result ! */ void __fex_st_result(siginfo_t *sip, ucontext_t *uap, fex_info_t *info) { fex_numeric_t r; unsigned long ex, op, ea, stack; /* get the exception type, opcode, and data address */ ex = sip->si_code; #if defined(__amd64) op = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.fop >> 16; ! ea = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.rdp; /* ??? */ #else op = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[OP] >> 16; ea = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[EA]; #endif ! /* ! * if the instruction is a compare, set the condition codes ! * to unordered and update the stack ! */ switch (op & 0x7f8) { case 0x010: case 0x050: case 0x090: case 0x0d0:
*** 1270,1280 **** case 0x690: /* f[u]com */ #if defined(__amd64) uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw |= 0x4500; #else ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] |= 0x4500; #endif return; case 0x018: case 0x058: --- 1385,1396 ---- case 0x690: /* f[u]com */ #if defined(__amd64) uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw |= 0x4500; #else ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] |= ! 0x4500; #endif return; case 0x018: case 0x058:
*** 1294,1329 **** case 0x6d0: /* f[u]comp */ #if defined(__amd64) uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw |= 0x4500; #else ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] |= 0x4500; #endif pop(uap); return; case 0x2e8: case 0x6d8: /* f[u]compp */ #if defined(__amd64) uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw |= 0x4500; #else ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] |= 0x4500; #endif pop(uap); pop(uap); return; case 0x1e0: if (op == 0x1e4) { /* ftst */ #if defined(__amd64) ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw |= 0x4500; #else ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] |= 0x4500; #endif return; } break; case 0x3e8: case 0x3f0: /* f[u]comi */ --- 1410,1451 ---- case 0x6d0: /* f[u]comp */ #if defined(__amd64) uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw |= 0x4500; #else ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] |= ! 0x4500; #endif pop(uap); return; case 0x2e8: case 0x6d8: /* f[u]compp */ #if defined(__amd64) uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw |= 0x4500; #else ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] |= ! 0x4500; #endif pop(uap); pop(uap); return; case 0x1e0: + if (op == 0x1e4) { /* ftst */ #if defined(__amd64) ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw |= ! 0x4500; #else ! uap->uc_mcontext.fpregs.fp_reg_set. ! fpchip_state.state[SW] |= 0x4500; #endif return; } + break; case 0x3e8: case 0x3f0: /* f[u]comi */
*** 1344,1607 **** #endif pop(uap); return; } ! /* if there is no result available and the exception is overflow ! or underflow, use the wrapped result */ r = info->res; if (r.type == fex_nodata) { if (ex == FPE_FLTOVF || ex == FPE_FLTUND) { /* for store instructions, do the scaling and store */ switch (op & 0x7f8) { case 0x110: case 0x118: case 0x150: case 0x158: case 0x190: case 0x198: if (!ea) return; if (ex == FPE_FLTOVF) ! *(float *)ea = (fpreg(uap, 0) * fov) * fov; else ! *(float *)ea = (fpreg(uap, 0) * fun) * fun; if ((op & 8) != 0) pop(uap); break; case 0x510: case 0x518: case 0x550: case 0x558: case 0x590: case 0x598: if (!ea) return; if (ex == FPE_FLTOVF) ! *(double *)ea = (fpreg(uap, 0) * dov) * dov; else ! *(double *)ea = (fpreg(uap, 0) * dun) * dun; if ((op & 8) != 0) pop(uap); break; } } #ifdef DEBUG ! else if (ex != FPE_FLTRES) printf("No result supplied, stack may be hosed\n"); #endif return; } ! /* otherwise convert the supplied result to the correct type, ! put it in the destination, and update the stack as need be */ /* store instructions */ switch (op & 0x7f8) { case 0x110: case 0x118: case 0x150: case 0x158: case 0x190: case 0x198: if (!ea) return; switch (r.type) { case fex_int: ! *(float *)ea = (float) r.val.i; break; case fex_llong: ! *(float *)ea = (float) r.val.l; break; case fex_float: *(float *)ea = r.val.f; break; case fex_double: ! *(float *)ea = (float) r.val.d; break; case fex_ldouble: ! *(float *)ea = (float) r.val.q; break; default: break; } if (ex != FPE_FLTRES && (op & 8) != 0) pop(uap); return; case 0x310: case 0x318: case 0x350: case 0x358: case 0x390: case 0x398: if (!ea) return; switch (r.type) { case fex_int: *(int *)ea = r.val.i; break; case fex_llong: ! *(int *)ea = (int) r.val.l; break; case fex_float: ! *(int *)ea = (int) r.val.f; break; case fex_double: ! *(int *)ea = (int) r.val.d; break; case fex_ldouble: ! *(int *)ea = (int) r.val.q; break; default: break; } if (ex != FPE_FLTRES && (op & 8) != 0) pop(uap); return; case 0x510: case 0x518: case 0x550: case 0x558: case 0x590: case 0x598: if (!ea) return; switch (r.type) { case fex_int: ! *(double *)ea = (double) r.val.i; break; case fex_llong: ! *(double *)ea = (double) r.val.l; break; case fex_float: ! *(double *)ea = (double) r.val.f; break; case fex_double: *(double *)ea = r.val.d; break; case fex_ldouble: ! *(double *)ea = (double) r.val.q; break; default: break; } if (ex != FPE_FLTRES && (op & 8) != 0) pop(uap); return; case 0x710: case 0x718: case 0x750: case 0x758: case 0x790: case 0x798: if (!ea) return; switch (r.type) { case fex_int: ! *(short *)ea = (short) r.val.i; break; case fex_llong: ! *(short *)ea = (short) r.val.l; break; case fex_float: ! *(short *)ea = (short) r.val.f; break; case fex_double: ! *(short *)ea = (short) r.val.d; break; case fex_ldouble: ! *(short *)ea = (short) r.val.q; break; default: break; } if (ex != FPE_FLTRES && (op & 8) != 0) pop(uap); return; case 0x730: case 0x770: case 0x7b0: /* fbstp; don't bother */ if (ea && ex != FPE_FLTRES) pop(uap); return; case 0x738: case 0x778: case 0x7b8: if (!ea) return; switch (r.type) { case fex_int: ! *(long long *)ea = (long long) r.val.i; break; case fex_llong: *(long long *)ea = r.val.l; break; case fex_float: ! *(long long *)ea = (long long) r.val.f; break; case fex_double: ! *(long long *)ea = (long long) r.val.d; break; case fex_ldouble: ! *(long long *)ea = (long long) r.val.q; break; default: break; } if (ex != FPE_FLTRES) pop(uap); return; } /* for all other instructions, the result goes into a register */ switch (r.type) { case fex_int: ! r.val.q = (long double) r.val.i; break; case fex_llong: ! r.val.q = (long double) r.val.l; break; case fex_float: ! r.val.q = (long double) r.val.f; break; case fex_double: ! r.val.q = (long double) r.val.d; break; default: break; } --- 1466,1770 ---- #endif pop(uap); return; } ! /* ! * if there is no result available and the exception is overflow ! * or underflow, use the wrapped result ! */ r = info->res; + if (r.type == fex_nodata) { if (ex == FPE_FLTOVF || ex == FPE_FLTUND) { /* for store instructions, do the scaling and store */ switch (op & 0x7f8) { case 0x110: case 0x118: case 0x150: case 0x158: case 0x190: case 0x198: + if (!ea) return; + if (ex == FPE_FLTOVF) ! *(float *)ea = (fpreg(uap, 0) * fov) * ! fov; else ! *(float *)ea = (fpreg(uap, 0) * fun) * ! fun; ! if ((op & 8) != 0) pop(uap); + break; case 0x510: case 0x518: case 0x550: case 0x558: case 0x590: case 0x598: + if (!ea) return; + if (ex == FPE_FLTOVF) ! *(double *)ea = (fpreg(uap, 0) * dov) * ! dov; else ! *(double *)ea = (fpreg(uap, 0) * dun) * ! dun; ! if ((op & 8) != 0) pop(uap); + break; } } + #ifdef DEBUG ! else if (ex != FPE_FLTRES) { printf("No result supplied, stack may be hosed\n"); + } #endif return; } ! /* ! * otherwise convert the supplied result to the correct type, put it ! * in the destination, and update the stack as need be ! */ /* store instructions */ switch (op & 0x7f8) { case 0x110: case 0x118: case 0x150: case 0x158: case 0x190: case 0x198: + if (!ea) return; + switch (r.type) { case fex_int: ! *(float *)ea = (float)r.val.i; break; case fex_llong: ! *(float *)ea = (float)r.val.l; break; case fex_float: *(float *)ea = r.val.f; break; case fex_double: ! *(float *)ea = (float)r.val.d; break; case fex_ldouble: ! *(float *)ea = (float)r.val.q; break; default: break; } + if (ex != FPE_FLTRES && (op & 8) != 0) pop(uap); + return; case 0x310: case 0x318: case 0x350: case 0x358: case 0x390: case 0x398: + if (!ea) return; + switch (r.type) { case fex_int: *(int *)ea = r.val.i; break; case fex_llong: ! *(int *)ea = (int)r.val.l; break; case fex_float: ! *(int *)ea = (int)r.val.f; break; case fex_double: ! *(int *)ea = (int)r.val.d; break; case fex_ldouble: ! *(int *)ea = (int)r.val.q; break; default: break; } + if (ex != FPE_FLTRES && (op & 8) != 0) pop(uap); + return; case 0x510: case 0x518: case 0x550: case 0x558: case 0x590: case 0x598: + if (!ea) return; + switch (r.type) { case fex_int: ! *(double *)ea = (double)r.val.i; break; case fex_llong: ! *(double *)ea = (double)r.val.l; break; case fex_float: ! *(double *)ea = (double)r.val.f; break; case fex_double: *(double *)ea = r.val.d; break; case fex_ldouble: ! *(double *)ea = (double)r.val.q; break; default: break; } + if (ex != FPE_FLTRES && (op & 8) != 0) pop(uap); + return; case 0x710: case 0x718: case 0x750: case 0x758: case 0x790: case 0x798: + if (!ea) return; + switch (r.type) { case fex_int: ! *(short *)ea = (short)r.val.i; break; case fex_llong: ! *(short *)ea = (short)r.val.l; break; case fex_float: ! *(short *)ea = (short)r.val.f; break; case fex_double: ! *(short *)ea = (short)r.val.d; break; case fex_ldouble: ! *(short *)ea = (short)r.val.q; break; default: break; } + if (ex != FPE_FLTRES && (op & 8) != 0) pop(uap); + return; case 0x730: case 0x770: case 0x7b0: + /* fbstp; don't bother */ if (ea && ex != FPE_FLTRES) pop(uap); + return; case 0x738: case 0x778: case 0x7b8: + if (!ea) return; + switch (r.type) { case fex_int: ! *(long long *)ea = (long long)r.val.i; break; case fex_llong: *(long long *)ea = r.val.l; break; case fex_float: ! *(long long *)ea = (long long)r.val.f; break; case fex_double: ! *(long long *)ea = (long long)r.val.d; break; case fex_ldouble: ! *(long long *)ea = (long long)r.val.q; break; default: break; } + if (ex != FPE_FLTRES) pop(uap); + return; } /* for all other instructions, the result goes into a register */ switch (r.type) { case fex_int: ! r.val.q = (long double)r.val.i; break; case fex_llong: ! r.val.q = (long double)r.val.l; break; case fex_float: ! r.val.q = (long double)r.val.f; break; case fex_double: ! r.val.q = (long double)r.val.d; break; default: break; }
*** 1612,1660 **** case 0x140: case 0x180: case 0x500: case 0x540: case 0x580: if (ea) push(r.val.q, uap); return; } ! /* for all other instructions, if the exception is overflow, ! underflow, or inexact, the stack has already been updated */ stack = (ex == FPE_FLTOVF || ex == FPE_FLTUND || ex == FPE_FLTRES); switch (op & 0x7f8) { case 0x1f0: /* oddballs */ switch (op) { case 0x1f1: /* fyl2x */ case 0x1f3: /* fpatan */ case 0x1f9: /* fyl2xp1 */ /* pop the stack, leaving the result in st */ if (!stack) pop(uap); fpreg(uap, 0) = r.val.q; return; case 0x1f2: /* fpatan */ /* fptan pushes 1.0 afterward */ ! if (stack) fpreg(uap, 1) = r.val.q; ! else { fpreg(uap, 0) = r.val.q; push(1.0L, uap); } return; case 0x1f4: /* fxtract */ case 0x1fb: /* fsincos */ /* leave the supplied result in st */ ! if (stack) fpreg(uap, 0) = r.val.q; ! else { fpreg(uap, 0) = 0.0; /* punt */ push(r.val.q, uap); } return; } /* all others leave the stack alone and the result in st */ fpreg(uap, 0) = r.val.q; --- 1775,1835 ---- case 0x140: case 0x180: case 0x500: case 0x540: case 0x580: + if (ea) push(r.val.q, uap); + return; } ! /* ! * for all other instructions, if the exception is overflow, ! * underflow, or inexact, the stack has already been updated ! */ stack = (ex == FPE_FLTOVF || ex == FPE_FLTUND || ex == FPE_FLTRES); + switch (op & 0x7f8) { case 0x1f0: /* oddballs */ + switch (op) { case 0x1f1: /* fyl2x */ case 0x1f3: /* fpatan */ case 0x1f9: /* fyl2xp1 */ + /* pop the stack, leaving the result in st */ if (!stack) pop(uap); + fpreg(uap, 0) = r.val.q; return; case 0x1f2: /* fpatan */ + /* fptan pushes 1.0 afterward */ ! if (stack) { fpreg(uap, 1) = r.val.q; ! } else { fpreg(uap, 0) = r.val.q; push(1.0L, uap); } + return; case 0x1f4: /* fxtract */ case 0x1fb: /* fsincos */ + /* leave the supplied result in st */ ! if (stack) { fpreg(uap, 0) = r.val.q; ! } else { fpreg(uap, 0) = 0.0; /* punt */ push(r.val.q, uap); } + return; } /* all others leave the stack alone and the result in st */ fpreg(uap, 0) = r.val.q;
*** 1673,1689 **** case 0x6c8: case 0x6e0: case 0x6e8: case 0x6f0: case 0x6f8: /* stack is popped afterward */ ! if (stack) fpreg(uap, (op - 1) & 7) = r.val.q; ! else { fpreg(uap, op & 7) = r.val.q; pop(uap); } return; default: fpreg(uap, 0) = r.val.q; return; --- 1848,1866 ---- case 0x6c8: case 0x6e0: case 0x6e8: case 0x6f0: case 0x6f8: + /* stack is popped afterward */ ! if (stack) { fpreg(uap, (op - 1) & 7) = r.val.q; ! } else { fpreg(uap, op & 7) = r.val.q; pop(uap); } + return; default: fpreg(uap, 0) = r.val.q; return;