1*25c28e83SPiotr Jasiukajtis /* 2*25c28e83SPiotr Jasiukajtis * CDDL HEADER START 3*25c28e83SPiotr Jasiukajtis * 4*25c28e83SPiotr Jasiukajtis * The contents of this file are subject to the terms of the 5*25c28e83SPiotr Jasiukajtis * Common Development and Distribution License (the "License"). 6*25c28e83SPiotr Jasiukajtis * You may not use this file except in compliance with the License. 7*25c28e83SPiotr Jasiukajtis * 8*25c28e83SPiotr Jasiukajtis * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*25c28e83SPiotr Jasiukajtis * or http://www.opensolaris.org/os/licensing. 10*25c28e83SPiotr Jasiukajtis * See the License for the specific language governing permissions 11*25c28e83SPiotr Jasiukajtis * and limitations under the License. 12*25c28e83SPiotr Jasiukajtis * 13*25c28e83SPiotr Jasiukajtis * When distributing Covered Code, include this CDDL HEADER in each 14*25c28e83SPiotr Jasiukajtis * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*25c28e83SPiotr Jasiukajtis * If applicable, add the following below this CDDL HEADER, with the 16*25c28e83SPiotr Jasiukajtis * fields enclosed by brackets "[]" replaced with your own identifying 17*25c28e83SPiotr Jasiukajtis * information: Portions Copyright [yyyy] [name of copyright owner] 18*25c28e83SPiotr Jasiukajtis * 19*25c28e83SPiotr Jasiukajtis * CDDL HEADER END 20*25c28e83SPiotr Jasiukajtis */ 21*25c28e83SPiotr Jasiukajtis 22*25c28e83SPiotr Jasiukajtis /* 23*25c28e83SPiotr Jasiukajtis * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 24*25c28e83SPiotr Jasiukajtis */ 25*25c28e83SPiotr Jasiukajtis /* 26*25c28e83SPiotr Jasiukajtis * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 27*25c28e83SPiotr Jasiukajtis * Use is subject to license terms. 28*25c28e83SPiotr Jasiukajtis */ 29*25c28e83SPiotr Jasiukajtis 30*25c28e83SPiotr Jasiukajtis #include "fenv_synonyms.h" 31*25c28e83SPiotr Jasiukajtis #include <stdio.h> 32*25c28e83SPiotr Jasiukajtis #include <unistd.h> 33*25c28e83SPiotr Jasiukajtis #include <stdlib.h> 34*25c28e83SPiotr Jasiukajtis #include <string.h> 35*25c28e83SPiotr Jasiukajtis #include <signal.h> 36*25c28e83SPiotr Jasiukajtis #include <siginfo.h> 37*25c28e83SPiotr Jasiukajtis #include <ucontext.h> 38*25c28e83SPiotr Jasiukajtis #include <thread.h> 39*25c28e83SPiotr Jasiukajtis #include <math.h> 40*25c28e83SPiotr Jasiukajtis #if defined(__SUNPRO_C) 41*25c28e83SPiotr Jasiukajtis #include <sunmath.h> 42*25c28e83SPiotr Jasiukajtis #endif 43*25c28e83SPiotr Jasiukajtis #include <fenv.h> 44*25c28e83SPiotr Jasiukajtis #include "fex_handler.h" 45*25c28e83SPiotr Jasiukajtis #include "fenv_inlines.h" 46*25c28e83SPiotr Jasiukajtis 47*25c28e83SPiotr Jasiukajtis #if defined(__amd64) 48*25c28e83SPiotr Jasiukajtis #define test_sse_hw 1 49*25c28e83SPiotr Jasiukajtis #else 50*25c28e83SPiotr Jasiukajtis /* 51*25c28e83SPiotr Jasiukajtis * The following variable lives in libc on Solaris 10, where it 52*25c28e83SPiotr Jasiukajtis * gets set to a nonzero value at startup time on systems with SSE. 53*25c28e83SPiotr Jasiukajtis */ 54*25c28e83SPiotr Jasiukajtis int _sse_hw = 0; 55*25c28e83SPiotr Jasiukajtis #pragma weak _sse_hw 56*25c28e83SPiotr Jasiukajtis #define test_sse_hw &_sse_hw && _sse_hw 57*25c28e83SPiotr Jasiukajtis #endif 58*25c28e83SPiotr Jasiukajtis 59*25c28e83SPiotr Jasiukajtis static int accrued = 0; 60*25c28e83SPiotr Jasiukajtis static thread_key_t accrued_key; 61*25c28e83SPiotr Jasiukajtis static mutex_t accrued_key_lock = DEFAULTMUTEX; 62*25c28e83SPiotr Jasiukajtis 63*25c28e83SPiotr Jasiukajtis int * 64*25c28e83SPiotr Jasiukajtis __fex_accrued() 65*25c28e83SPiotr Jasiukajtis { 66*25c28e83SPiotr Jasiukajtis int *p; 67*25c28e83SPiotr Jasiukajtis 68*25c28e83SPiotr Jasiukajtis if (thr_main()) 69*25c28e83SPiotr Jasiukajtis return &accrued; 70*25c28e83SPiotr Jasiukajtis else { 71*25c28e83SPiotr Jasiukajtis p = NULL; 72*25c28e83SPiotr Jasiukajtis mutex_lock(&accrued_key_lock); 73*25c28e83SPiotr Jasiukajtis if (thr_getspecific(accrued_key, (void **)&p) != 0 && 74*25c28e83SPiotr Jasiukajtis thr_keycreate(&accrued_key, free) != 0) { 75*25c28e83SPiotr Jasiukajtis mutex_unlock(&accrued_key_lock); 76*25c28e83SPiotr Jasiukajtis return NULL; 77*25c28e83SPiotr Jasiukajtis } 78*25c28e83SPiotr Jasiukajtis mutex_unlock(&accrued_key_lock); 79*25c28e83SPiotr Jasiukajtis if (!p) { 80*25c28e83SPiotr Jasiukajtis if ((p = (int*) malloc(sizeof(int))) == NULL) 81*25c28e83SPiotr Jasiukajtis return NULL; 82*25c28e83SPiotr Jasiukajtis if (thr_setspecific(accrued_key, (void *)p) != 0) { 83*25c28e83SPiotr Jasiukajtis (void)free(p); 84*25c28e83SPiotr Jasiukajtis return NULL; 85*25c28e83SPiotr Jasiukajtis } 86*25c28e83SPiotr Jasiukajtis *p = 0; 87*25c28e83SPiotr Jasiukajtis } 88*25c28e83SPiotr Jasiukajtis return p; 89*25c28e83SPiotr Jasiukajtis } 90*25c28e83SPiotr Jasiukajtis } 91*25c28e83SPiotr Jasiukajtis 92*25c28e83SPiotr Jasiukajtis void 93*25c28e83SPiotr Jasiukajtis __fenv_getfsr(unsigned long *fsr) 94*25c28e83SPiotr Jasiukajtis { 95*25c28e83SPiotr Jasiukajtis unsigned int cwsw, mxcsr; 96*25c28e83SPiotr Jasiukajtis 97*25c28e83SPiotr Jasiukajtis __fenv_getcwsw(&cwsw); 98*25c28e83SPiotr Jasiukajtis /* clear reserved bits for no particularly good reason */ 99*25c28e83SPiotr Jasiukajtis cwsw &= ~0xe0c00000u; 100*25c28e83SPiotr Jasiukajtis if (test_sse_hw) { 101*25c28e83SPiotr Jasiukajtis /* pick up exception flags (excluding denormal operand 102*25c28e83SPiotr Jasiukajtis flag) from mxcsr */ 103*25c28e83SPiotr Jasiukajtis __fenv_getmxcsr(&mxcsr); 104*25c28e83SPiotr Jasiukajtis cwsw |= (mxcsr & 0x3d); 105*25c28e83SPiotr Jasiukajtis } 106*25c28e83SPiotr Jasiukajtis cwsw |= *__fex_accrued(); 107*25c28e83SPiotr Jasiukajtis *fsr = cwsw ^ 0x003f0000u; 108*25c28e83SPiotr Jasiukajtis } 109*25c28e83SPiotr Jasiukajtis 110*25c28e83SPiotr Jasiukajtis void 111*25c28e83SPiotr Jasiukajtis __fenv_setfsr(const unsigned long *fsr) 112*25c28e83SPiotr Jasiukajtis { 113*25c28e83SPiotr Jasiukajtis unsigned int cwsw, mxcsr; 114*25c28e83SPiotr Jasiukajtis int te; 115*25c28e83SPiotr Jasiukajtis 116*25c28e83SPiotr Jasiukajtis /* save accrued exception flags corresponding to enabled exceptions */ 117*25c28e83SPiotr Jasiukajtis cwsw = (unsigned int)*fsr; 118*25c28e83SPiotr Jasiukajtis te = __fenv_get_te(cwsw); 119*25c28e83SPiotr Jasiukajtis *__fex_accrued() = cwsw & te; 120*25c28e83SPiotr Jasiukajtis cwsw = (cwsw & ~te) ^ 0x003f0000; 121*25c28e83SPiotr Jasiukajtis if (test_sse_hw) { 122*25c28e83SPiotr Jasiukajtis /* propagate rounding direction, masks, and exception flags 123*25c28e83SPiotr Jasiukajtis (excluding denormal operand mask and flag) to mxcsr */ 124*25c28e83SPiotr Jasiukajtis __fenv_getmxcsr(&mxcsr); 125*25c28e83SPiotr Jasiukajtis mxcsr = (mxcsr & ~0x7ebd) | ((cwsw >> 13) & 0x6000) | 126*25c28e83SPiotr Jasiukajtis ((cwsw >> 9) & 0x1e80) | (cwsw & 0x3d); 127*25c28e83SPiotr Jasiukajtis __fenv_setmxcsr(&mxcsr); 128*25c28e83SPiotr Jasiukajtis } 129*25c28e83SPiotr Jasiukajtis __fenv_setcwsw(&cwsw); 130*25c28e83SPiotr Jasiukajtis } 131*25c28e83SPiotr Jasiukajtis 132*25c28e83SPiotr Jasiukajtis /* Offsets into the fp environment save area (assumes 32-bit protected mode) */ 133*25c28e83SPiotr Jasiukajtis #define CW 0 /* control word */ 134*25c28e83SPiotr Jasiukajtis #define SW 1 /* status word */ 135*25c28e83SPiotr Jasiukajtis #define TW 2 /* tag word */ 136*25c28e83SPiotr Jasiukajtis #define IP 3 /* instruction pointer */ 137*25c28e83SPiotr Jasiukajtis #define OP 4 /* opcode */ 138*25c28e83SPiotr Jasiukajtis #define EA 5 /* operand address */ 139*25c28e83SPiotr Jasiukajtis 140*25c28e83SPiotr Jasiukajtis /* macro for accessing fp registers in the save area */ 141*25c28e83SPiotr Jasiukajtis #if defined(__amd64) 142*25c28e83SPiotr Jasiukajtis #define fpreg(u,x) *(long double *)(10*(x)+(char*)&(u)->uc_mcontext.fpregs.fp_reg_set.fpchip_state.st) 143*25c28e83SPiotr Jasiukajtis #else 144*25c28e83SPiotr Jasiukajtis #define fpreg(u,x) *(long double *)(10*(x)+(char*)&(u)->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[7]) 145*25c28e83SPiotr Jasiukajtis #endif 146*25c28e83SPiotr Jasiukajtis 147*25c28e83SPiotr Jasiukajtis /* 148*25c28e83SPiotr Jasiukajtis * Fix sip->si_code; the Solaris x86 kernel can get it wrong 149*25c28e83SPiotr Jasiukajtis */ 150*25c28e83SPiotr Jasiukajtis void 151*25c28e83SPiotr Jasiukajtis __fex_get_x86_exc(siginfo_t *sip, ucontext_t *uap) 152*25c28e83SPiotr Jasiukajtis { 153*25c28e83SPiotr Jasiukajtis unsigned sw, cw; 154*25c28e83SPiotr Jasiukajtis 155*25c28e83SPiotr Jasiukajtis sw = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.status; 156*25c28e83SPiotr Jasiukajtis #if defined(__amd64) 157*25c28e83SPiotr Jasiukajtis cw = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.cw; 158*25c28e83SPiotr Jasiukajtis #else 159*25c28e83SPiotr Jasiukajtis cw = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[CW]; 160*25c28e83SPiotr Jasiukajtis #endif 161*25c28e83SPiotr Jasiukajtis if ((sw & FE_INVALID) && !(cw & (1 << fp_trap_invalid))) 162*25c28e83SPiotr Jasiukajtis /* store 0 for stack fault, FPE_FLTINV for IEEE invalid op */ 163*25c28e83SPiotr Jasiukajtis sip->si_code = ((sw & 0x40)? 0 : FPE_FLTINV); 164*25c28e83SPiotr Jasiukajtis else if ((sw & FE_DIVBYZERO) && !(cw & (1 << fp_trap_division))) 165*25c28e83SPiotr Jasiukajtis sip->si_code = FPE_FLTDIV; 166*25c28e83SPiotr Jasiukajtis else if ((sw & FE_OVERFLOW) && !(cw & (1 << fp_trap_overflow))) 167*25c28e83SPiotr Jasiukajtis sip->si_code = FPE_FLTOVF; 168*25c28e83SPiotr Jasiukajtis else if ((sw & FE_UNDERFLOW) && !(cw & (1 << fp_trap_underflow))) 169*25c28e83SPiotr Jasiukajtis sip->si_code = FPE_FLTUND; 170*25c28e83SPiotr Jasiukajtis else if ((sw & FE_INEXACT) && !(cw & (1 << fp_trap_inexact))) 171*25c28e83SPiotr Jasiukajtis sip->si_code = FPE_FLTRES; 172*25c28e83SPiotr Jasiukajtis else 173*25c28e83SPiotr Jasiukajtis sip->si_code = 0; 174*25c28e83SPiotr Jasiukajtis } 175*25c28e83SPiotr Jasiukajtis 176*25c28e83SPiotr Jasiukajtis static enum fp_class_type 177*25c28e83SPiotr Jasiukajtis my_fp_classf(float *x) 178*25c28e83SPiotr Jasiukajtis { 179*25c28e83SPiotr Jasiukajtis int i = *(int*)x & ~0x80000000; 180*25c28e83SPiotr Jasiukajtis 181*25c28e83SPiotr Jasiukajtis if (i < 0x7f800000) { 182*25c28e83SPiotr Jasiukajtis if (i < 0x00800000) 183*25c28e83SPiotr Jasiukajtis return ((i == 0)? fp_zero : fp_subnormal); 184*25c28e83SPiotr Jasiukajtis return fp_normal; 185*25c28e83SPiotr Jasiukajtis } 186*25c28e83SPiotr Jasiukajtis else if (i == 0x7f800000) 187*25c28e83SPiotr Jasiukajtis return fp_infinity; 188*25c28e83SPiotr Jasiukajtis else if (i & 0x400000) 189*25c28e83SPiotr Jasiukajtis return fp_quiet; 190*25c28e83SPiotr Jasiukajtis else 191*25c28e83SPiotr Jasiukajtis return fp_signaling; 192*25c28e83SPiotr Jasiukajtis } 193*25c28e83SPiotr Jasiukajtis 194*25c28e83SPiotr Jasiukajtis static enum fp_class_type 195*25c28e83SPiotr Jasiukajtis my_fp_class(double *x) 196*25c28e83SPiotr Jasiukajtis { 197*25c28e83SPiotr Jasiukajtis int i = *(1+(int*)x) & ~0x80000000; 198*25c28e83SPiotr Jasiukajtis 199*25c28e83SPiotr Jasiukajtis if (i < 0x7ff00000) { 200*25c28e83SPiotr Jasiukajtis if (i < 0x00100000) 201*25c28e83SPiotr Jasiukajtis return (((i | *(int*)x) == 0)? fp_zero : fp_subnormal); 202*25c28e83SPiotr Jasiukajtis return fp_normal; 203*25c28e83SPiotr Jasiukajtis } 204*25c28e83SPiotr Jasiukajtis else if (i == 0x7ff00000 && *(int*)x == 0) 205*25c28e83SPiotr Jasiukajtis return fp_infinity; 206*25c28e83SPiotr Jasiukajtis else if (i & 0x80000) 207*25c28e83SPiotr Jasiukajtis return fp_quiet; 208*25c28e83SPiotr Jasiukajtis else 209*25c28e83SPiotr Jasiukajtis return fp_signaling; 210*25c28e83SPiotr Jasiukajtis } 211*25c28e83SPiotr Jasiukajtis 212*25c28e83SPiotr Jasiukajtis static enum fp_class_type 213*25c28e83SPiotr Jasiukajtis my_fp_classl(long double *x) 214*25c28e83SPiotr Jasiukajtis { 215*25c28e83SPiotr Jasiukajtis int i = *(2+(int*)x) & 0x7fff; 216*25c28e83SPiotr Jasiukajtis 217*25c28e83SPiotr Jasiukajtis if (i < 0x7fff) { 218*25c28e83SPiotr Jasiukajtis if (i < 1) { 219*25c28e83SPiotr Jasiukajtis if (*(1+(int*)x) < 0) return fp_normal; /* pseudo-denormal */ 220*25c28e83SPiotr Jasiukajtis return (((*(1+(int*)x) | *(int*)x) == 0)? 221*25c28e83SPiotr Jasiukajtis fp_zero : fp_subnormal); 222*25c28e83SPiotr Jasiukajtis } 223*25c28e83SPiotr Jasiukajtis return ((*(1+(int*)x) < 0)? fp_normal : 224*25c28e83SPiotr Jasiukajtis (enum fp_class_type) -1); /* unsupported format */ 225*25c28e83SPiotr Jasiukajtis } 226*25c28e83SPiotr Jasiukajtis else if (*(1+(int*)x) == 0x80000000 && *(int*)x == 0) 227*25c28e83SPiotr Jasiukajtis return fp_infinity; 228*25c28e83SPiotr Jasiukajtis else if (*(1+(unsigned*)x) >= 0xc0000000) 229*25c28e83SPiotr Jasiukajtis return fp_quiet; 230*25c28e83SPiotr Jasiukajtis else if (*(1+(int*)x) < 0) 231*25c28e83SPiotr Jasiukajtis return fp_signaling; 232*25c28e83SPiotr Jasiukajtis else 233*25c28e83SPiotr Jasiukajtis return (enum fp_class_type) -1; /* unsupported format */ 234*25c28e83SPiotr Jasiukajtis } 235*25c28e83SPiotr Jasiukajtis 236*25c28e83SPiotr Jasiukajtis /* 237*25c28e83SPiotr Jasiukajtis * Determine which type of invalid operation exception occurred 238*25c28e83SPiotr Jasiukajtis */ 239*25c28e83SPiotr Jasiukajtis enum fex_exception 240*25c28e83SPiotr Jasiukajtis __fex_get_invalid_type(siginfo_t *sip, ucontext_t *uap) 241*25c28e83SPiotr Jasiukajtis { 242*25c28e83SPiotr Jasiukajtis unsigned op; 243*25c28e83SPiotr Jasiukajtis unsigned long ea; 244*25c28e83SPiotr Jasiukajtis enum fp_class_type t1, t2; 245*25c28e83SPiotr Jasiukajtis 246*25c28e83SPiotr Jasiukajtis /* get the opcode and data address */ 247*25c28e83SPiotr Jasiukajtis #if defined(__amd64) 248*25c28e83SPiotr Jasiukajtis op = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.fop >> 16; 249*25c28e83SPiotr Jasiukajtis ea = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.rdp; 250*25c28e83SPiotr Jasiukajtis #else 251*25c28e83SPiotr Jasiukajtis op = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[OP] >> 16; 252*25c28e83SPiotr Jasiukajtis ea = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[EA]; 253*25c28e83SPiotr Jasiukajtis #endif 254*25c28e83SPiotr Jasiukajtis 255*25c28e83SPiotr Jasiukajtis /* if the instruction is fld, the source must be snan (it can't be 256*25c28e83SPiotr Jasiukajtis an unsupported format, since fldt doesn't raise any exceptions) */ 257*25c28e83SPiotr Jasiukajtis switch (op & 0x7f8) { 258*25c28e83SPiotr Jasiukajtis case 0x100: 259*25c28e83SPiotr Jasiukajtis case 0x140: 260*25c28e83SPiotr Jasiukajtis case 0x180: 261*25c28e83SPiotr Jasiukajtis case 0x500: 262*25c28e83SPiotr Jasiukajtis case 0x540: 263*25c28e83SPiotr Jasiukajtis case 0x580: 264*25c28e83SPiotr Jasiukajtis return fex_inv_snan; 265*25c28e83SPiotr Jasiukajtis } 266*25c28e83SPiotr Jasiukajtis 267*25c28e83SPiotr Jasiukajtis /* otherwise st is one of the operands; see if it's snan */ 268*25c28e83SPiotr Jasiukajtis t1 = my_fp_classl(&fpreg(uap, 0)); 269*25c28e83SPiotr Jasiukajtis if (t1 == fp_signaling) 270*25c28e83SPiotr Jasiukajtis return fex_inv_snan; 271*25c28e83SPiotr Jasiukajtis else if (t1 == (enum fp_class_type) -1) 272*25c28e83SPiotr Jasiukajtis return (enum fex_exception) -1; 273*25c28e83SPiotr Jasiukajtis 274*25c28e83SPiotr Jasiukajtis /* determine the class of the second operand if there is one */ 275*25c28e83SPiotr Jasiukajtis t2 = fp_normal; 276*25c28e83SPiotr Jasiukajtis switch (op & 0x7e0) { 277*25c28e83SPiotr Jasiukajtis case 0x600: 278*25c28e83SPiotr Jasiukajtis case 0x620: 279*25c28e83SPiotr Jasiukajtis case 0x640: 280*25c28e83SPiotr Jasiukajtis case 0x660: 281*25c28e83SPiotr Jasiukajtis case 0x680: 282*25c28e83SPiotr Jasiukajtis case 0x6a0: 283*25c28e83SPiotr Jasiukajtis /* short memory operand */ 284*25c28e83SPiotr Jasiukajtis if (!ea) 285*25c28e83SPiotr Jasiukajtis return (enum fex_exception) -1; 286*25c28e83SPiotr Jasiukajtis if (*(short *)ea == 0) 287*25c28e83SPiotr Jasiukajtis t2 = fp_zero; 288*25c28e83SPiotr Jasiukajtis break; 289*25c28e83SPiotr Jasiukajtis 290*25c28e83SPiotr Jasiukajtis case 0x200: 291*25c28e83SPiotr Jasiukajtis case 0x220: 292*25c28e83SPiotr Jasiukajtis case 0x240: 293*25c28e83SPiotr Jasiukajtis case 0x260: 294*25c28e83SPiotr Jasiukajtis case 0x280: 295*25c28e83SPiotr Jasiukajtis case 0x2a0: 296*25c28e83SPiotr Jasiukajtis /* int memory operand */ 297*25c28e83SPiotr Jasiukajtis if (!ea) 298*25c28e83SPiotr Jasiukajtis return (enum fex_exception) -1; 299*25c28e83SPiotr Jasiukajtis if (*(int *)ea == 0) 300*25c28e83SPiotr Jasiukajtis t2 = fp_zero; 301*25c28e83SPiotr Jasiukajtis break; 302*25c28e83SPiotr Jasiukajtis 303*25c28e83SPiotr Jasiukajtis case 0x000: 304*25c28e83SPiotr Jasiukajtis case 0x020: 305*25c28e83SPiotr Jasiukajtis case 0x040: 306*25c28e83SPiotr Jasiukajtis case 0x060: 307*25c28e83SPiotr Jasiukajtis case 0x080: 308*25c28e83SPiotr Jasiukajtis case 0x0a0: 309*25c28e83SPiotr Jasiukajtis /* single precision memory operand */ 310*25c28e83SPiotr Jasiukajtis if (!ea) 311*25c28e83SPiotr Jasiukajtis return (enum fex_exception) -1; 312*25c28e83SPiotr Jasiukajtis t2 = my_fp_classf((float *)ea); 313*25c28e83SPiotr Jasiukajtis break; 314*25c28e83SPiotr Jasiukajtis 315*25c28e83SPiotr Jasiukajtis case 0x400: 316*25c28e83SPiotr Jasiukajtis case 0x420: 317*25c28e83SPiotr Jasiukajtis case 0x440: 318*25c28e83SPiotr Jasiukajtis case 0x460: 319*25c28e83SPiotr Jasiukajtis case 0x480: 320*25c28e83SPiotr Jasiukajtis case 0x4a0: 321*25c28e83SPiotr Jasiukajtis /* double precision memory operand */ 322*25c28e83SPiotr Jasiukajtis if (!ea) 323*25c28e83SPiotr Jasiukajtis return (enum fex_exception) -1; 324*25c28e83SPiotr Jasiukajtis t2 = my_fp_class((double *)ea); 325*25c28e83SPiotr Jasiukajtis break; 326*25c28e83SPiotr Jasiukajtis 327*25c28e83SPiotr Jasiukajtis case 0x0c0: 328*25c28e83SPiotr Jasiukajtis case 0x0e0: 329*25c28e83SPiotr Jasiukajtis case 0x3e0: 330*25c28e83SPiotr Jasiukajtis case 0x4c0: 331*25c28e83SPiotr Jasiukajtis case 0x4e0: 332*25c28e83SPiotr Jasiukajtis case 0x5e0: 333*25c28e83SPiotr Jasiukajtis case 0x6c0: 334*25c28e83SPiotr Jasiukajtis case 0x6e0: 335*25c28e83SPiotr Jasiukajtis case 0x7e0: 336*25c28e83SPiotr Jasiukajtis /* register operand determined by opcode */ 337*25c28e83SPiotr Jasiukajtis switch (op & 0x7f8) { 338*25c28e83SPiotr Jasiukajtis case 0x3e0: 339*25c28e83SPiotr Jasiukajtis case 0x3f8: 340*25c28e83SPiotr Jasiukajtis case 0x5f0: 341*25c28e83SPiotr Jasiukajtis case 0x5f8: 342*25c28e83SPiotr Jasiukajtis case 0x7e0: 343*25c28e83SPiotr Jasiukajtis case 0x7f8: 344*25c28e83SPiotr Jasiukajtis /* weed out nonexistent opcodes */ 345*25c28e83SPiotr Jasiukajtis break; 346*25c28e83SPiotr Jasiukajtis 347*25c28e83SPiotr Jasiukajtis default: 348*25c28e83SPiotr Jasiukajtis t2 = my_fp_classl(&fpreg(uap, op & 7)); 349*25c28e83SPiotr Jasiukajtis } 350*25c28e83SPiotr Jasiukajtis break; 351*25c28e83SPiotr Jasiukajtis 352*25c28e83SPiotr Jasiukajtis case 0x1e0: 353*25c28e83SPiotr Jasiukajtis case 0x2e0: 354*25c28e83SPiotr Jasiukajtis /* special forms */ 355*25c28e83SPiotr Jasiukajtis switch (op) { 356*25c28e83SPiotr Jasiukajtis case 0x1f1: /* fyl2x */ 357*25c28e83SPiotr Jasiukajtis case 0x1f3: /* fpatan */ 358*25c28e83SPiotr Jasiukajtis case 0x1f5: /* fprem1 */ 359*25c28e83SPiotr Jasiukajtis case 0x1f8: /* fprem */ 360*25c28e83SPiotr Jasiukajtis case 0x1f9: /* fyl2xp1 */ 361*25c28e83SPiotr Jasiukajtis case 0x1fd: /* fscale */ 362*25c28e83SPiotr Jasiukajtis case 0x2e9: /* fucompp */ 363*25c28e83SPiotr Jasiukajtis t2 = my_fp_classl(&fpreg(uap, 1)); 364*25c28e83SPiotr Jasiukajtis break; 365*25c28e83SPiotr Jasiukajtis } 366*25c28e83SPiotr Jasiukajtis break; 367*25c28e83SPiotr Jasiukajtis } 368*25c28e83SPiotr Jasiukajtis 369*25c28e83SPiotr Jasiukajtis /* see if the second op is snan */ 370*25c28e83SPiotr Jasiukajtis if (t2 == fp_signaling) 371*25c28e83SPiotr Jasiukajtis return fex_inv_snan; 372*25c28e83SPiotr Jasiukajtis else if (t2 == (enum fp_class_type) -1) 373*25c28e83SPiotr Jasiukajtis return (enum fex_exception) -1; 374*25c28e83SPiotr Jasiukajtis 375*25c28e83SPiotr Jasiukajtis /* determine the type of operation */ 376*25c28e83SPiotr Jasiukajtis switch (op & 0x7f8) { 377*25c28e83SPiotr Jasiukajtis case 0x000: 378*25c28e83SPiotr Jasiukajtis case 0x020: 379*25c28e83SPiotr Jasiukajtis case 0x028: 380*25c28e83SPiotr Jasiukajtis case 0x040: 381*25c28e83SPiotr Jasiukajtis case 0x060: 382*25c28e83SPiotr Jasiukajtis case 0x068: 383*25c28e83SPiotr Jasiukajtis case 0x080: 384*25c28e83SPiotr Jasiukajtis case 0x0a0: 385*25c28e83SPiotr Jasiukajtis case 0x0a8: 386*25c28e83SPiotr Jasiukajtis case 0x0c0: 387*25c28e83SPiotr Jasiukajtis case 0x0e0: 388*25c28e83SPiotr Jasiukajtis case 0x0e8: 389*25c28e83SPiotr Jasiukajtis case 0x400: 390*25c28e83SPiotr Jasiukajtis case 0x420: 391*25c28e83SPiotr Jasiukajtis case 0x428: 392*25c28e83SPiotr Jasiukajtis case 0x440: 393*25c28e83SPiotr Jasiukajtis case 0x460: 394*25c28e83SPiotr Jasiukajtis case 0x468: 395*25c28e83SPiotr Jasiukajtis case 0x480: 396*25c28e83SPiotr Jasiukajtis case 0x4a0: 397*25c28e83SPiotr Jasiukajtis case 0x4a8: 398*25c28e83SPiotr Jasiukajtis case 0x4c0: 399*25c28e83SPiotr Jasiukajtis case 0x4e0: 400*25c28e83SPiotr Jasiukajtis case 0x4e8: 401*25c28e83SPiotr Jasiukajtis case 0x6c0: 402*25c28e83SPiotr Jasiukajtis case 0x6e0: 403*25c28e83SPiotr Jasiukajtis case 0x6e8: 404*25c28e83SPiotr Jasiukajtis /* fadd, fsub, fsubr */ 405*25c28e83SPiotr Jasiukajtis if (t1 == fp_infinity && t2 == fp_infinity) 406*25c28e83SPiotr Jasiukajtis return fex_inv_isi; 407*25c28e83SPiotr Jasiukajtis break; 408*25c28e83SPiotr Jasiukajtis 409*25c28e83SPiotr Jasiukajtis case 0x008: 410*25c28e83SPiotr Jasiukajtis case 0x048: 411*25c28e83SPiotr Jasiukajtis case 0x088: 412*25c28e83SPiotr Jasiukajtis case 0x0c8: 413*25c28e83SPiotr Jasiukajtis case 0x208: 414*25c28e83SPiotr Jasiukajtis case 0x248: 415*25c28e83SPiotr Jasiukajtis case 0x288: 416*25c28e83SPiotr Jasiukajtis case 0x408: 417*25c28e83SPiotr Jasiukajtis case 0x448: 418*25c28e83SPiotr Jasiukajtis case 0x488: 419*25c28e83SPiotr Jasiukajtis case 0x4c8: 420*25c28e83SPiotr Jasiukajtis case 0x608: 421*25c28e83SPiotr Jasiukajtis case 0x648: 422*25c28e83SPiotr Jasiukajtis case 0x688: 423*25c28e83SPiotr Jasiukajtis case 0x6c8: 424*25c28e83SPiotr Jasiukajtis /* fmul */ 425*25c28e83SPiotr Jasiukajtis if ((t1 == fp_zero && t2 == fp_infinity) || (t2 == fp_zero && 426*25c28e83SPiotr Jasiukajtis t1 == fp_infinity)) 427*25c28e83SPiotr Jasiukajtis return fex_inv_zmi; 428*25c28e83SPiotr Jasiukajtis break; 429*25c28e83SPiotr Jasiukajtis 430*25c28e83SPiotr Jasiukajtis case 0x030: 431*25c28e83SPiotr Jasiukajtis case 0x038: 432*25c28e83SPiotr Jasiukajtis case 0x070: 433*25c28e83SPiotr Jasiukajtis case 0x078: 434*25c28e83SPiotr Jasiukajtis case 0x0b0: 435*25c28e83SPiotr Jasiukajtis case 0x0b8: 436*25c28e83SPiotr Jasiukajtis case 0x0f0: 437*25c28e83SPiotr Jasiukajtis case 0x0f8: 438*25c28e83SPiotr Jasiukajtis case 0x230: 439*25c28e83SPiotr Jasiukajtis case 0x238: 440*25c28e83SPiotr Jasiukajtis case 0x270: 441*25c28e83SPiotr Jasiukajtis case 0x278: 442*25c28e83SPiotr Jasiukajtis case 0x2b0: 443*25c28e83SPiotr Jasiukajtis case 0x2b8: 444*25c28e83SPiotr Jasiukajtis case 0x430: 445*25c28e83SPiotr Jasiukajtis case 0x438: 446*25c28e83SPiotr Jasiukajtis case 0x470: 447*25c28e83SPiotr Jasiukajtis case 0x478: 448*25c28e83SPiotr Jasiukajtis case 0x4b0: 449*25c28e83SPiotr Jasiukajtis case 0x4b8: 450*25c28e83SPiotr Jasiukajtis case 0x4f0: 451*25c28e83SPiotr Jasiukajtis case 0x4f8: 452*25c28e83SPiotr Jasiukajtis case 0x630: 453*25c28e83SPiotr Jasiukajtis case 0x638: 454*25c28e83SPiotr Jasiukajtis case 0x670: 455*25c28e83SPiotr Jasiukajtis case 0x678: 456*25c28e83SPiotr Jasiukajtis case 0x6b0: 457*25c28e83SPiotr Jasiukajtis case 0x6b8: 458*25c28e83SPiotr Jasiukajtis case 0x6f0: 459*25c28e83SPiotr Jasiukajtis case 0x6f8: 460*25c28e83SPiotr Jasiukajtis /* fdiv */ 461*25c28e83SPiotr Jasiukajtis if (t1 == fp_zero && t2 == fp_zero) 462*25c28e83SPiotr Jasiukajtis return fex_inv_zdz; 463*25c28e83SPiotr Jasiukajtis else if (t1 == fp_infinity && t2 == fp_infinity) 464*25c28e83SPiotr Jasiukajtis return fex_inv_idi; 465*25c28e83SPiotr Jasiukajtis break; 466*25c28e83SPiotr Jasiukajtis 467*25c28e83SPiotr Jasiukajtis case 0x1f0: 468*25c28e83SPiotr Jasiukajtis case 0x1f8: 469*25c28e83SPiotr Jasiukajtis /* fsqrt, other special ops */ 470*25c28e83SPiotr Jasiukajtis return fex_inv_sqrt; 471*25c28e83SPiotr Jasiukajtis 472*25c28e83SPiotr Jasiukajtis case 0x010: 473*25c28e83SPiotr Jasiukajtis case 0x018: 474*25c28e83SPiotr Jasiukajtis case 0x050: 475*25c28e83SPiotr Jasiukajtis case 0x058: 476*25c28e83SPiotr Jasiukajtis case 0x090: 477*25c28e83SPiotr Jasiukajtis case 0x098: 478*25c28e83SPiotr Jasiukajtis case 0x0d0: 479*25c28e83SPiotr Jasiukajtis case 0x0d8: 480*25c28e83SPiotr Jasiukajtis case 0x210: 481*25c28e83SPiotr Jasiukajtis case 0x218: 482*25c28e83SPiotr Jasiukajtis case 0x250: 483*25c28e83SPiotr Jasiukajtis case 0x258: 484*25c28e83SPiotr Jasiukajtis case 0x290: 485*25c28e83SPiotr Jasiukajtis case 0x298: 486*25c28e83SPiotr Jasiukajtis case 0x2e8: 487*25c28e83SPiotr Jasiukajtis case 0x3f0: 488*25c28e83SPiotr Jasiukajtis case 0x410: 489*25c28e83SPiotr Jasiukajtis case 0x418: 490*25c28e83SPiotr Jasiukajtis case 0x450: 491*25c28e83SPiotr Jasiukajtis case 0x458: 492*25c28e83SPiotr Jasiukajtis case 0x490: 493*25c28e83SPiotr Jasiukajtis case 0x498: 494*25c28e83SPiotr Jasiukajtis case 0x4d0: 495*25c28e83SPiotr Jasiukajtis case 0x4d8: 496*25c28e83SPiotr Jasiukajtis case 0x5e0: 497*25c28e83SPiotr Jasiukajtis case 0x5e8: 498*25c28e83SPiotr Jasiukajtis case 0x610: 499*25c28e83SPiotr Jasiukajtis case 0x618: 500*25c28e83SPiotr Jasiukajtis case 0x650: 501*25c28e83SPiotr Jasiukajtis case 0x658: 502*25c28e83SPiotr Jasiukajtis case 0x690: 503*25c28e83SPiotr Jasiukajtis case 0x698: 504*25c28e83SPiotr Jasiukajtis case 0x6d0: 505*25c28e83SPiotr Jasiukajtis case 0x6d8: 506*25c28e83SPiotr Jasiukajtis case 0x7f0: 507*25c28e83SPiotr Jasiukajtis /* fcom */ 508*25c28e83SPiotr Jasiukajtis if (t1 == fp_quiet || t2 == fp_quiet) 509*25c28e83SPiotr Jasiukajtis return fex_inv_cmp; 510*25c28e83SPiotr Jasiukajtis break; 511*25c28e83SPiotr Jasiukajtis 512*25c28e83SPiotr Jasiukajtis case 0x1e0: 513*25c28e83SPiotr Jasiukajtis /* ftst */ 514*25c28e83SPiotr Jasiukajtis if (op == 0x1e4 && t1 == fp_quiet) 515*25c28e83SPiotr Jasiukajtis return fex_inv_cmp; 516*25c28e83SPiotr Jasiukajtis break; 517*25c28e83SPiotr Jasiukajtis 518*25c28e83SPiotr Jasiukajtis case 0x310: 519*25c28e83SPiotr Jasiukajtis case 0x318: 520*25c28e83SPiotr Jasiukajtis case 0x350: 521*25c28e83SPiotr Jasiukajtis case 0x358: 522*25c28e83SPiotr Jasiukajtis case 0x390: 523*25c28e83SPiotr Jasiukajtis case 0x398: 524*25c28e83SPiotr Jasiukajtis case 0x710: 525*25c28e83SPiotr Jasiukajtis case 0x718: 526*25c28e83SPiotr Jasiukajtis case 0x730: 527*25c28e83SPiotr Jasiukajtis case 0x738: 528*25c28e83SPiotr Jasiukajtis case 0x750: 529*25c28e83SPiotr Jasiukajtis case 0x758: 530*25c28e83SPiotr Jasiukajtis case 0x770: 531*25c28e83SPiotr Jasiukajtis case 0x778: 532*25c28e83SPiotr Jasiukajtis case 0x790: 533*25c28e83SPiotr Jasiukajtis case 0x798: 534*25c28e83SPiotr Jasiukajtis case 0x7b0: 535*25c28e83SPiotr Jasiukajtis case 0x7b8: 536*25c28e83SPiotr Jasiukajtis /* fist, fbst */ 537*25c28e83SPiotr Jasiukajtis return fex_inv_int; 538*25c28e83SPiotr Jasiukajtis } 539*25c28e83SPiotr Jasiukajtis 540*25c28e83SPiotr Jasiukajtis return (enum fex_exception) -1; 541*25c28e83SPiotr Jasiukajtis } 542*25c28e83SPiotr Jasiukajtis 543*25c28e83SPiotr Jasiukajtis /* scale factors for exponent unwrapping */ 544*25c28e83SPiotr Jasiukajtis static const long double 545*25c28e83SPiotr Jasiukajtis two12288 = 1.139165225263043370845938579315932009e+3699l, /* 2^12288 */ 546*25c28e83SPiotr Jasiukajtis twom12288 = 8.778357852076208839765066529179033145e-3700l, /* 2^-12288 */ 547*25c28e83SPiotr Jasiukajtis twom12288mulp = 8.778357852076208839289190796475222545e-3700l; 548*25c28e83SPiotr Jasiukajtis /* (")*(1-2^-64) */ 549*25c28e83SPiotr Jasiukajtis 550*25c28e83SPiotr Jasiukajtis /* inline templates */ 551*25c28e83SPiotr Jasiukajtis extern long double f2xm1(long double); 552*25c28e83SPiotr Jasiukajtis extern long double fyl2x(long double, long double); 553*25c28e83SPiotr Jasiukajtis extern long double fptan(long double); 554*25c28e83SPiotr Jasiukajtis extern long double fpatan(long double, long double); 555*25c28e83SPiotr Jasiukajtis extern long double fxtract(long double); 556*25c28e83SPiotr Jasiukajtis extern long double fprem1(long double, long double); 557*25c28e83SPiotr Jasiukajtis extern long double fprem(long double, long double); 558*25c28e83SPiotr Jasiukajtis extern long double fyl2xp1(long double, long double); 559*25c28e83SPiotr Jasiukajtis extern long double fsqrt(long double); 560*25c28e83SPiotr Jasiukajtis extern long double fsincos(long double); 561*25c28e83SPiotr Jasiukajtis extern long double frndint(long double); 562*25c28e83SPiotr Jasiukajtis extern long double fscale(long double, long double); 563*25c28e83SPiotr Jasiukajtis extern long double fsin(long double); 564*25c28e83SPiotr Jasiukajtis extern long double fcos(long double); 565*25c28e83SPiotr Jasiukajtis 566*25c28e83SPiotr Jasiukajtis /* 567*25c28e83SPiotr Jasiukajtis * Get the operands, generate the default untrapped result with 568*25c28e83SPiotr Jasiukajtis * exceptions, and set a code indicating the type of operation 569*25c28e83SPiotr Jasiukajtis */ 570*25c28e83SPiotr Jasiukajtis void 571*25c28e83SPiotr Jasiukajtis __fex_get_op(siginfo_t *sip, ucontext_t *uap, fex_info_t *info) 572*25c28e83SPiotr Jasiukajtis { 573*25c28e83SPiotr Jasiukajtis fex_numeric_t t; 574*25c28e83SPiotr Jasiukajtis long double op2v, x; 575*25c28e83SPiotr Jasiukajtis unsigned int cwsw, ex, sw, op; 576*25c28e83SPiotr Jasiukajtis unsigned long ea; 577*25c28e83SPiotr Jasiukajtis volatile int c; 578*25c28e83SPiotr Jasiukajtis 579*25c28e83SPiotr Jasiukajtis /* get the exception type, status word, opcode, and data address */ 580*25c28e83SPiotr Jasiukajtis ex = sip->si_code; 581*25c28e83SPiotr Jasiukajtis sw = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.status; 582*25c28e83SPiotr Jasiukajtis #if defined(__amd64) 583*25c28e83SPiotr Jasiukajtis op = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.fop >> 16; 584*25c28e83SPiotr Jasiukajtis ea = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.rdp; 585*25c28e83SPiotr Jasiukajtis #else 586*25c28e83SPiotr Jasiukajtis op = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[OP] >> 16; 587*25c28e83SPiotr Jasiukajtis ea = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[EA]; 588*25c28e83SPiotr Jasiukajtis #endif 589*25c28e83SPiotr Jasiukajtis 590*25c28e83SPiotr Jasiukajtis /* initialize res to the default untrapped result and ex to the 591*25c28e83SPiotr Jasiukajtis corresponding flags (assume trapping is disabled and flags 592*25c28e83SPiotr Jasiukajtis are clear) */ 593*25c28e83SPiotr Jasiukajtis 594*25c28e83SPiotr Jasiukajtis /* single operand instructions */ 595*25c28e83SPiotr Jasiukajtis info->op = fex_cnvt; 596*25c28e83SPiotr Jasiukajtis info->op2.type = fex_nodata; 597*25c28e83SPiotr Jasiukajtis switch (op & 0x7f8) { 598*25c28e83SPiotr Jasiukajtis /* load instructions */ 599*25c28e83SPiotr Jasiukajtis case 0x100: 600*25c28e83SPiotr Jasiukajtis case 0x140: 601*25c28e83SPiotr Jasiukajtis case 0x180: 602*25c28e83SPiotr Jasiukajtis if (!ea) { 603*25c28e83SPiotr Jasiukajtis info->op = fex_other; 604*25c28e83SPiotr Jasiukajtis info->op1.type = info->op2.type = info->res.type = fex_nodata; 605*25c28e83SPiotr Jasiukajtis info->flags = 0; 606*25c28e83SPiotr Jasiukajtis return; 607*25c28e83SPiotr Jasiukajtis } 608*25c28e83SPiotr Jasiukajtis info->op1.type = fex_float; 609*25c28e83SPiotr Jasiukajtis info->op1.val.f = *(float *)ea; 610*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble; 611*25c28e83SPiotr Jasiukajtis info->res.val.q = (long double) info->op1.val.f; 612*25c28e83SPiotr Jasiukajtis goto done; 613*25c28e83SPiotr Jasiukajtis 614*25c28e83SPiotr Jasiukajtis case 0x500: 615*25c28e83SPiotr Jasiukajtis case 0x540: 616*25c28e83SPiotr Jasiukajtis case 0x580: 617*25c28e83SPiotr Jasiukajtis if (!ea) { 618*25c28e83SPiotr Jasiukajtis info->op = fex_other; 619*25c28e83SPiotr Jasiukajtis info->op1.type = info->op2.type = info->res.type = fex_nodata; 620*25c28e83SPiotr Jasiukajtis info->flags = 0; 621*25c28e83SPiotr Jasiukajtis return; 622*25c28e83SPiotr Jasiukajtis } 623*25c28e83SPiotr Jasiukajtis info->op1.type = fex_double; 624*25c28e83SPiotr Jasiukajtis info->op1.val.d = *(double *)ea; 625*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble; 626*25c28e83SPiotr Jasiukajtis info->res.val.q = (long double) info->op1.val.d; 627*25c28e83SPiotr Jasiukajtis goto done; 628*25c28e83SPiotr Jasiukajtis 629*25c28e83SPiotr Jasiukajtis /* store instructions */ 630*25c28e83SPiotr Jasiukajtis case 0x110: 631*25c28e83SPiotr Jasiukajtis case 0x118: 632*25c28e83SPiotr Jasiukajtis case 0x150: 633*25c28e83SPiotr Jasiukajtis case 0x158: 634*25c28e83SPiotr Jasiukajtis case 0x190: 635*25c28e83SPiotr Jasiukajtis case 0x198: 636*25c28e83SPiotr Jasiukajtis info->res.type = fex_float; 637*25c28e83SPiotr Jasiukajtis if (ex == FPE_FLTRES && (op & 8) != 0) { 638*25c28e83SPiotr Jasiukajtis /* inexact, stack popped */ 639*25c28e83SPiotr Jasiukajtis if (!ea) { 640*25c28e83SPiotr Jasiukajtis info->op = fex_other; 641*25c28e83SPiotr Jasiukajtis info->op1.type = info->op2.type = info->res.type = fex_nodata; 642*25c28e83SPiotr Jasiukajtis info->flags = 0; 643*25c28e83SPiotr Jasiukajtis return; 644*25c28e83SPiotr Jasiukajtis } 645*25c28e83SPiotr Jasiukajtis info->op1.type = fex_nodata; 646*25c28e83SPiotr Jasiukajtis info->res.val.f = *(float *)ea; 647*25c28e83SPiotr Jasiukajtis info->flags = FE_INEXACT; 648*25c28e83SPiotr Jasiukajtis return; 649*25c28e83SPiotr Jasiukajtis } 650*25c28e83SPiotr Jasiukajtis info->op1.type = fex_ldouble; 651*25c28e83SPiotr Jasiukajtis info->op1.val.q = fpreg(uap, 0); 652*25c28e83SPiotr Jasiukajtis info->res.val.f = (float) info->op1.val.q; 653*25c28e83SPiotr Jasiukajtis goto done; 654*25c28e83SPiotr Jasiukajtis 655*25c28e83SPiotr Jasiukajtis case 0x310: 656*25c28e83SPiotr Jasiukajtis case 0x318: 657*25c28e83SPiotr Jasiukajtis case 0x350: 658*25c28e83SPiotr Jasiukajtis case 0x358: 659*25c28e83SPiotr Jasiukajtis case 0x390: 660*25c28e83SPiotr Jasiukajtis case 0x398: 661*25c28e83SPiotr Jasiukajtis info->res.type = fex_int; 662*25c28e83SPiotr Jasiukajtis if (ex == FPE_FLTRES && (op & 8) != 0) { 663*25c28e83SPiotr Jasiukajtis /* inexact, stack popped */ 664*25c28e83SPiotr Jasiukajtis if (!ea) { 665*25c28e83SPiotr Jasiukajtis info->op = fex_other; 666*25c28e83SPiotr Jasiukajtis info->op1.type = info->op2.type = info->res.type = fex_nodata; 667*25c28e83SPiotr Jasiukajtis info->flags = 0; 668*25c28e83SPiotr Jasiukajtis return; 669*25c28e83SPiotr Jasiukajtis } 670*25c28e83SPiotr Jasiukajtis info->op1.type = fex_nodata; 671*25c28e83SPiotr Jasiukajtis info->res.val.i = *(int *)ea; 672*25c28e83SPiotr Jasiukajtis info->flags = FE_INEXACT; 673*25c28e83SPiotr Jasiukajtis return; 674*25c28e83SPiotr Jasiukajtis } 675*25c28e83SPiotr Jasiukajtis info->op1.type = fex_ldouble; 676*25c28e83SPiotr Jasiukajtis info->op1.val.q = fpreg(uap, 0); 677*25c28e83SPiotr Jasiukajtis info->res.val.i = (int) info->op1.val.q; 678*25c28e83SPiotr Jasiukajtis goto done; 679*25c28e83SPiotr Jasiukajtis 680*25c28e83SPiotr Jasiukajtis case 0x510: 681*25c28e83SPiotr Jasiukajtis case 0x518: 682*25c28e83SPiotr Jasiukajtis case 0x550: 683*25c28e83SPiotr Jasiukajtis case 0x558: 684*25c28e83SPiotr Jasiukajtis case 0x590: 685*25c28e83SPiotr Jasiukajtis case 0x598: 686*25c28e83SPiotr Jasiukajtis info->res.type = fex_double; 687*25c28e83SPiotr Jasiukajtis if (ex == FPE_FLTRES && (op & 8) != 0) { 688*25c28e83SPiotr Jasiukajtis /* inexact, stack popped */ 689*25c28e83SPiotr Jasiukajtis if (!ea) { 690*25c28e83SPiotr Jasiukajtis info->op = fex_other; 691*25c28e83SPiotr Jasiukajtis info->op1.type = info->op2.type = info->res.type = fex_nodata; 692*25c28e83SPiotr Jasiukajtis info->flags = 0; 693*25c28e83SPiotr Jasiukajtis return; 694*25c28e83SPiotr Jasiukajtis } 695*25c28e83SPiotr Jasiukajtis info->op1.type = fex_nodata; 696*25c28e83SPiotr Jasiukajtis info->res.val.d = *(double *)ea; 697*25c28e83SPiotr Jasiukajtis info->flags = FE_INEXACT; 698*25c28e83SPiotr Jasiukajtis return; 699*25c28e83SPiotr Jasiukajtis } 700*25c28e83SPiotr Jasiukajtis info->op1.type = fex_ldouble; 701*25c28e83SPiotr Jasiukajtis info->op1.val.q = fpreg(uap, 0); 702*25c28e83SPiotr Jasiukajtis info->res.val.d = (double) info->op1.val.q; 703*25c28e83SPiotr Jasiukajtis goto done; 704*25c28e83SPiotr Jasiukajtis 705*25c28e83SPiotr Jasiukajtis case 0x710: 706*25c28e83SPiotr Jasiukajtis case 0x718: 707*25c28e83SPiotr Jasiukajtis case 0x750: 708*25c28e83SPiotr Jasiukajtis case 0x758: 709*25c28e83SPiotr Jasiukajtis case 0x790: 710*25c28e83SPiotr Jasiukajtis case 0x798: 711*25c28e83SPiotr Jasiukajtis info->res.type = fex_int; 712*25c28e83SPiotr Jasiukajtis if (ex == FPE_FLTRES && (op & 8) != 0) { 713*25c28e83SPiotr Jasiukajtis /* inexact, stack popped */ 714*25c28e83SPiotr Jasiukajtis if (!ea) { 715*25c28e83SPiotr Jasiukajtis info->op = fex_other; 716*25c28e83SPiotr Jasiukajtis info->op1.type = info->op2.type = info->res.type = fex_nodata; 717*25c28e83SPiotr Jasiukajtis info->flags = 0; 718*25c28e83SPiotr Jasiukajtis return; 719*25c28e83SPiotr Jasiukajtis } 720*25c28e83SPiotr Jasiukajtis info->op1.type = fex_nodata; 721*25c28e83SPiotr Jasiukajtis info->res.val.i = *(short *)ea; 722*25c28e83SPiotr Jasiukajtis info->flags = FE_INEXACT; 723*25c28e83SPiotr Jasiukajtis return; 724*25c28e83SPiotr Jasiukajtis } 725*25c28e83SPiotr Jasiukajtis info->op1.type = fex_ldouble; 726*25c28e83SPiotr Jasiukajtis info->op1.val.q = fpreg(uap, 0); 727*25c28e83SPiotr Jasiukajtis info->res.val.i = (short) info->op1.val.q; 728*25c28e83SPiotr Jasiukajtis goto done; 729*25c28e83SPiotr Jasiukajtis 730*25c28e83SPiotr Jasiukajtis case 0x730: 731*25c28e83SPiotr Jasiukajtis case 0x770: 732*25c28e83SPiotr Jasiukajtis case 0x7b0: 733*25c28e83SPiotr Jasiukajtis /* fbstp; don't bother */ 734*25c28e83SPiotr Jasiukajtis info->op = fex_other; 735*25c28e83SPiotr Jasiukajtis info->op1.type = info->res.type = fex_nodata; 736*25c28e83SPiotr Jasiukajtis info->flags = 0; 737*25c28e83SPiotr Jasiukajtis return; 738*25c28e83SPiotr Jasiukajtis 739*25c28e83SPiotr Jasiukajtis case 0x738: 740*25c28e83SPiotr Jasiukajtis case 0x778: 741*25c28e83SPiotr Jasiukajtis case 0x7b8: 742*25c28e83SPiotr Jasiukajtis info->res.type = fex_llong; 743*25c28e83SPiotr Jasiukajtis if (ex == FPE_FLTRES) { 744*25c28e83SPiotr Jasiukajtis /* inexact, stack popped */ 745*25c28e83SPiotr Jasiukajtis if (!ea) { 746*25c28e83SPiotr Jasiukajtis info->op = fex_other; 747*25c28e83SPiotr Jasiukajtis info->op1.type = info->op2.type = info->res.type = fex_nodata; 748*25c28e83SPiotr Jasiukajtis info->flags = 0; 749*25c28e83SPiotr Jasiukajtis return; 750*25c28e83SPiotr Jasiukajtis } 751*25c28e83SPiotr Jasiukajtis info->op1.type = fex_nodata; 752*25c28e83SPiotr Jasiukajtis info->res.val.l = *(long long *)ea; 753*25c28e83SPiotr Jasiukajtis info->flags = FE_INEXACT; 754*25c28e83SPiotr Jasiukajtis return; 755*25c28e83SPiotr Jasiukajtis } 756*25c28e83SPiotr Jasiukajtis info->op1.type = fex_ldouble; 757*25c28e83SPiotr Jasiukajtis info->op1.val.q = fpreg(uap, 0); 758*25c28e83SPiotr Jasiukajtis info->res.val.l = (long long) info->op1.val.q; 759*25c28e83SPiotr Jasiukajtis goto done; 760*25c28e83SPiotr Jasiukajtis } 761*25c28e83SPiotr Jasiukajtis 762*25c28e83SPiotr Jasiukajtis /* all other ops (except compares) have destinations on the stack 763*25c28e83SPiotr Jasiukajtis so overflow, underflow, and inexact will stomp their operands */ 764*25c28e83SPiotr Jasiukajtis if (ex == FPE_FLTOVF || ex == FPE_FLTUND || ex == FPE_FLTRES) { 765*25c28e83SPiotr Jasiukajtis /* find the trapped result */ 766*25c28e83SPiotr Jasiukajtis info->op1.type = info->op2.type = fex_nodata; 767*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble; 768*25c28e83SPiotr Jasiukajtis switch (op & 0x7f8) { 769*25c28e83SPiotr Jasiukajtis case 0x1f0: 770*25c28e83SPiotr Jasiukajtis /* fptan pushes 1.0 afterward, so result is in st(1) */ 771*25c28e83SPiotr Jasiukajtis info->res.val.q = ((op == 0x1f2)? fpreg(uap, 1) : 772*25c28e83SPiotr Jasiukajtis fpreg(uap, 0)); 773*25c28e83SPiotr Jasiukajtis break; 774*25c28e83SPiotr Jasiukajtis 775*25c28e83SPiotr Jasiukajtis case 0x4c0: 776*25c28e83SPiotr Jasiukajtis case 0x4c8: 777*25c28e83SPiotr Jasiukajtis case 0x4e0: 778*25c28e83SPiotr Jasiukajtis case 0x4e8: 779*25c28e83SPiotr Jasiukajtis case 0x4f0: 780*25c28e83SPiotr Jasiukajtis case 0x4f8: 781*25c28e83SPiotr Jasiukajtis info->res.val.q = fpreg(uap, op & 7); 782*25c28e83SPiotr Jasiukajtis break; 783*25c28e83SPiotr Jasiukajtis 784*25c28e83SPiotr Jasiukajtis case 0x6c0: 785*25c28e83SPiotr Jasiukajtis case 0x6c8: 786*25c28e83SPiotr Jasiukajtis case 0x6e0: 787*25c28e83SPiotr Jasiukajtis case 0x6e8: 788*25c28e83SPiotr Jasiukajtis case 0x6f0: 789*25c28e83SPiotr Jasiukajtis case 0x6f8: 790*25c28e83SPiotr Jasiukajtis /* stack was popped afterward */ 791*25c28e83SPiotr Jasiukajtis info->res.val.q = fpreg(uap, (op - 1) & 7); 792*25c28e83SPiotr Jasiukajtis break; 793*25c28e83SPiotr Jasiukajtis 794*25c28e83SPiotr Jasiukajtis default: 795*25c28e83SPiotr Jasiukajtis info->res.val.q = fpreg(uap, 0); 796*25c28e83SPiotr Jasiukajtis } 797*25c28e83SPiotr Jasiukajtis 798*25c28e83SPiotr Jasiukajtis /* reconstruct default untrapped result */ 799*25c28e83SPiotr Jasiukajtis if (ex == FPE_FLTOVF) { 800*25c28e83SPiotr Jasiukajtis /* generate an overflow with the sign of the result */ 801*25c28e83SPiotr Jasiukajtis x = two12288; 802*25c28e83SPiotr Jasiukajtis *(4+(short*)&x) |= (*(4+(short*)&info->res.val.q) & 0x8000); 803*25c28e83SPiotr Jasiukajtis info->res.val.q = x * two12288; 804*25c28e83SPiotr Jasiukajtis info->flags = FE_OVERFLOW | FE_INEXACT; 805*25c28e83SPiotr Jasiukajtis __fenv_getcwsw(&cwsw); 806*25c28e83SPiotr Jasiukajtis cwsw &= ~FE_ALL_EXCEPT; 807*25c28e83SPiotr Jasiukajtis __fenv_setcwsw(&cwsw); 808*25c28e83SPiotr Jasiukajtis } 809*25c28e83SPiotr Jasiukajtis else if (ex == FPE_FLTUND) { 810*25c28e83SPiotr Jasiukajtis /* undo the scaling; we can't distinguish a chopped result 811*25c28e83SPiotr Jasiukajtis from an exact one without futzing around to trap all in- 812*25c28e83SPiotr Jasiukajtis exact exceptions so as to keep the flag clear, so we just 813*25c28e83SPiotr Jasiukajtis punt */ 814*25c28e83SPiotr Jasiukajtis if (sw & 0x200) /* result was rounded up */ 815*25c28e83SPiotr Jasiukajtis info->res.val.q = (info->res.val.q * twom12288) * twom12288mulp; 816*25c28e83SPiotr Jasiukajtis else 817*25c28e83SPiotr Jasiukajtis info->res.val.q = (info->res.val.q * twom12288) * twom12288; 818*25c28e83SPiotr Jasiukajtis __fenv_getcwsw(&cwsw); 819*25c28e83SPiotr Jasiukajtis info->flags = (cwsw & FE_INEXACT) | FE_UNDERFLOW; 820*25c28e83SPiotr Jasiukajtis cwsw &= ~FE_ALL_EXCEPT; 821*25c28e83SPiotr Jasiukajtis __fenv_setcwsw(&cwsw); 822*25c28e83SPiotr Jasiukajtis } 823*25c28e83SPiotr Jasiukajtis else 824*25c28e83SPiotr Jasiukajtis info->flags = FE_INEXACT; 825*25c28e83SPiotr Jasiukajtis 826*25c28e83SPiotr Jasiukajtis /* determine the operation code */ 827*25c28e83SPiotr Jasiukajtis switch (op) { 828*25c28e83SPiotr Jasiukajtis case 0x1f0: /* f2xm1 */ 829*25c28e83SPiotr Jasiukajtis case 0x1f1: /* fyl2x */ 830*25c28e83SPiotr Jasiukajtis case 0x1f2: /* fptan */ 831*25c28e83SPiotr Jasiukajtis case 0x1f3: /* fpatan */ 832*25c28e83SPiotr Jasiukajtis case 0x1f5: /* fprem1 */ 833*25c28e83SPiotr Jasiukajtis case 0x1f8: /* fprem */ 834*25c28e83SPiotr Jasiukajtis case 0x1f9: /* fyl2xp1 */ 835*25c28e83SPiotr Jasiukajtis case 0x1fb: /* fsincos */ 836*25c28e83SPiotr Jasiukajtis case 0x1fc: /* frndint */ 837*25c28e83SPiotr Jasiukajtis case 0x1fd: /* fscale */ 838*25c28e83SPiotr Jasiukajtis case 0x1fe: /* fsin */ 839*25c28e83SPiotr Jasiukajtis case 0x1ff: /* fcos */ 840*25c28e83SPiotr Jasiukajtis info->op = fex_other; 841*25c28e83SPiotr Jasiukajtis return; 842*25c28e83SPiotr Jasiukajtis 843*25c28e83SPiotr Jasiukajtis case 0x1fa: /* fsqrt */ 844*25c28e83SPiotr Jasiukajtis info->op = fex_sqrt; 845*25c28e83SPiotr Jasiukajtis return; 846*25c28e83SPiotr Jasiukajtis } 847*25c28e83SPiotr Jasiukajtis 848*25c28e83SPiotr Jasiukajtis info->op = fex_other; 849*25c28e83SPiotr Jasiukajtis switch (op & 0x7c0) { 850*25c28e83SPiotr Jasiukajtis case 0x000: 851*25c28e83SPiotr Jasiukajtis case 0x040: 852*25c28e83SPiotr Jasiukajtis case 0x080: 853*25c28e83SPiotr Jasiukajtis case 0x0c0: 854*25c28e83SPiotr Jasiukajtis case 0x200: 855*25c28e83SPiotr Jasiukajtis case 0x240: 856*25c28e83SPiotr Jasiukajtis case 0x280: 857*25c28e83SPiotr Jasiukajtis case 0x400: 858*25c28e83SPiotr Jasiukajtis case 0x440: 859*25c28e83SPiotr Jasiukajtis case 0x480: 860*25c28e83SPiotr Jasiukajtis case 0x4c0: 861*25c28e83SPiotr Jasiukajtis case 0x600: 862*25c28e83SPiotr Jasiukajtis case 0x640: 863*25c28e83SPiotr Jasiukajtis case 0x680: 864*25c28e83SPiotr Jasiukajtis case 0x6c0: 865*25c28e83SPiotr Jasiukajtis switch (op & 0x38) { 866*25c28e83SPiotr Jasiukajtis case 0x00: 867*25c28e83SPiotr Jasiukajtis info->op = fex_add; 868*25c28e83SPiotr Jasiukajtis break; 869*25c28e83SPiotr Jasiukajtis 870*25c28e83SPiotr Jasiukajtis case 0x08: 871*25c28e83SPiotr Jasiukajtis info->op = fex_mul; 872*25c28e83SPiotr Jasiukajtis break; 873*25c28e83SPiotr Jasiukajtis 874*25c28e83SPiotr Jasiukajtis case 0x20: 875*25c28e83SPiotr Jasiukajtis case 0x28: 876*25c28e83SPiotr Jasiukajtis info->op = fex_sub; 877*25c28e83SPiotr Jasiukajtis break; 878*25c28e83SPiotr Jasiukajtis 879*25c28e83SPiotr Jasiukajtis case 0x30: 880*25c28e83SPiotr Jasiukajtis case 0x38: 881*25c28e83SPiotr Jasiukajtis info->op = fex_div; 882*25c28e83SPiotr Jasiukajtis break; 883*25c28e83SPiotr Jasiukajtis } 884*25c28e83SPiotr Jasiukajtis } 885*25c28e83SPiotr Jasiukajtis return; 886*25c28e83SPiotr Jasiukajtis } 887*25c28e83SPiotr Jasiukajtis 888*25c28e83SPiotr Jasiukajtis /* for other exceptions, the operands are preserved, so we can 889*25c28e83SPiotr Jasiukajtis just emulate the operation with traps disabled */ 890*25c28e83SPiotr Jasiukajtis 891*25c28e83SPiotr Jasiukajtis /* one operand is always in st */ 892*25c28e83SPiotr Jasiukajtis info->op1.type = fex_ldouble; 893*25c28e83SPiotr Jasiukajtis info->op1.val.q = fpreg(uap, 0); 894*25c28e83SPiotr Jasiukajtis 895*25c28e83SPiotr Jasiukajtis /* oddball instructions */ 896*25c28e83SPiotr Jasiukajtis info->op = fex_other; 897*25c28e83SPiotr Jasiukajtis switch (op) { 898*25c28e83SPiotr Jasiukajtis case 0x1e4: /* ftst */ 899*25c28e83SPiotr Jasiukajtis info->op = fex_cmp; 900*25c28e83SPiotr Jasiukajtis info->op2.type = fex_ldouble; 901*25c28e83SPiotr Jasiukajtis info->op2.val.q = 0.0l; 902*25c28e83SPiotr Jasiukajtis info->res.type = fex_nodata; 903*25c28e83SPiotr Jasiukajtis c = (info->op1.val.q < info->op2.val.q); 904*25c28e83SPiotr Jasiukajtis goto done; 905*25c28e83SPiotr Jasiukajtis 906*25c28e83SPiotr Jasiukajtis case 0x1f0: /* f2xm1 */ 907*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble; 908*25c28e83SPiotr Jasiukajtis info->res.val.q = f2xm1(info->op1.val.q); 909*25c28e83SPiotr Jasiukajtis goto done; 910*25c28e83SPiotr Jasiukajtis 911*25c28e83SPiotr Jasiukajtis case 0x1f1: /* fyl2x */ 912*25c28e83SPiotr Jasiukajtis info->op2.type = fex_ldouble; 913*25c28e83SPiotr Jasiukajtis info->op2.val.q = fpreg(uap, 1); 914*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble; 915*25c28e83SPiotr Jasiukajtis info->res.val.q = fyl2x(info->op1.val.q, info->op2.val.q); 916*25c28e83SPiotr Jasiukajtis goto done; 917*25c28e83SPiotr Jasiukajtis 918*25c28e83SPiotr Jasiukajtis case 0x1f2: /* fptan */ 919*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble; 920*25c28e83SPiotr Jasiukajtis info->res.val.q = fptan(info->op1.val.q); 921*25c28e83SPiotr Jasiukajtis goto done; 922*25c28e83SPiotr Jasiukajtis 923*25c28e83SPiotr Jasiukajtis case 0x1f3: /* fpatan */ 924*25c28e83SPiotr Jasiukajtis info->op2.type = fex_ldouble; 925*25c28e83SPiotr Jasiukajtis info->op2.val.q = fpreg(uap, 1); 926*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble; 927*25c28e83SPiotr Jasiukajtis info->res.val.q = fpatan(info->op1.val.q, info->op2.val.q); 928*25c28e83SPiotr Jasiukajtis goto done; 929*25c28e83SPiotr Jasiukajtis 930*25c28e83SPiotr Jasiukajtis case 0x1f4: /* fxtract */ 931*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble; 932*25c28e83SPiotr Jasiukajtis info->res.val.q = fxtract(info->op1.val.q); 933*25c28e83SPiotr Jasiukajtis goto done; 934*25c28e83SPiotr Jasiukajtis 935*25c28e83SPiotr Jasiukajtis case 0x1f5: /* fprem1 */ 936*25c28e83SPiotr Jasiukajtis info->op2.type = fex_ldouble; 937*25c28e83SPiotr Jasiukajtis info->op2.val.q = fpreg(uap, 1); 938*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble; 939*25c28e83SPiotr Jasiukajtis info->res.val.q = fprem1(info->op1.val.q, info->op2.val.q); 940*25c28e83SPiotr Jasiukajtis goto done; 941*25c28e83SPiotr Jasiukajtis 942*25c28e83SPiotr Jasiukajtis case 0x1f8: /* fprem */ 943*25c28e83SPiotr Jasiukajtis info->op2.type = fex_ldouble; 944*25c28e83SPiotr Jasiukajtis info->op2.val.q = fpreg(uap, 1); 945*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble; 946*25c28e83SPiotr Jasiukajtis info->res.val.q = fprem(info->op1.val.q, info->op2.val.q); 947*25c28e83SPiotr Jasiukajtis goto done; 948*25c28e83SPiotr Jasiukajtis 949*25c28e83SPiotr Jasiukajtis case 0x1f9: /* fyl2xp1 */ 950*25c28e83SPiotr Jasiukajtis info->op2.type = fex_ldouble; 951*25c28e83SPiotr Jasiukajtis info->op2.val.q = fpreg(uap, 1); 952*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble; 953*25c28e83SPiotr Jasiukajtis info->res.val.q = fyl2xp1(info->op1.val.q, info->op2.val.q); 954*25c28e83SPiotr Jasiukajtis goto done; 955*25c28e83SPiotr Jasiukajtis 956*25c28e83SPiotr Jasiukajtis case 0x1fa: /* fsqrt */ 957*25c28e83SPiotr Jasiukajtis info->op = fex_sqrt; 958*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble; 959*25c28e83SPiotr Jasiukajtis info->res.val.q = fsqrt(info->op1.val.q); 960*25c28e83SPiotr Jasiukajtis goto done; 961*25c28e83SPiotr Jasiukajtis 962*25c28e83SPiotr Jasiukajtis case 0x1fb: /* fsincos */ 963*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble; 964*25c28e83SPiotr Jasiukajtis info->res.val.q = fsincos(info->op1.val.q); 965*25c28e83SPiotr Jasiukajtis goto done; 966*25c28e83SPiotr Jasiukajtis 967*25c28e83SPiotr Jasiukajtis case 0x1fc: /* frndint */ 968*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble; 969*25c28e83SPiotr Jasiukajtis info->res.val.q = frndint(info->op1.val.q); 970*25c28e83SPiotr Jasiukajtis goto done; 971*25c28e83SPiotr Jasiukajtis 972*25c28e83SPiotr Jasiukajtis case 0x1fd: /* fscale */ 973*25c28e83SPiotr Jasiukajtis info->op2.type = fex_ldouble; 974*25c28e83SPiotr Jasiukajtis info->op2.val.q = fpreg(uap, 1); 975*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble; 976*25c28e83SPiotr Jasiukajtis info->res.val.q = fscale(info->op1.val.q, info->op2.val.q); 977*25c28e83SPiotr Jasiukajtis goto done; 978*25c28e83SPiotr Jasiukajtis 979*25c28e83SPiotr Jasiukajtis case 0x1fe: /* fsin */ 980*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble; 981*25c28e83SPiotr Jasiukajtis info->res.val.q = fsin(info->op1.val.q); 982*25c28e83SPiotr Jasiukajtis goto done; 983*25c28e83SPiotr Jasiukajtis 984*25c28e83SPiotr Jasiukajtis case 0x1ff: /* fcos */ 985*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble; 986*25c28e83SPiotr Jasiukajtis info->res.val.q = fcos(info->op1.val.q); 987*25c28e83SPiotr Jasiukajtis goto done; 988*25c28e83SPiotr Jasiukajtis 989*25c28e83SPiotr Jasiukajtis case 0x2e9: /* fucompp */ 990*25c28e83SPiotr Jasiukajtis info->op = fex_cmp; 991*25c28e83SPiotr Jasiukajtis info->op2.type = fex_ldouble; 992*25c28e83SPiotr Jasiukajtis info->op2.val.q = fpreg(uap, 1); 993*25c28e83SPiotr Jasiukajtis info->res.type = fex_nodata; 994*25c28e83SPiotr Jasiukajtis c = (info->op1.val.q == info->op2.val.q); 995*25c28e83SPiotr Jasiukajtis goto done; 996*25c28e83SPiotr Jasiukajtis } 997*25c28e83SPiotr Jasiukajtis 998*25c28e83SPiotr Jasiukajtis /* fucom[p], fcomi[p], fucomi[p] */ 999*25c28e83SPiotr Jasiukajtis switch (op & 0x7f8) { 1000*25c28e83SPiotr Jasiukajtis case 0x3e8: 1001*25c28e83SPiotr Jasiukajtis case 0x5e0: 1002*25c28e83SPiotr Jasiukajtis case 0x5e8: 1003*25c28e83SPiotr Jasiukajtis case 0x7e8: /* unordered compares */ 1004*25c28e83SPiotr Jasiukajtis info->op = fex_cmp; 1005*25c28e83SPiotr Jasiukajtis info->op2.type = fex_ldouble; 1006*25c28e83SPiotr Jasiukajtis info->op2.val.q = fpreg(uap, op & 7); 1007*25c28e83SPiotr Jasiukajtis info->res.type = fex_nodata; 1008*25c28e83SPiotr Jasiukajtis c = (info->op1.val.q == info->op2.val.q); 1009*25c28e83SPiotr Jasiukajtis goto done; 1010*25c28e83SPiotr Jasiukajtis 1011*25c28e83SPiotr Jasiukajtis case 0x3f0: 1012*25c28e83SPiotr Jasiukajtis case 0x7f0: /* ordered compares */ 1013*25c28e83SPiotr Jasiukajtis info->op = fex_cmp; 1014*25c28e83SPiotr Jasiukajtis info->op2.type = fex_ldouble; 1015*25c28e83SPiotr Jasiukajtis info->op2.val.q = fpreg(uap, op & 7); 1016*25c28e83SPiotr Jasiukajtis info->res.type = fex_nodata; 1017*25c28e83SPiotr Jasiukajtis c = (info->op1.val.q < info->op2.val.q); 1018*25c28e83SPiotr Jasiukajtis goto done; 1019*25c28e83SPiotr Jasiukajtis } 1020*25c28e83SPiotr Jasiukajtis 1021*25c28e83SPiotr Jasiukajtis /* all other instructions come in groups of the form 1022*25c28e83SPiotr Jasiukajtis fadd, fmul, fcom, fcomp, fsub, fsubr, fdiv, fdivr */ 1023*25c28e83SPiotr Jasiukajtis 1024*25c28e83SPiotr Jasiukajtis /* get the second operand */ 1025*25c28e83SPiotr Jasiukajtis switch (op & 0x7c0) { 1026*25c28e83SPiotr Jasiukajtis case 0x000: 1027*25c28e83SPiotr Jasiukajtis case 0x040: 1028*25c28e83SPiotr Jasiukajtis case 0x080: 1029*25c28e83SPiotr Jasiukajtis if (!ea) { 1030*25c28e83SPiotr Jasiukajtis info->op = fex_other; 1031*25c28e83SPiotr Jasiukajtis info->op1.type = info->op2.type = info->res.type = fex_nodata; 1032*25c28e83SPiotr Jasiukajtis info->flags = 0; 1033*25c28e83SPiotr Jasiukajtis return; 1034*25c28e83SPiotr Jasiukajtis } 1035*25c28e83SPiotr Jasiukajtis info->op2.type = fex_float; 1036*25c28e83SPiotr Jasiukajtis info->op2.val.f = *(float *)ea; 1037*25c28e83SPiotr Jasiukajtis op2v = (long double) info->op2.val.f; 1038*25c28e83SPiotr Jasiukajtis break; 1039*25c28e83SPiotr Jasiukajtis 1040*25c28e83SPiotr Jasiukajtis case 0x0c0: 1041*25c28e83SPiotr Jasiukajtis info->op2.type = fex_ldouble; 1042*25c28e83SPiotr Jasiukajtis op2v = info->op2.val.q = fpreg(uap, op & 7); 1043*25c28e83SPiotr Jasiukajtis break; 1044*25c28e83SPiotr Jasiukajtis 1045*25c28e83SPiotr Jasiukajtis case 0x200: 1046*25c28e83SPiotr Jasiukajtis case 0x240: 1047*25c28e83SPiotr Jasiukajtis case 0x280: 1048*25c28e83SPiotr Jasiukajtis if (!ea) { 1049*25c28e83SPiotr Jasiukajtis info->op = fex_other; 1050*25c28e83SPiotr Jasiukajtis info->op1.type = info->op2.type = info->res.type = fex_nodata; 1051*25c28e83SPiotr Jasiukajtis info->flags = 0; 1052*25c28e83SPiotr Jasiukajtis return; 1053*25c28e83SPiotr Jasiukajtis } 1054*25c28e83SPiotr Jasiukajtis info->op2.type = fex_int; 1055*25c28e83SPiotr Jasiukajtis info->op2.val.i = *(int *)ea; 1056*25c28e83SPiotr Jasiukajtis op2v = (long double) info->op2.val.i; 1057*25c28e83SPiotr Jasiukajtis break; 1058*25c28e83SPiotr Jasiukajtis 1059*25c28e83SPiotr Jasiukajtis case 0x400: 1060*25c28e83SPiotr Jasiukajtis case 0x440: 1061*25c28e83SPiotr Jasiukajtis case 0x480: 1062*25c28e83SPiotr Jasiukajtis if (!ea) { 1063*25c28e83SPiotr Jasiukajtis info->op = fex_other; 1064*25c28e83SPiotr Jasiukajtis info->op1.type = info->op2.type = info->res.type = fex_nodata; 1065*25c28e83SPiotr Jasiukajtis info->flags = 0; 1066*25c28e83SPiotr Jasiukajtis return; 1067*25c28e83SPiotr Jasiukajtis } 1068*25c28e83SPiotr Jasiukajtis info->op2.type = fex_double; 1069*25c28e83SPiotr Jasiukajtis info->op2.val.d = *(double *)ea; 1070*25c28e83SPiotr Jasiukajtis op2v = (long double) info->op2.val.d; 1071*25c28e83SPiotr Jasiukajtis break; 1072*25c28e83SPiotr Jasiukajtis 1073*25c28e83SPiotr Jasiukajtis case 0x4c0: 1074*25c28e83SPiotr Jasiukajtis case 0x6c0: 1075*25c28e83SPiotr Jasiukajtis info->op2.type = fex_ldouble; 1076*25c28e83SPiotr Jasiukajtis info->op2.val.q = fpreg(uap, op & 7); 1077*25c28e83SPiotr Jasiukajtis t = info->op1; 1078*25c28e83SPiotr Jasiukajtis info->op1 = info->op2; 1079*25c28e83SPiotr Jasiukajtis info->op2 = t; 1080*25c28e83SPiotr Jasiukajtis op2v = info->op2.val.q; 1081*25c28e83SPiotr Jasiukajtis break; 1082*25c28e83SPiotr Jasiukajtis 1083*25c28e83SPiotr Jasiukajtis case 0x600: 1084*25c28e83SPiotr Jasiukajtis case 0x640: 1085*25c28e83SPiotr Jasiukajtis case 0x680: 1086*25c28e83SPiotr Jasiukajtis if (!ea) { 1087*25c28e83SPiotr Jasiukajtis info->op = fex_other; 1088*25c28e83SPiotr Jasiukajtis info->op1.type = info->op2.type = info->res.type = fex_nodata; 1089*25c28e83SPiotr Jasiukajtis info->flags = 0; 1090*25c28e83SPiotr Jasiukajtis return; 1091*25c28e83SPiotr Jasiukajtis } 1092*25c28e83SPiotr Jasiukajtis info->op2.type = fex_int; 1093*25c28e83SPiotr Jasiukajtis info->op2.val.i = *(short *)ea; 1094*25c28e83SPiotr Jasiukajtis op2v = (long double) info->op2.val.i; 1095*25c28e83SPiotr Jasiukajtis break; 1096*25c28e83SPiotr Jasiukajtis 1097*25c28e83SPiotr Jasiukajtis default: 1098*25c28e83SPiotr Jasiukajtis info->op = fex_other; 1099*25c28e83SPiotr Jasiukajtis info->op1.type = info->op2.type = info->res.type = fex_nodata; 1100*25c28e83SPiotr Jasiukajtis info->flags = 0; 1101*25c28e83SPiotr Jasiukajtis return; 1102*25c28e83SPiotr Jasiukajtis } 1103*25c28e83SPiotr Jasiukajtis 1104*25c28e83SPiotr Jasiukajtis /* distinguish different operations in the group */ 1105*25c28e83SPiotr Jasiukajtis info->res.type = fex_ldouble; 1106*25c28e83SPiotr Jasiukajtis switch (op & 0x38) { 1107*25c28e83SPiotr Jasiukajtis case 0x00: 1108*25c28e83SPiotr Jasiukajtis info->op = fex_add; 1109*25c28e83SPiotr Jasiukajtis info->res.val.q = info->op1.val.q + op2v; 1110*25c28e83SPiotr Jasiukajtis break; 1111*25c28e83SPiotr Jasiukajtis 1112*25c28e83SPiotr Jasiukajtis case 0x08: 1113*25c28e83SPiotr Jasiukajtis info->op = fex_mul; 1114*25c28e83SPiotr Jasiukajtis info->res.val.q = info->op1.val.q * op2v; 1115*25c28e83SPiotr Jasiukajtis break; 1116*25c28e83SPiotr Jasiukajtis 1117*25c28e83SPiotr Jasiukajtis case 0x10: 1118*25c28e83SPiotr Jasiukajtis case 0x18: 1119*25c28e83SPiotr Jasiukajtis info->op = fex_cmp; 1120*25c28e83SPiotr Jasiukajtis info->res.type = fex_nodata; 1121*25c28e83SPiotr Jasiukajtis c = (info->op1.val.q < op2v); 1122*25c28e83SPiotr Jasiukajtis break; 1123*25c28e83SPiotr Jasiukajtis 1124*25c28e83SPiotr Jasiukajtis case 0x20: 1125*25c28e83SPiotr Jasiukajtis info->op = fex_sub; 1126*25c28e83SPiotr Jasiukajtis info->res.val.q = info->op1.val.q - op2v; 1127*25c28e83SPiotr Jasiukajtis break; 1128*25c28e83SPiotr Jasiukajtis 1129*25c28e83SPiotr Jasiukajtis case 0x28: 1130*25c28e83SPiotr Jasiukajtis info->op = fex_sub; 1131*25c28e83SPiotr Jasiukajtis info->res.val.q = op2v - info->op1.val.q; 1132*25c28e83SPiotr Jasiukajtis t = info->op1; 1133*25c28e83SPiotr Jasiukajtis info->op1 = info->op2; 1134*25c28e83SPiotr Jasiukajtis info->op2 = t; 1135*25c28e83SPiotr Jasiukajtis break; 1136*25c28e83SPiotr Jasiukajtis 1137*25c28e83SPiotr Jasiukajtis case 0x30: 1138*25c28e83SPiotr Jasiukajtis info->op = fex_div; 1139*25c28e83SPiotr Jasiukajtis info->res.val.q = info->op1.val.q / op2v; 1140*25c28e83SPiotr Jasiukajtis break; 1141*25c28e83SPiotr Jasiukajtis 1142*25c28e83SPiotr Jasiukajtis case 0x38: 1143*25c28e83SPiotr Jasiukajtis info->op = fex_div; 1144*25c28e83SPiotr Jasiukajtis info->res.val.q = op2v / info->op1.val.q; 1145*25c28e83SPiotr Jasiukajtis t = info->op1; 1146*25c28e83SPiotr Jasiukajtis info->op1 = info->op2; 1147*25c28e83SPiotr Jasiukajtis info->op2 = t; 1148*25c28e83SPiotr Jasiukajtis break; 1149*25c28e83SPiotr Jasiukajtis 1150*25c28e83SPiotr Jasiukajtis default: 1151*25c28e83SPiotr Jasiukajtis info->op = fex_other; 1152*25c28e83SPiotr Jasiukajtis info->op1.type = info->op2.type = info->res.type = fex_nodata; 1153*25c28e83SPiotr Jasiukajtis info->flags = 0; 1154*25c28e83SPiotr Jasiukajtis return; 1155*25c28e83SPiotr Jasiukajtis } 1156*25c28e83SPiotr Jasiukajtis 1157*25c28e83SPiotr Jasiukajtis done: 1158*25c28e83SPiotr Jasiukajtis __fenv_getcwsw(&cwsw); 1159*25c28e83SPiotr Jasiukajtis info->flags = cwsw & FE_ALL_EXCEPT; 1160*25c28e83SPiotr Jasiukajtis cwsw &= ~FE_ALL_EXCEPT; 1161*25c28e83SPiotr Jasiukajtis __fenv_setcwsw(&cwsw); 1162*25c28e83SPiotr Jasiukajtis } 1163*25c28e83SPiotr Jasiukajtis 1164*25c28e83SPiotr Jasiukajtis /* pop the saved stack */ 1165*25c28e83SPiotr Jasiukajtis static void pop(ucontext_t *uap) 1166*25c28e83SPiotr Jasiukajtis { 1167*25c28e83SPiotr Jasiukajtis unsigned top; 1168*25c28e83SPiotr Jasiukajtis 1169*25c28e83SPiotr Jasiukajtis fpreg(uap, 0) = fpreg(uap, 1); 1170*25c28e83SPiotr Jasiukajtis fpreg(uap, 1) = fpreg(uap, 2); 1171*25c28e83SPiotr Jasiukajtis fpreg(uap, 2) = fpreg(uap, 3); 1172*25c28e83SPiotr Jasiukajtis fpreg(uap, 3) = fpreg(uap, 4); 1173*25c28e83SPiotr Jasiukajtis fpreg(uap, 4) = fpreg(uap, 5); 1174*25c28e83SPiotr Jasiukajtis fpreg(uap, 5) = fpreg(uap, 6); 1175*25c28e83SPiotr Jasiukajtis fpreg(uap, 6) = fpreg(uap, 7); 1176*25c28e83SPiotr Jasiukajtis #if defined(__amd64) 1177*25c28e83SPiotr Jasiukajtis top = (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw >> 10) 1178*25c28e83SPiotr Jasiukajtis & 0xe; 1179*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.fctw |= (3 << top); 1180*25c28e83SPiotr Jasiukajtis top = (top + 2) & 0xe; 1181*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw = 1182*25c28e83SPiotr Jasiukajtis (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw & ~0x3800) 1183*25c28e83SPiotr Jasiukajtis | (top << 10); 1184*25c28e83SPiotr Jasiukajtis #else 1185*25c28e83SPiotr Jasiukajtis top = (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] >> 10) 1186*25c28e83SPiotr Jasiukajtis & 0xe; 1187*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[TW] |= (3 << top); 1188*25c28e83SPiotr Jasiukajtis top = (top + 2) & 0xe; 1189*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] = 1190*25c28e83SPiotr Jasiukajtis (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] & ~0x3800) 1191*25c28e83SPiotr Jasiukajtis | (top << 10); 1192*25c28e83SPiotr Jasiukajtis #endif 1193*25c28e83SPiotr Jasiukajtis } 1194*25c28e83SPiotr Jasiukajtis 1195*25c28e83SPiotr Jasiukajtis /* push x onto the saved stack */ 1196*25c28e83SPiotr Jasiukajtis static void push(long double x, ucontext_t *uap) 1197*25c28e83SPiotr Jasiukajtis { 1198*25c28e83SPiotr Jasiukajtis unsigned top; 1199*25c28e83SPiotr Jasiukajtis 1200*25c28e83SPiotr Jasiukajtis fpreg(uap, 7) = fpreg(uap, 6); 1201*25c28e83SPiotr Jasiukajtis fpreg(uap, 6) = fpreg(uap, 5); 1202*25c28e83SPiotr Jasiukajtis fpreg(uap, 5) = fpreg(uap, 4); 1203*25c28e83SPiotr Jasiukajtis fpreg(uap, 4) = fpreg(uap, 3); 1204*25c28e83SPiotr Jasiukajtis fpreg(uap, 3) = fpreg(uap, 2); 1205*25c28e83SPiotr Jasiukajtis fpreg(uap, 2) = fpreg(uap, 1); 1206*25c28e83SPiotr Jasiukajtis fpreg(uap, 1) = fpreg(uap, 0); 1207*25c28e83SPiotr Jasiukajtis fpreg(uap, 0) = x; 1208*25c28e83SPiotr Jasiukajtis #if defined(__amd64) 1209*25c28e83SPiotr Jasiukajtis top = (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw >> 10) 1210*25c28e83SPiotr Jasiukajtis & 0xe; 1211*25c28e83SPiotr Jasiukajtis top = (top - 2) & 0xe; 1212*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.fctw &= ~(3 << top); 1213*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw = 1214*25c28e83SPiotr Jasiukajtis (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw & ~0x3800) 1215*25c28e83SPiotr Jasiukajtis | (top << 10); 1216*25c28e83SPiotr Jasiukajtis #else 1217*25c28e83SPiotr Jasiukajtis top = (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] >> 10) 1218*25c28e83SPiotr Jasiukajtis & 0xe; 1219*25c28e83SPiotr Jasiukajtis top = (top - 2) & 0xe; 1220*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[TW] &= ~(3 << top); 1221*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] = 1222*25c28e83SPiotr Jasiukajtis (uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] & ~0x3800) 1223*25c28e83SPiotr Jasiukajtis | (top << 10); 1224*25c28e83SPiotr Jasiukajtis #endif 1225*25c28e83SPiotr Jasiukajtis } 1226*25c28e83SPiotr Jasiukajtis 1227*25c28e83SPiotr Jasiukajtis /* scale factors for exponent wrapping */ 1228*25c28e83SPiotr Jasiukajtis static const float 1229*25c28e83SPiotr Jasiukajtis fun = 7.922816251e+28f, /* 2^96 */ 1230*25c28e83SPiotr Jasiukajtis fov = 1.262177448e-29f; /* 2^-96 */ 1231*25c28e83SPiotr Jasiukajtis static const double 1232*25c28e83SPiotr Jasiukajtis dun = 1.552518092300708935e+231, /* 2^768 */ 1233*25c28e83SPiotr Jasiukajtis dov = 6.441148769597133308e-232; /* 2^-768 */ 1234*25c28e83SPiotr Jasiukajtis 1235*25c28e83SPiotr Jasiukajtis /* 1236*25c28e83SPiotr Jasiukajtis * Store the specified result; if no result is given but the exception 1237*25c28e83SPiotr Jasiukajtis * is underflow or overflow, use the default trapped result 1238*25c28e83SPiotr Jasiukajtis */ 1239*25c28e83SPiotr Jasiukajtis void 1240*25c28e83SPiotr Jasiukajtis __fex_st_result(siginfo_t *sip, ucontext_t *uap, fex_info_t *info) 1241*25c28e83SPiotr Jasiukajtis { 1242*25c28e83SPiotr Jasiukajtis fex_numeric_t r; 1243*25c28e83SPiotr Jasiukajtis unsigned long ex, op, ea, stack; 1244*25c28e83SPiotr Jasiukajtis 1245*25c28e83SPiotr Jasiukajtis /* get the exception type, opcode, and data address */ 1246*25c28e83SPiotr Jasiukajtis ex = sip->si_code; 1247*25c28e83SPiotr Jasiukajtis #if defined(__amd64) 1248*25c28e83SPiotr Jasiukajtis op = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.fop >> 16; 1249*25c28e83SPiotr Jasiukajtis ea = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.rdp; /*???*/ 1250*25c28e83SPiotr Jasiukajtis #else 1251*25c28e83SPiotr Jasiukajtis op = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[OP] >> 16; 1252*25c28e83SPiotr Jasiukajtis ea = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[EA]; 1253*25c28e83SPiotr Jasiukajtis #endif 1254*25c28e83SPiotr Jasiukajtis 1255*25c28e83SPiotr Jasiukajtis /* if the instruction is a compare, set the condition codes 1256*25c28e83SPiotr Jasiukajtis to unordered and update the stack */ 1257*25c28e83SPiotr Jasiukajtis switch (op & 0x7f8) { 1258*25c28e83SPiotr Jasiukajtis case 0x010: 1259*25c28e83SPiotr Jasiukajtis case 0x050: 1260*25c28e83SPiotr Jasiukajtis case 0x090: 1261*25c28e83SPiotr Jasiukajtis case 0x0d0: 1262*25c28e83SPiotr Jasiukajtis case 0x210: 1263*25c28e83SPiotr Jasiukajtis case 0x250: 1264*25c28e83SPiotr Jasiukajtis case 0x290: 1265*25c28e83SPiotr Jasiukajtis case 0x410: 1266*25c28e83SPiotr Jasiukajtis case 0x450: 1267*25c28e83SPiotr Jasiukajtis case 0x490: 1268*25c28e83SPiotr Jasiukajtis case 0x4d0: 1269*25c28e83SPiotr Jasiukajtis case 0x5e0: 1270*25c28e83SPiotr Jasiukajtis case 0x610: 1271*25c28e83SPiotr Jasiukajtis case 0x650: 1272*25c28e83SPiotr Jasiukajtis case 0x690: 1273*25c28e83SPiotr Jasiukajtis /* f[u]com */ 1274*25c28e83SPiotr Jasiukajtis #if defined(__amd64) 1275*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw |= 0x4500; 1276*25c28e83SPiotr Jasiukajtis #else 1277*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] |= 0x4500; 1278*25c28e83SPiotr Jasiukajtis #endif 1279*25c28e83SPiotr Jasiukajtis return; 1280*25c28e83SPiotr Jasiukajtis 1281*25c28e83SPiotr Jasiukajtis case 0x018: 1282*25c28e83SPiotr Jasiukajtis case 0x058: 1283*25c28e83SPiotr Jasiukajtis case 0x098: 1284*25c28e83SPiotr Jasiukajtis case 0x0d8: 1285*25c28e83SPiotr Jasiukajtis case 0x218: 1286*25c28e83SPiotr Jasiukajtis case 0x258: 1287*25c28e83SPiotr Jasiukajtis case 0x298: 1288*25c28e83SPiotr Jasiukajtis case 0x418: 1289*25c28e83SPiotr Jasiukajtis case 0x458: 1290*25c28e83SPiotr Jasiukajtis case 0x498: 1291*25c28e83SPiotr Jasiukajtis case 0x4d8: 1292*25c28e83SPiotr Jasiukajtis case 0x5e8: 1293*25c28e83SPiotr Jasiukajtis case 0x618: 1294*25c28e83SPiotr Jasiukajtis case 0x658: 1295*25c28e83SPiotr Jasiukajtis case 0x698: 1296*25c28e83SPiotr Jasiukajtis case 0x6d0: 1297*25c28e83SPiotr Jasiukajtis /* f[u]comp */ 1298*25c28e83SPiotr Jasiukajtis #if defined(__amd64) 1299*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw |= 0x4500; 1300*25c28e83SPiotr Jasiukajtis #else 1301*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] |= 0x4500; 1302*25c28e83SPiotr Jasiukajtis #endif 1303*25c28e83SPiotr Jasiukajtis pop(uap); 1304*25c28e83SPiotr Jasiukajtis return; 1305*25c28e83SPiotr Jasiukajtis 1306*25c28e83SPiotr Jasiukajtis case 0x2e8: 1307*25c28e83SPiotr Jasiukajtis case 0x6d8: 1308*25c28e83SPiotr Jasiukajtis /* f[u]compp */ 1309*25c28e83SPiotr Jasiukajtis #if defined(__amd64) 1310*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw |= 0x4500; 1311*25c28e83SPiotr Jasiukajtis #else 1312*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] |= 0x4500; 1313*25c28e83SPiotr Jasiukajtis #endif 1314*25c28e83SPiotr Jasiukajtis pop(uap); 1315*25c28e83SPiotr Jasiukajtis pop(uap); 1316*25c28e83SPiotr Jasiukajtis return; 1317*25c28e83SPiotr Jasiukajtis 1318*25c28e83SPiotr Jasiukajtis case 0x1e0: 1319*25c28e83SPiotr Jasiukajtis if (op == 0x1e4) { /* ftst */ 1320*25c28e83SPiotr Jasiukajtis #if defined(__amd64) 1321*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw |= 0x4500; 1322*25c28e83SPiotr Jasiukajtis #else 1323*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[SW] |= 0x4500; 1324*25c28e83SPiotr Jasiukajtis #endif 1325*25c28e83SPiotr Jasiukajtis return; 1326*25c28e83SPiotr Jasiukajtis } 1327*25c28e83SPiotr Jasiukajtis break; 1328*25c28e83SPiotr Jasiukajtis 1329*25c28e83SPiotr Jasiukajtis case 0x3e8: 1330*25c28e83SPiotr Jasiukajtis case 0x3f0: 1331*25c28e83SPiotr Jasiukajtis /* f[u]comi */ 1332*25c28e83SPiotr Jasiukajtis #if defined(__amd64) 1333*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.gregs[REG_PS] |= 0x45; 1334*25c28e83SPiotr Jasiukajtis #else 1335*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.gregs[EFL] |= 0x45; 1336*25c28e83SPiotr Jasiukajtis #endif 1337*25c28e83SPiotr Jasiukajtis return; 1338*25c28e83SPiotr Jasiukajtis 1339*25c28e83SPiotr Jasiukajtis case 0x7e8: 1340*25c28e83SPiotr Jasiukajtis case 0x7f0: 1341*25c28e83SPiotr Jasiukajtis /* f[u]comip */ 1342*25c28e83SPiotr Jasiukajtis #if defined(__amd64) 1343*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.gregs[REG_PS] |= 0x45; 1344*25c28e83SPiotr Jasiukajtis #else 1345*25c28e83SPiotr Jasiukajtis uap->uc_mcontext.gregs[EFL] |= 0x45; 1346*25c28e83SPiotr Jasiukajtis #endif 1347*25c28e83SPiotr Jasiukajtis pop(uap); 1348*25c28e83SPiotr Jasiukajtis return; 1349*25c28e83SPiotr Jasiukajtis } 1350*25c28e83SPiotr Jasiukajtis 1351*25c28e83SPiotr Jasiukajtis /* if there is no result available and the exception is overflow 1352*25c28e83SPiotr Jasiukajtis or underflow, use the wrapped result */ 1353*25c28e83SPiotr Jasiukajtis r = info->res; 1354*25c28e83SPiotr Jasiukajtis if (r.type == fex_nodata) { 1355*25c28e83SPiotr Jasiukajtis if (ex == FPE_FLTOVF || ex == FPE_FLTUND) { 1356*25c28e83SPiotr Jasiukajtis /* for store instructions, do the scaling and store */ 1357*25c28e83SPiotr Jasiukajtis switch (op & 0x7f8) { 1358*25c28e83SPiotr Jasiukajtis case 0x110: 1359*25c28e83SPiotr Jasiukajtis case 0x118: 1360*25c28e83SPiotr Jasiukajtis case 0x150: 1361*25c28e83SPiotr Jasiukajtis case 0x158: 1362*25c28e83SPiotr Jasiukajtis case 0x190: 1363*25c28e83SPiotr Jasiukajtis case 0x198: 1364*25c28e83SPiotr Jasiukajtis if (!ea) 1365*25c28e83SPiotr Jasiukajtis return; 1366*25c28e83SPiotr Jasiukajtis if (ex == FPE_FLTOVF) 1367*25c28e83SPiotr Jasiukajtis *(float *)ea = (fpreg(uap, 0) * fov) * fov; 1368*25c28e83SPiotr Jasiukajtis else 1369*25c28e83SPiotr Jasiukajtis *(float *)ea = (fpreg(uap, 0) * fun) * fun; 1370*25c28e83SPiotr Jasiukajtis if ((op & 8) != 0) 1371*25c28e83SPiotr Jasiukajtis pop(uap); 1372*25c28e83SPiotr Jasiukajtis break; 1373*25c28e83SPiotr Jasiukajtis 1374*25c28e83SPiotr Jasiukajtis case 0x510: 1375*25c28e83SPiotr Jasiukajtis case 0x518: 1376*25c28e83SPiotr Jasiukajtis case 0x550: 1377*25c28e83SPiotr Jasiukajtis case 0x558: 1378*25c28e83SPiotr Jasiukajtis case 0x590: 1379*25c28e83SPiotr Jasiukajtis case 0x598: 1380*25c28e83SPiotr Jasiukajtis if (!ea) 1381*25c28e83SPiotr Jasiukajtis return; 1382*25c28e83SPiotr Jasiukajtis if (ex == FPE_FLTOVF) 1383*25c28e83SPiotr Jasiukajtis *(double *)ea = (fpreg(uap, 0) * dov) * dov; 1384*25c28e83SPiotr Jasiukajtis else 1385*25c28e83SPiotr Jasiukajtis *(double *)ea = (fpreg(uap, 0) * dun) * dun; 1386*25c28e83SPiotr Jasiukajtis if ((op & 8) != 0) 1387*25c28e83SPiotr Jasiukajtis pop(uap); 1388*25c28e83SPiotr Jasiukajtis break; 1389*25c28e83SPiotr Jasiukajtis } 1390*25c28e83SPiotr Jasiukajtis } 1391*25c28e83SPiotr Jasiukajtis #ifdef DEBUG 1392*25c28e83SPiotr Jasiukajtis else if (ex != FPE_FLTRES) 1393*25c28e83SPiotr Jasiukajtis printf("No result supplied, stack may be hosed\n"); 1394*25c28e83SPiotr Jasiukajtis #endif 1395*25c28e83SPiotr Jasiukajtis return; 1396*25c28e83SPiotr Jasiukajtis } 1397*25c28e83SPiotr Jasiukajtis 1398*25c28e83SPiotr Jasiukajtis /* otherwise convert the supplied result to the correct type, 1399*25c28e83SPiotr Jasiukajtis put it in the destination, and update the stack as need be */ 1400*25c28e83SPiotr Jasiukajtis 1401*25c28e83SPiotr Jasiukajtis /* store instructions */ 1402*25c28e83SPiotr Jasiukajtis switch (op & 0x7f8) { 1403*25c28e83SPiotr Jasiukajtis case 0x110: 1404*25c28e83SPiotr Jasiukajtis case 0x118: 1405*25c28e83SPiotr Jasiukajtis case 0x150: 1406*25c28e83SPiotr Jasiukajtis case 0x158: 1407*25c28e83SPiotr Jasiukajtis case 0x190: 1408*25c28e83SPiotr Jasiukajtis case 0x198: 1409*25c28e83SPiotr Jasiukajtis if (!ea) 1410*25c28e83SPiotr Jasiukajtis return; 1411*25c28e83SPiotr Jasiukajtis switch (r.type) { 1412*25c28e83SPiotr Jasiukajtis case fex_int: 1413*25c28e83SPiotr Jasiukajtis *(float *)ea = (float) r.val.i; 1414*25c28e83SPiotr Jasiukajtis break; 1415*25c28e83SPiotr Jasiukajtis 1416*25c28e83SPiotr Jasiukajtis case fex_llong: 1417*25c28e83SPiotr Jasiukajtis *(float *)ea = (float) r.val.l; 1418*25c28e83SPiotr Jasiukajtis break; 1419*25c28e83SPiotr Jasiukajtis 1420*25c28e83SPiotr Jasiukajtis case fex_float: 1421*25c28e83SPiotr Jasiukajtis *(float *)ea = r.val.f; 1422*25c28e83SPiotr Jasiukajtis break; 1423*25c28e83SPiotr Jasiukajtis 1424*25c28e83SPiotr Jasiukajtis case fex_double: 1425*25c28e83SPiotr Jasiukajtis *(float *)ea = (float) r.val.d; 1426*25c28e83SPiotr Jasiukajtis break; 1427*25c28e83SPiotr Jasiukajtis 1428*25c28e83SPiotr Jasiukajtis case fex_ldouble: 1429*25c28e83SPiotr Jasiukajtis *(float *)ea = (float) r.val.q; 1430*25c28e83SPiotr Jasiukajtis break; 1431*25c28e83SPiotr Jasiukajtis 1432*25c28e83SPiotr Jasiukajtis default: 1433*25c28e83SPiotr Jasiukajtis break; 1434*25c28e83SPiotr Jasiukajtis } 1435*25c28e83SPiotr Jasiukajtis if (ex != FPE_FLTRES && (op & 8) != 0) 1436*25c28e83SPiotr Jasiukajtis pop(uap); 1437*25c28e83SPiotr Jasiukajtis return; 1438*25c28e83SPiotr Jasiukajtis 1439*25c28e83SPiotr Jasiukajtis case 0x310: 1440*25c28e83SPiotr Jasiukajtis case 0x318: 1441*25c28e83SPiotr Jasiukajtis case 0x350: 1442*25c28e83SPiotr Jasiukajtis case 0x358: 1443*25c28e83SPiotr Jasiukajtis case 0x390: 1444*25c28e83SPiotr Jasiukajtis case 0x398: 1445*25c28e83SPiotr Jasiukajtis if (!ea) 1446*25c28e83SPiotr Jasiukajtis return; 1447*25c28e83SPiotr Jasiukajtis switch (r.type) { 1448*25c28e83SPiotr Jasiukajtis case fex_int: 1449*25c28e83SPiotr Jasiukajtis *(int *)ea = r.val.i; 1450*25c28e83SPiotr Jasiukajtis break; 1451*25c28e83SPiotr Jasiukajtis 1452*25c28e83SPiotr Jasiukajtis case fex_llong: 1453*25c28e83SPiotr Jasiukajtis *(int *)ea = (int) r.val.l; 1454*25c28e83SPiotr Jasiukajtis break; 1455*25c28e83SPiotr Jasiukajtis 1456*25c28e83SPiotr Jasiukajtis case fex_float: 1457*25c28e83SPiotr Jasiukajtis *(int *)ea = (int) r.val.f; 1458*25c28e83SPiotr Jasiukajtis break; 1459*25c28e83SPiotr Jasiukajtis 1460*25c28e83SPiotr Jasiukajtis case fex_double: 1461*25c28e83SPiotr Jasiukajtis *(int *)ea = (int) r.val.d; 1462*25c28e83SPiotr Jasiukajtis break; 1463*25c28e83SPiotr Jasiukajtis 1464*25c28e83SPiotr Jasiukajtis case fex_ldouble: 1465*25c28e83SPiotr Jasiukajtis *(int *)ea = (int) r.val.q; 1466*25c28e83SPiotr Jasiukajtis break; 1467*25c28e83SPiotr Jasiukajtis 1468*25c28e83SPiotr Jasiukajtis default: 1469*25c28e83SPiotr Jasiukajtis break; 1470*25c28e83SPiotr Jasiukajtis } 1471*25c28e83SPiotr Jasiukajtis if (ex != FPE_FLTRES && (op & 8) != 0) 1472*25c28e83SPiotr Jasiukajtis pop(uap); 1473*25c28e83SPiotr Jasiukajtis return; 1474*25c28e83SPiotr Jasiukajtis 1475*25c28e83SPiotr Jasiukajtis case 0x510: 1476*25c28e83SPiotr Jasiukajtis case 0x518: 1477*25c28e83SPiotr Jasiukajtis case 0x550: 1478*25c28e83SPiotr Jasiukajtis case 0x558: 1479*25c28e83SPiotr Jasiukajtis case 0x590: 1480*25c28e83SPiotr Jasiukajtis case 0x598: 1481*25c28e83SPiotr Jasiukajtis if (!ea) 1482*25c28e83SPiotr Jasiukajtis return; 1483*25c28e83SPiotr Jasiukajtis switch (r.type) { 1484*25c28e83SPiotr Jasiukajtis case fex_int: 1485*25c28e83SPiotr Jasiukajtis *(double *)ea = (double) r.val.i; 1486*25c28e83SPiotr Jasiukajtis break; 1487*25c28e83SPiotr Jasiukajtis 1488*25c28e83SPiotr Jasiukajtis case fex_llong: 1489*25c28e83SPiotr Jasiukajtis *(double *)ea = (double) r.val.l; 1490*25c28e83SPiotr Jasiukajtis break; 1491*25c28e83SPiotr Jasiukajtis 1492*25c28e83SPiotr Jasiukajtis case fex_float: 1493*25c28e83SPiotr Jasiukajtis *(double *)ea = (double) r.val.f; 1494*25c28e83SPiotr Jasiukajtis break; 1495*25c28e83SPiotr Jasiukajtis 1496*25c28e83SPiotr Jasiukajtis case fex_double: 1497*25c28e83SPiotr Jasiukajtis *(double *)ea = r.val.d; 1498*25c28e83SPiotr Jasiukajtis break; 1499*25c28e83SPiotr Jasiukajtis 1500*25c28e83SPiotr Jasiukajtis case fex_ldouble: 1501*25c28e83SPiotr Jasiukajtis *(double *)ea = (double) r.val.q; 1502*25c28e83SPiotr Jasiukajtis break; 1503*25c28e83SPiotr Jasiukajtis 1504*25c28e83SPiotr Jasiukajtis default: 1505*25c28e83SPiotr Jasiukajtis break; 1506*25c28e83SPiotr Jasiukajtis } 1507*25c28e83SPiotr Jasiukajtis if (ex != FPE_FLTRES && (op & 8) != 0) 1508*25c28e83SPiotr Jasiukajtis pop(uap); 1509*25c28e83SPiotr Jasiukajtis return; 1510*25c28e83SPiotr Jasiukajtis 1511*25c28e83SPiotr Jasiukajtis case 0x710: 1512*25c28e83SPiotr Jasiukajtis case 0x718: 1513*25c28e83SPiotr Jasiukajtis case 0x750: 1514*25c28e83SPiotr Jasiukajtis case 0x758: 1515*25c28e83SPiotr Jasiukajtis case 0x790: 1516*25c28e83SPiotr Jasiukajtis case 0x798: 1517*25c28e83SPiotr Jasiukajtis if (!ea) 1518*25c28e83SPiotr Jasiukajtis return; 1519*25c28e83SPiotr Jasiukajtis switch (r.type) { 1520*25c28e83SPiotr Jasiukajtis case fex_int: 1521*25c28e83SPiotr Jasiukajtis *(short *)ea = (short) r.val.i; 1522*25c28e83SPiotr Jasiukajtis break; 1523*25c28e83SPiotr Jasiukajtis 1524*25c28e83SPiotr Jasiukajtis case fex_llong: 1525*25c28e83SPiotr Jasiukajtis *(short *)ea = (short) r.val.l; 1526*25c28e83SPiotr Jasiukajtis break; 1527*25c28e83SPiotr Jasiukajtis 1528*25c28e83SPiotr Jasiukajtis case fex_float: 1529*25c28e83SPiotr Jasiukajtis *(short *)ea = (short) r.val.f; 1530*25c28e83SPiotr Jasiukajtis break; 1531*25c28e83SPiotr Jasiukajtis 1532*25c28e83SPiotr Jasiukajtis case fex_double: 1533*25c28e83SPiotr Jasiukajtis *(short *)ea = (short) r.val.d; 1534*25c28e83SPiotr Jasiukajtis break; 1535*25c28e83SPiotr Jasiukajtis 1536*25c28e83SPiotr Jasiukajtis case fex_ldouble: 1537*25c28e83SPiotr Jasiukajtis *(short *)ea = (short) r.val.q; 1538*25c28e83SPiotr Jasiukajtis break; 1539*25c28e83SPiotr Jasiukajtis 1540*25c28e83SPiotr Jasiukajtis default: 1541*25c28e83SPiotr Jasiukajtis break; 1542*25c28e83SPiotr Jasiukajtis } 1543*25c28e83SPiotr Jasiukajtis if (ex != FPE_FLTRES && (op & 8) != 0) 1544*25c28e83SPiotr Jasiukajtis pop(uap); 1545*25c28e83SPiotr Jasiukajtis return; 1546*25c28e83SPiotr Jasiukajtis 1547*25c28e83SPiotr Jasiukajtis case 0x730: 1548*25c28e83SPiotr Jasiukajtis case 0x770: 1549*25c28e83SPiotr Jasiukajtis case 0x7b0: 1550*25c28e83SPiotr Jasiukajtis /* fbstp; don't bother */ 1551*25c28e83SPiotr Jasiukajtis if (ea && ex != FPE_FLTRES) 1552*25c28e83SPiotr Jasiukajtis pop(uap); 1553*25c28e83SPiotr Jasiukajtis return; 1554*25c28e83SPiotr Jasiukajtis 1555*25c28e83SPiotr Jasiukajtis case 0x738: 1556*25c28e83SPiotr Jasiukajtis case 0x778: 1557*25c28e83SPiotr Jasiukajtis case 0x7b8: 1558*25c28e83SPiotr Jasiukajtis if (!ea) 1559*25c28e83SPiotr Jasiukajtis return; 1560*25c28e83SPiotr Jasiukajtis switch (r.type) { 1561*25c28e83SPiotr Jasiukajtis case fex_int: 1562*25c28e83SPiotr Jasiukajtis *(long long *)ea = (long long) r.val.i; 1563*25c28e83SPiotr Jasiukajtis break; 1564*25c28e83SPiotr Jasiukajtis 1565*25c28e83SPiotr Jasiukajtis case fex_llong: 1566*25c28e83SPiotr Jasiukajtis *(long long *)ea = r.val.l; 1567*25c28e83SPiotr Jasiukajtis break; 1568*25c28e83SPiotr Jasiukajtis 1569*25c28e83SPiotr Jasiukajtis case fex_float: 1570*25c28e83SPiotr Jasiukajtis *(long long *)ea = (long long) r.val.f; 1571*25c28e83SPiotr Jasiukajtis break; 1572*25c28e83SPiotr Jasiukajtis 1573*25c28e83SPiotr Jasiukajtis case fex_double: 1574*25c28e83SPiotr Jasiukajtis *(long long *)ea = (long long) r.val.d; 1575*25c28e83SPiotr Jasiukajtis break; 1576*25c28e83SPiotr Jasiukajtis 1577*25c28e83SPiotr Jasiukajtis case fex_ldouble: 1578*25c28e83SPiotr Jasiukajtis *(long long *)ea = (long long) r.val.q; 1579*25c28e83SPiotr Jasiukajtis break; 1580*25c28e83SPiotr Jasiukajtis 1581*25c28e83SPiotr Jasiukajtis default: 1582*25c28e83SPiotr Jasiukajtis break; 1583*25c28e83SPiotr Jasiukajtis } 1584*25c28e83SPiotr Jasiukajtis if (ex != FPE_FLTRES) 1585*25c28e83SPiotr Jasiukajtis pop(uap); 1586*25c28e83SPiotr Jasiukajtis return; 1587*25c28e83SPiotr Jasiukajtis } 1588*25c28e83SPiotr Jasiukajtis 1589*25c28e83SPiotr Jasiukajtis /* for all other instructions, the result goes into a register */ 1590*25c28e83SPiotr Jasiukajtis switch (r.type) { 1591*25c28e83SPiotr Jasiukajtis case fex_int: 1592*25c28e83SPiotr Jasiukajtis r.val.q = (long double) r.val.i; 1593*25c28e83SPiotr Jasiukajtis break; 1594*25c28e83SPiotr Jasiukajtis 1595*25c28e83SPiotr Jasiukajtis case fex_llong: 1596*25c28e83SPiotr Jasiukajtis r.val.q = (long double) r.val.l; 1597*25c28e83SPiotr Jasiukajtis break; 1598*25c28e83SPiotr Jasiukajtis 1599*25c28e83SPiotr Jasiukajtis case fex_float: 1600*25c28e83SPiotr Jasiukajtis r.val.q = (long double) r.val.f; 1601*25c28e83SPiotr Jasiukajtis break; 1602*25c28e83SPiotr Jasiukajtis 1603*25c28e83SPiotr Jasiukajtis case fex_double: 1604*25c28e83SPiotr Jasiukajtis r.val.q = (long double) r.val.d; 1605*25c28e83SPiotr Jasiukajtis break; 1606*25c28e83SPiotr Jasiukajtis 1607*25c28e83SPiotr Jasiukajtis default: 1608*25c28e83SPiotr Jasiukajtis break; 1609*25c28e83SPiotr Jasiukajtis } 1610*25c28e83SPiotr Jasiukajtis 1611*25c28e83SPiotr Jasiukajtis /* for load instructions, push the result onto the stack */ 1612*25c28e83SPiotr Jasiukajtis switch (op & 0x7f8) { 1613*25c28e83SPiotr Jasiukajtis case 0x100: 1614*25c28e83SPiotr Jasiukajtis case 0x140: 1615*25c28e83SPiotr Jasiukajtis case 0x180: 1616*25c28e83SPiotr Jasiukajtis case 0x500: 1617*25c28e83SPiotr Jasiukajtis case 0x540: 1618*25c28e83SPiotr Jasiukajtis case 0x580: 1619*25c28e83SPiotr Jasiukajtis if (ea) 1620*25c28e83SPiotr Jasiukajtis push(r.val.q, uap); 1621*25c28e83SPiotr Jasiukajtis return; 1622*25c28e83SPiotr Jasiukajtis } 1623*25c28e83SPiotr Jasiukajtis 1624*25c28e83SPiotr Jasiukajtis /* for all other instructions, if the exception is overflow, 1625*25c28e83SPiotr Jasiukajtis underflow, or inexact, the stack has already been updated */ 1626*25c28e83SPiotr Jasiukajtis stack = (ex == FPE_FLTOVF || ex == FPE_FLTUND || ex == FPE_FLTRES); 1627*25c28e83SPiotr Jasiukajtis switch (op & 0x7f8) { 1628*25c28e83SPiotr Jasiukajtis case 0x1f0: /* oddballs */ 1629*25c28e83SPiotr Jasiukajtis switch (op) { 1630*25c28e83SPiotr Jasiukajtis case 0x1f1: /* fyl2x */ 1631*25c28e83SPiotr Jasiukajtis case 0x1f3: /* fpatan */ 1632*25c28e83SPiotr Jasiukajtis case 0x1f9: /* fyl2xp1 */ 1633*25c28e83SPiotr Jasiukajtis /* pop the stack, leaving the result in st */ 1634*25c28e83SPiotr Jasiukajtis if (!stack) 1635*25c28e83SPiotr Jasiukajtis pop(uap); 1636*25c28e83SPiotr Jasiukajtis fpreg(uap, 0) = r.val.q; 1637*25c28e83SPiotr Jasiukajtis return; 1638*25c28e83SPiotr Jasiukajtis 1639*25c28e83SPiotr Jasiukajtis case 0x1f2: /* fpatan */ 1640*25c28e83SPiotr Jasiukajtis /* fptan pushes 1.0 afterward */ 1641*25c28e83SPiotr Jasiukajtis if (stack) 1642*25c28e83SPiotr Jasiukajtis fpreg(uap, 1) = r.val.q; 1643*25c28e83SPiotr Jasiukajtis else { 1644*25c28e83SPiotr Jasiukajtis fpreg(uap, 0) = r.val.q; 1645*25c28e83SPiotr Jasiukajtis push(1.0L, uap); 1646*25c28e83SPiotr Jasiukajtis } 1647*25c28e83SPiotr Jasiukajtis return; 1648*25c28e83SPiotr Jasiukajtis 1649*25c28e83SPiotr Jasiukajtis case 0x1f4: /* fxtract */ 1650*25c28e83SPiotr Jasiukajtis case 0x1fb: /* fsincos */ 1651*25c28e83SPiotr Jasiukajtis /* leave the supplied result in st */ 1652*25c28e83SPiotr Jasiukajtis if (stack) 1653*25c28e83SPiotr Jasiukajtis fpreg(uap, 0) = r.val.q; 1654*25c28e83SPiotr Jasiukajtis else { 1655*25c28e83SPiotr Jasiukajtis fpreg(uap, 0) = 0.0; /* punt */ 1656*25c28e83SPiotr Jasiukajtis push(r.val.q, uap); 1657*25c28e83SPiotr Jasiukajtis } 1658*25c28e83SPiotr Jasiukajtis return; 1659*25c28e83SPiotr Jasiukajtis } 1660*25c28e83SPiotr Jasiukajtis 1661*25c28e83SPiotr Jasiukajtis /* all others leave the stack alone and the result in st */ 1662*25c28e83SPiotr Jasiukajtis fpreg(uap, 0) = r.val.q; 1663*25c28e83SPiotr Jasiukajtis return; 1664*25c28e83SPiotr Jasiukajtis 1665*25c28e83SPiotr Jasiukajtis case 0x4c0: 1666*25c28e83SPiotr Jasiukajtis case 0x4c8: 1667*25c28e83SPiotr Jasiukajtis case 0x4e0: 1668*25c28e83SPiotr Jasiukajtis case 0x4e8: 1669*25c28e83SPiotr Jasiukajtis case 0x4f0: 1670*25c28e83SPiotr Jasiukajtis case 0x4f8: 1671*25c28e83SPiotr Jasiukajtis fpreg(uap, op & 7) = r.val.q; 1672*25c28e83SPiotr Jasiukajtis return; 1673*25c28e83SPiotr Jasiukajtis 1674*25c28e83SPiotr Jasiukajtis case 0x6c0: 1675*25c28e83SPiotr Jasiukajtis case 0x6c8: 1676*25c28e83SPiotr Jasiukajtis case 0x6e0: 1677*25c28e83SPiotr Jasiukajtis case 0x6e8: 1678*25c28e83SPiotr Jasiukajtis case 0x6f0: 1679*25c28e83SPiotr Jasiukajtis case 0x6f8: 1680*25c28e83SPiotr Jasiukajtis /* stack is popped afterward */ 1681*25c28e83SPiotr Jasiukajtis if (stack) 1682*25c28e83SPiotr Jasiukajtis fpreg(uap, (op - 1) & 7) = r.val.q; 1683*25c28e83SPiotr Jasiukajtis else { 1684*25c28e83SPiotr Jasiukajtis fpreg(uap, op & 7) = r.val.q; 1685*25c28e83SPiotr Jasiukajtis pop(uap); 1686*25c28e83SPiotr Jasiukajtis } 1687*25c28e83SPiotr Jasiukajtis return; 1688*25c28e83SPiotr Jasiukajtis 1689*25c28e83SPiotr Jasiukajtis default: 1690*25c28e83SPiotr Jasiukajtis fpreg(uap, 0) = r.val.q; 1691*25c28e83SPiotr Jasiukajtis return; 1692*25c28e83SPiotr Jasiukajtis } 1693*25c28e83SPiotr Jasiukajtis } 1694