diff options
Diffstat (limited to 'op-i386.c')
-rw-r--r-- | op-i386.c | 837 |
1 files changed, 2 insertions, 835 deletions
@@ -626,95 +626,6 @@ void OPPROTO op_jmp_im(void) EIP = PARAM1; } -#if 0 -/* full interrupt support (only useful for real CPU emulation, not - finished) - I won't do it any time soon, finish it if you want ! */ -void raise_interrupt(int intno, int is_int, int error_code, - unsigned int next_eip) -{ - SegmentDescriptorTable *dt; - uint8_t *ptr; - int type, dpl, cpl; - uint32_t e1, e2; - - dt = &env->idt; - if (intno * 8 + 7 > dt->limit) - raise_exception_err(EXCP0D_GPF, intno * 8 + 2); - ptr = dt->base + intno * 8; - e1 = ldl(ptr); - e2 = ldl(ptr + 4); - /* check gate type */ - type = (e2 >> DESC_TYPE_SHIFT) & 0x1f; - switch(type) { - case 5: /* task gate */ - case 6: /* 286 interrupt gate */ - case 7: /* 286 trap gate */ - case 14: /* 386 interrupt gate */ - case 15: /* 386 trap gate */ - break; - default: - raise_exception_err(EXCP0D_GPF, intno * 8 + 2); - break; - } - dpl = (e2 >> DESC_DPL_SHIFT) & 3; - cpl = env->segs[R_CS] & 3; - /* check privledge if software int */ - if (is_int && dpl < cpl) - raise_exception_err(EXCP0D_GPF, intno * 8 + 2); - /* check valid bit */ - if (!(e2 & DESC_P_MASK)) - raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2); -} - -#else - -/* - * is_int is TRUE if coming from the int instruction. next_eip is the - * EIP value AFTER the interrupt instruction. It is only relevant if - * is_int is TRUE. - */ -void raise_interrupt(int intno, int is_int, int error_code, - unsigned int next_eip) -{ - SegmentDescriptorTable *dt; - uint8_t *ptr; - int dpl, cpl; - uint32_t e2; - - dt = &env->idt; - ptr = dt->base + (intno * 8); - e2 = ldl(ptr + 4); - - dpl = (e2 >> DESC_DPL_SHIFT) & 3; - cpl = 3; - /* check privledge if software int */ - if (is_int && dpl < cpl) - raise_exception_err(EXCP0D_GPF, intno * 8 + 2); - - /* Since we emulate only user space, we cannot do more than - exiting the emulation with the suitable exception and error - code */ - if (is_int) - EIP = next_eip; - env->exception_index = intno; - env->error_code = error_code; - - cpu_loop_exit(); -} - -#endif - -/* shortcuts to generate exceptions */ -void raise_exception_err(int exception_index, int error_code) -{ - raise_interrupt(exception_index, 0, error_code, 0); -} - -void raise_exception(int exception_index) -{ - raise_interrupt(exception_index, 0, 0, 0); -} - void OPPROTO op_raise_interrupt(void) { int intno; @@ -833,7 +744,7 @@ label ## n:\ #define JUMP_TB(tbparam, n, eip)\ do {\ static void __attribute__((unused)) *__op_label ## n = &&label ## n;\ - goto *((TranslationBlock *)tbparam)->tb_next[n];\ + goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n]);\ label ## n:\ T0 = (long)(tbparam) + (n);\ EIP = eip;\ @@ -1044,46 +955,6 @@ void OPPROTO op_rdtsc(void) EDX = val >> 32; } -/* We simulate a pre-MMX pentium as in valgrind */ -#define CPUID_FP87 (1 << 0) -#define CPUID_VME (1 << 1) -#define CPUID_DE (1 << 2) -#define CPUID_PSE (1 << 3) -#define CPUID_TSC (1 << 4) -#define CPUID_MSR (1 << 5) -#define CPUID_PAE (1 << 6) -#define CPUID_MCE (1 << 7) -#define CPUID_CX8 (1 << 8) -#define CPUID_APIC (1 << 9) -#define CPUID_SEP (1 << 11) /* sysenter/sysexit */ -#define CPUID_MTRR (1 << 12) -#define CPUID_PGE (1 << 13) -#define CPUID_MCA (1 << 14) -#define CPUID_CMOV (1 << 15) -/* ... */ -#define CPUID_MMX (1 << 23) -#define CPUID_FXSR (1 << 24) -#define CPUID_SSE (1 << 25) -#define CPUID_SSE2 (1 << 26) - -void helper_cpuid(void) -{ - if (EAX == 0) { - EAX = 1; /* max EAX index supported */ - EBX = 0x756e6547; - ECX = 0x6c65746e; - EDX = 0x49656e69; - } else if (EAX == 1) { - /* EAX = 1 info */ - EAX = 0x52b; - EBX = 0; - ECX = 0; - EDX = CPUID_FP87 | CPUID_DE | CPUID_PSE | - CPUID_TSC | CPUID_MSR | CPUID_MCE | - CPUID_CX8; - } -} - void OPPROTO op_cpuid(void) { helper_cpuid(); @@ -1221,79 +1092,6 @@ void OPPROTO op_das(void) /* segment handling */ -/* only works if protected mode and not VM86 */ -void load_seg(int seg_reg, int selector, unsigned cur_eip) -{ - SegmentCache *sc; - SegmentDescriptorTable *dt; - int index; - uint32_t e1, e2; - uint8_t *ptr; - - sc = &env->seg_cache[seg_reg]; - if ((selector & 0xfffc) == 0) { - /* null selector case */ - if (seg_reg == R_SS) { - EIP = cur_eip; - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); - } else { - /* XXX: each access should trigger an exception */ - sc->base = NULL; - sc->limit = 0; - sc->seg_32bit = 1; - } - } else { - if (selector & 0x4) - dt = &env->ldt; - else - dt = &env->gdt; - index = selector & ~7; - if ((index + 7) > dt->limit) { - EIP = cur_eip; - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); - } - ptr = dt->base + index; - e1 = ldl(ptr); - e2 = ldl(ptr + 4); - if (!(e2 & DESC_S_MASK) || - (e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) { - EIP = cur_eip; - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); - } - - if (seg_reg == R_SS) { - if ((e2 & (DESC_CS_MASK | DESC_W_MASK)) == 0) { - EIP = cur_eip; - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); - } - } else { - if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) { - EIP = cur_eip; - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); - } - } - - if (!(e2 & DESC_P_MASK)) { - EIP = cur_eip; - if (seg_reg == R_SS) - raise_exception_err(EXCP0C_STACK, selector & 0xfffc); - else - raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); - } - - sc->base = (void *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000)); - sc->limit = (e1 & 0xffff) | (e2 & 0x000f0000); - if (e2 & (1 << 23)) - sc->limit = (sc->limit << 12) | 0xfff; - sc->seg_32bit = (e2 >> 22) & 1; -#if 0 - fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx seg_32bit=%d\n", - selector, (unsigned long)sc->base, sc->limit, sc->seg_32bit); -#endif - } - env->segs[seg_reg] = selector; -} - void OPPROTO op_movl_seg_T0(void) { load_seg(PARAM1, T0 & 0xffff, PARAM2); @@ -1326,61 +1124,11 @@ void OPPROTO op_addl_A0_seg(void) A0 += *(unsigned long *)((char *)env + PARAM1); } -void helper_lsl(void) -{ - unsigned int selector, limit; - SegmentDescriptorTable *dt; - int index; - uint32_t e1, e2; - uint8_t *ptr; - - CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z; - selector = T0 & 0xffff; - if (selector & 0x4) - dt = &env->ldt; - else - dt = &env->gdt; - index = selector & ~7; - if ((index + 7) > dt->limit) - return; - ptr = dt->base + index; - e1 = ldl(ptr); - e2 = ldl(ptr + 4); - limit = (e1 & 0xffff) | (e2 & 0x000f0000); - if (e2 & (1 << 23)) - limit = (limit << 12) | 0xfff; - T1 = limit; - CC_SRC |= CC_Z; -} - void OPPROTO op_lsl(void) { helper_lsl(); } -void helper_lar(void) -{ - unsigned int selector; - SegmentDescriptorTable *dt; - int index; - uint32_t e2; - uint8_t *ptr; - - CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z; - selector = T0 & 0xffff; - if (selector & 0x4) - dt = &env->ldt; - else - dt = &env->gdt; - index = selector & ~7; - if ((index + 7) > dt->limit) - return; - ptr = dt->base + index; - e2 = ldl(ptr + 4); - T1 = e2 & 0x00f0ff00; - CC_SRC |= CC_Z; -} - void OPPROTO op_lar(void) { helper_lar(); @@ -1678,37 +1426,6 @@ CCTable cc_table[CC_OP_NB] = { functions comes from the LGPL'ed x86 emulator found in the Willows TWIN windows emulator. */ -#ifdef USE_X86LDOUBLE -/* use long double functions */ -#define lrint lrintl -#define llrint llrintl -#define fabs fabsl -#define sin sinl -#define cos cosl -#define sqrt sqrtl -#define pow powl -#define log logl -#define tan tanl -#define atan2 atan2l -#define floor floorl -#define ceil ceill -#define rint rintl -#endif - -extern int lrint(CPU86_LDouble x); -extern int64_t llrint(CPU86_LDouble x); -extern CPU86_LDouble fabs(CPU86_LDouble x); -extern CPU86_LDouble sin(CPU86_LDouble x); -extern CPU86_LDouble cos(CPU86_LDouble x); -extern CPU86_LDouble sqrt(CPU86_LDouble x); -extern CPU86_LDouble pow(CPU86_LDouble, CPU86_LDouble); -extern CPU86_LDouble log(CPU86_LDouble x); -extern CPU86_LDouble tan(CPU86_LDouble x); -extern CPU86_LDouble atan2(CPU86_LDouble, CPU86_LDouble); -extern CPU86_LDouble floor(CPU86_LDouble x); -extern CPU86_LDouble ceil(CPU86_LDouble x); -extern CPU86_LDouble rint(CPU86_LDouble x); - #if defined(__powerpc__) extern CPU86_LDouble copysign(CPU86_LDouble, CPU86_LDouble); @@ -1729,60 +1446,6 @@ double qemu_rint(double x) #define rint qemu_rint #endif -#define RC_MASK 0xc00 -#define RC_NEAR 0x000 -#define RC_DOWN 0x400 -#define RC_UP 0x800 -#define RC_CHOP 0xc00 - -#define MAXTAN 9223372036854775808.0 - -#ifdef USE_X86LDOUBLE - -/* only for x86 */ -typedef union { - long double d; - struct { - unsigned long long lower; - unsigned short upper; - } l; -} CPU86_LDoubleU; - -/* the following deal with x86 long double-precision numbers */ -#define MAXEXPD 0x7fff -#define EXPBIAS 16383 -#define EXPD(fp) (fp.l.upper & 0x7fff) -#define SIGND(fp) ((fp.l.upper) & 0x8000) -#define MANTD(fp) (fp.l.lower) -#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS - -#else - -typedef union { - double d; -#ifndef WORDS_BIGENDIAN - struct { - uint32_t lower; - int32_t upper; - } l; -#else - struct { - int32_t upper; - uint32_t lower; - } l; -#endif - int64_t ll; -} CPU86_LDoubleU; - -/* the following deal with IEEE double-precision numbers */ -#define MAXEXPD 0x7ff -#define EXPBIAS 1023 -#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF) -#define SIGND(fp) ((fp.l.upper) & 0x80000000) -#define MANTD(fp) (fp.ll & ((1LL << 52) - 1)) -#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20) -#endif - /* fp load FT0 */ void OPPROTO op_flds_FT0_A0(void) @@ -1899,24 +1562,6 @@ void OPPROTO op_fldt_ST0_A0(void) ST0 = *(long double *)A0; } #else -static inline CPU86_LDouble helper_fldt(uint8_t *ptr) -{ - CPU86_LDoubleU temp; - int upper, e; - /* mantissa */ - upper = lduw(ptr + 8); - /* XXX: handle overflow ? */ - e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */ - e |= (upper >> 4) & 0x800; /* sign */ - temp.ll = ((ldq(ptr) >> 11) & ((1LL << 52) - 1)) | ((uint64_t)e << 52); - return temp.d; -} - -void helper_fldt_ST0_A0(void) -{ - ST0 = helper_fldt((uint8_t *)A0); -} - void OPPROTO op_fldt_ST0_A0(void) { helper_fldt_ST0_A0(); @@ -2013,25 +1658,6 @@ void OPPROTO op_fstt_ST0_A0(void) *(long double *)A0 = ST0; } #else - -static inline void helper_fstt(CPU86_LDouble f, uint8_t *ptr) -{ - CPU86_LDoubleU temp; - int e; - temp.d = f; - /* mantissa */ - stq(ptr, (MANTD(temp) << 11) | (1LL << 63)); - /* exponent + sign */ - e = EXPD(temp) - EXPBIAS + 16383; - e |= SIGND(temp) >> 16; - stw(ptr + 8, e); -} - -void helper_fstt_ST0_A0(void) -{ - helper_fstt(ST0, (uint8_t *)A0); -} - void OPPROTO op_fstt_ST0_A0(void) { helper_fstt_ST0_A0(); @@ -2080,98 +1706,11 @@ void OPPROTO op_fistll_ST0_A0(void) stq((void *)A0, val); } -/* BCD ops */ - -#define MUL10(iv) ( iv + iv + (iv << 3) ) - -void helper_fbld_ST0_A0(void) -{ - uint8_t *seg; - CPU86_LDouble fpsrcop; - int m32i; - unsigned int v; - - /* in this code, seg/m32i will be used as temporary ptr/int */ - seg = (uint8_t *)A0 + 8; - v = ldub(seg--); - /* XXX: raise exception */ - if (v != 0) - return; - v = ldub(seg--); - /* XXX: raise exception */ - if ((v & 0xf0) != 0) - return; - m32i = v; /* <-- d14 */ - v = ldub(seg--); - m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d13 */ - m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d12 */ - v = ldub(seg--); - m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d11 */ - m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d10 */ - v = ldub(seg--); - m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d9 */ - m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d8 */ - fpsrcop = ((CPU86_LDouble)m32i) * 100000000.0; - - v = ldub(seg--); - m32i = (v >> 4); /* <-- d7 */ - m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d6 */ - v = ldub(seg--); - m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d5 */ - m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d4 */ - v = ldub(seg--); - m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d3 */ - m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d2 */ - v = ldub(seg); - m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d1 */ - m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d0 */ - fpsrcop += ((CPU86_LDouble)m32i); - if ( ldub(seg+9) & 0x80 ) - fpsrcop = -fpsrcop; - ST0 = fpsrcop; -} - void OPPROTO op_fbld_ST0_A0(void) { helper_fbld_ST0_A0(); } -void helper_fbst_ST0_A0(void) -{ - CPU86_LDouble fptemp; - CPU86_LDouble fpsrcop; - int v; - uint8_t *mem_ref, *mem_end; - - fpsrcop = rint(ST0); - mem_ref = (uint8_t *)A0; - mem_end = mem_ref + 8; - if ( fpsrcop < 0.0 ) { - stw(mem_end, 0x8000); - fpsrcop = -fpsrcop; - } else { - stw(mem_end, 0x0000); - } - while (mem_ref < mem_end) { - if (fpsrcop == 0.0) - break; - fptemp = floor(fpsrcop/10.0); - v = ((int)(fpsrcop - fptemp*10.0)); - if (fptemp == 0.0) { - stb(mem_ref++, v); - break; - } - fpsrcop = fptemp; - fptemp = floor(fpsrcop/10.0); - v |= (((int)(fpsrcop - fptemp*10.0)) << 4); - stb(mem_ref++, v); - fpsrcop = fptemp; - } - while (mem_ref < mem_end) { - stb(mem_ref++, 0); - } -} - void OPPROTO op_fbst_ST0_A0(void) { helper_fbst_ST0_A0(); @@ -2179,18 +1718,6 @@ void OPPROTO op_fbst_ST0_A0(void) /* FPU move */ -static inline void fpush(void) -{ - env->fpstt = (env->fpstt - 1) & 7; - env->fptags[env->fpstt] = 0; /* validate stack entry */ -} - -static inline void fpop(void) -{ - env->fptags[env->fpstt] = 1; /* invvalidate stack entry */ - env->fpstt = (env->fpstt + 1) & 7; -} - void OPPROTO op_fpush(void) { fpush(); @@ -2370,33 +1897,6 @@ void OPPROTO op_fabs_ST0(void) ST0 = fabs(ST0); } -void helper_fxam_ST0(void) -{ - CPU86_LDoubleU temp; - int expdif; - - temp.d = ST0; - - env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */ - if (SIGND(temp)) - env->fpus |= 0x200; /* C1 <-- 1 */ - - expdif = EXPD(temp); - if (expdif == MAXEXPD) { - if (MANTD(temp) == 0) - env->fpus |= 0x500 /*Infinity*/; - else - env->fpus |= 0x100 /*NaN*/; - } else if (expdif == 0) { - if (MANTD(temp) == 0) - env->fpus |= 0x4000 /*Zero*/; - else - env->fpus |= 0x4400 /*Denormal*/; - } else { - env->fpus |= 0x400; - } -} - void OPPROTO op_fxam_ST0(void) { helper_fxam_ST0(); @@ -2442,217 +1942,6 @@ void OPPROTO op_fldz_FT0(void) ST0 = *(CPU86_LDouble *)&f15rk[0]; } -void helper_f2xm1(void) -{ - ST0 = pow(2.0,ST0) - 1.0; -} - -void helper_fyl2x(void) -{ - CPU86_LDouble fptemp; - - fptemp = ST0; - if (fptemp>0.0){ - fptemp = log(fptemp)/log(2.0); /* log2(ST) */ - ST1 *= fptemp; - fpop(); - } else { - env->fpus &= (~0x4700); - env->fpus |= 0x400; - } -} - -void helper_fptan(void) -{ - CPU86_LDouble fptemp; - - fptemp = ST0; - if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) { - env->fpus |= 0x400; - } else { - ST0 = tan(fptemp); - fpush(); - ST0 = 1.0; - env->fpus &= (~0x400); /* C2 <-- 0 */ - /* the above code is for |arg| < 2**52 only */ - } -} - -void helper_fpatan(void) -{ - CPU86_LDouble fptemp, fpsrcop; - - fpsrcop = ST1; - fptemp = ST0; - ST1 = atan2(fpsrcop,fptemp); - fpop(); -} - -void helper_fxtract(void) -{ - CPU86_LDoubleU temp; - unsigned int expdif; - - temp.d = ST0; - expdif = EXPD(temp) - EXPBIAS; - /*DP exponent bias*/ - ST0 = expdif; - fpush(); - BIASEXPONENT(temp); - ST0 = temp.d; -} - -void helper_fprem1(void) -{ - CPU86_LDouble dblq, fpsrcop, fptemp; - CPU86_LDoubleU fpsrcop1, fptemp1; - int expdif; - int q; - - fpsrcop = ST0; - fptemp = ST1; - fpsrcop1.d = fpsrcop; - fptemp1.d = fptemp; - expdif = EXPD(fpsrcop1) - EXPD(fptemp1); - if (expdif < 53) { - dblq = fpsrcop / fptemp; - dblq = (dblq < 0.0)? ceil(dblq): floor(dblq); - ST0 = fpsrcop - fptemp*dblq; - q = (int)dblq; /* cutting off top bits is assumed here */ - env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */ - /* (C0,C1,C3) <-- (q2,q1,q0) */ - env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */ - env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */ - env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */ - } else { - env->fpus |= 0x400; /* C2 <-- 1 */ - fptemp = pow(2.0, expdif-50); - fpsrcop = (ST0 / ST1) / fptemp; - /* fpsrcop = integer obtained by rounding to the nearest */ - fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)? - floor(fpsrcop): ceil(fpsrcop); - ST0 -= (ST1 * fpsrcop * fptemp); - } -} - -void helper_fprem(void) -{ - CPU86_LDouble dblq, fpsrcop, fptemp; - CPU86_LDoubleU fpsrcop1, fptemp1; - int expdif; - int q; - - fpsrcop = ST0; - fptemp = ST1; - fpsrcop1.d = fpsrcop; - fptemp1.d = fptemp; - expdif = EXPD(fpsrcop1) - EXPD(fptemp1); - if ( expdif < 53 ) { - dblq = fpsrcop / fptemp; - dblq = (dblq < 0.0)? ceil(dblq): floor(dblq); - ST0 = fpsrcop - fptemp*dblq; - q = (int)dblq; /* cutting off top bits is assumed here */ - env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */ - /* (C0,C1,C3) <-- (q2,q1,q0) */ - env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */ - env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */ - env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */ - } else { - env->fpus |= 0x400; /* C2 <-- 1 */ - fptemp = pow(2.0, expdif-50); - fpsrcop = (ST0 / ST1) / fptemp; - /* fpsrcop = integer obtained by chopping */ - fpsrcop = (fpsrcop < 0.0)? - -(floor(fabs(fpsrcop))): floor(fpsrcop); - ST0 -= (ST1 * fpsrcop * fptemp); - } -} - -void helper_fyl2xp1(void) -{ - CPU86_LDouble fptemp; - - fptemp = ST0; - if ((fptemp+1.0)>0.0) { - fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */ - ST1 *= fptemp; - fpop(); - } else { - env->fpus &= (~0x4700); - env->fpus |= 0x400; - } -} - -void helper_fsqrt(void) -{ - CPU86_LDouble fptemp; - - fptemp = ST0; - if (fptemp<0.0) { - env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */ - env->fpus |= 0x400; - } - ST0 = sqrt(fptemp); -} - -void helper_fsincos(void) -{ - CPU86_LDouble fptemp; - - fptemp = ST0; - if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) { - env->fpus |= 0x400; - } else { - ST0 = sin(fptemp); - fpush(); - ST0 = cos(fptemp); - env->fpus &= (~0x400); /* C2 <-- 0 */ - /* the above code is for |arg| < 2**63 only */ - } -} - -void helper_frndint(void) -{ - ST0 = rint(ST0); -} - -void helper_fscale(void) -{ - CPU86_LDouble fpsrcop, fptemp; - - fpsrcop = 2.0; - fptemp = pow(fpsrcop,ST1); - ST0 *= fptemp; -} - -void helper_fsin(void) -{ - CPU86_LDouble fptemp; - - fptemp = ST0; - if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) { - env->fpus |= 0x400; - } else { - ST0 = sin(fptemp); - env->fpus &= (~0x400); /* C2 <-- 0 */ - /* the above code is for |arg| < 2**53 only */ - } -} - -void helper_fcos(void) -{ - CPU86_LDouble fptemp; - - fptemp = ST0; - if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) { - env->fpus |= 0x400; - } else { - ST0 = cos(fptemp); - env->fpus &= (~0x400); /* C2 <-- 0 */ - /* the above code is for |arg5 < 2**63 only */ - } -} - /* associated heplers to reduce generated code length and to simplify relocation (FP constants are usually stored in .rodata section) */ @@ -2789,129 +2078,6 @@ void OPPROTO op_fninit(void) env->fptags[7] = 1; } -void helper_fstenv(uint8_t *ptr, int data32) -{ - int fpus, fptag, exp, i; - uint64_t mant; - CPU86_LDoubleU tmp; - - fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; - fptag = 0; - for (i=7; i>=0; i--) { - fptag <<= 2; - if (env->fptags[i]) { - fptag |= 3; - } else { - tmp.d = env->fpregs[i]; - exp = EXPD(tmp); - mant = MANTD(tmp); - if (exp == 0 && mant == 0) { - /* zero */ - fptag |= 1; - } else if (exp == 0 || exp == MAXEXPD -#ifdef USE_X86LDOUBLE - || (mant & (1LL << 63)) == 0 -#endif - ) { - /* NaNs, infinity, denormal */ - fptag |= 2; - } - } - } - if (data32) { - /* 32 bit */ - stl(ptr, env->fpuc); - stl(ptr + 4, fpus); - stl(ptr + 8, fptag); - stl(ptr + 12, 0); - stl(ptr + 16, 0); - stl(ptr + 20, 0); - stl(ptr + 24, 0); - } else { - /* 16 bit */ - stw(ptr, env->fpuc); - stw(ptr + 2, fpus); - stw(ptr + 4, fptag); - stw(ptr + 6, 0); - stw(ptr + 8, 0); - stw(ptr + 10, 0); - stw(ptr + 12, 0); - } -} - -void helper_fldenv(uint8_t *ptr, int data32) -{ - int i, fpus, fptag; - - if (data32) { - env->fpuc = lduw(ptr); - fpus = lduw(ptr + 4); - fptag = lduw(ptr + 8); - } - else { - env->fpuc = lduw(ptr); - fpus = lduw(ptr + 2); - fptag = lduw(ptr + 4); - } - env->fpstt = (fpus >> 11) & 7; - env->fpus = fpus & ~0x3800; - for(i = 0;i < 7; i++) { - env->fptags[i] = ((fptag & 3) == 3); - fptag >>= 2; - } -} - -void helper_fsave(uint8_t *ptr, int data32) -{ - CPU86_LDouble tmp; - int i; - - helper_fstenv(ptr, data32); - - ptr += (14 << data32); - for(i = 0;i < 8; i++) { - tmp = ST(i); -#ifdef USE_X86LDOUBLE - *(long double *)ptr = tmp; -#else - helper_fstt(tmp, ptr); -#endif - ptr += 10; - } - - /* fninit */ - env->fpus = 0; - env->fpstt = 0; - env->fpuc = 0x37f; - env->fptags[0] = 1; - env->fptags[1] = 1; - env->fptags[2] = 1; - env->fptags[3] = 1; - env->fptags[4] = 1; - env->fptags[5] = 1; - env->fptags[6] = 1; - env->fptags[7] = 1; -} - -void helper_frstor(uint8_t *ptr, int data32) -{ - CPU86_LDouble tmp; - int i; - - helper_fldenv(ptr, data32); - ptr += (14 << data32); - - for(i = 0;i < 8; i++) { -#ifdef USE_X86LDOUBLE - tmp = *(long double *)ptr; -#else - tmp = helper_fldt(ptr); -#endif - ST(i) = tmp; - ptr += 10; - } -} - void OPPROTO op_fnstenv_A0(void) { helper_fstenv((uint8_t *)A0, PARAM1); @@ -2942,3 +2108,4 @@ void OPPROTO op_unlock(void) { cpu_unlock(); } + |