mirror of
https://github.com/qemu/qemu.git
synced 2024-11-26 04:13:39 +08:00
converted x87 FPU ops to TCG
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4444 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
4da450e616
commit
19e6c4b8bc
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
740
target-i386/op.c
740
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)
|
||||
void OPPROTO op_fcomi_dummy(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)
|
||||
{
|
||||
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)
|
||||
|
@ -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,\
|
||||
|
Loading…
Reference in New Issue
Block a user