diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-10-28 23:06:17 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-10-28 23:06:17 +0000 |
commit | 9951bf39f90519a2a2eb3809eb13a27471b9398d (patch) | |
tree | b57278f408e3c9b8c27c152e2a4fa7dece1f3b96 | |
parent | 8948b5d6136eb0d338a71f94f5d607dd353c421d (diff) |
fixed long double accesses when using soft MMU
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@428 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | target-i386/exec.h | 259 | ||||
-rw-r--r-- | target-i386/helper.c | 10 | ||||
-rw-r--r-- | target-i386/op.c | 18 |
3 files changed, 150 insertions, 137 deletions
diff --git a/target-i386/exec.h b/target-i386/exec.h index eb13186cf6..dc1df94ab4 100644 --- a/target-i386/exec.h +++ b/target-i386/exec.h @@ -171,6 +171,115 @@ void helper_wrmsr(void); void helper_lsl(void); void helper_lar(void); +/* XXX: move that to a generic header */ +#if !defined(CONFIG_USER_ONLY) + +#define ldul_user ldl_user +#define ldul_kernel ldl_kernel + +#define ACCESS_TYPE 0 +#define MEMSUFFIX _kernel +#define DATA_SIZE 1 +#include "softmmu_header.h" + +#define DATA_SIZE 2 +#include "softmmu_header.h" + +#define DATA_SIZE 4 +#include "softmmu_header.h" + +#define DATA_SIZE 8 +#include "softmmu_header.h" +#undef ACCESS_TYPE +#undef MEMSUFFIX + +#define ACCESS_TYPE 1 +#define MEMSUFFIX _user +#define DATA_SIZE 1 +#include "softmmu_header.h" + +#define DATA_SIZE 2 +#include "softmmu_header.h" + +#define DATA_SIZE 4 +#include "softmmu_header.h" + +#define DATA_SIZE 8 +#include "softmmu_header.h" +#undef ACCESS_TYPE +#undef MEMSUFFIX + +/* these access are slower, they must be as rare as possible */ +#define ACCESS_TYPE 2 +#define MEMSUFFIX _data +#define DATA_SIZE 1 +#include "softmmu_header.h" + +#define DATA_SIZE 2 +#include "softmmu_header.h" + +#define DATA_SIZE 4 +#include "softmmu_header.h" + +#define DATA_SIZE 8 +#include "softmmu_header.h" +#undef ACCESS_TYPE +#undef MEMSUFFIX + +#define ldub(p) ldub_data(p) +#define ldsb(p) ldsb_data(p) +#define lduw(p) lduw_data(p) +#define ldsw(p) ldsw_data(p) +#define ldl(p) ldl_data(p) +#define ldq(p) ldq_data(p) + +#define stb(p, v) stb_data(p, v) +#define stw(p, v) stw_data(p, v) +#define stl(p, v) stl_data(p, v) +#define stq(p, v) stq_data(p, v) + +static inline double ldfq(void *ptr) +{ + union { + double d; + uint64_t i; + } u; + u.i = ldq(ptr); + return u.d; +} + +static inline void stfq(void *ptr, double v) +{ + union { + double d; + uint64_t i; + } u; + u.d = v; + stq(ptr, u.i); +} + +static inline float ldfl(void *ptr) +{ + union { + float f; + uint32_t i; + } u; + u.i = ldl(ptr); + return u.f; +} + +static inline void stfl(void *ptr, float v) +{ + union { + float f; + uint32_t i; + } u; + u.f = v; + stl(ptr, u.i); +} + +#endif /* !defined(CONFIG_USER_ONLY) */ + #ifdef USE_X86LDOUBLE /* use long double functions */ #define lrint lrintl @@ -317,7 +426,47 @@ static inline void helper_fstt(CPU86_LDouble f, uint8_t *ptr) e |= SIGND(temp) >> 16; stw(ptr + 8, e); } -#endif +#else + +/* XXX: same endianness assumed */ + +#ifdef CONFIG_USER_ONLY + +static inline CPU86_LDouble helper_fldt(uint8_t *ptr) +{ + return *(CPU86_LDouble *)ptr; +} + +static inline void helper_fstt(CPU86_LDouble f, uint8_t *ptr) +{ + *(CPU86_LDouble *)ptr = f; +} + +#else + +/* we use memory access macros */ + +static inline CPU86_LDouble helper_fldt(uint8_t *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, uint8_t *ptr) +{ + CPU86_LDoubleU temp; + + temp.d = f; + stq(ptr, temp.l.lower); + stw(ptr + 8, temp.l.upper); +} + +#endif /* !CONFIG_USER_ONLY */ + +#endif /* USE_X86LDOUBLE */ const CPU86_LDouble f15rk[7]; @@ -368,111 +517,3 @@ static inline void load_eflags(int eflags, int update_mask) (eflags & update_mask); } -/* XXX: move that to a generic header */ -#if !defined(CONFIG_USER_ONLY) - -#define ldul_user ldl_user -#define ldul_kernel ldl_kernel - -#define ACCESS_TYPE 0 -#define MEMSUFFIX _kernel -#define DATA_SIZE 1 -#include "softmmu_header.h" - -#define DATA_SIZE 2 -#include "softmmu_header.h" - -#define DATA_SIZE 4 -#include "softmmu_header.h" - -#define DATA_SIZE 8 -#include "softmmu_header.h" -#undef ACCESS_TYPE -#undef MEMSUFFIX - -#define ACCESS_TYPE 1 -#define MEMSUFFIX _user -#define DATA_SIZE 1 -#include "softmmu_header.h" - -#define DATA_SIZE 2 -#include "softmmu_header.h" - -#define DATA_SIZE 4 -#include "softmmu_header.h" - -#define DATA_SIZE 8 -#include "softmmu_header.h" -#undef ACCESS_TYPE -#undef MEMSUFFIX - -/* these access are slower, they must be as rare as possible */ -#define ACCESS_TYPE 2 -#define MEMSUFFIX _data -#define DATA_SIZE 1 -#include "softmmu_header.h" - -#define DATA_SIZE 2 -#include "softmmu_header.h" - -#define DATA_SIZE 4 -#include "softmmu_header.h" - -#define DATA_SIZE 8 -#include "softmmu_header.h" -#undef ACCESS_TYPE -#undef MEMSUFFIX - -#define ldub(p) ldub_data(p) -#define ldsb(p) ldsb_data(p) -#define lduw(p) lduw_data(p) -#define ldsw(p) ldsw_data(p) -#define ldl(p) ldl_data(p) -#define ldq(p) ldq_data(p) - -#define stb(p, v) stb_data(p, v) -#define stw(p, v) stw_data(p, v) -#define stl(p, v) stl_data(p, v) -#define stq(p, v) stq_data(p, v) - -static inline double ldfq(void *ptr) -{ - union { - double d; - uint64_t i; - } u; - u.i = ldq(ptr); - return u.d; -} - -static inline void stfq(void *ptr, double v) -{ - union { - double d; - uint64_t i; - } u; - u.d = v; - stq(ptr, u.i); -} - -static inline float ldfl(void *ptr) -{ - union { - float f; - uint32_t i; - } u; - u.i = ldl(ptr); - return u.f; -} - -static inline void stfl(void *ptr, float v) -{ - union { - float f; - uint32_t i; - } u; - u.f = v; - stl(ptr, u.i); -} - -#endif /* !defined(CONFIG_USER_ONLY) */ diff --git a/target-i386/helper.c b/target-i386/helper.c index 43b8168a1c..1c0920bcf8 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1318,7 +1318,6 @@ void helper_lar(void) /* FPU helpers */ -#ifndef USE_X86LDOUBLE void helper_fldt_ST0_A0(void) { int new_fpstt; @@ -1332,7 +1331,6 @@ void helper_fstt_ST0_A0(void) { helper_fstt(ST0, (uint8_t *)A0); } -#endif /* BCD ops */ @@ -1729,11 +1727,7 @@ void helper_fsave(uint8_t *ptr, int data32) ptr += (14 << data32); for(i = 0;i < 8; i++) { tmp = ST(i); -#ifdef USE_X86LDOUBLE - *(long double *)ptr = tmp; -#else helper_fstt(tmp, ptr); -#endif ptr += 10; } @@ -1760,11 +1754,7 @@ void helper_frstor(uint8_t *ptr, int data32) ptr += (14 << data32); for(i = 0;i < 8; i++) { -#ifdef USE_X86LDOUBLE - tmp = *(long double *)ptr; -#else tmp = helper_fldt(ptr); -#endif ST(i) = tmp; ptr += 10; } diff --git a/target-i386/op.c b/target-i386/op.c index 0f4dbd18e2..f1276f7a64 100644 --- a/target-i386/op.c +++ b/target-i386/op.c @@ -1471,21 +1471,10 @@ void OPPROTO op_fldl_ST0_A0(void) env->fptags[new_fpstt] = 0; /* validate stack entry */ } -#ifdef USE_X86LDOUBLE -void OPPROTO op_fldt_ST0_A0(void) -{ - int new_fpstt; - new_fpstt = (env->fpstt - 1) & 7; - env->fpregs[new_fpstt] = *(long double *)A0; - env->fpstt = new_fpstt; - env->fptags[new_fpstt] = 0; /* validate stack entry */ -} -#else void OPPROTO op_fldt_ST0_A0(void) { helper_fldt_ST0_A0(); } -#endif /* helpers are needed to avoid static constant reference. XXX: find a better way */ #ifdef USE_INT_TO_FLOAT_HELPERS @@ -1595,17 +1584,10 @@ void OPPROTO op_fstl_ST0_A0(void) stfq((void *)A0, (double)ST0); } -#ifdef USE_X86LDOUBLE -void OPPROTO op_fstt_ST0_A0(void) -{ - *(long double *)A0 = ST0; -} -#else void OPPROTO op_fstt_ST0_A0(void) { helper_fstt_ST0_A0(); } -#endif void OPPROTO op_fist_ST0_A0(void) { |