diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-05-12 19:10:44 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-05-12 19:10:44 +0000 |
commit | 19e6c4b8bc0d692cd31900657714102a418f75e7 (patch) | |
tree | 4f8a674c11b3a30edc6e64bfa93485fbb8837b8d /target-i386 | |
parent | 4da450e6167830c88225915eb7e75b582b634215 (diff) | |
download | qemu-19e6c4b8bc0d692cd31900657714102a418f75e7.zip |
converted x87 FPU ops to TCG
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4444 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-i386')
-rw-r--r-- | target-i386/exec.h | 56 | ||||
-rw-r--r-- | target-i386/helper.c | 446 | ||||
-rw-r--r-- | target-i386/helper.h | 89 | ||||
-rw-r--r-- | target-i386/op.c | 740 | ||||
-rw-r--r-- | target-i386/translate.c | 370 |
5 files changed, 756 insertions, 945 deletions
diff --git a/target-i386/exec.h b/target-i386/exec.h index 2c482b2c7d..3dee6c375f 100644 --- a/target-i386/exec.h +++ b/target-i386/exec.h @@ -231,6 +231,12 @@ static inline void stfl(target_ulong ptr, float v) #define floatx_to_int64 floatx80_to_int64 #define floatx_to_int32_round_to_zero floatx80_to_int32_round_to_zero #define floatx_to_int64_round_to_zero floatx80_to_int64_round_to_zero +#define int32_to_floatx int32_to_floatx80 +#define int64_to_floatx int64_to_floatx80 +#define float32_to_floatx float32_to_floatx80 +#define float64_to_floatx float64_to_floatx80 +#define floatx_to_float32 floatx80_to_float32 +#define floatx_to_float64 floatx80_to_float64 #define floatx_abs floatx80_abs #define floatx_chs floatx80_chs #define floatx_round_to_int floatx80_round_to_int @@ -251,6 +257,12 @@ static inline void stfl(target_ulong ptr, float v) #define floatx_to_int64 float64_to_int64 #define floatx_to_int32_round_to_zero float64_to_int32_round_to_zero #define floatx_to_int64_round_to_zero float64_to_int64_round_to_zero +#define int32_to_floatx int32_to_float64 +#define int64_to_floatx int64_to_float64 +#define float32_to_floatx float32_to_float64 +#define float64_to_floatx(x, e) (x) +#define floatx_to_float32 float64_to_float32 +#define floatx_to_float64(x, e) (x) #define floatx_abs float64_abs #define floatx_chs float64_chs #define floatx_round_to_int float64_round_to_int @@ -378,22 +390,6 @@ static inline void helper_fstt(CPU86_LDouble f, target_ulong ptr) } #else -/* XXX: same endianness assumed */ - -#ifdef CONFIG_USER_ONLY - -static inline CPU86_LDouble helper_fldt(target_ulong ptr) -{ - return *(CPU86_LDouble *)(unsigned long)ptr; -} - -static inline void helper_fstt(CPU86_LDouble f, target_ulong ptr) -{ - *(CPU86_LDouble *)(unsigned long)ptr = f; -} - -#else - /* we use memory access macros */ static inline CPU86_LDouble helper_fldt(target_ulong ptr) @@ -414,8 +410,6 @@ static inline void helper_fstt(CPU86_LDouble f, target_ulong ptr) stw(ptr + 8, temp.l.upper); } -#endif /* !CONFIG_USER_ONLY */ - #endif /* USE_X86LDOUBLE */ #define FPUS_IE (1 << 0) @@ -432,33 +426,7 @@ static inline void helper_fstt(CPU86_LDouble f, target_ulong ptr) extern const CPU86_LDouble f15rk[7]; -void helper_fldt_ST0_A0(void); -void helper_fstt_ST0_A0(void); void fpu_raise_exception(void); -CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b); -void helper_fbld_ST0_A0(void); -void helper_fbst_ST0_A0(void); -void helper_f2xm1(void); -void helper_fyl2x(void); -void helper_fptan(void); -void helper_fpatan(void); -void helper_fxtract(void); -void helper_fprem1(void); -void helper_fprem(void); -void helper_fyl2xp1(void); -void helper_fsqrt(void); -void helper_fsincos(void); -void helper_frndint(void); -void helper_fscale(void); -void helper_fsin(void); -void helper_fcos(void); -void helper_fxam_ST0(void); -void helper_fstenv(target_ulong ptr, int data32); -void helper_fldenv(target_ulong ptr, int data32); -void helper_fsave(target_ulong ptr, int data32); -void helper_frstor(target_ulong ptr, int data32); -void helper_fxsave(target_ulong ptr, int data64); -void helper_fxrstor(target_ulong ptr, int data64); void restore_native_fp_state(CPUState *env); void save_native_fp_state(CPUState *env); float approx_rsqrt(float a); diff --git a/target-i386/helper.c b/target-i386/helper.c index 30a6eccb83..aa79e51580 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -3071,21 +3071,7 @@ void helper_verw(void) CC_SRC = eflags | CC_Z; } -/* FPU helpers */ - -void helper_fldt_ST0_A0(void) -{ - int new_fpstt; - new_fpstt = (env->fpstt - 1) & 7; - env->fpregs[new_fpstt].d = helper_fldt(A0); - env->fpstt = new_fpstt; - env->fptags[new_fpstt] = 0; /* validate stack entry */ -} - -void helper_fstt_ST0_A0(void) -{ - helper_fstt(ST0, A0); -} +/* x87 FPU helpers */ static void fpu_set_exception(int mask) { @@ -3094,7 +3080,7 @@ static void fpu_set_exception(int mask) env->fpus |= FPUS_SE | FPUS_B; } -CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b) +static inline CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b) { if (b == 0.0) fpu_set_exception(FPUS_ZE); @@ -3113,9 +3099,427 @@ void fpu_raise_exception(void) #endif } +void helper_flds_FT0(uint32_t val) +{ + union { + float32 f; + uint32_t i; + } u; + u.i = val; + FT0 = float32_to_floatx(u.f, &env->fp_status); +} + +void helper_fldl_FT0(uint64_t val) +{ + union { + float64 f; + uint64_t i; + } u; + u.i = val; + FT0 = float64_to_floatx(u.f, &env->fp_status); +} + +void helper_fildl_FT0(int32_t val) +{ + FT0 = int32_to_floatx(val, &env->fp_status); +} + +void helper_flds_ST0(uint32_t val) +{ + int new_fpstt; + union { + float32 f; + uint32_t i; + } u; + new_fpstt = (env->fpstt - 1) & 7; + u.i = val; + env->fpregs[new_fpstt].d = float32_to_floatx(u.f, &env->fp_status); + env->fpstt = new_fpstt; + env->fptags[new_fpstt] = 0; /* validate stack entry */ +} + +void helper_fldl_ST0(uint64_t val) +{ + int new_fpstt; + union { + float64 f; + uint64_t i; + } u; + new_fpstt = (env->fpstt - 1) & 7; + u.i = val; + env->fpregs[new_fpstt].d = float64_to_floatx(u.f, &env->fp_status); + env->fpstt = new_fpstt; + env->fptags[new_fpstt] = 0; /* validate stack entry */ +} + +void helper_fildl_ST0(int32_t val) +{ + int new_fpstt; + new_fpstt = (env->fpstt - 1) & 7; + env->fpregs[new_fpstt].d = int32_to_floatx(val, &env->fp_status); + env->fpstt = new_fpstt; + env->fptags[new_fpstt] = 0; /* validate stack entry */ +} + +void helper_fildll_ST0(int64_t val) +{ + int new_fpstt; + new_fpstt = (env->fpstt - 1) & 7; + env->fpregs[new_fpstt].d = int64_to_floatx(val, &env->fp_status); + env->fpstt = new_fpstt; + env->fptags[new_fpstt] = 0; /* validate stack entry */ +} + +uint32_t helper_fsts_ST0(void) +{ + union { + float32 f; + uint32_t i; + } u; + u.f = floatx_to_float32(ST0, &env->fp_status); + return u.i; +} + +uint64_t helper_fstl_ST0(void) +{ + union { + float64 f; + uint64_t i; + } u; + u.f = floatx_to_float64(ST0, &env->fp_status); + return u.i; +} + +int32_t helper_fist_ST0(void) +{ + int32_t val; + val = floatx_to_int32(ST0, &env->fp_status); + if (val != (int16_t)val) + val = -32768; + return val; +} + +int32_t helper_fistl_ST0(void) +{ + int32_t val; + val = floatx_to_int32(ST0, &env->fp_status); + return val; +} + +int64_t helper_fistll_ST0(void) +{ + int64_t val; + val = floatx_to_int64(ST0, &env->fp_status); + return val; +} + +int32_t helper_fistt_ST0(void) +{ + int32_t val; + val = floatx_to_int32_round_to_zero(ST0, &env->fp_status); + if (val != (int16_t)val) + val = -32768; + return val; +} + +int32_t helper_fisttl_ST0(void) +{ + int32_t val; + val = floatx_to_int32_round_to_zero(ST0, &env->fp_status); + return val; +} + +int64_t helper_fisttll_ST0(void) +{ + int64_t val; + val = floatx_to_int64_round_to_zero(ST0, &env->fp_status); + return val; +} + +void helper_fldt_ST0(target_ulong ptr) +{ + int new_fpstt; + new_fpstt = (env->fpstt - 1) & 7; + env->fpregs[new_fpstt].d = helper_fldt(ptr); + env->fpstt = new_fpstt; + env->fptags[new_fpstt] = 0; /* validate stack entry */ +} + +void helper_fstt_ST0(target_ulong ptr) +{ + helper_fstt(ST0, ptr); +} + +void helper_fpush(void) +{ + fpush(); +} + +void helper_fpop(void) +{ + fpop(); +} + +void helper_fdecstp(void) +{ + env->fpstt = (env->fpstt - 1) & 7; + env->fpus &= (~0x4700); +} + +void helper_fincstp(void) +{ + env->fpstt = (env->fpstt + 1) & 7; + env->fpus &= (~0x4700); +} + +/* FPU move */ + +void helper_ffree_STN(int st_index) +{ + env->fptags[(env->fpstt + st_index) & 7] = 1; +} + +void helper_fmov_ST0_FT0(void) +{ + ST0 = FT0; +} + +void helper_fmov_FT0_STN(int st_index) +{ + FT0 = ST(st_index); +} + +void helper_fmov_ST0_STN(int st_index) +{ + ST0 = ST(st_index); +} + +void helper_fmov_STN_ST0(int st_index) +{ + ST(st_index) = ST0; +} + +void helper_fxchg_ST0_STN(int st_index) +{ + CPU86_LDouble tmp; + tmp = ST(st_index); + ST(st_index) = ST0; + ST0 = tmp; +} + +/* FPU operations */ + +static const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500}; + +void helper_fcom_ST0_FT0(void) +{ + int ret; + + ret = floatx_compare(ST0, FT0, &env->fp_status); + env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1]; + FORCE_RET(); +} + +void helper_fucom_ST0_FT0(void) +{ + int ret; + + ret = floatx_compare_quiet(ST0, FT0, &env->fp_status); + env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret+ 1]; + FORCE_RET(); +} + +static const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C}; + +void helper_fcomi_ST0_FT0(void) +{ + int eflags; + int ret; + + ret = floatx_compare(ST0, FT0, &env->fp_status); + eflags = cc_table[CC_OP].compute_all(); + eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1]; + CC_SRC = eflags; + FORCE_RET(); +} + +void helper_fucomi_ST0_FT0(void) +{ + int eflags; + int ret; + + ret = floatx_compare_quiet(ST0, FT0, &env->fp_status); + eflags = cc_table[CC_OP].compute_all(); + eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1]; + CC_SRC = eflags; + FORCE_RET(); +} + +void helper_fadd_ST0_FT0(void) +{ + ST0 += FT0; +} + +void helper_fmul_ST0_FT0(void) +{ + ST0 *= FT0; +} + +void helper_fsub_ST0_FT0(void) +{ + ST0 -= FT0; +} + +void helper_fsubr_ST0_FT0(void) +{ + ST0 = FT0 - ST0; +} + +void helper_fdiv_ST0_FT0(void) +{ + ST0 = helper_fdiv(ST0, FT0); +} + +void helper_fdivr_ST0_FT0(void) +{ + ST0 = helper_fdiv(FT0, ST0); +} + +/* fp operations between STN and ST0 */ + +void helper_fadd_STN_ST0(int st_index) +{ + ST(st_index) += ST0; +} + +void helper_fmul_STN_ST0(int st_index) +{ + ST(st_index) *= ST0; +} + +void helper_fsub_STN_ST0(int st_index) +{ + ST(st_index) -= ST0; +} + +void helper_fsubr_STN_ST0(int st_index) +{ + CPU86_LDouble *p; + p = &ST(st_index); + *p = ST0 - *p; +} + +void helper_fdiv_STN_ST0(int st_index) +{ + CPU86_LDouble *p; + p = &ST(st_index); + *p = helper_fdiv(*p, ST0); +} + +void helper_fdivr_STN_ST0(int st_index) +{ + CPU86_LDouble *p; + p = &ST(st_index); + *p = helper_fdiv(ST0, *p); +} + +/* misc FPU operations */ +void helper_fchs_ST0(void) +{ + ST0 = floatx_chs(ST0); +} + +void helper_fabs_ST0(void) +{ + ST0 = floatx_abs(ST0); +} + +void helper_fld1_ST0(void) +{ + ST0 = f15rk[1]; +} + +void helper_fldl2t_ST0(void) +{ + ST0 = f15rk[6]; +} + +void helper_fldl2e_ST0(void) +{ + ST0 = f15rk[5]; +} + +void helper_fldpi_ST0(void) +{ + ST0 = f15rk[2]; +} + +void helper_fldlg2_ST0(void) +{ + ST0 = f15rk[3]; +} + +void helper_fldln2_ST0(void) +{ + ST0 = f15rk[4]; +} + +void helper_fldz_ST0(void) +{ + ST0 = f15rk[0]; +} + +void helper_fldz_FT0(void) +{ + FT0 = f15rk[0]; +} + +uint32_t helper_fnstsw(void) +{ + return (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; +} + +uint32_t helper_fnstcw(void) +{ + return env->fpuc; +} + +void helper_fldcw(uint32_t val) +{ + env->fpuc = val; + update_fp_status(); +} + +void helper_fclex(void) +{ + env->fpus &= 0x7f00; +} + +void helper_fwait(void) +{ + if (env->fpus & FPUS_SE) + fpu_raise_exception(); + FORCE_RET(); +} + +void helper_fninit(void) +{ + 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; +} + /* BCD ops */ -void helper_fbld_ST0_A0(void) +void helper_fbld_ST0(target_ulong ptr) { CPU86_LDouble tmp; uint64_t val; @@ -3124,24 +3528,24 @@ void helper_fbld_ST0_A0(void) val = 0; for(i = 8; i >= 0; i--) { - v = ldub(A0 + i); + v = ldub(ptr + i); val = (val * 100) + ((v >> 4) * 10) + (v & 0xf); } tmp = val; - if (ldub(A0 + 9) & 0x80) + if (ldub(ptr + 9) & 0x80) tmp = -tmp; fpush(); ST0 = tmp; } -void helper_fbst_ST0_A0(void) +void helper_fbst_ST0(target_ulong ptr) { int v; target_ulong mem_ref, mem_end; int64_t val; val = floatx_to_int64(ST0, &env->fp_status); - mem_ref = A0; + mem_ref = ptr; mem_end = mem_ref + 9; if (val < 0) { stb(mem_end, 0x80); diff --git a/target-i386/helper.h b/target-i386/helper.h index bc06fa3a8b..4371c8378e 100644 --- a/target-i386/helper.h +++ b/target-i386/helper.h @@ -2,6 +2,95 @@ void TCG_HELPER_PROTO helper_divl_EAX_T0(target_ulong t0); void TCG_HELPER_PROTO helper_idivl_EAX_T0(target_ulong t0); + +/* x86 FPU */ + +void helper_flds_FT0(uint32_t val); +void helper_fldl_FT0(uint64_t val); +void helper_fildl_FT0(int32_t val); +void helper_flds_ST0(uint32_t val); +void helper_fldl_ST0(uint64_t val); +void helper_fildl_ST0(int32_t val); +void helper_fildll_ST0(int64_t val); +uint32_t helper_fsts_ST0(void); +uint64_t helper_fstl_ST0(void); +int32_t helper_fist_ST0(void); +int32_t helper_fistl_ST0(void); +int64_t helper_fistll_ST0(void); +int32_t helper_fistt_ST0(void); +int32_t helper_fisttl_ST0(void); +int64_t helper_fisttll_ST0(void); +void helper_fldt_ST0(target_ulong ptr); +void helper_fstt_ST0(target_ulong ptr); +void helper_fpush(void); +void helper_fpop(void); +void helper_fdecstp(void); +void helper_fincstp(void); +void helper_ffree_STN(int st_index); +void helper_fmov_ST0_FT0(void); +void helper_fmov_FT0_STN(int st_index); +void helper_fmov_ST0_STN(int st_index); +void helper_fmov_STN_ST0(int st_index); +void helper_fxchg_ST0_STN(int st_index); +void helper_fcom_ST0_FT0(void); +void helper_fucom_ST0_FT0(void); +void helper_fcomi_ST0_FT0(void); +void helper_fucomi_ST0_FT0(void); +void helper_fadd_ST0_FT0(void); +void helper_fmul_ST0_FT0(void); +void helper_fsub_ST0_FT0(void); +void helper_fsubr_ST0_FT0(void); +void helper_fdiv_ST0_FT0(void); +void helper_fdivr_ST0_FT0(void); +void helper_fadd_STN_ST0(int st_index); +void helper_fmul_STN_ST0(int st_index); +void helper_fsub_STN_ST0(int st_index); +void helper_fsubr_STN_ST0(int st_index); +void helper_fdiv_STN_ST0(int st_index); +void helper_fdivr_STN_ST0(int st_index); +void helper_fchs_ST0(void); +void helper_fabs_ST0(void); +void helper_fxam_ST0(void); +void helper_fld1_ST0(void); +void helper_fldl2t_ST0(void); +void helper_fldl2e_ST0(void); +void helper_fldpi_ST0(void); +void helper_fldlg2_ST0(void); +void helper_fldln2_ST0(void); +void helper_fldz_ST0(void); +void helper_fldz_FT0(void); +uint32_t helper_fnstsw(void); +uint32_t helper_fnstcw(void); +void helper_fldcw(uint32_t val); +void helper_fclex(void); +void helper_fwait(void); +void helper_fninit(void); +void helper_fbld_ST0(target_ulong ptr); +void helper_fbst_ST0(target_ulong ptr); +void helper_f2xm1(void); +void helper_fyl2x(void); +void helper_fptan(void); +void helper_fpatan(void); +void helper_fxtract(void); +void helper_fprem1(void); +void helper_fprem(void); +void helper_fyl2xp1(void); +void helper_fsqrt(void); +void helper_fsincos(void); +void helper_frndint(void); +void helper_fscale(void); +void helper_fsin(void); +void helper_fcos(void); +void helper_fxam_ST0(void); +void helper_fstenv(target_ulong ptr, int data32); +void helper_fldenv(target_ulong ptr, int data32); +void helper_fsave(target_ulong ptr, int data32); +void helper_frstor(target_ulong ptr, int data32); +void helper_fxsave(target_ulong ptr, int data64); +void helper_fxrstor(target_ulong ptr, int data64); + +/* MMX/SSE */ + void TCG_HELPER_PROTO helper_enter_mmx(void); void TCG_HELPER_PROTO helper_emms(void); void TCG_HELPER_PROTO helper_movq(uint64_t *d, uint64_t *s); diff --git a/target-i386/op.c b/target-i386/op.c index c87a600332..e184a8dcf1 100644 --- a/target-i386/op.c +++ b/target-i386/op.c @@ -1401,735 +1401,9 @@ CCTable cc_table[CC_OP_NB] = { #endif }; -/* floating point support. Some of the code for complicated x87 - functions comes from the LGPL'ed x86 emulator found in the Willows - TWIN windows emulator. */ - -/* fp load FT0 */ - -void OPPROTO op_flds_FT0_A0(void) -{ -#ifdef USE_FP_CONVERT - FP_CONVERT.i32 = ldl(A0); - FT0 = FP_CONVERT.f; -#else - FT0 = ldfl(A0); -#endif -} - -void OPPROTO op_fldl_FT0_A0(void) -{ -#ifdef USE_FP_CONVERT - FP_CONVERT.i64 = ldq(A0); - FT0 = FP_CONVERT.d; -#else - FT0 = ldfq(A0); -#endif -} - -/* helpers are needed to avoid static constant reference. XXX: find a better way */ -#ifdef USE_INT_TO_FLOAT_HELPERS - -void helper_fild_FT0_A0(void) -{ - FT0 = (CPU86_LDouble)ldsw(A0); -} - -void helper_fildl_FT0_A0(void) -{ - FT0 = (CPU86_LDouble)((int32_t)ldl(A0)); -} - -void helper_fildll_FT0_A0(void) -{ - FT0 = (CPU86_LDouble)((int64_t)ldq(A0)); -} - -void OPPROTO op_fild_FT0_A0(void) -{ - helper_fild_FT0_A0(); -} - -void OPPROTO op_fildl_FT0_A0(void) -{ - helper_fildl_FT0_A0(); -} - -void OPPROTO op_fildll_FT0_A0(void) -{ - helper_fildll_FT0_A0(); -} - -#else - -void OPPROTO op_fild_FT0_A0(void) -{ -#ifdef USE_FP_CONVERT - FP_CONVERT.i32 = ldsw(A0); - FT0 = (CPU86_LDouble)FP_CONVERT.i32; -#else - FT0 = (CPU86_LDouble)ldsw(A0); -#endif -} - -void OPPROTO op_fildl_FT0_A0(void) -{ -#ifdef USE_FP_CONVERT - FP_CONVERT.i32 = (int32_t) ldl(A0); - FT0 = (CPU86_LDouble)FP_CONVERT.i32; -#else - FT0 = (CPU86_LDouble)((int32_t)ldl(A0)); -#endif -} - -void OPPROTO op_fildll_FT0_A0(void) -{ -#ifdef USE_FP_CONVERT - FP_CONVERT.i64 = (int64_t) ldq(A0); - FT0 = (CPU86_LDouble)FP_CONVERT.i64; -#else - FT0 = (CPU86_LDouble)((int64_t)ldq(A0)); -#endif -} -#endif - -/* fp load ST0 */ - -void OPPROTO op_flds_ST0_A0(void) -{ - int new_fpstt; - new_fpstt = (env->fpstt - 1) & 7; -#ifdef USE_FP_CONVERT - FP_CONVERT.i32 = ldl(A0); - env->fpregs[new_fpstt].d = FP_CONVERT.f; -#else - env->fpregs[new_fpstt].d = ldfl(A0); -#endif - env->fpstt = new_fpstt; - env->fptags[new_fpstt] = 0; /* validate stack entry */ -} - -void OPPROTO op_fldl_ST0_A0(void) -{ - int new_fpstt; - new_fpstt = (env->fpstt - 1) & 7; -#ifdef USE_FP_CONVERT - FP_CONVERT.i64 = ldq(A0); - env->fpregs[new_fpstt].d = FP_CONVERT.d; -#else - env->fpregs[new_fpstt].d = ldfq(A0); -#endif - env->fpstt = new_fpstt; - env->fptags[new_fpstt] = 0; /* validate stack entry */ -} - -void OPPROTO op_fldt_ST0_A0(void) -{ - helper_fldt_ST0_A0(); -} - -/* helpers are needed to avoid static constant reference. XXX: find a better way */ -#ifdef USE_INT_TO_FLOAT_HELPERS - -void helper_fild_ST0_A0(void) -{ - int new_fpstt; - new_fpstt = (env->fpstt - 1) & 7; - env->fpregs[new_fpstt].d = (CPU86_LDouble)ldsw(A0); - env->fpstt = new_fpstt; - env->fptags[new_fpstt] = 0; /* validate stack entry */ -} - -void helper_fildl_ST0_A0(void) -{ - int new_fpstt; - new_fpstt = (env->fpstt - 1) & 7; - env->fpregs[new_fpstt].d = (CPU86_LDouble)((int32_t)ldl(A0)); - env->fpstt = new_fpstt; - env->fptags[new_fpstt] = 0; /* validate stack entry */ -} - -void helper_fildll_ST0_A0(void) -{ - int new_fpstt; - new_fpstt = (env->fpstt - 1) & 7; - env->fpregs[new_fpstt].d = (CPU86_LDouble)((int64_t)ldq(A0)); - env->fpstt = new_fpstt; - env->fptags[new_fpstt] = 0; /* validate stack entry */ -} - -void OPPROTO op_fild_ST0_A0(void) -{ - helper_fild_ST0_A0(); -} - -void OPPROTO op_fildl_ST0_A0(void) -{ - helper_fildl_ST0_A0(); -} - -void OPPROTO op_fildll_ST0_A0(void) -{ - helper_fildll_ST0_A0(); -} - -#else - -void OPPROTO op_fild_ST0_A0(void) -{ - int new_fpstt; - new_fpstt = (env->fpstt - 1) & 7; -#ifdef USE_FP_CONVERT - FP_CONVERT.i32 = ldsw(A0); - env->fpregs[new_fpstt].d = (CPU86_LDouble)FP_CONVERT.i32; -#else - env->fpregs[new_fpstt].d = (CPU86_LDouble)ldsw(A0); -#endif - env->fpstt = new_fpstt; - env->fptags[new_fpstt] = 0; /* validate stack entry */ -} - -void OPPROTO op_fildl_ST0_A0(void) -{ - int new_fpstt; - new_fpstt = (env->fpstt - 1) & 7; -#ifdef USE_FP_CONVERT - FP_CONVERT.i32 = (int32_t) ldl(A0); - env->fpregs[new_fpstt].d = (CPU86_LDouble)FP_CONVERT.i32; -#else - env->fpregs[new_fpstt].d = (CPU86_LDouble)((int32_t)ldl(A0)); -#endif - env->fpstt = new_fpstt; - env->fptags[new_fpstt] = 0; /* validate stack entry */ -} - -void OPPROTO op_fildll_ST0_A0(void) -{ - int new_fpstt; - new_fpstt = (env->fpstt - 1) & 7; -#ifdef USE_FP_CONVERT - FP_CONVERT.i64 = (int64_t) ldq(A0); - env->fpregs[new_fpstt].d = (CPU86_LDouble)FP_CONVERT.i64; -#else - env->fpregs[new_fpstt].d = (CPU86_LDouble)((int64_t)ldq(A0)); -#endif - env->fpstt = new_fpstt; - env->fptags[new_fpstt] = 0; /* validate stack entry */ -} - -#endif - -/* fp store */ - -void OPPROTO op_fsts_ST0_A0(void) -{ -#ifdef USE_FP_CONVERT - FP_CONVERT.f = (float)ST0; - stfl(A0, FP_CONVERT.f); -#else - stfl(A0, (float)ST0); -#endif - FORCE_RET(); -} - -void OPPROTO op_fstl_ST0_A0(void) -{ - stfq(A0, (double)ST0); - FORCE_RET(); -} - -void OPPROTO op_fstt_ST0_A0(void) -{ - helper_fstt_ST0_A0(); -} - -void OPPROTO op_fist_ST0_A0(void) -{ -#if defined(__sparc__) && !defined(__sparc_v9__) - register CPU86_LDouble d asm("o0"); -#else - CPU86_LDouble d; -#endif - int val; - - d = ST0; - val = floatx_to_int32(d, &env->fp_status); - if (val != (int16_t)val) - val = -32768; - stw(A0, val); - FORCE_RET(); -} - -void OPPROTO op_fistl_ST0_A0(void) -{ -#if defined(__sparc__) && !defined(__sparc_v9__) - register CPU86_LDouble d asm("o0"); -#else - CPU86_LDouble d; -#endif - int val; - - d = ST0; - val = floatx_to_int32(d, &env->fp_status); - stl(A0, val); - FORCE_RET(); -} - -void OPPROTO op_fistll_ST0_A0(void) -{ -#if defined(__sparc__) && !defined(__sparc_v9__) - register CPU86_LDouble d asm("o0"); -#else - CPU86_LDouble d; -#endif - int64_t val; - - d = ST0; - val = floatx_to_int64(d, &env->fp_status); - stq(A0, val); - FORCE_RET(); -} - -void OPPROTO op_fistt_ST0_A0(void) -{ -#if defined(__sparc__) && !defined(__sparc_v9__) - register CPU86_LDouble d asm("o0"); -#else - CPU86_LDouble d; -#endif - int val; - - d = ST0; - val = floatx_to_int32_round_to_zero(d, &env->fp_status); - if (val != (int16_t)val) - val = -32768; - stw(A0, val); - FORCE_RET(); -} - -void OPPROTO op_fisttl_ST0_A0(void) -{ -#if defined(__sparc__) && !defined(__sparc_v9__) - register CPU86_LDouble d asm("o0"); -#else - CPU86_LDouble d; -#endif - int val; - - d = ST0; - val = floatx_to_int32_round_to_zero(d, &env->fp_status); - stl(A0, val); - FORCE_RET(); -} - -void OPPROTO op_fisttll_ST0_A0(void) -{ -#if defined(__sparc__) && !defined(__sparc_v9__) - register CPU86_LDouble d asm("o0"); -#else - CPU86_LDouble d; -#endif - int64_t val; - - d = ST0; - val = floatx_to_int64_round_to_zero(d, &env->fp_status); - stq(A0, val); - FORCE_RET(); -} - -void OPPROTO op_fbld_ST0_A0(void) -{ - helper_fbld_ST0_A0(); -} - -void OPPROTO op_fbst_ST0_A0(void) -{ - helper_fbst_ST0_A0(); -} - -/* FPU move */ - -void OPPROTO op_fpush(void) -{ - fpush(); -} - -void OPPROTO op_fpop(void) -{ - fpop(); -} - -void OPPROTO op_fdecstp(void) -{ - env->fpstt = (env->fpstt - 1) & 7; - env->fpus &= (~0x4700); -} - -void OPPROTO op_fincstp(void) -{ - env->fpstt = (env->fpstt + 1) & 7; - env->fpus &= (~0x4700); -} - -void OPPROTO op_ffree_STN(void) -{ - env->fptags[(env->fpstt + PARAM1) & 7] = 1; -} - -void OPPROTO op_fmov_ST0_FT0(void) -{ - ST0 = FT0; -} - -void OPPROTO op_fmov_FT0_STN(void) -{ - FT0 = ST(PARAM1); -} - -void OPPROTO op_fmov_ST0_STN(void) -{ - ST0 = ST(PARAM1); -} - -void OPPROTO op_fmov_STN_ST0(void) -{ - ST(PARAM1) = ST0; -} - -void OPPROTO op_fxchg_ST0_STN(void) +void OPPROTO op_fcomi_dummy(void) { - CPU86_LDouble tmp; - tmp = ST(PARAM1); - ST(PARAM1) = ST0; - ST0 = tmp; -} - -/* FPU operations */ - -const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500}; - -void OPPROTO op_fcom_ST0_FT0(void) -{ - int ret; - - ret = floatx_compare(ST0, FT0, &env->fp_status); - env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1]; - FORCE_RET(); -} - -void OPPROTO op_fucom_ST0_FT0(void) -{ - int ret; - - ret = floatx_compare_quiet(ST0, FT0, &env->fp_status); - env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret+ 1]; - FORCE_RET(); -} - -const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C}; - -void OPPROTO op_fcomi_ST0_FT0(void) -{ - int eflags; - int ret; - - ret = floatx_compare(ST0, FT0, &env->fp_status); - eflags = cc_table[CC_OP].compute_all(); - eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1]; - CC_SRC = eflags; - FORCE_RET(); -} - -void OPPROTO op_fucomi_ST0_FT0(void) -{ - int eflags; - int ret; - - ret = floatx_compare_quiet(ST0, FT0, &env->fp_status); - eflags = cc_table[CC_OP].compute_all(); - eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1]; - CC_SRC = eflags; - FORCE_RET(); -} - -void OPPROTO op_fcmov_ST0_STN_T0(void) -{ - if (T0) { - ST0 = ST(PARAM1); - } - FORCE_RET(); -} - -void OPPROTO op_fadd_ST0_FT0(void) -{ - ST0 += FT0; -} - -void OPPROTO op_fmul_ST0_FT0(void) -{ - ST0 *= FT0; -} - -void OPPROTO op_fsub_ST0_FT0(void) -{ - ST0 -= FT0; -} - -void OPPROTO op_fsubr_ST0_FT0(void) -{ - ST0 = FT0 - ST0; -} - -void OPPROTO op_fdiv_ST0_FT0(void) -{ - ST0 = helper_fdiv(ST0, FT0); -} - -void OPPROTO op_fdivr_ST0_FT0(void) -{ - ST0 = helper_fdiv(FT0, ST0); -} - -/* fp operations between STN and ST0 */ - -void OPPROTO op_fadd_STN_ST0(void) -{ - ST(PARAM1) += ST0; -} - -void OPPROTO op_fmul_STN_ST0(void) -{ - ST(PARAM1) *= ST0; -} - -void OPPROTO op_fsub_STN_ST0(void) -{ - ST(PARAM1) -= ST0; -} - -void OPPROTO op_fsubr_STN_ST0(void) -{ - CPU86_LDouble *p; - p = &ST(PARAM1); - *p = ST0 - *p; -} - -void OPPROTO op_fdiv_STN_ST0(void) -{ - CPU86_LDouble *p; - p = &ST(PARAM1); - *p = helper_fdiv(*p, ST0); -} - -void OPPROTO op_fdivr_STN_ST0(void) -{ - CPU86_LDouble *p; - p = &ST(PARAM1); - *p = helper_fdiv(ST0, *p); -} - -/* misc FPU operations */ -void OPPROTO op_fchs_ST0(void) -{ - ST0 = floatx_chs(ST0); -} - -void OPPROTO op_fabs_ST0(void) -{ - ST0 = floatx_abs(ST0); -} - -void OPPROTO op_fxam_ST0(void) -{ - helper_fxam_ST0(); -} - -void OPPROTO op_fld1_ST0(void) -{ - ST0 = f15rk[1]; -} - -void OPPROTO op_fldl2t_ST0(void) -{ - ST0 = f15rk[6]; -} - -void OPPROTO op_fldl2e_ST0(void) -{ - ST0 = f15rk[5]; -} - -void OPPROTO op_fldpi_ST0(void) -{ - ST0 = f15rk[2]; -} - -void OPPROTO op_fldlg2_ST0(void) -{ - ST0 = f15rk[3]; -} - -void OPPROTO op_fldln2_ST0(void) -{ - ST0 = f15rk[4]; -} - -void OPPROTO op_fldz_ST0(void) -{ - ST0 = f15rk[0]; -} - -void OPPROTO op_fldz_FT0(void) -{ - FT0 = f15rk[0]; -} - -/* associated heplers to reduce generated code length and to simplify - relocation (FP constants are usually stored in .rodata section) */ - -void OPPROTO op_f2xm1(void) -{ - helper_f2xm1(); -} - -void OPPROTO op_fyl2x(void) -{ - helper_fyl2x(); -} - -void OPPROTO op_fptan(void) -{ - helper_fptan(); -} - -void OPPROTO op_fpatan(void) -{ - helper_fpatan(); -} - -void OPPROTO op_fxtract(void) -{ - helper_fxtract(); -} - -void OPPROTO op_fprem1(void) -{ - helper_fprem1(); -} - - -void OPPROTO op_fprem(void) -{ - helper_fprem(); -} - -void OPPROTO op_fyl2xp1(void) -{ - helper_fyl2xp1(); -} - -void OPPROTO op_fsqrt(void) -{ - helper_fsqrt(); -} - -void OPPROTO op_fsincos(void) -{ - helper_fsincos(); -} - -void OPPROTO op_frndint(void) -{ - helper_frndint(); -} - -void OPPROTO op_fscale(void) -{ - helper_fscale(); -} - -void OPPROTO op_fsin(void) -{ - helper_fsin(); -} - -void OPPROTO op_fcos(void) -{ - helper_fcos(); -} - -void OPPROTO op_fnstsw_A0(void) -{ - int fpus; - fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; - stw(A0, fpus); - FORCE_RET(); -} - -void OPPROTO op_fnstsw_EAX(void) -{ - int fpus; - fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; - EAX = (EAX & ~0xffff) | fpus; -} - -void OPPROTO op_fnstcw_A0(void) -{ - stw(A0, env->fpuc); - FORCE_RET(); -} - -void OPPROTO op_fldcw_A0(void) -{ - env->fpuc = lduw(A0); - update_fp_status(); -} - -void OPPROTO op_fclex(void) -{ - env->fpus &= 0x7f00; -} - -void OPPROTO op_fwait(void) -{ - if (env->fpus & FPUS_SE) - fpu_raise_exception(); - FORCE_RET(); -} - -void OPPROTO op_fninit(void) -{ - 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 OPPROTO op_fnstenv_A0(void) -{ - helper_fstenv(A0, PARAM1); -} - -void OPPROTO op_fldenv_A0(void) -{ - helper_fldenv(A0, PARAM1); -} - -void OPPROTO op_fnsave_A0(void) -{ - helper_fsave(A0, PARAM1); -} - -void OPPROTO op_frstor_A0(void) -{ - helper_frstor(A0, PARAM1); + T0 = 0; } /* threading support */ @@ -2149,16 +1423,6 @@ void OPPROTO op_com_dummy(void) T0 = 0; } -void OPPROTO op_fxsave_A0(void) -{ - helper_fxsave(A0, PARAM1); -} - -void OPPROTO op_fxrstor_A0(void) -{ - helper_fxrstor(A0, PARAM1); -} - /* Secure Virtual Machine ops */ void OPPROTO op_vmrun(void) diff --git a/target-i386/translate.c b/target-i386/translate.c index 846628b7a3..7db6b254b4 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -1288,27 +1288,27 @@ static GenOpFunc *gen_setcc_sub[4][8] = { #endif }; -static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = { - gen_op_fadd_ST0_FT0, - gen_op_fmul_ST0_FT0, - gen_op_fcom_ST0_FT0, - gen_op_fcom_ST0_FT0, - gen_op_fsub_ST0_FT0, - gen_op_fsubr_ST0_FT0, - gen_op_fdiv_ST0_FT0, - gen_op_fdivr_ST0_FT0, +static void *helper_fp_arith_ST0_FT0[8] = { + helper_fadd_ST0_FT0, + helper_fmul_ST0_FT0, + helper_fcom_ST0_FT0, + helper_fcom_ST0_FT0, + helper_fsub_ST0_FT0, + helper_fsubr_ST0_FT0, + helper_fdiv_ST0_FT0, + helper_fdivr_ST0_FT0, }; /* NOTE the exception in "r" op ordering */ -static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = { - gen_op_fadd_STN_ST0, - gen_op_fmul_STN_ST0, +static void *helper_fp_arith_STN_ST0[8] = { + helper_fadd_STN_ST0, + helper_fmul_STN_ST0, NULL, NULL, - gen_op_fsubr_STN_ST0, - gen_op_fsub_STN_ST0, - gen_op_fdivr_STN_ST0, - gen_op_fdiv_STN_ST0, + helper_fsubr_STN_ST0, + helper_fsub_STN_ST0, + helper_fdivr_STN_ST0, + helper_fdiv_STN_ST0, }; /* if d == OR_TMP0, it means memory operand (address in A0) */ @@ -3014,7 +3014,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm])); tcg_gen_helper_1_1(helper_movmskps, cpu_tmp2, cpu_ptr0); - tcg_gen_extu_i32_i64(cpu_T[0], cpu_tmp2); + tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2); gen_op_mov_reg_T0(OT_LONG, reg); break; case 0x150: /* movmskpd */ @@ -3022,7 +3022,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm])); tcg_gen_helper_1_1(helper_movmskpd, cpu_tmp2, cpu_ptr0); - tcg_gen_extu_i32_i64(cpu_T[0], cpu_tmp2); + tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2); gen_op_mov_reg_T0(OT_LONG, reg); break; case 0x02a: /* cvtpi2ps */ @@ -3113,7 +3113,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset); if (ot == OT_LONG) { tcg_gen_helper_1_1(sse_op2, cpu_tmp2, cpu_ptr0); - tcg_gen_extu_i32_i64(cpu_T[0], cpu_tmp2); + tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2); } else { tcg_gen_helper_1_1(sse_op2, cpu_T[0], cpu_ptr0); } @@ -3301,7 +3301,6 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) } } - /* convert one instruction. s->is_jmp is set if the translation must be stopped. Return the next pc value */ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) @@ -4536,24 +4535,32 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) switch(op >> 4) { case 0: - gen_op_flds_FT0_A0(); + gen_op_ld_T0_A0(OT_LONG); + tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]); + tcg_gen_helper_0_1(helper_flds_FT0, cpu_tmp2); break; case 1: - gen_op_fildl_FT0_A0(); + gen_op_ld_T0_A0(OT_LONG); + tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]); + tcg_gen_helper_0_1(helper_fildl_FT0, cpu_tmp2); break; case 2: - gen_op_fldl_FT0_A0(); + tcg_gen_qemu_ld64(cpu_tmp1, cpu_A0, + (s->mem_index >> 2) - 1); + tcg_gen_helper_0_1(helper_fldl_FT0, cpu_tmp1); break; case 3: default: - gen_op_fild_FT0_A0(); + gen_op_ld_T0_A0(OT_WORD); + tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]); + tcg_gen_helper_0_1(helper_fildl_FT0, cpu_tmp2); break; } - gen_op_fp_arith_ST0_FT0[op1](); + tcg_gen_helper_0_0(helper_fp_arith_ST0_FT0[op1]); if (op1 == 3) { /* fcomp needs pop */ - gen_op_fpop(); + tcg_gen_helper_0_0(helper_fpop); } } break; @@ -4567,96 +4574,158 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0: switch(op >> 4) { case 0: - gen_op_flds_ST0_A0(); + gen_op_ld_T0_A0(OT_LONG); + tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]); + tcg_gen_helper_0_1(helper_flds_ST0, cpu_tmp2); break; case 1: - gen_op_fildl_ST0_A0(); + gen_op_ld_T0_A0(OT_LONG); + tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]); + tcg_gen_helper_0_1(helper_fildl_ST0, cpu_tmp2); break; case 2: - gen_op_fldl_ST0_A0(); + tcg_gen_qemu_ld64(cpu_tmp1, cpu_A0, + (s->mem_index >> 2) - 1); + tcg_gen_helper_0_1(helper_fldl_ST0, cpu_tmp1); break; case 3: default: - gen_op_fild_ST0_A0(); + gen_op_ld_T0_A0(OT_WORD); + tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]); + tcg_gen_helper_0_1(helper_fildl_ST0, cpu_tmp2); break; } break; case 1: + /* XXX: the corresponding CPUID bit must be tested ! */ switch(op >> 4) { case 1: - gen_op_fisttl_ST0_A0(); + tcg_gen_helper_1_0(helper_fisttl_ST0, cpu_tmp2); + tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2); + gen_op_st_T0_A0(OT_LONG); break; case 2: - gen_op_fisttll_ST0_A0(); + tcg_gen_helper_1_0(helper_fisttll_ST0, cpu_tmp1); + tcg_gen_qemu_st64(cpu_tmp1, cpu_A0, + (s->mem_index >> 2) - 1); break; case 3: default: - gen_op_fistt_ST0_A0(); + tcg_gen_helper_1_0(helper_fistt_ST0, cpu_tmp2); + tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2); + gen_op_st_T0_A0(OT_WORD); + break; } - gen_op_fpop(); + tcg_gen_helper_0_0(helper_fpop); break; default: switch(op >> 4) { case 0: - gen_op_fsts_ST0_A0(); + tcg_gen_helper_1_0(helper_fsts_ST0, cpu_tmp2); + tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2); + gen_op_st_T0_A0(OT_LONG); break; case 1: - gen_op_fistl_ST0_A0(); + tcg_gen_helper_1_0(helper_fistl_ST0, cpu_tmp2); + tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2); + gen_op_st_T0_A0(OT_LONG); break; case 2: - gen_op_fstl_ST0_A0(); + tcg_gen_helper_1_0(helper_fstl_ST0, cpu_tmp1); + tcg_gen_qemu_st64(cpu_tmp1, cpu_A0, + (s->mem_index >> 2) - 1); break; case 3: default: - gen_op_fist_ST0_A0(); + tcg_gen_helper_1_0(helper_fist_ST0, cpu_tmp2); + tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2); + gen_op_st_T0_A0(OT_WORD); break; } if ((op & 7) == 3) - gen_op_fpop(); + tcg_gen_helper_0_0(helper_fpop); break; } break; case 0x0c: /* fldenv mem */ - gen_op_fldenv_A0(s->dflag); + if (s->cc_op != CC_OP_DYNAMIC) + gen_op_set_cc_op(s->cc_op); + gen_jmp_im(pc_start - s->cs_base); + tcg_gen_helper_0_2(helper_fldenv, + cpu_A0, tcg_const_i32(s->dflag)); break; case 0x0d: /* fldcw mem */ - gen_op_fldcw_A0(); + gen_op_ld_T0_A0(OT_WORD + s->mem_index); + tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]); + tcg_gen_helper_0_1(helper_fldcw, cpu_tmp2); break; case 0x0e: /* fnstenv mem */ - gen_op_fnstenv_A0(s->dflag); + if (s->cc_op != CC_OP_DYNAMIC) + gen_op_set_cc_op(s->cc_op); + gen_jmp_im(pc_start - s->cs_base); + tcg_gen_helper_0_2(helper_fstenv, + cpu_A0, tcg_const_i32(s->dflag)); break; case 0x0f: /* fnstcw mem */ - gen_op_fnstcw_A0(); + tcg_gen_helper_1_0(helper_fnstcw, cpu_tmp2); + tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2); + gen_op_st_T0_A0(OT_WORD + s->mem_index); break; case 0x1d: /* fldt mem */ - gen_op_fldt_ST0_A0(); + if (s->cc_op != CC_OP_DYNAMIC) + gen_op_set_cc_op(s->cc_op); + gen_jmp_im(pc_start - s->cs_base); + tcg_gen_helper_0_1(helper_fldt_ST0, cpu_A0); break; case 0x1f: /* fstpt mem */ - gen_op_fstt_ST0_A0(); - gen_op_fpop(); + if (s->cc_op != CC_OP_DYNAMIC) + gen_op_set_cc_op(s->cc_op); + gen_jmp_im(pc_start - s->cs_base); + tcg_gen_helper_0_1(helper_fstt_ST0, cpu_A0); + tcg_gen_helper_0_0(helper_fpop); break; case 0x2c: /* frstor mem */ - gen_op_frstor_A0(s->dflag); + if (s->cc_op != CC_OP_DYNAMIC) + gen_op_set_cc_op(s->cc_op); + gen_jmp_im(pc_start - s->cs_base); + tcg_gen_helper_0_2(helper_frstor, + cpu_A0, tcg_const_i32(s->dflag)); break; case 0x2e: /* fnsave mem */ - gen_op_fnsave_A0(s->dflag); + if (s->cc_op != CC_OP_DYNAMIC) + gen_op_set_cc_op(s->cc_op); + gen_jmp_im(pc_start - s->cs_base); + tcg_gen_helper_0_2(helper_fsave, + cpu_A0, tcg_const_i32(s->dflag)); break; case 0x2f: /* fnstsw mem */ - gen_op_fnstsw_A0(); + tcg_gen_helper_1_0(helper_fnstsw, cpu_tmp2); + tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2); + gen_op_st_T0_A0(OT_WORD + s->mem_index); break; case 0x3c: /* fbld */ - gen_op_fbld_ST0_A0(); + if (s->cc_op != CC_OP_DYNAMIC) + gen_op_set_cc_op(s->cc_op); + gen_jmp_im(pc_start - s->cs_base); + tcg_gen_helper_0_1(helper_fbld_ST0, cpu_A0); break; case 0x3e: /* fbstp */ - gen_op_fbst_ST0_A0(); - gen_op_fpop(); + if (s->cc_op != CC_OP_DYNAMIC) + gen_op_set_cc_op(s->cc_op); + gen_jmp_im(pc_start - s->cs_base); + tcg_gen_helper_0_1(helper_fbst_ST0, cpu_A0); + tcg_gen_helper_0_0(helper_fpop); break; case 0x3d: /* fildll */ - gen_op_fildll_ST0_A0(); + tcg_gen_qemu_ld64(cpu_tmp1, cpu_A0, + (s->mem_index >> 2) - 1); + tcg_gen_helper_0_1(helper_fildll_ST0, cpu_tmp1); break; case 0x3f: /* fistpll */ - gen_op_fistll_ST0_A0(); - gen_op_fpop(); + tcg_gen_helper_1_0(helper_fistll_ST0, cpu_tmp1); + tcg_gen_qemu_st64(cpu_tmp1, cpu_A0, + (s->mem_index >> 2) - 1); + tcg_gen_helper_0_0(helper_fpop); break; default: goto illegal_op; @@ -4667,13 +4736,13 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) switch(op) { case 0x08: /* fld sti */ - gen_op_fpush(); - gen_op_fmov_ST0_STN((opreg + 1) & 7); + tcg_gen_helper_0_0(helper_fpush); + tcg_gen_helper_0_1(helper_fmov_ST0_STN, tcg_const_i32((opreg + 1) & 7)); break; case 0x09: /* fxchg sti */ case 0x29: /* fxchg4 sti, undocumented op */ case 0x39: /* fxchg7 sti, undocumented op */ - gen_op_fxchg_ST0_STN(opreg); + tcg_gen_helper_0_1(helper_fxchg_ST0_STN, tcg_const_i32(opreg)); break; case 0x0a: /* grp d9/2 */ switch(rm) { @@ -4682,7 +4751,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); - gen_op_fwait(); + tcg_gen_helper_0_0(helper_fwait); break; default: goto illegal_op; @@ -4691,17 +4760,17 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0x0c: /* grp d9/4 */ switch(rm) { case 0: /* fchs */ - gen_op_fchs_ST0(); + tcg_gen_helper_0_0(helper_fchs_ST0); break; case 1: /* fabs */ - gen_op_fabs_ST0(); + tcg_gen_helper_0_0(helper_fabs_ST0); break; case 4: /* ftst */ - gen_op_fldz_FT0(); - gen_op_fcom_ST0_FT0(); + tcg_gen_helper_0_0(helper_fldz_FT0); + tcg_gen_helper_0_0(helper_fcom_ST0_FT0); break; case 5: /* fxam */ - gen_op_fxam_ST0(); + tcg_gen_helper_0_0(helper_fxam_ST0); break; default: goto illegal_op; @@ -4711,32 +4780,32 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) { switch(rm) { case 0: - gen_op_fpush(); - gen_op_fld1_ST0(); + tcg_gen_helper_0_0(helper_fpush); + tcg_gen_helper_0_0(helper_fld1_ST0); break; case 1: - gen_op_fpush(); - gen_op_fldl2t_ST0(); + tcg_gen_helper_0_0(helper_fpush); + tcg_gen_helper_0_0(helper_fldl2t_ST0); break; case 2: - gen_op_fpush(); - gen_op_fldl2e_ST0(); + tcg_gen_helper_0_0(helper_fpush); + tcg_gen_helper_0_0(helper_fldl2e_ST0); break; case 3: - gen_op_fpush(); - gen_op_fldpi_ST0(); + tcg_gen_helper_0_0(helper_fpush); + tcg_gen_helper_0_0(helper_fldpi_ST0); break; case 4: - gen_op_fpush(); - gen_op_fldlg2_ST0(); + tcg_gen_helper_0_0(helper_fpush); + tcg_gen_helper_0_0(helper_fldlg2_ST0); break; case 5: - gen_op_fpush(); - gen_op_fldln2_ST0(); + tcg_gen_helper_0_0(helper_fpush); + tcg_gen_helper_0_0(helper_fldln2_ST0); break; case 6: - gen_op_fpush(); - gen_op_fldz_ST0(); + tcg_gen_helper_0_0(helper_fpush); + tcg_gen_helper_0_0(helper_fldz_ST0); break; default: goto illegal_op; @@ -4746,58 +4815,58 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0x0e: /* grp d9/6 */ switch(rm) { case 0: /* f2xm1 */ - gen_op_f2xm1(); + tcg_gen_helper_0_0(helper_f2xm1); break; case 1: /* fyl2x */ - gen_op_fyl2x(); + tcg_gen_helper_0_0(helper_fyl2x); break; case 2: /* fptan */ - gen_op_fptan(); + tcg_gen_helper_0_0(helper_fptan); break; case 3: /* fpatan */ - gen_op_fpatan(); + tcg_gen_helper_0_0(helper_fpatan); break; case 4: /* fxtract */ - gen_op_fxtract(); + tcg_gen_helper_0_0(helper_fxtract); break; case 5: /* fprem1 */ - gen_op_fprem1(); + tcg_gen_helper_0_0(helper_fprem1); break; case 6: /* fdecstp */ - gen_op_fdecstp(); + tcg_gen_helper_0_0(helper_fdecstp); break; default: case 7: /* fincstp */ - gen_op_fincstp(); + tcg_gen_helper_0_0(helper_fincstp); break; } break; case 0x0f: /* grp d9/7 */ switch(rm) { case 0: /* fprem */ - gen_op_fprem(); + tcg_gen_helper_0_0(helper_fprem); break; case 1: /* fyl2xp1 */ - gen_op_fyl2xp1(); + tcg_gen_helper_0_0(helper_fyl2xp1); break; case 2: /* fsqrt */ - gen_op_fsqrt(); + tcg_gen_helper_0_0(helper_fsqrt); break; case 3: /* fsincos */ - gen_op_fsincos(); + tcg_gen_helper_0_0(helper_fsincos); break; case 5: /* fscale */ - gen_op_fscale(); + tcg_gen_helper_0_0(helper_fscale); break; case 4: /* frndint */ - gen_op_frndint(); + tcg_gen_helper_0_0(helper_frndint); break; case 6: /* fsin */ - gen_op_fsin(); + tcg_gen_helper_0_0(helper_fsin); break; default: case 7: /* fcos */ - gen_op_fcos(); + tcg_gen_helper_0_0(helper_fcos); break; } break; @@ -4809,34 +4878,34 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) op1 = op & 7; if (op >= 0x20) { - gen_op_fp_arith_STN_ST0[op1](opreg); + tcg_gen_helper_0_1(helper_fp_arith_STN_ST0[op1], tcg_const_i32(opreg)); if (op >= 0x30) - gen_op_fpop(); + tcg_gen_helper_0_0(helper_fpop); } else { - gen_op_fmov_FT0_STN(opreg); - gen_op_fp_arith_ST0_FT0[op1](); + tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(opreg)); + tcg_gen_helper_0_0(helper_fp_arith_ST0_FT0[op1]); } } break; case 0x02: /* fcom */ case 0x22: /* fcom2, undocumented op */ - gen_op_fmov_FT0_STN(opreg); - gen_op_fcom_ST0_FT0(); + tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(opreg)); + tcg_gen_helper_0_0(helper_fcom_ST0_FT0); break; case 0x03: /* fcomp */ case 0x23: /* fcomp3, undocumented op */ case 0x32: /* fcomp5, undocumented op */ - gen_op_fmov_FT0_STN(opreg); - gen_op_fcom_ST0_FT0(); - gen_op_fpop(); + tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(opreg)); + tcg_gen_helper_0_0(helper_fcom_ST0_FT0); + tcg_gen_helper_0_0(helper_fpop); break; case 0x15: /* da/5 */ switch(rm) { case 1: /* fucompp */ - gen_op_fmov_FT0_STN(1); - gen_op_fucom_ST0_FT0(); - gen_op_fpop(); - gen_op_fpop(); + tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(1)); + tcg_gen_helper_0_0(helper_fucom_ST0_FT0); + tcg_gen_helper_0_0(helper_fpop); + tcg_gen_helper_0_0(helper_fpop); break; default: goto illegal_op; @@ -4849,10 +4918,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 1: /* fdisi (287 only, just do nop here) */ break; case 2: /* fclex */ - gen_op_fclex(); + tcg_gen_helper_0_0(helper_fclex); break; case 3: /* fninit */ - gen_op_fninit(); + tcg_gen_helper_0_0(helper_fninit); break; case 4: /* fsetpm (287 only, just do nop here) */ break; @@ -4863,59 +4932,63 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0x1d: /* fucomi */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - gen_op_fmov_FT0_STN(opreg); - gen_op_fucomi_ST0_FT0(); + tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(opreg)); + tcg_gen_helper_0_0(helper_fucomi_ST0_FT0); + gen_op_fcomi_dummy(); s->cc_op = CC_OP_EFLAGS; break; case 0x1e: /* fcomi */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - gen_op_fmov_FT0_STN(opreg); - gen_op_fcomi_ST0_FT0(); + tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(opreg)); + tcg_gen_helper_0_0(helper_fcomi_ST0_FT0); + gen_op_fcomi_dummy(); s->cc_op = CC_OP_EFLAGS; break; case 0x28: /* ffree sti */ - gen_op_ffree_STN(opreg); + tcg_gen_helper_0_1(helper_ffree_STN, tcg_const_i32(opreg)); break; case 0x2a: /* fst sti */ - gen_op_fmov_STN_ST0(opreg); + tcg_gen_helper_0_1(helper_fmov_STN_ST0, tcg_const_i32(opreg)); break; case 0x2b: /* fstp sti */ case 0x0b: /* fstp1 sti, undocumented op */ case 0x3a: /* fstp8 sti, undocumented op */ case 0x3b: /* fstp9 sti, undocumented op */ - gen_op_fmov_STN_ST0(opreg); - gen_op_fpop(); + tcg_gen_helper_0_1(helper_fmov_STN_ST0, tcg_const_i32(opreg)); + tcg_gen_helper_0_0(helper_fpop); break; case 0x2c: /* fucom st(i) */ - gen_op_fmov_FT0_STN(opreg); - gen_op_fucom_ST0_FT0(); + tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(opreg)); + tcg_gen_helper_0_0(helper_fucom_ST0_FT0); break; case 0x2d: /* fucomp st(i) */ - gen_op_fmov_FT0_STN(opreg); - gen_op_fucom_ST0_FT0(); - gen_op_fpop(); + tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(opreg)); + tcg_gen_helper_0_0(helper_fucom_ST0_FT0); + tcg_gen_helper_0_0(helper_fpop); break; case 0x33: /* de/3 */ switch(rm) { case 1: /* fcompp */ - gen_op_fmov_FT0_STN(1); - gen_op_fcom_ST0_FT0(); - gen_op_fpop(); - gen_op_fpop(); + tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(1)); + tcg_gen_helper_0_0(helper_fcom_ST0_FT0); + tcg_gen_helper_0_0(helper_fpop); + tcg_gen_helper_0_0(helper_fpop); break; default: goto illegal_op; } break; case 0x38: /* ffreep sti, undocumented op */ - gen_op_ffree_STN(opreg); - gen_op_fpop(); + tcg_gen_helper_0_1(helper_ffree_STN, tcg_const_i32(opreg)); + tcg_gen_helper_0_0(helper_fpop); break; case 0x3c: /* df/4 */ switch(rm) { case 0: - gen_op_fnstsw_EAX(); + tcg_gen_helper_1_0(helper_fnstsw, cpu_tmp2); + tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2); + gen_op_mov_reg_T0(OT_WORD, R_EAX); break; default: goto illegal_op; @@ -4924,23 +4997,25 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0x3d: /* fucomip */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - gen_op_fmov_FT0_STN(opreg); - gen_op_fucomi_ST0_FT0(); - gen_op_fpop(); + tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(opreg)); + tcg_gen_helper_0_0(helper_fucomi_ST0_FT0); + tcg_gen_helper_0_0(helper_fpop); + gen_op_fcomi_dummy(); s->cc_op = CC_OP_EFLAGS; break; case 0x3e: /* fcomip */ if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - gen_op_fmov_FT0_STN(opreg); - gen_op_fcomi_ST0_FT0(); - gen_op_fpop(); + tcg_gen_helper_0_1(helper_fmov_FT0_STN, tcg_const_i32(opreg)); + tcg_gen_helper_0_0(helper_fcomi_ST0_FT0); + tcg_gen_helper_0_0(helper_fpop); + gen_op_fcomi_dummy(); s->cc_op = CC_OP_EFLAGS; break; case 0x10 ... 0x13: /* fcmovxx */ case 0x18 ... 0x1b: { - int op1; + int op1, l1; const static uint8_t fcmov_cc[8] = { (JCC_B << 1), (JCC_Z << 1), @@ -4949,7 +5024,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) }; op1 = fcmov_cc[op & 3] | ((op >> 3) & 1); gen_setcc(s, op1); - gen_op_fcmov_ST0_STN_T0(opreg); + l1 = gen_new_label(); + tcg_gen_brcond_tl(TCG_COND_EQ, cpu_T[0], tcg_const_tl(0), l1); + tcg_gen_helper_0_1(helper_fmov_ST0_STN, tcg_const_i32(opreg)); + gen_set_label(l1); } break; default: @@ -5550,7 +5628,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); - gen_op_fwait(); + tcg_gen_helper_0_0(helper_fwait); } break; case 0xcc: /* int3 */ @@ -6301,7 +6379,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) break; } gen_lea_modrm(s, modrm, ®_addr, &offset_addr); - gen_op_fxsave_A0((s->dflag == 2)); + if (s->cc_op != CC_OP_DYNAMIC) + gen_op_set_cc_op(s->cc_op); + gen_jmp_im(pc_start - s->cs_base); + tcg_gen_helper_0_2(helper_fxsave, + cpu_A0, tcg_const_i32((s->dflag == 2))); break; case 1: /* fxrstor */ if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) || @@ -6312,7 +6394,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) break; } gen_lea_modrm(s, modrm, ®_addr, &offset_addr); - gen_op_fxrstor_A0((s->dflag == 2)); + if (s->cc_op != CC_OP_DYNAMIC) + gen_op_set_cc_op(s->cc_op); + gen_jmp_im(pc_start - s->cs_base); + tcg_gen_helper_0_2(helper_fxrstor, + cpu_A0, tcg_const_i32((s->dflag == 2))); break; case 2: /* ldmxcsr */ case 3: /* stmxcsr */ @@ -6615,8 +6701,8 @@ static uint16_t opc_write_flags[NB_OPS] = { [INDEX_op_lsl] = CC_Z, [INDEX_op_verr] = CC_Z, [INDEX_op_verw] = CC_Z, - [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C, - [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C, + [INDEX_op_fcomi_dummy] = CC_Z | CC_P | CC_C, + [INDEX_op_fcomi_dummy] = CC_Z | CC_P | CC_C, #define DEF_WRITEF(SUFFIX)\ [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\ |