⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sys_float.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 2 页
字号:
#if defined(__x86_64__)    if ((opcode & 0xF0) == 0x40)	opcode = *pc++;#endif    do {	switch (opcode) {	case 0x0F:	    opcode = *pc++;	    switch (opcode) {	    case 0x2A: /* cvtpi2ps,cvtsi2sd,cvtsi2ss /r */	    case 0x2C: /* cvttpd2pi,cvttps2pi,cvttsd2si,cvtss2si /r */	    case 0x2D: /* cvtpd2pi,cvtps2pi,cvtsd2si,cvtss2si /r */	    case 0x2E: /* ucomisd,ucomiss /r */	    case 0x2F: /* comisd,comiss /r */	    case 0x51: /* sqrtpd,sqrtps,sqrtsd,sqrtss /r */	    case 0x58: /* addpd,addps,addsd,addss /r */	    case 0x59: /* mulpd,mulps,mulsd,mulss /r */	    case 0x5A: /* cvtpd2ps,cvtps2pd,cvtsd2ss,cvtss2sd /r */	    case 0x5B: /* cvtdq2ps,cvtps2dq,cvttps2dq /r */	    case 0x5C: /* subpd,subps,subsd,subss /r */	    case 0x5D: /* minpd,minps,minsd,minss /r */	    case 0x5E: /* divpd,divps,divsd,divss /r */	    case 0x5F: /* maxpd,maxps,maxsd,maxss /r */	    case 0xE6: /* cvtpd2dq,cvttpd2dq /r */		nr_skip_bytes = 0;		continue;	    case 0xC2: /* cmppd,cmpps,cmpsd,cmpss /r /ib */		nr_skip_bytes = 1;		continue;	    }	}	fprintf(stderr, "%s: unexpected code at %p:", __FUNCTION__, pc0);	do {	    fprintf(stderr, " %02X", *pc0++);	} while (pc0 < pc);	fprintf(stderr, "\r\n");	abort();    } while (0);    /* Past the opcode. Parse and skip the mod/rm and sib bytes. */    opcode = *pc++;    switch ((opcode >> 6) & 3) {	/* inspect mod */    case 0:	switch (opcode & 7) {		/* inspect r/m */	case 4:	    opcode = *pc++;		/* sib */	    switch (opcode & 7) {	/* inspect base */	    case 5:		nr_skip_bytes += 4;	/* disp32 */		break;	    }	    break;	case 5:	    nr_skip_bytes += 4;		/* disp32 */	    break;	}	break;    case 1:	nr_skip_bytes += 1;		/* disp8 */	switch (opcode & 7) {		/* inspect r/m */	case 4:	    pc += 1;			/* sib */	    break;	}	break;    case 2:	nr_skip_bytes += 4;		/* disp32 */	switch (opcode & 7) {		/* inspect r/m */	case 4:	    pc += 1;			/* sib */	    break;	}	break;    case 3:	break;    }    /* Past mod/rm and sib. Skip any disp, and /ib for cmp{pd,ps,sd,ss}. */    pc += nr_skip_bytes;    /* The longest instruction handled above is 11 bytes. So there is       no need to check the 15-byte instruction length limit here. */    /* Done. */    mc_pc(mc) = (long)pc;}#endif /* (__linux__ && (__x86_64__ || __i386__)) || (__DARWIN__ && __i386__) || (__FreeBSD__ && (__x86_64__ || __i386__)) || (__OpenBSD__ && __x86_64__) || (__sun__ && __x86_64__) */#if (defined(__linux__) && (defined(__i386__) || defined(__x86_64__) || defined(__sparc__) || defined(__powerpc__))) || (defined(__DARWIN__) && (defined(__i386__) || defined(__ppc__))) || (defined(__FreeBSD__) && (defined(__x86_64__) || defined(__i386__))) || (defined(__OpenBSD__) && defined(__x86_64__)) || (defined(__sun__) && defined(__x86_64__))#if defined(__linux__) && defined(__i386__)#include <asm/sigcontext.h>#elif defined(__FreeBSD__) && defined(__x86_64__)#include <sys/types.h>#include <machine/fpu.h>#elif defined(__FreeBSD__) && defined(__i386__)#include <sys/types.h>#include <machine/npx.h>#elif defined(__OpenBSD__) && defined(__x86_64__)#include <sys/types.h>#include <machine/fpu.h>#endif#if !(defined(__OpenBSD__) && defined(__x86_64__))#include <ucontext.h>#endif#include <string.h>static void fpe_sig_action(int sig, siginfo_t *si, void *puc){    ucontext_t *uc = puc;#if defined(__linux__)#if defined(__x86_64__)    mcontext_t *mc = &uc->uc_mcontext;    fpregset_t fpstate = mc->fpregs;    /* A failed SSE2 instruction will restart. To avoid       looping, we must update RIP to skip the instruction       (leaving garbage in the destination).       The alternative is to mask SSE2 exceptions now and       unmask them again later in erts_check_fpe(), but that       relies too much on other code being cooperative. */    if (fpstate->mxcsr & 0x000D) { /* OE|ZE|IE; see unmask_sse2() */	fpstate->mxcsr &= ~(0x003F|0x0680);	skip_sse2_insn(mc);    }    fpstate->swd &= ~0xFF;#elif defined(__i386__)    mcontext_t *mc = &uc->uc_mcontext;    fpregset_t fpstate = mc->fpregs;    if ((fpstate->status >> 16) == X86_FXSR_MAGIC &&	((struct _fpstate*)fpstate)->mxcsr & 0x000D) {	((struct _fpstate*)fpstate)->mxcsr &= ~(0x003F|0x0680);	skip_sse2_insn(mc);    }    fpstate->sw &= ~0xFF;#elif defined(__sparc__)    /* on SPARC the 3rd parameter points to a sigcontext not a ucontext */    struct sigcontext *sc = (struct sigcontext*)puc;    sc->si_regs.pc = sc->si_regs.npc;    sc->si_regs.npc = (unsigned long)sc->si_regs.npc + 4;#elif defined(__powerpc__)#if defined(__powerpc64__)    mcontext_t *mc = &uc->uc_mcontext;    unsigned long *regs = &mc->gp_regs[0];#else    mcontext_t *mc = uc->uc_mcontext.uc_regs;    unsigned long *regs = &mc->gregs[0];#endif    regs[PT_NIP] += 4;    regs[PT_FPSCR] = 0x80|0x40|0x10;	/* VE, OE, ZE; not UE or XE */#endif#elif defined(__DARWIN__) && defined(__i386__)    mcontext_t mc = uc->uc_mcontext;    if (mc->fs.fpu_mxcsr & 0x000D) {	mc->fs.fpu_mxcsr &= ~(0x003F|0x0680);	skip_sse2_insn(mc);    }    *(unsigned short *)&mc->fs.fpu_fsw &= ~0xFF;#elif defined(__DARWIN__) && defined(__ppc__)    mcontext_t mc = uc->uc_mcontext;    mc->ss.srr0 += 4;    mc->fs.fpscr = 0x80|0x40|0x10;#elif defined(__FreeBSD__) && defined(__x86_64__)    mcontext_t *mc = &uc->uc_mcontext;    struct savefpu *savefpu = (struct savefpu*)&mc->mc_fpstate;    struct envxmm *envxmm = &savefpu->sv_env;    if (envxmm->en_mxcsr & 0x000D) {	envxmm->en_mxcsr &= ~(0x003F|0x0680);	skip_sse2_insn(mc);    }    envxmm->en_sw &= ~0xFF;#elif defined(__FreeBSD__) && defined(__i386__)    mcontext_t *mc = &uc->uc_mcontext;    union savefpu *savefpu = (union savefpu*)&mc->mc_fpstate;    if (mc->mc_fpformat == _MC_FPFMT_XMM) {	struct envxmm *envxmm = &savefpu->sv_xmm.sv_env;	if (envxmm->en_mxcsr & 0x000D) {	    envxmm->en_mxcsr &= ~(0x003F|0x0680);	    skip_sse2_insn(mc);	}	envxmm->en_sw &= ~0xFF;    } else {	struct env87 *env87 = &savefpu->sv_87.sv_env;	env87->en_sw &= ~0xFF;    }#elif defined(__OpenBSD__) && defined(__x86_64__)    struct fxsave64 *fxsave = uc->sc_fpstate;    if (fxsave->fx_mxcsr & 0x000D) {	fxsave->fx_mxcsr &= ~(0x003F|0x0680);	skip_sse2_insn(uc);    }    fxsave->fx_fsw &= ~0xFF;#elif defined(__sun__) && defined(__x86_64__)    mcontext_t *mc = &uc->uc_mcontext;    struct fpchip_state *fpstate = &mc->fpregs.fp_reg_set.fpchip_state;    if (fpstate->mxcsr & 0x000D) {	fpstate->mxcsr &= ~(0x003F|0x0680);	skip_sse2_insn(mc);    }    fpstate->sw &= ~0xFF;#endif    set_current_fp_exception();}static void erts_thread_catch_fp_exceptions(void){    struct sigaction act;    memset(&act, 0, sizeof act);    act.sa_sigaction = fpe_sig_action;    act.sa_flags = SA_SIGINFO;    sigaction(SIGFPE, &act, NULL);    unmask_fpe();}#else  /* !((__linux__ && (__i386__ || __x86_64__ || __powerpc__)) || (__DARWIN__ && (__i386__ || __ppc__))) */static void fpe_sig_handler(int sig){    set_current_fp_exception();}static void erts_thread_catch_fp_exceptions(void){    sys_sigset(SIGFPE, fpe_sig_handler);    unmask_fpe();}#endif /* (__linux__ && (__i386__ || __x86_64__ || __powerpc__)) || (__DARWIN__ && (__i386__ || __ppc__))) *//* once-only initialisation early in the main thread */void erts_sys_init_float(void){    erts_init_fp_exception();    erts_thread_catch_fp_exceptions();}#endif /* NO_FPE_SIGNALS */void erts_thread_init_float(void){#ifdef ERTS_SMP    /* This allows Erlang schedulers to leave Erlang-process context       and still have working FP exceptions. XXX: is this needed? */    erts_thread_init_fp_exception();#endif#if !defined(NO_FPE_SIGNALS) && (defined(__DARWIN__) || defined(__FreeBSD__))    /* Darwin (7.9.0) does not appear to propagate FP exception settings       to a new thread from its parent. So if we want FP exceptions, we       must manually re-enable them in each new thread.       FreeBSD 6.1 appears to suffer from a similar issue. */    erts_thread_catch_fp_exceptions();#endif}/* The following check is incorporated from the Vee machine */    #define ISDIGIT(d) ((d) >= '0' && (d) <= '9')/*  ** Convert a double to ascii format 0.dddde[+|-]ddd ** return number of characters converted ** ** These two functions should maybe use localeconv() to pick up ** the current radix character, but since it is uncertain how ** expensive such a system call is, and since no-one has heard ** of other radix characters than '.' and ',' an ad-hoc  ** low execution time solution is used instead. */intsys_double_to_chars(double fp, char *buf){    char *s = buf;        (void) sprintf(buf, "%.20e", fp);    /* Search upto decimal point */    if (*s == '+' || *s == '-') s++;    while (ISDIGIT(*s)) s++;    if (*s == ',') *s++ = '.'; /* Replace ',' with '.' */    /* Scan to end of string */    while (*s) s++;    return s-buf; /* i.e strlen(buf) */}/* Float conversion */intsys_chars_to_double(char* buf, double* fp){    volatile int *fpexnp = erts_get_current_fp_exception();    char *s = buf, *t, *dp;    /* Robert says that something like this is what he really wanted:     * (The [.,] radix test is NOT what Robert wanted - it was added later)     *     * 7 == sscanf(Tbuf, "%[+-]%[0-9][.,]%[0-9]%[eE]%[+-]%[0-9]%s", ....);     * if (*s2 == 0 || *s3 == 0 || *s4 == 0 || *s6 == 0 || *s7)     *   break;     */    /* Scan string to check syntax. */    if (*s == '+' || *s == '-') s++;    if (!ISDIGIT(*s))		/* Leading digits. */      return -1;    while (ISDIGIT(*s)) s++;    if (*s != '.' && *s != ',')	/* Decimal part. */      return -1;    dp = s++;			/* Remember decimal point pos just in case */    if (!ISDIGIT(*s))      return -1;    while (ISDIGIT(*s)) s++;    if (*s == 'e' || *s == 'E') {	/* There is an exponent. */	s++;	if (*s == '+' || *s == '-') s++;	if (!ISDIGIT(*s))	  return -1;	while (ISDIGIT(*s)) s++;    }    if (*s)			/* That should be it */      return -1;#ifdef NO_FPE_SIGNALS    errno = 0;#endif    __ERTS_FP_CHECK_INIT(fpexnp);    *fp = strtod(buf, &t);    __ERTS_FP_ERROR_THOROUGH(fpexnp, *fp, return -1);    if (t != s) {		/* Whole string not scanned */	/* Try again with other radix char */	*dp = (*dp == '.') ? ',' : '.';	errno = 0;	__ERTS_FP_CHECK_INIT(fpexnp);	*fp = strtod(buf, &t);	__ERTS_FP_ERROR_THOROUGH(fpexnp, *fp, return -1);    }#ifdef DEBUG    if (errno == ERANGE)	fprintf(stderr, "errno = ERANGE in list_to_float\n\r");#endif#ifdef NO_FPE_SIGNALS    if (errno == ERANGE)	return -1;#endif/***  Replaces following code:**   if (errno == ERANGE) {**       *fp = 1.2e300;		**       *fp = *fp / 1.5e-100;	**   }				*/    return 0;}intmatherr(struct exception *exc){    set_current_fp_exception();    return 1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -