mirror of
https://github.com/qemu/qemu.git
synced 2024-11-26 04:13:39 +08:00
fixed long double accesses when using soft MMU
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@428 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
8948b5d613
commit
9951bf39f9
@ -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) */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user