Merge "target-i386: Fix FPU helpers." into idea133
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index de23359..44f29e1 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -661,16 +661,6 @@
CC_OP_NB,
};
-#ifdef FLOATX80
-#define USE_X86LDOUBLE
-#endif
-
-#ifdef USE_X86LDOUBLE
-typedef floatx80 CPU86_LDouble;
-#else
-typedef float64 CPU86_LDouble;
-#endif
-
typedef struct SegmentCache {
uint32_t selector;
target_ulong base;
@@ -775,18 +765,11 @@
unsigned int fpus;
unsigned int fpuc;
uint8_t fptags[8]; /* 0 = valid, 1 = empty */
- union {
-#ifdef USE_X86LDOUBLE
- CPU86_LDouble d __attribute__((aligned(16)));
-#else
- CPU86_LDouble d;
-#endif
- MMXReg mmx;
- } fpregs[8];
+ FPReg fpregs[8];
/* emulator internal variables */
float_status fp_status;
- CPU86_LDouble ft0;
+ floatx80 ft0;
float_status mmx_status; /* for 3DNow! float ops */
float_status sse_status;
@@ -955,8 +938,8 @@
/* op_helper.c */
/* used for debug or cpu save/restore */
-void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f);
-CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper);
+void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, floatx80 f);
+floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper);
/* cpu-exec.c */
/* the following helpers are only usable in user mode simulation as
diff --git a/target-i386/exec.h b/target-i386/exec.h
index d39f8de..00a248f 100644
--- a/target-i386/exec.h
+++ b/target-i386/exec.h
@@ -89,41 +89,6 @@
#endif /* !defined(CONFIG_USER_ONLY) */
-#ifdef USE_X86LDOUBLE
-/* use long double functions */
-#define floatx_to_int32 floatx80_to_int32
-#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
-#define floatx_compare floatx80_compare
-#define floatx_compare_quiet floatx80_compare_quiet
-#else
-#define floatx_to_int32 float64_to_int32
-#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
-#define floatx_compare float64_compare
-#define floatx_compare_quiet float64_compare_quiet
-#endif
-
#define RC_MASK 0xc00
#define RC_NEAR 0x000
#define RC_DOWN 0x400
@@ -132,17 +97,6 @@
#define MAXTAN 9223372036854775808.0
-#ifdef USE_X86LDOUBLE
-
-/* only for x86 */
-typedef union {
- long double d;
- struct {
- unsigned long long lower;
- unsigned short upper;
- } l;
-} CPU86_LDoubleU;
-
/* the following deal with x86 long double-precision numbers */
#define MAXEXPD 0x7fff
#define EXPBIAS 16383
@@ -151,40 +105,6 @@
#define MANTD(fp) (fp.l.lower)
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
-#else
-
-/* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */
-typedef union {
- double d;
-#if !defined(WORDS_BIGENDIAN) && !defined(__arm__)
- struct {
- uint32_t lower;
- int32_t upper;
- } l;
-#else
- struct {
- int32_t upper;
- uint32_t lower;
- } l;
-#endif
-#ifndef __arm__
- int64_t ll;
-#endif
-} CPU86_LDoubleU;
-
-/* the following deal with IEEE double-precision numbers */
-#define MAXEXPD 0x7ff
-#define EXPBIAS 1023
-#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF)
-#define SIGND(fp) ((fp.l.upper) & 0x80000000)
-#ifdef __arm__
-#define MANTD(fp) (fp.l.lower | ((uint64_t)(fp.l.upper & ((1 << 20) - 1)) << 32))
-#else
-#define MANTD(fp) (fp.ll & ((1LL << 52) - 1))
-#endif
-#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20)
-#endif
-
static inline void fpush(void)
{
env->fpstt = (env->fpstt - 1) & 7;
@@ -197,64 +117,20 @@
env->fpstt = (env->fpstt + 1) & 7;
}
-#ifndef USE_X86LDOUBLE
-static inline CPU86_LDouble helper_fldt(target_ulong ptr)
+static inline floatx80 helper_fldt(target_ulong ptr)
{
- CPU86_LDoubleU temp;
- int upper, e;
- uint64_t ll;
+ floatx80 temp;
- /* mantissa */
- upper = lduw(ptr + 8);
- /* XXX: handle overflow ? */
- e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
- e |= (upper >> 4) & 0x800; /* sign */
- ll = (ldq(ptr) >> 11) & ((1LL << 52) - 1);
-#ifdef __arm__
- temp.l.upper = (e << 20) | (ll >> 32);
- temp.l.lower = ll;
-#else
- temp.ll = ll | ((uint64_t)e << 52);
-#endif
- return temp.d;
+ temp.low = ldq(ptr);
+ temp.high = lduw(ptr + 8);
+ return temp;
}
-static inline void helper_fstt(CPU86_LDouble f, target_ulong ptr)
+static inline void helper_fstt(floatx80 f, target_ulong ptr)
{
- CPU86_LDoubleU temp;
- int e;
-
- temp.d = f;
- /* mantissa */
- stq(ptr, (MANTD(temp) << 11) | (1LL << 63));
- /* exponent + sign */
- e = EXPD(temp) - EXPBIAS + 16383;
- e |= SIGND(temp) >> 16;
- stw(ptr + 8, e);
+ stq(ptr, f.low);
+ stw(ptr + 8, f.high);
}
-#else
-
-/* we use memory access macros */
-
-static inline CPU86_LDouble helper_fldt(target_ulong ptr)
-{
- CPU86_LDoubleU temp;
-
- temp.l.lower = ldq(ptr);
- temp.l.upper = lduw(ptr + 8);
- return temp.d;
-}
-
-static inline void helper_fstt(CPU86_LDouble f, target_ulong ptr)
-{
- CPU86_LDoubleU temp;
-
- temp.d = f;
- stq(ptr, temp.l.lower);
- stw(ptr + 8, temp.l.upper);
-}
-
-#endif /* USE_X86LDOUBLE */
#define FPUS_IE (1 << 0)
#define FPUS_DE (1 << 1)
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 1b96133..29af579 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -804,21 +804,8 @@
fptag,
env->mxcsr);
for(i=0;i<8;i++) {
-#if defined(USE_X86LDOUBLE)
- union {
- long double d;
- struct {
- uint64_t lower;
- uint16_t upper;
- } l;
- } tmp;
- tmp.d = env->fpregs[i].d;
- cpu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
- i, tmp.l.lower, tmp.l.upper);
-#else
cpu_fprintf(f, "FPR%d=%016" PRIx64,
i, env->fpregs[i].mmx.q);
-#endif
if ((i & 1) == 1)
cpu_fprintf(f, "\n");
else
diff --git a/target-i386/machine.c b/target-i386/machine.c
index 665b6bd..65409ac 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -51,31 +51,15 @@
qemu_put_be16s(f, &fpus);
qemu_put_be16s(f, &fptag);
-#ifdef USE_X86LDOUBLE
- fpregs_format = 0;
-#else
fpregs_format = 1;
-#endif
qemu_put_be16s(f, &fpregs_format);
for(i = 0; i < 8; i++) {
-#ifdef USE_X86LDOUBLE
- {
- uint64_t mant;
- uint16_t exp;
- /* we save the real CPU data (in case of MMX usage only 'mant'
- contains the MMX register */
- cpu_get_fp80(&mant, &exp, env->fpregs[i].d);
- qemu_put_be64(f, mant);
- qemu_put_be16(f, exp);
- }
-#else
/* if we use doubles for float emulation, we save the doubles to
avoid losing information in case of MMX usage. It can give
problems if the image is restored on a CPU where long
doubles are used instead. */
qemu_put_be64(f, env->fpregs[i].mmx.MMX_Q(0));
-#endif
}
for(i = 0; i < 6; i++)
@@ -161,30 +145,6 @@
}
}
-#ifdef USE_X86LDOUBLE
-/* XXX: add that in a FPU generic layer */
-union x86_longdouble {
- uint64_t mant;
- uint16_t exp;
-};
-
-#define MANTD1(fp) (fp & ((1LL << 52) - 1))
-#define EXPBIAS1 1023
-#define EXPD1(fp) ((fp >> 52) & 0x7FF)
-#define SIGND1(fp) ((fp >> 32) & 0x80000000)
-
-static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp)
-{
- int e;
- /* mantissa */
- p->mant = (MANTD1(temp) << 11) | (1LL << 63);
- /* exponent + sign */
- e = EXPD1(temp) - EXPBIAS1 + 16383;
- e |= SIGND1(temp) >> 16;
- p->exp = e;
-}
-#endif
-
int cpu_load(QEMUFile *f, void *opaque, int version_id)
{
CPUX86State *env = opaque;
@@ -218,33 +178,15 @@
case 0:
mant = qemu_get_be64(f);
exp = qemu_get_be16(f);
-#ifdef USE_X86LDOUBLE
- env->fpregs[i].d = cpu_set_fp80(mant, exp);
-#else
/* difficult case */
if (guess_mmx)
env->fpregs[i].mmx.MMX_Q(0) = mant;
else
env->fpregs[i].d = cpu_set_fp80(mant, exp);
-#endif
break;
case 1:
mant = qemu_get_be64(f);
-#ifdef USE_X86LDOUBLE
- {
- union x86_longdouble *p;
- /* difficult case */
- p = (void *)&env->fpregs[i];
- if (guess_mmx) {
- p->mant = mant;
- p->exp = 0xffff;
- } else {
- fp64_to_fp80(p, mant);
- }
- }
-#else
env->fpregs[i].mmx.MMX_Q(0) = mant;
-#endif
break;
default:
return -EINVAL;
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index d980a05..1cdc2bf 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -96,15 +96,19 @@
6, 7, 8, 0, 1, 2, 3, 4,
};
-static const CPU86_LDouble f15rk[7] =
+#define floatx80_lg2 make_floatx80( 0x3ffd, 0x9a209a84fbcff799LL )
+#define floatx80_l2e make_floatx80( 0x3fff, 0xb8aa3b295c17f0bcLL )
+#define floatx80_l2t make_floatx80( 0x4000, 0xd49a784bcd1b8afeLL )
+
+static const floatx80 f15rk[7] =
{
- 0.00000000000000000000L,
- 1.00000000000000000000L,
- 3.14159265358979323851L, /*pi*/
- 0.30102999566398119523L, /*lg2*/
- 0.69314718055994530943L, /*ln2*/
- 1.44269504088896340739L, /*l2e*/
- 3.32192809488736234781L, /*l2t*/
+ floatx80_zero,
+ floatx80_one,
+ floatx80_pi,
+ floatx80_lg2,
+ floatx80_ln2,
+ floatx80_l2e,
+ floatx80_l2t,
};
/* broken thread support */
@@ -3411,6 +3415,28 @@
/* x87 FPU helpers */
+static inline double floatx80_to_double(CPUX86State *env, floatx80 a)
+{
+ union {
+ float64 f64;
+ double d;
+ } u;
+
+ u.f64 = floatx80_to_float64(a, &env->fp_status);
+ return u.d;
+}
+
+static inline floatx80 double_to_floatx80(CPUX86State *env, double a)
+{
+ union {
+ float64 f64;
+ double d;
+ } u;
+
+ u.d = a;
+ return float64_to_floatx80(u.f64, &env->fp_status);
+}
+
static void fpu_set_exception(int mask)
{
env->fpus |= mask;
@@ -3418,16 +3444,12 @@
env->fpus |= FPUS_SE | FPUS_B;
}
-static inline CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b)
+static inline floatx80 helper_fdiv(floatx80 a, floatx80 b)
{
- // NOTE: work-around to prevent a mysterious crash
- // This code will be replaced by better one in a future patch.
- if (float64_is_zero(b)) {
+ if (floatx80_is_zero(b)) {
fpu_set_exception(FPUS_ZE);
- return float64_div(a, b, &env->fp_status);
- } else {
- return a / b;
}
+ return floatx80_div(a, b, &env->fp_status);
}
static void fpu_raise_exception(void)
@@ -3449,7 +3471,7 @@
uint32_t i;
} u;
u.i = val;
- FT0 = float32_to_floatx(u.f, &env->fp_status);
+ FT0 = float32_to_floatx80(u.f, &env->fp_status);
}
void helper_fldl_FT0(uint64_t val)
@@ -3459,12 +3481,12 @@
uint64_t i;
} u;
u.i = val;
- FT0 = float64_to_floatx(u.f, &env->fp_status);
+ FT0 = float64_to_floatx80(u.f, &env->fp_status);
}
void helper_fildl_FT0(int32_t val)
{
- FT0 = int32_to_floatx(val, &env->fp_status);
+ FT0 = int32_to_floatx80(val, &env->fp_status);
}
void helper_flds_ST0(uint32_t val)
@@ -3476,7 +3498,7 @@
} u;
new_fpstt = (env->fpstt - 1) & 7;
u.i = val;
- env->fpregs[new_fpstt].d = float32_to_floatx(u.f, &env->fp_status);
+ env->fpregs[new_fpstt].d = float32_to_floatx80(u.f, &env->fp_status);
env->fpstt = new_fpstt;
env->fptags[new_fpstt] = 0; /* validate stack entry */
}
@@ -3490,7 +3512,7 @@
} u;
new_fpstt = (env->fpstt - 1) & 7;
u.i = val;
- env->fpregs[new_fpstt].d = float64_to_floatx(u.f, &env->fp_status);
+ env->fpregs[new_fpstt].d = float64_to_floatx80(u.f, &env->fp_status);
env->fpstt = new_fpstt;
env->fptags[new_fpstt] = 0; /* validate stack entry */
}
@@ -3499,7 +3521,7 @@
{
int new_fpstt;
new_fpstt = (env->fpstt - 1) & 7;
- env->fpregs[new_fpstt].d = int32_to_floatx(val, &env->fp_status);
+ env->fpregs[new_fpstt].d = int32_to_floatx80(val, &env->fp_status);
env->fpstt = new_fpstt;
env->fptags[new_fpstt] = 0; /* validate stack entry */
}
@@ -3508,7 +3530,7 @@
{
int new_fpstt;
new_fpstt = (env->fpstt - 1) & 7;
- env->fpregs[new_fpstt].d = int64_to_floatx(val, &env->fp_status);
+ env->fpregs[new_fpstt].d = int64_to_floatx80(val, &env->fp_status);
env->fpstt = new_fpstt;
env->fptags[new_fpstt] = 0; /* validate stack entry */
}
@@ -3519,7 +3541,7 @@
float32 f;
uint32_t i;
} u;
- u.f = floatx_to_float32(ST0, &env->fp_status);
+ u.f = floatx80_to_float32(ST0, &env->fp_status);
return u.i;
}
@@ -3529,14 +3551,14 @@
float64 f;
uint64_t i;
} u;
- u.f = floatx_to_float64(ST0, &env->fp_status);
+ u.f = floatx80_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);
+ val = floatx80_to_int32(ST0, &env->fp_status);
if (val != (int16_t)val)
val = -32768;
return val;
@@ -3545,21 +3567,21 @@
int32_t helper_fistl_ST0(void)
{
int32_t val;
- val = floatx_to_int32(ST0, &env->fp_status);
+ val = floatx80_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);
+ val = floatx80_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);
+ val = floatx80_to_int32_round_to_zero(ST0, &env->fp_status);
if (val != (int16_t)val)
val = -32768;
return val;
@@ -3568,14 +3590,14 @@
int32_t helper_fisttl_ST0(void)
{
int32_t val;
- val = floatx_to_int32_round_to_zero(ST0, &env->fp_status);
+ val = floatx80_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);
+ val = floatx80_to_int64_round_to_zero(ST0, &env->fp_status);
return val;
}
@@ -3644,7 +3666,7 @@
void helper_fxchg_ST0_STN(int st_index)
{
- CPU86_LDouble tmp;
+ floatx80 tmp;
tmp = ST(st_index);
ST(st_index) = ST0;
ST0 = tmp;
@@ -3658,7 +3680,7 @@
{
int ret;
- ret = floatx_compare(ST0, FT0, &env->fp_status);
+ ret = floatx80_compare(ST0, FT0, &env->fp_status);
env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
}
@@ -3666,7 +3688,7 @@
{
int ret;
- ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
+ ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status);
env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret+ 1];
}
@@ -3677,7 +3699,7 @@
int eflags;
int ret;
- ret = floatx_compare(ST0, FT0, &env->fp_status);
+ ret = floatx80_compare(ST0, FT0, &env->fp_status);
eflags = helper_cc_compute_all(CC_OP);
eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
CC_SRC = eflags;
@@ -3688,7 +3710,7 @@
int eflags;
int ret;
- ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
+ ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status);
eflags = helper_cc_compute_all(CC_OP);
eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
CC_SRC = eflags;
@@ -3696,22 +3718,22 @@
void helper_fadd_ST0_FT0(void)
{
- ST0 += FT0;
+ ST0 = floatx80_add(ST0, FT0, &env->fp_status);
}
void helper_fmul_ST0_FT0(void)
{
- ST0 *= FT0;
+ ST0 = floatx80_mul(ST0, FT0, &env->fp_status);
}
void helper_fsub_ST0_FT0(void)
{
- ST0 -= FT0;
+ ST0 = floatx80_sub(ST0, FT0, &env->fp_status);
}
void helper_fsubr_ST0_FT0(void)
{
- ST0 = FT0 - ST0;
+ ST0 = floatx80_sub(FT0, ST0, &env->fp_status);
}
void helper_fdiv_ST0_FT0(void)
@@ -3728,36 +3750,36 @@
void helper_fadd_STN_ST0(int st_index)
{
- ST(st_index) += ST0;
+ ST(st_index) = floatx80_add(ST(st_index), ST0, &env->fp_status);
}
void helper_fmul_STN_ST0(int st_index)
{
- ST(st_index) *= ST0;
+ ST(st_index) = floatx80_mul(ST(st_index), ST0, &env->fp_status);
}
void helper_fsub_STN_ST0(int st_index)
{
- ST(st_index) -= ST0;
+ ST(st_index) = floatx80_sub(ST(st_index), ST0, &env->fp_status);
}
void helper_fsubr_STN_ST0(int st_index)
{
- CPU86_LDouble *p;
+ floatx80 *p;
p = &ST(st_index);
- *p = ST0 - *p;
+ *p = floatx80_sub(ST0, *p, &env->fp_status);
}
void helper_fdiv_STN_ST0(int st_index)
{
- CPU86_LDouble *p;
+ floatx80 *p;
p = &ST(st_index);
*p = helper_fdiv(*p, ST0);
}
void helper_fdivr_STN_ST0(int st_index)
{
- CPU86_LDouble *p;
+ floatx80 *p;
p = &ST(st_index);
*p = helper_fdiv(ST0, *p);
}
@@ -3765,12 +3787,12 @@
/* misc FPU operations */
void helper_fchs_ST0(void)
{
- ST0 = floatx_chs(ST0);
+ ST0 = floatx80_chs(ST0);
}
void helper_fabs_ST0(void)
{
- ST0 = floatx_abs(ST0);
+ ST0 = floatx80_abs(ST0);
}
void helper_fld1_ST0(void)
@@ -3844,7 +3866,6 @@
break;
}
set_float_rounding_mode(rnd_type, &env->fp_status);
-#ifdef FLOATX80
switch((env->fpuc >> 8) & 3) {
case 0:
rnd_type = 32;
@@ -3858,7 +3879,6 @@
break;
}
set_floatx80_rounding_precision(rnd_type, &env->fp_status);
-#endif
}
void helper_fldcw(uint32_t val)
@@ -3897,7 +3917,7 @@
void helper_fbld_ST0(target_ulong ptr)
{
- CPU86_LDouble tmp;
+ floatx80 tmp;
uint64_t val;
unsigned int v;
int i;
@@ -3907,9 +3927,10 @@
v = ldub(ptr + i);
val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
}
- tmp = val;
- if (ldub(ptr + 9) & 0x80)
- tmp = -tmp;
+ tmp = int64_to_floatx80(val, &env->fp_status);
+ if (ldub(ptr + 9) & 0x80) {
+ floatx80_chs(tmp);
+ }
fpush();
ST0 = tmp;
}
@@ -3920,7 +3941,7 @@
target_ulong mem_ref, mem_end;
int64_t val;
- val = floatx_to_int64(ST0, &env->fp_status);
+ val = floatx80_to_int64(ST0, &env->fp_status);
mem_ref = ptr;
mem_end = mem_ref + 9;
if (val < 0) {
@@ -3944,17 +3965,19 @@
void helper_f2xm1(void)
{
- ST0 = pow(2.0,ST0) - 1.0;
+ double val = floatx80_to_double(env, ST0);
+ val = pow(2.0, val) - 1.0;
+ ST0 = double_to_floatx80(env, val);
}
void helper_fyl2x(void)
{
- CPU86_LDouble fptemp;
+ double fptemp = floatx80_to_double(env, ST0);
- fptemp = ST0;
if (fptemp>0.0){
fptemp = log(fptemp)/log(2.0); /* log2(ST) */
- ST1 *= fptemp;
+ fptemp *= floatx80_to_double(env, ST1);
+ ST1 = double_to_floatx80(env, fptemp);
fpop();
} else {
env->fpus &= (~0x4700);
@@ -3964,15 +3987,15 @@
void helper_fptan(void)
{
- CPU86_LDouble fptemp;
+ double fptemp = floatx80_to_double(env, ST0);
- fptemp = ST0;
if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
env->fpus |= 0x400;
} else {
- ST0 = tan(fptemp);
+ fptemp = tan(fptemp);
+ ST0 = double_to_floatx80(env, fptemp);
fpush();
- ST0 = 1.0;
+ ST0 = floatx80_one;
env->fpus &= (~0x400); /* C2 <-- 0 */
/* the above code is for |arg| < 2**52 only */
}
@@ -3980,23 +4003,23 @@
void helper_fpatan(void)
{
- CPU86_LDouble fptemp, fpsrcop;
+ double fptemp, fpsrcop;
- fpsrcop = ST1;
- fptemp = ST0;
- ST1 = atan2(fpsrcop,fptemp);
+ fpsrcop = floatx80_to_double(env, ST1);
+ fptemp = floatx80_to_double(env, ST0);
+ ST1 = double_to_floatx80(env, atan2(fpsrcop,fptemp));
fpop();
}
void helper_fxtract(void)
{
- CPU86_LDoubleU temp;
+ CPU_LDoubleU temp;
unsigned int expdif;
temp.d = ST0;
expdif = EXPD(temp) - EXPBIAS;
/*DP exponent bias*/
- ST0 = expdif;
+ ST0 = int32_to_floatx80(expdif, &env->fp_status);
fpush();
BIASEXPONENT(temp);
ST0 = temp.d;
@@ -4004,21 +4027,24 @@
void helper_fprem1(void)
{
- CPU86_LDouble dblq, fpsrcop, fptemp;
- CPU86_LDoubleU fpsrcop1, fptemp1;
+ double st0, st1, dblq, fpsrcop, fptemp;
+ CPU_LDoubleU fpsrcop1, fptemp1;
int expdif;
signed long long int q;
- if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
- ST0 = 0.0 / 0.0; /* NaN */
+ st0 = floatx80_to_double(env, ST0);
+ st1 = floatx80_to_double(env, ST1);
+
+ if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) {
+ ST0 = double_to_floatx80(env, 0.0 / 0.0); /* NaN */
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
return;
}
- fpsrcop = ST0;
- fptemp = ST1;
- fpsrcop1.d = fpsrcop;
- fptemp1.d = fptemp;
+ fpsrcop = st0;
+ fptemp = st1;
+ fpsrcop1.d = ST0;
+ fptemp1.d = ST1;
expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
if (expdif < 0) {
@@ -4032,7 +4058,7 @@
dblq = fpsrcop / fptemp;
/* round dblq towards nearest integer */
dblq = rint(dblq);
- ST0 = fpsrcop - fptemp * dblq;
+ st0 = fpsrcop - fptemp * dblq;
/* convert dblq to q by truncating towards zero */
if (dblq < 0.0)
@@ -4048,54 +4074,59 @@
} else {
env->fpus |= 0x400; /* C2 <-- 1 */
fptemp = pow(2.0, expdif - 50);
- fpsrcop = (ST0 / ST1) / fptemp;
+ fpsrcop = (st0 / st1) / fptemp;
/* fpsrcop = integer obtained by chopping */
fpsrcop = (fpsrcop < 0.0) ?
-(floor(fabs(fpsrcop))) : floor(fpsrcop);
- ST0 -= (ST1 * fpsrcop * fptemp);
+ st0 -= (st1 * fpsrcop * fptemp);
}
+ ST0 = double_to_floatx80(env, st0);
}
void helper_fprem(void)
{
- CPU86_LDouble dblq, fpsrcop, fptemp;
- CPU86_LDoubleU fpsrcop1, fptemp1;
+ double st0, st1, dblq, fpsrcop, fptemp;
+ CPU_LDoubleU fpsrcop1, fptemp1;
int expdif;
signed long long int q;
- if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
- ST0 = 0.0 / 0.0; /* NaN */
+ st0 = floatx80_to_double(env, ST0);
+ st1 = floatx80_to_double(env, ST1);
+
+ if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) {
+ ST0 = double_to_floatx80(env, 0.0 / 0.0); /* NaN */
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
return;
}
- fpsrcop = (CPU86_LDouble)ST0;
- fptemp = (CPU86_LDouble)ST1;
- fpsrcop1.d = fpsrcop;
- fptemp1.d = fptemp;
+ fpsrcop = st0;
+ fptemp = st1;
+ fpsrcop1.d = ST0;
+ fptemp1.d = ST1;
expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
if (expdif < 0) {
/* optimisation? taken from the AMD docs */
- env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
+ env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
/* ST0 is unchanged */
return;
}
- if ( expdif < 53 ) {
- dblq = fpsrcop/*ST0*/ / fptemp/*ST1*/;
+ if (expdif < 53) {
+ dblq = fpsrcop / fptemp; /* ST0 / ST1*/;
/* round dblq towards zero */
dblq = (dblq < 0.0) ? ceil(dblq) : floor(dblq);
- ST0 = fpsrcop/*ST0*/ - fptemp * dblq;
+ st0 = fpsrcop - fptemp * dblq; /* fpsrcop is ST0 */
/* convert dblq to q by truncating towards zero */
- if (dblq < 0.0)
+ if (dblq < 0.0) {
q = (signed long long int)(-dblq);
- else
+ } else {
q = (signed long long int)dblq;
+ }
- env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
- /* (C0,C3,C1) <-- (q2,q1,q0) */
+ env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
+ /* (C0,C3,C1) <-- (q2,q1,q0) */
env->fpus |= (q & 0x4) << (8 - 2); /* (C0) <-- q2 */
env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
env->fpus |= (q & 0x1) << (9 - 0); /* (C1) <-- q0 */
@@ -4103,22 +4134,23 @@
int N = 32 + (expdif % 32); /* as per AMD docs */
env->fpus |= 0x400; /* C2 <-- 1 */
fptemp = pow(2.0, (double)(expdif - N));
- fpsrcop = (ST0 / ST1) / fptemp;
+ fpsrcop = (st0 / st1) / fptemp;
/* fpsrcop = integer obtained by chopping */
fpsrcop = (fpsrcop < 0.0) ?
-(floor(fabs(fpsrcop))) : floor(fpsrcop);
- ST0 -= (ST1 * fpsrcop * fptemp);
+ st0 -= (st1 * fpsrcop * fptemp);
}
+ ST0 = double_to_floatx80(env, st0);
}
void helper_fyl2xp1(void)
{
- CPU86_LDouble fptemp;
+ double fptemp = floatx80_to_double(env, ST0);
- fptemp = ST0;
if ((fptemp+1.0)>0.0) {
fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
- ST1 *= fptemp;
+ fptemp *= floatx80_to_double(env, ST1);
+ ST1 = double_to_floatx80(env, fptemp);
fpop();
} else {
env->fpus &= (~0x4700);
@@ -4128,27 +4160,25 @@
void helper_fsqrt(void)
{
- CPU86_LDouble fptemp;
+ double fptemp = floatx80_to_double(env, ST0);
- fptemp = ST0;
if (fptemp<0.0) {
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
env->fpus |= 0x400;
}
- ST0 = sqrt(fptemp);
+ ST0 = floatx80_sqrt(ST0, &env->fp_status);
}
void helper_fsincos(void)
{
- CPU86_LDouble fptemp;
+ double fptemp = floatx80_to_double(env, ST0);
- fptemp = ST0;
if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
env->fpus |= 0x400;
} else {
- ST0 = sin(fptemp);
+ ST0 = double_to_floatx80(env, sin(fptemp));
fpush();
- ST0 = cos(fptemp);
+ ST0 = double_to_floatx80(env, cos(fptemp));
env->fpus &= (~0x400); /* C2 <-- 0 */
/* the above code is for |arg| < 2**63 only */
}
@@ -4156,23 +4186,25 @@
void helper_frndint(void)
{
- ST0 = floatx_round_to_int(ST0, &env->fp_status);
+ ST0 = floatx80_round_to_int(ST0, &env->fp_status);
}
void helper_fscale(void)
{
- ST0 = ldexp (ST0, (int)(ST1));
+ double st0 = floatx80_to_double(env, ST0);
+ double st1 = floatx80_to_double(env, ST1);
+ double val = ldexp(st0, (int)st1);
+ ST0 = double_to_floatx80(env, val);
}
void helper_fsin(void)
{
- CPU86_LDouble fptemp;
+ double fptemp = floatx80_to_double(env, ST0);
- fptemp = ST0;
if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
env->fpus |= 0x400;
} else {
- ST0 = sin(fptemp);
+ ST0 = double_to_floatx80(env, sin(fptemp));
env->fpus &= (~0x400); /* C2 <-- 0 */
/* the above code is for |arg| < 2**53 only */
}
@@ -4180,13 +4212,12 @@
void helper_fcos(void)
{
- CPU86_LDouble fptemp;
+ double fptemp = floatx80_to_double(env, ST0);
- fptemp = ST0;
if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
env->fpus |= 0x400;
} else {
- ST0 = cos(fptemp);
+ ST0 = double_to_floatx80(env, cos(fptemp));
env->fpus &= (~0x400); /* C2 <-- 0 */
/* the above code is for |arg5 < 2**63 only */
}
@@ -4194,7 +4225,7 @@
void helper_fxam_ST0(void)
{
- CPU86_LDoubleU temp;
+ CPU_LDoubleU temp;
int expdif;
temp.d = ST0;
@@ -4206,19 +4237,17 @@
/* XXX: test fptags too */
expdif = EXPD(temp);
if (expdif == MAXEXPD) {
-#ifdef USE_X86LDOUBLE
- if (MANTD(temp) == 0x8000000000000000ULL)
-#else
- if (MANTD(temp) == 0)
-#endif
+ if (MANTD(temp) == 0x8000000000000000ULL) {
env->fpus |= 0x500 /*Infinity*/;
- else
+ } else {
env->fpus |= 0x100 /*NaN*/;
+ }
} else if (expdif == 0) {
- if (MANTD(temp) == 0)
+ if (MANTD(temp) == 0) {
env->fpus |= 0x4000 /*Zero*/;
- else
+ } else {
env->fpus |= 0x4400 /*Denormal*/;
+ }
} else {
env->fpus |= 0x400;
}
@@ -4228,7 +4257,7 @@
{
int fpus, fptag, exp, i;
uint64_t mant;
- CPU86_LDoubleU tmp;
+ CPU_LDoubleU tmp;
fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
fptag = 0;
@@ -4244,10 +4273,7 @@
/* zero */
fptag |= 1;
} else if (exp == 0 || exp == MAXEXPD
-#ifdef USE_X86LDOUBLE
- || (mant & (1LL << 63)) == 0
-#endif
- ) {
+ || (mant & (1LL << 63)) == 0) {
/* NaNs, infinity, denormal */
fptag |= 2;
}
@@ -4279,12 +4305,12 @@
int i, fpus, fptag;
if (data32) {
- env->fpuc = lduw(ptr);
+ env->fpuc = lduw(ptr);
fpus = lduw(ptr + 4);
fptag = lduw(ptr + 8);
}
else {
- env->fpuc = lduw(ptr);
+ env->fpuc = lduw(ptr);
fpus = lduw(ptr + 2);
fptag = lduw(ptr + 4);
}
@@ -4298,7 +4324,7 @@
void helper_fsave(target_ulong ptr, int data32)
{
- CPU86_LDouble tmp;
+ floatx80 tmp;
int i;
helper_fstenv(ptr, data32);
@@ -4326,7 +4352,7 @@
void helper_frstor(target_ulong ptr, int data32)
{
- CPU86_LDouble tmp;
+ floatx80 tmp;
int i;
helper_fldenv(ptr, data32);
@@ -4342,7 +4368,7 @@
void helper_fxsave(target_ulong ptr, int data64)
{
int fpus, fptag, i, nb_xmm_regs;
- CPU86_LDouble tmp;
+ floatx80 tmp;
target_ulong addr;
fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
@@ -4398,7 +4424,7 @@
void helper_fxrstor(target_ulong ptr, int data64)
{
int i, fpus, fptag, nb_xmm_regs;
- CPU86_LDouble tmp;
+ floatx80 tmp;
target_ulong addr;
env->fpuc = lduw(ptr);
@@ -4440,61 +4466,23 @@
}
}
-#ifndef USE_X86LDOUBLE
-
-void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
+void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, floatx80 f)
{
- CPU86_LDoubleU temp;
- int e;
-
- temp.d = f;
- /* mantissa */
- *pmant = (MANTD(temp) << 11) | (1LL << 63);
- /* exponent + sign */
- e = EXPD(temp) - EXPBIAS + 16383;
- e |= SIGND(temp) >> 16;
- *pexp = e;
-}
-
-CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
-{
- CPU86_LDoubleU temp;
- int e;
- uint64_t ll;
-
- /* XXX: handle overflow ? */
- e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
- e |= (upper >> 4) & 0x800; /* sign */
- ll = (mant >> 11) & ((1LL << 52) - 1);
-#ifdef __arm__
- temp.l.upper = (e << 20) | (ll >> 32);
- temp.l.lower = ll;
-#else
- temp.ll = ll | ((uint64_t)e << 52);
-#endif
- return temp.d;
-}
-
-#else
-
-void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
-{
- CPU86_LDoubleU temp;
+ CPU_LDoubleU temp;
temp.d = f;
*pmant = temp.l.lower;
*pexp = temp.l.upper;
}
-CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
+floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper)
{
- CPU86_LDoubleU temp;
+ CPU_LDoubleU temp;
temp.l.upper = upper;
temp.l.lower = mant;
return temp.d;
}
-#endif
#ifdef TARGET_X86_64