提交 19e6c4b8 编写于 作者: B bellard

converted x87 FPU ops to TCG

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4444 c046a42c-6fe2-441c-8c8c-71466251a162
上级 4da450e6
......@@ -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);
......
......@@ -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)
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册