Print this page
11210 libm should be cstyle(1ONBLD) clean
@@ -20,10 +20,11 @@
*/
/*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/
+
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -49,43 +50,49 @@
/*
* 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 {
+ 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;
+ return (NULL);
}
+
mutex_unlock(&accrued_key_lock);
+
if (!p) {
- if ((p = (int*) malloc(sizeof(int))) == NULL)
- return NULL;
+ if ((p = (int *)malloc(sizeof (int))) == NULL)
+ return (NULL);
+
if (thr_setspecific(accrued_key, (void *)p) != 0) {
- (void)free(p);
- return NULL;
+ (void) free(p);
+ return (NULL);
}
+
*p = 0;
}
- return p;
+
+ return (p);
}
}
void
__fenv_getfsr(unsigned long *fsr)
@@ -93,16 +100,20 @@
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 */
+ /*
+ * pick up exception flags (excluding denormal operand flag)
+ * from mxcsr
+ */
__fenv_getmxcsr(&mxcsr);
cwsw |= (mxcsr & 0x3d);
}
+
cwsw |= *__fex_accrued();
*fsr = cwsw ^ 0x003f0000u;
}
void
@@ -114,18 +125,22 @@
/* 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 */
+ /*
+ * 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);
+ 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,18 +150,20 @@
#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)
+#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])
+#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
-*/
+ * 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,13 +171,14 @@
#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);
+ 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,70 +190,76 @@
}
static enum fp_class_type
my_fp_classf(float *x)
{
- int i = *(int*)x & ~0x80000000;
+ int i = *(int *)x & ~0x80000000;
if (i < 0x7f800000) {
if (i < 0x00800000)
- return ((i == 0)? fp_zero : fp_subnormal);
- return fp_normal;
+ 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);
}
- 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;
+ int i = *(1 + (int *)x) & ~0x80000000;
if (i < 0x7ff00000) {
if (i < 0x00100000)
- return (((i | *(int*)x) == 0)? fp_zero : fp_subnormal);
- return fp_normal;
+ 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);
}
- 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;
+ 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 */
+ 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
-*/
+ * 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,79 +272,93 @@
#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) */
+ /*
+ * 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ return ((enum fex_exception)-1);
+
t2 = my_fp_class((double *)ea);
break;
case 0x0c0:
case 0x0e0:
@@ -329,10 +367,11 @@
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,14 +382,16 @@
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,18 +400,19 @@
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;
+ 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,13 +439,15 @@
case 0x4e0:
case 0x4e8:
case 0x6c0:
case 0x6e0:
case 0x6e8:
+
/* fadd, fsub, fsubr */
if (t1 == fp_infinity && t2 == fp_infinity)
- return fex_inv_isi;
+ return (fex_inv_isi);
+
break;
case 0x008:
case 0x048:
case 0x088:
@@ -417,14 +461,16 @@
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;
+ return (fex_inv_zmi);
+
break;
case 0x030:
case 0x038:
case 0x070:
@@ -453,21 +499,23 @@
case 0x678:
case 0x6b0:
case 0x6b8:
case 0x6f0:
case 0x6f8:
+
/* fdiv */
if (t1 == fp_zero && t2 == fp_zero)
- return fex_inv_zdz;
+ return (fex_inv_zdz);
else if (t1 == fp_infinity && t2 == fp_infinity)
- return fex_inv_idi;
+ return (fex_inv_idi);
+
break;
case 0x1f0:
case 0x1f8:
/* fsqrt, other special ops */
- return fex_inv_sqrt;
+ return (fex_inv_sqrt);
case 0x010:
case 0x018:
case 0x050:
case 0x058:
@@ -500,19 +548,23 @@
case 0x690:
case 0x698:
case 0x6d0:
case 0x6d8:
case 0x7f0:
+
/* fcom */
if (t1 == fp_quiet || t2 == fp_quiet)
- return fex_inv_cmp;
+ return (fex_inv_cmp);
+
break;
case 0x1e0:
+
/* ftst */
if (op == 0x1e4 && t1 == fp_quiet)
- return fex_inv_cmp;
+ return (fex_inv_cmp);
+
break;
case 0x310:
case 0x318:
case 0x350:
@@ -530,22 +582,26 @@
case 0x790:
case 0x798:
case 0x7b0:
case 0x7b8:
/* fist, fbst */
- return fex_inv_int;
+ return (fex_inv_int);
}
- return (enum fex_exception) -1;
+ 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
- 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);
@@ -560,13 +616,13 @@
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
-*/
+ * 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,148 +639,173 @@
#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) */
+ /*
+ * 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->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;
+ 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->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;
+ 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->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;
+ 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->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;
+ 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->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;
+ 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->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;
+ info->res.val.i = (short)info->op1.val.q;
goto done;
case 0x730:
case 0x770:
case 0x7b0:
@@ -736,39 +817,46 @@
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->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;
+ 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 */
+ /*
+ * 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) :
+ info->res.val.q = ((op == 0x1f2) ? fpreg(uap, 1) :
fpreg(uap, 0));
break;
case 0x4c0:
case 0x4c8:
@@ -795,33 +883,38 @@
/* 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);
+ *(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 */
+ } 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;
+ info->res.val.q = (info->res.val.q *
+ twom12288) * twom12288mulp;
else
- info->res.val.q = (info->res.val.q * twom12288) * twom12288;
+ 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
+ } else {
info->flags = FE_INEXACT;
+ }
/* determine the operation code */
switch (op) {
case 0x1f0: /* f2xm1 */
case 0x1f1: /* fyl2x */
@@ -842,10 +935,11 @@
info->op = fex_sqrt;
return;
}
info->op = fex_other;
+
switch (op & 0x7c0) {
case 0x000:
case 0x040:
case 0x080:
case 0x0c0:
@@ -858,10 +952,11 @@
case 0x4c0:
case 0x600:
case 0x640:
case 0x680:
case 0x6c0:
+
switch (op & 0x38) {
case 0x00:
info->op = fex_add;
break;
@@ -878,22 +973,26 @@
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 */
+ /*
+ * 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,60 +1113,71 @@
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 */
+ /*
+ * 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->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;
+ 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->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;
+ 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->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;
+ op2v = (long double)info->op2.val.d;
break;
case 0x4c0:
case 0x6c0:
info->op2.type = fex_ldouble;
@@ -1079,19 +1189,22 @@
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->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;
+ 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,10 +1212,11 @@
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,11 +1272,12 @@
cwsw &= ~FE_ALL_EXCEPT;
__fenv_setcwsw(&cwsw);
}
/* pop the saved stack */
-static void pop(ucontext_t *uap)
+static void
+pop(ucontext_t *uap)
{
unsigned top;
fpreg(uap, 0) = fpreg(uap, 1);
fpreg(uap, 1) = fpreg(uap, 2);
@@ -1170,30 +1285,30 @@
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;
+ 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);
+ (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 = (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);
+ (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)
+static void
+push(long double x, ucontext_t *uap)
{
unsigned top;
fpreg(uap, 7) = fpreg(uap, 6);
fpreg(uap, 6) = fpreg(uap, 5);
@@ -1202,58 +1317,58 @@
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 = (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);
+ (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 = (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[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);
+ (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 */
+static const float fun = 7.922816251e+28f, /* 2^96 */
fov = 1.262177448e-29f; /* 2^-96 */
-static const double
- dun = 1.552518092300708935e+231, /* 2^768 */
+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
-*/
+ * 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; /*???*/
+ 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 */
+ /*
+ * 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,11 +1385,12 @@
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;
+ uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] |=
+ 0x4500;
#endif
return;
case 0x018:
case 0x058:
@@ -1294,36 +1410,42 @@
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;
+ 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;
+ 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;
+ uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw |=
+ 0x4500;
#else
- uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] |= 0x4500;
+ uap->uc_mcontext.fpregs.fp_reg_set.
+ fpchip_state.state[SW] |= 0x4500;
#endif
return;
}
+
break;
case 0x3e8:
case 0x3f0:
/* f[u]comi */
@@ -1344,264 +1466,305 @@
#endif
pop(uap);
return;
}
- /* if there is no result available and the exception is overflow
- or underflow, use the wrapped result */
+ /*
+ * 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;
+ *(float *)ea = (fpreg(uap, 0) * fov) *
+ fov;
else
- *(float *)ea = (fpreg(uap, 0) * fun) * fun;
+ *(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;
+ *(double *)ea = (fpreg(uap, 0) * dov) *
+ dov;
else
- *(double *)ea = (fpreg(uap, 0) * dun) * dun;
+ *(double *)ea = (fpreg(uap, 0) * dun) *
+ dun;
+
if ((op & 8) != 0)
pop(uap);
+
break;
}
}
+
#ifdef DEBUG
- else if (ex != FPE_FLTRES)
+ 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 */
+ /*
+ * 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;
+ *(float *)ea = (float)r.val.i;
break;
case fex_llong:
- *(float *)ea = (float) r.val.l;
+ *(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;
+ *(float *)ea = (float)r.val.d;
break;
case fex_ldouble:
- *(float *)ea = (float) r.val.q;
+ *(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;
+ *(int *)ea = (int)r.val.l;
break;
case fex_float:
- *(int *)ea = (int) r.val.f;
+ *(int *)ea = (int)r.val.f;
break;
case fex_double:
- *(int *)ea = (int) r.val.d;
+ *(int *)ea = (int)r.val.d;
break;
case fex_ldouble:
- *(int *)ea = (int) r.val.q;
+ *(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;
+ *(double *)ea = (double)r.val.i;
break;
case fex_llong:
- *(double *)ea = (double) r.val.l;
+ *(double *)ea = (double)r.val.l;
break;
case fex_float:
- *(double *)ea = (double) r.val.f;
+ *(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;
+ *(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;
+ *(short *)ea = (short)r.val.i;
break;
case fex_llong:
- *(short *)ea = (short) r.val.l;
+ *(short *)ea = (short)r.val.l;
break;
case fex_float:
- *(short *)ea = (short) r.val.f;
+ *(short *)ea = (short)r.val.f;
break;
case fex_double:
- *(short *)ea = (short) r.val.d;
+ *(short *)ea = (short)r.val.d;
break;
case fex_ldouble:
- *(short *)ea = (short) r.val.q;
+ *(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;
+ *(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;
+ *(long long *)ea = (long long)r.val.f;
break;
case fex_double:
- *(long long *)ea = (long long) r.val.d;
+ *(long long *)ea = (long long)r.val.d;
break;
case fex_ldouble:
- *(long long *)ea = (long long) r.val.q;
+ *(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;
+ r.val.q = (long double)r.val.i;
break;
case fex_llong:
- r.val.q = (long double) r.val.l;
+ r.val.q = (long double)r.val.l;
break;
case fex_float:
- r.val.q = (long double) r.val.f;
+ r.val.q = (long double)r.val.f;
break;
case fex_double:
- r.val.q = (long double) r.val.d;
+ r.val.q = (long double)r.val.d;
break;
default:
break;
}
@@ -1612,49 +1775,61 @@
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 */
+ /*
+ * 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)
+ if (stack) {
fpreg(uap, 1) = r.val.q;
- else {
+ } 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)
+ if (stack) {
fpreg(uap, 0) = r.val.q;
- else {
+ } 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,17 +1848,19 @@
case 0x6c8:
case 0x6e0:
case 0x6e8:
case 0x6f0:
case 0x6f8:
+
/* stack is popped afterward */
- if (stack)
+ if (stack) {
fpreg(uap, (op - 1) & 7) = r.val.q;
- else {
+ } else {
fpreg(uap, op & 7) = r.val.q;
pop(uap);
}
+
return;
default:
fpreg(uap, 0) = r.val.q;
return;