fpu: Begin using host FPU for hard x87 emulation

This is a start to hard float support for x87. It can fail in several
ways and has lots of room for improvement, but based on practical
testing it appears reliable and significantly increases performance in
FP-bottlenecked game code. Improvement to rounding, exception handling,
and performance accompanied by rigorous testing will be necessary next
steps for this work.
This commit is contained in:
Matt Borgerson 2021-03-05 03:17:30 -07:00 committed by mborgerson
parent 9d545d17e7
commit 99d251caa0
8 changed files with 421 additions and 82 deletions

View File

@ -96,11 +96,24 @@ typedef uint64_t float64;
#define const_float16(x) (x)
#define const_float32(x) (x)
#define const_float64(x) (x)
#if defined(XBOX) && defined(__x86_64__)
/* GCC produced x86-64 structure should be 16B packed */
typedef struct {
union {
struct {
uint64_t low;
uint16_t high;
};
long double fval;
};
} floatx80;
#else
typedef struct {
uint64_t low;
uint16_t high;
} floatx80;
#define make_floatx80(exp, mant) ((floatx80) { mant, exp })
#endif
#define make_floatx80(exp, mant) ((floatx80) { .low = mant, .high = exp })
#define make_floatx80_init(exp, mant) { .low = mant, .high = exp }
typedef struct {
#ifdef HOST_WORDS_BIGENDIAN

View File

@ -1,6 +1,6 @@
obj-y += helper.o cpu.o gdbstub.o xsave_helper.o
obj-$(CONFIG_TCG) += translate.o
obj-$(CONFIG_TCG) += bpt_helper.o cc_helper.o excp_helper.o fpu_helper.o
obj-$(CONFIG_TCG) += bpt_helper.o cc_helper.o excp_helper.o fpu_helper.o fpu_helper_hard.o
obj-$(CONFIG_TCG) += int_helper.o mem_helper.o misc_helper.o mpx_helper.o
obj-$(CONFIG_TCG) += seg_helper.o smm_helper.o svm_helper.o
obj-$(call lnot,$(CONFIG_TCG)) += tcg-stub.o

View File

@ -68,13 +68,208 @@
#define floatx80_ln2_d make_floatx80(0x3ffe, 0xb17217f7d1cf79abLL)
#define floatx80_pi_d make_floatx80(0x4000, 0xc90fdaa22168c234LL)
#if defined(XBOX) && defined(__x86_64__)
#ifdef USE_HARD_FPU
/*
* FIXME: rounding and exceptions
*/
static inline
floatx80 pack(floatx80 v, float_status *status)
{
switch (status->floatx80_rounding_precision) {
case 32: return (floatx80){ .fval = (float)v.fval };
case 64: return (floatx80){ .fval = (double)v.fval };
default: return v; /* 80 */
}
}
static inline
floatx80 floatx80_add__hard(floatx80 a, floatx80 b, float_status *status)
{
return pack((floatx80){ .fval = (a.fval + b.fval) }, status);
}
static inline
floatx80 floatx80_sub__hard(floatx80 a, floatx80 b, float_status *status)
{
return pack((floatx80){ .fval = (a.fval - b.fval) }, status);
}
static inline
floatx80 floatx80_mul__hard(floatx80 a, floatx80 b, float_status *status)
{
return pack((floatx80){ .fval = (a.fval * b.fval) }, status);
}
static inline
floatx80 floatx80_div__hard(floatx80 a, floatx80 b, float_status *status)
{
/* FIXME: Exceptions */
return pack((floatx80){ .fval = (a.fval / b.fval) }, status);
}
static inline
FloatRelation floatx80_compare__hard(floatx80 a, floatx80 b, float_status *status)
{
if (a.fval < b.fval) return float_relation_less;
if (a.fval > b.fval) return float_relation_greater;
if (a.fval == b.fval) return float_relation_equal;
return float_relation_unordered;
}
static inline
floatx80 float32_to_floatx80__hard(float32 val, float_status *status)
{
return (floatx80){ .fval = *(float *)&val };
}
static inline
float32 floatx80_to_float32__hard(floatx80 a, float_status *status)
{
union {
float32 f32;
float f;
} x;
x.f = a.fval;
return x.f32;
}
static inline
floatx80 float64_to_floatx80__hard(float64 val, float_status *status)
{
return (floatx80){ .fval = *(double *)&val };
}
static inline
float64 floatx80_to_float64__hard(floatx80 a, float_status *status)
{
union {
float64 f64;
double d;
} x;
x.d = a.fval;
return x.f64;
}
static inline
floatx80 int32_to_floatx80__hard(int32_t a, float_status *status)
{
return (floatx80){ .fval = a };
}
#define floatx80_add floatx80_add__hard
#define floatx80_sub floatx80_sub__hard
#define floatx80_mul floatx80_mul__hard
#define floatx80_div floatx80_div__hard
#define floatx80_compare floatx80_compare__hard
#define float32_to_floatx80 float32_to_floatx80__hard
#define floatx80_to_float32 floatx80_to_float32__hard
#define float64_to_floatx80 float64_to_floatx80__hard
#define floatx80_to_float64 floatx80_to_float64__hard
#define int32_to_floatx80 int32_to_floatx80__hard
#endif /* USE_HARD_FPU */
#ifdef USE_HARD_FPU
#define MAP_HELPER_SOFT_HARD(func) helper_ ## func ## __hard
#else
#define MAP_HELPER_SOFT_HARD(func) helper_ ## func ## __soft
#endif
#define helper_flds_FT0 MAP_HELPER_SOFT_HARD(flds_FT0)
#define helper_fldl_FT0 MAP_HELPER_SOFT_HARD(fldl_FT0)
#define helper_fildl_FT0 MAP_HELPER_SOFT_HARD(fildl_FT0)
#define helper_flds_ST0 MAP_HELPER_SOFT_HARD(flds_ST0)
#define helper_fldl_ST0 MAP_HELPER_SOFT_HARD(fldl_ST0)
#define helper_fildl_ST0 MAP_HELPER_SOFT_HARD(fildl_ST0)
#define helper_fildll_ST0 MAP_HELPER_SOFT_HARD(fildll_ST0)
#define helper_fsts_ST0 MAP_HELPER_SOFT_HARD(fsts_ST0)
#define helper_fstl_ST0 MAP_HELPER_SOFT_HARD(fstl_ST0)
#define helper_fist_ST0 MAP_HELPER_SOFT_HARD(fist_ST0)
#define helper_fistl_ST0 MAP_HELPER_SOFT_HARD(fistl_ST0)
#define helper_fistll_ST0 MAP_HELPER_SOFT_HARD(fistll_ST0)
#define helper_fistt_ST0 MAP_HELPER_SOFT_HARD(fistt_ST0)
#define helper_fisttl_ST0 MAP_HELPER_SOFT_HARD(fisttl_ST0)
#define helper_fisttll_ST0 MAP_HELPER_SOFT_HARD(fisttll_ST0)
#define helper_fldt_ST0 MAP_HELPER_SOFT_HARD(fldt_ST0)
#define helper_fstt_ST0 MAP_HELPER_SOFT_HARD(fstt_ST0)
#define helper_fpush MAP_HELPER_SOFT_HARD(fpush)
#define helper_fpop MAP_HELPER_SOFT_HARD(fpop)
#define helper_fdecstp MAP_HELPER_SOFT_HARD(fdecstp)
#define helper_fincstp MAP_HELPER_SOFT_HARD(fincstp)
#define helper_ffree_STN MAP_HELPER_SOFT_HARD(ffree_STN)
#define helper_fmov_ST0_FT0 MAP_HELPER_SOFT_HARD(fmov_ST0_FT0)
#define helper_fmov_FT0_STN MAP_HELPER_SOFT_HARD(fmov_FT0_STN)
#define helper_fmov_ST0_STN MAP_HELPER_SOFT_HARD(fmov_ST0_STN)
#define helper_fmov_STN_ST0 MAP_HELPER_SOFT_HARD(fmov_STN_ST0)
#define helper_fxchg_ST0_STN MAP_HELPER_SOFT_HARD(fxchg_ST0_STN)
#define helper_fcom_ST0_FT0 MAP_HELPER_SOFT_HARD(fcom_ST0_FT0)
#define helper_fucom_ST0_FT0 MAP_HELPER_SOFT_HARD(fucom_ST0_FT0)
#define helper_fcomi_ST0_FT0 MAP_HELPER_SOFT_HARD(fcomi_ST0_FT0)
#define helper_fucomi_ST0_FT0 MAP_HELPER_SOFT_HARD(fucomi_ST0_FT0)
#define helper_fadd_ST0_FT0 MAP_HELPER_SOFT_HARD(fadd_ST0_FT0)
#define helper_fmul_ST0_FT0 MAP_HELPER_SOFT_HARD(fmul_ST0_FT0)
#define helper_fsub_ST0_FT0 MAP_HELPER_SOFT_HARD(fsub_ST0_FT0)
#define helper_fsubr_ST0_FT0 MAP_HELPER_SOFT_HARD(fsubr_ST0_FT0)
#define helper_fdiv_ST0_FT0 MAP_HELPER_SOFT_HARD(fdiv_ST0_FT0)
#define helper_fdivr_ST0_FT0 MAP_HELPER_SOFT_HARD(fdivr_ST0_FT0)
#define helper_fadd_STN_ST0 MAP_HELPER_SOFT_HARD(fadd_STN_ST0)
#define helper_fmul_STN_ST0 MAP_HELPER_SOFT_HARD(fmul_STN_ST0)
#define helper_fsub_STN_ST0 MAP_HELPER_SOFT_HARD(fsub_STN_ST0)
#define helper_fsubr_STN_ST0 MAP_HELPER_SOFT_HARD(fsubr_STN_ST0)
#define helper_fdiv_STN_ST0 MAP_HELPER_SOFT_HARD(fdiv_STN_ST0)
#define helper_fdivr_STN_ST0 MAP_HELPER_SOFT_HARD(fdivr_STN_ST0)
#define helper_fchs_ST0 MAP_HELPER_SOFT_HARD(fchs_ST0)
#define helper_fabs_ST0 MAP_HELPER_SOFT_HARD(fabs_ST0)
#define helper_fxam_ST0 MAP_HELPER_SOFT_HARD(fxam_ST0)
#define helper_fld1_ST0 MAP_HELPER_SOFT_HARD(fld1_ST0)
#define helper_fldl2t_ST0 MAP_HELPER_SOFT_HARD(fldl2t_ST0)
#define helper_fldl2e_ST0 MAP_HELPER_SOFT_HARD(fldl2e_ST0)
#define helper_fldpi_ST0 MAP_HELPER_SOFT_HARD(fldpi_ST0)
#define helper_fldlg2_ST0 MAP_HELPER_SOFT_HARD(fldlg2_ST0)
#define helper_fldln2_ST0 MAP_HELPER_SOFT_HARD(fldln2_ST0)
#define helper_fldz_ST0 MAP_HELPER_SOFT_HARD(fldz_ST0)
#define helper_fldz_FT0 MAP_HELPER_SOFT_HARD(fldz_FT0)
#define helper_fnstsw MAP_HELPER_SOFT_HARD(fnstsw)
#define helper_fnstcw MAP_HELPER_SOFT_HARD(fnstcw)
#define helper_fldcw MAP_HELPER_SOFT_HARD(fldcw)
#define helper_fclex MAP_HELPER_SOFT_HARD(fclex)
#define helper_fwait MAP_HELPER_SOFT_HARD(fwait)
#define helper_fninit MAP_HELPER_SOFT_HARD(fninit)
#define helper_fbld_ST0 MAP_HELPER_SOFT_HARD(fbld_ST0)
#define helper_fbst_ST0 MAP_HELPER_SOFT_HARD(fbst_ST0)
#define helper_f2xm1 MAP_HELPER_SOFT_HARD(f2xm1)
#define helper_fyl2x MAP_HELPER_SOFT_HARD(fyl2x)
#define helper_fptan MAP_HELPER_SOFT_HARD(fptan)
#define helper_fpatan MAP_HELPER_SOFT_HARD(fpatan)
#define helper_fxtract MAP_HELPER_SOFT_HARD(fxtract)
#define helper_fprem1 MAP_HELPER_SOFT_HARD(fprem1)
#define helper_fprem MAP_HELPER_SOFT_HARD(fprem)
#define helper_fyl2xp1 MAP_HELPER_SOFT_HARD(fyl2xp1)
#define helper_fsqrt MAP_HELPER_SOFT_HARD(fsqrt)
#define helper_fsincos MAP_HELPER_SOFT_HARD(fsincos)
#define helper_frndint MAP_HELPER_SOFT_HARD(frndint)
#define helper_fscale MAP_HELPER_SOFT_HARD(fscale)
#define helper_fsin MAP_HELPER_SOFT_HARD(fsin)
#define helper_fcos MAP_HELPER_SOFT_HARD(fcos)
#define helper_fstenv MAP_HELPER_SOFT_HARD(fstenv)
#define helper_fldenv MAP_HELPER_SOFT_HARD(fldenv)
#define helper_fsave MAP_HELPER_SOFT_HARD(fsave)
#define helper_frstor MAP_HELPER_SOFT_HARD(frstor)
#endif /* defined(XBOX) && defined(__x86_64__) */
#if !defined(CONFIG_USER_ONLY)
static qemu_irq ferr_irq;
#ifndef USE_HARD_FPU
void x86_register_ferr_irq(qemu_irq irq)
{
ferr_irq = irq;
}
#endif
static void cpu_clear_ignne(void)
{
@ -82,6 +277,7 @@ static void cpu_clear_ignne(void)
env->hflags2 &= ~HF2_IGNNE_MASK;
}
#ifndef USE_HARD_FPU
void cpu_set_ignne(void)
{
CPUX86State *env = &X86_CPU(first_cpu)->env;
@ -96,6 +292,7 @@ void cpu_set_ignne(void)
qemu_irq_lower(ferr_irq);
}
#endif
#endif
static inline void fpush(CPUX86State *env)
@ -154,6 +351,7 @@ static inline floatx80 double_to_floatx80(CPUX86State *env, double a)
return float64_to_floatx80(u.f64, &env->fp_status);
}
#ifndef USE_HARD_FPU
static void fpu_set_exception(CPUX86State *env, int mask)
{
env->fpus |= mask;
@ -161,6 +359,7 @@ static void fpu_set_exception(CPUX86State *env, int mask)
env->fpus |= FPUS_SE | FPUS_B;
}
}
#endif
static inline uint8_t save_exception_flags(CPUX86State *env)
{
@ -171,6 +370,7 @@ static inline uint8_t save_exception_flags(CPUX86State *env)
static void merge_exception_flags(CPUX86State *env, uint8_t old_flags)
{
#ifndef USE_HARD_FPU
uint8_t new_flags = get_float_exception_flags(&env->fp_status);
float_raise(old_flags, &env->fp_status);
fpu_set_exception(env,
@ -180,6 +380,7 @@ static void merge_exception_flags(CPUX86State *env, uint8_t old_flags)
(new_flags & float_flag_underflow ? FPUS_UE : 0) |
(new_flags & float_flag_inexact ? FPUS_PE : 0) |
(new_flags & float_flag_input_denormal ? FPUS_DE : 0)));
#endif
}
static inline floatx80 helper_fdiv(CPUX86State *env, floatx80 a, floatx80 b)
@ -702,6 +903,7 @@ uint32_t helper_fnstcw(CPUX86State *env)
return env->fpuc;
}
#ifndef USE_HARD_FPU
void update_fp_status(CPUX86State *env)
{
int rnd_type;
@ -737,6 +939,7 @@ void update_fp_status(CPUX86State *env)
}
set_floatx80_rounding_precision(rnd_type, &env->fp_status);
}
#endif
void helper_fldcw(CPUX86State *env, uint32_t val)
{
@ -2494,6 +2697,9 @@ void helper_frstor(CPUX86State *env, target_ulong ptr, int data32)
}
}
#ifndef USE_HARD_FPU
#if defined(CONFIG_USER_ONLY)
void cpu_x86_fsave(CPUX86State *env, target_ulong ptr, int data32)
{
@ -3040,3 +3246,4 @@ void helper_movq(CPUX86State *env, void *d, void *s)
#define SHIFT 1
#include "ops_sse.h"
#endif

View File

@ -0,0 +1,4 @@
#if defined(XBOX) && defined(__x86_64__)
#define USE_HARD_FPU 1
#include "fpu_helper.c"
#endif

View File

@ -110,87 +110,110 @@ DEF_HELPER_1(skinit, void, env)
DEF_HELPER_2(invlpga, void, env, int)
/* x86 FPU */
#if defined(XBOX) && defined(__x86_64__)
#define HS_DEF_HELPER_1(name, ret, t1) \
DEF_HELPER_1(name ## __soft, ret, t1) \
DEF_HELPER_1(name ## __hard, ret, t1)
#define HS_DEF_HELPER_2(name, ret, t1, t2) \
DEF_HELPER_2(name ## __soft, ret, t1, t2) \
DEF_HELPER_2(name ## __hard, ret, t1, t2)
#define HS_DEF_HELPER_3(name, ret, t1, t2, t3) \
DEF_HELPER_3(name ## __soft, ret, t1, t2, t3) \
DEF_HELPER_3(name ## __hard, ret, t1, t2, t3)
#else
#define HS_DEF_HELPER_1(name, ret, t1) \
DEF_HELPER_1(name, ret, t1)
#define HS_DEF_HELPER_2(name, ret, t1, t2) \
DEF_HELPER_2(name, ret, t1, t2)
#define HS_DEF_HELPER_3(name, ret, t1, t2, t3) \
DEF_HELPER_3(name, ret, t1, t2, t3)
#endif
HS_DEF_HELPER_2(flds_FT0, void, env, i32)
HS_DEF_HELPER_2(fldl_FT0, void, env, i64)
HS_DEF_HELPER_2(fildl_FT0, void, env, s32)
HS_DEF_HELPER_2(flds_ST0, void, env, i32)
HS_DEF_HELPER_2(fldl_ST0, void, env, i64)
HS_DEF_HELPER_2(fildl_ST0, void, env, s32)
HS_DEF_HELPER_2(fildll_ST0, void, env, s64)
HS_DEF_HELPER_1(fsts_ST0, i32, env)
HS_DEF_HELPER_1(fstl_ST0, i64, env)
HS_DEF_HELPER_1(fist_ST0, s32, env)
HS_DEF_HELPER_1(fistl_ST0, s32, env)
HS_DEF_HELPER_1(fistll_ST0, s64, env)
HS_DEF_HELPER_1(fistt_ST0, s32, env)
HS_DEF_HELPER_1(fisttl_ST0, s32, env)
HS_DEF_HELPER_1(fisttll_ST0, s64, env)
HS_DEF_HELPER_2(fldt_ST0, void, env, tl)
HS_DEF_HELPER_2(fstt_ST0, void, env, tl)
HS_DEF_HELPER_1(fpush, void, env)
HS_DEF_HELPER_1(fpop, void, env)
HS_DEF_HELPER_1(fdecstp, void, env)
HS_DEF_HELPER_1(fincstp, void, env)
HS_DEF_HELPER_2(ffree_STN, void, env, int)
HS_DEF_HELPER_1(fmov_ST0_FT0, void, env)
HS_DEF_HELPER_2(fmov_FT0_STN, void, env, int)
HS_DEF_HELPER_2(fmov_ST0_STN, void, env, int)
HS_DEF_HELPER_2(fmov_STN_ST0, void, env, int)
HS_DEF_HELPER_2(fxchg_ST0_STN, void, env, int)
HS_DEF_HELPER_1(fcom_ST0_FT0, void, env)
HS_DEF_HELPER_1(fucom_ST0_FT0, void, env)
HS_DEF_HELPER_1(fcomi_ST0_FT0, void, env)
HS_DEF_HELPER_1(fucomi_ST0_FT0, void, env)
HS_DEF_HELPER_1(fadd_ST0_FT0, void, env)
HS_DEF_HELPER_1(fmul_ST0_FT0, void, env)
HS_DEF_HELPER_1(fsub_ST0_FT0, void, env)
HS_DEF_HELPER_1(fsubr_ST0_FT0, void, env)
HS_DEF_HELPER_1(fdiv_ST0_FT0, void, env)
HS_DEF_HELPER_1(fdivr_ST0_FT0, void, env)
HS_DEF_HELPER_2(fadd_STN_ST0, void, env, int)
HS_DEF_HELPER_2(fmul_STN_ST0, void, env, int)
HS_DEF_HELPER_2(fsub_STN_ST0, void, env, int)
HS_DEF_HELPER_2(fsubr_STN_ST0, void, env, int)
HS_DEF_HELPER_2(fdiv_STN_ST0, void, env, int)
HS_DEF_HELPER_2(fdivr_STN_ST0, void, env, int)
HS_DEF_HELPER_1(fchs_ST0, void, env)
HS_DEF_HELPER_1(fabs_ST0, void, env)
HS_DEF_HELPER_1(fxam_ST0, void, env)
HS_DEF_HELPER_1(fld1_ST0, void, env)
HS_DEF_HELPER_1(fldl2t_ST0, void, env)
HS_DEF_HELPER_1(fldl2e_ST0, void, env)
HS_DEF_HELPER_1(fldpi_ST0, void, env)
HS_DEF_HELPER_1(fldlg2_ST0, void, env)
HS_DEF_HELPER_1(fldln2_ST0, void, env)
HS_DEF_HELPER_1(fldz_ST0, void, env)
HS_DEF_HELPER_1(fldz_FT0, void, env)
HS_DEF_HELPER_1(fnstsw, i32, env)
HS_DEF_HELPER_1(fnstcw, i32, env)
HS_DEF_HELPER_2(fldcw, void, env, i32)
HS_DEF_HELPER_1(fclex, void, env)
HS_DEF_HELPER_1(fwait, void, env)
HS_DEF_HELPER_1(fninit, void, env)
HS_DEF_HELPER_2(fbld_ST0, void, env, tl)
HS_DEF_HELPER_2(fbst_ST0, void, env, tl)
HS_DEF_HELPER_1(f2xm1, void, env)
HS_DEF_HELPER_1(fyl2x, void, env)
HS_DEF_HELPER_1(fptan, void, env)
HS_DEF_HELPER_1(fpatan, void, env)
HS_DEF_HELPER_1(fxtract, void, env)
HS_DEF_HELPER_1(fprem1, void, env)
HS_DEF_HELPER_1(fprem, void, env)
HS_DEF_HELPER_1(fyl2xp1, void, env)
HS_DEF_HELPER_1(fsqrt, void, env)
HS_DEF_HELPER_1(fsincos, void, env)
HS_DEF_HELPER_1(frndint, void, env)
HS_DEF_HELPER_1(fscale, void, env)
HS_DEF_HELPER_1(fsin, void, env)
HS_DEF_HELPER_1(fcos, void, env)
HS_DEF_HELPER_3(fstenv, void, env, tl, int)
HS_DEF_HELPER_3(fldenv, void, env, tl, int)
HS_DEF_HELPER_3(fsave, void, env, tl, int)
HS_DEF_HELPER_3(frstor, void, env, tl, int)
#undef HS_DEF_HELPER_1
#undef HS_DEF_HELPER_2
#undef HS_DEF_HELPER_3
DEF_HELPER_2(flds_FT0, void, env, i32)
DEF_HELPER_2(fldl_FT0, void, env, i64)
DEF_HELPER_2(fildl_FT0, void, env, s32)
DEF_HELPER_2(flds_ST0, void, env, i32)
DEF_HELPER_2(fldl_ST0, void, env, i64)
DEF_HELPER_2(fildl_ST0, void, env, s32)
DEF_HELPER_2(fildll_ST0, void, env, s64)
DEF_HELPER_1(fsts_ST0, i32, env)
DEF_HELPER_1(fstl_ST0, i64, env)
DEF_HELPER_1(fist_ST0, s32, env)
DEF_HELPER_1(fistl_ST0, s32, env)
DEF_HELPER_1(fistll_ST0, s64, env)
DEF_HELPER_1(fistt_ST0, s32, env)
DEF_HELPER_1(fisttl_ST0, s32, env)
DEF_HELPER_1(fisttll_ST0, s64, env)
DEF_HELPER_2(fldt_ST0, void, env, tl)
DEF_HELPER_2(fstt_ST0, void, env, tl)
DEF_HELPER_1(fpush, void, env)
DEF_HELPER_1(fpop, void, env)
DEF_HELPER_1(fdecstp, void, env)
DEF_HELPER_1(fincstp, void, env)
DEF_HELPER_2(ffree_STN, void, env, int)
DEF_HELPER_1(fmov_ST0_FT0, void, env)
DEF_HELPER_2(fmov_FT0_STN, void, env, int)
DEF_HELPER_2(fmov_ST0_STN, void, env, int)
DEF_HELPER_2(fmov_STN_ST0, void, env, int)
DEF_HELPER_2(fxchg_ST0_STN, void, env, int)
DEF_HELPER_1(fcom_ST0_FT0, void, env)
DEF_HELPER_1(fucom_ST0_FT0, void, env)
DEF_HELPER_1(fcomi_ST0_FT0, void, env)
DEF_HELPER_1(fucomi_ST0_FT0, void, env)
DEF_HELPER_1(fadd_ST0_FT0, void, env)
DEF_HELPER_1(fmul_ST0_FT0, void, env)
DEF_HELPER_1(fsub_ST0_FT0, void, env)
DEF_HELPER_1(fsubr_ST0_FT0, void, env)
DEF_HELPER_1(fdiv_ST0_FT0, void, env)
DEF_HELPER_1(fdivr_ST0_FT0, void, env)
DEF_HELPER_2(fadd_STN_ST0, void, env, int)
DEF_HELPER_2(fmul_STN_ST0, void, env, int)
DEF_HELPER_2(fsub_STN_ST0, void, env, int)
DEF_HELPER_2(fsubr_STN_ST0, void, env, int)
DEF_HELPER_2(fdiv_STN_ST0, void, env, int)
DEF_HELPER_2(fdivr_STN_ST0, void, env, int)
DEF_HELPER_1(fchs_ST0, void, env)
DEF_HELPER_1(fabs_ST0, void, env)
DEF_HELPER_1(fxam_ST0, void, env)
DEF_HELPER_1(fld1_ST0, void, env)
DEF_HELPER_1(fldl2t_ST0, void, env)
DEF_HELPER_1(fldl2e_ST0, void, env)
DEF_HELPER_1(fldpi_ST0, void, env)
DEF_HELPER_1(fldlg2_ST0, void, env)
DEF_HELPER_1(fldln2_ST0, void, env)
DEF_HELPER_1(fldz_ST0, void, env)
DEF_HELPER_1(fldz_FT0, void, env)
DEF_HELPER_1(fnstsw, i32, env)
DEF_HELPER_1(fnstcw, i32, env)
DEF_HELPER_2(fldcw, void, env, i32)
DEF_HELPER_1(fclex, void, env)
DEF_HELPER_1(fwait, void, env)
DEF_HELPER_1(fninit, void, env)
DEF_HELPER_2(fbld_ST0, void, env, tl)
DEF_HELPER_2(fbst_ST0, void, env, tl)
DEF_HELPER_1(f2xm1, void, env)
DEF_HELPER_1(fyl2x, void, env)
DEF_HELPER_1(fptan, void, env)
DEF_HELPER_1(fpatan, void, env)
DEF_HELPER_1(fxtract, void, env)
DEF_HELPER_1(fprem1, void, env)
DEF_HELPER_1(fprem, void, env)
DEF_HELPER_1(fyl2xp1, void, env)
DEF_HELPER_1(fsqrt, void, env)
DEF_HELPER_1(fsincos, void, env)
DEF_HELPER_1(frndint, void, env)
DEF_HELPER_1(fscale, void, env)
DEF_HELPER_1(fsin, void, env)
DEF_HELPER_1(fcos, void, env)
DEF_HELPER_3(fstenv, void, env, tl, int)
DEF_HELPER_3(fldenv, void, env, tl, int)
DEF_HELPER_3(fsave, void, env, tl, int)
DEF_HELPER_3(frstor, void, env, tl, int)
DEF_HELPER_FLAGS_2(fxsave, TCG_CALL_NO_WG, void, env, tl)
DEF_HELPER_FLAGS_2(fxrstor, TCG_CALL_NO_WG, void, env, tl)
DEF_HELPER_FLAGS_3(xsave, TCG_CALL_NO_WG, void, env, tl, i64)

View File

@ -32,6 +32,93 @@
#include "trace-tcg.h"
#include "exec/log.h"
#if defined(XBOX) && defined(__x86_64__)
#include "ui/xemu-settings.h"
static int g_use_hard_fpu;
#define MAP_GEN_HELPER_SOFT_HARD(name) \
(g_use_hard_fpu ? gen_helper_##name##__hard : gen_helper_##name##__soft)
#define gen_helper_flds_FT0 MAP_GEN_HELPER_SOFT_HARD(flds_FT0)
#define gen_helper_fldl_FT0 MAP_GEN_HELPER_SOFT_HARD(fldl_FT0)
#define gen_helper_fildl_FT0 MAP_GEN_HELPER_SOFT_HARD(fildl_FT0)
#define gen_helper_flds_ST0 MAP_GEN_HELPER_SOFT_HARD(flds_ST0)
#define gen_helper_fldl_ST0 MAP_GEN_HELPER_SOFT_HARD(fldl_ST0)
#define gen_helper_fildl_ST0 MAP_GEN_HELPER_SOFT_HARD(fildl_ST0)
#define gen_helper_fildll_ST0 MAP_GEN_HELPER_SOFT_HARD(fildll_ST0)
#define gen_helper_fsts_ST0 MAP_GEN_HELPER_SOFT_HARD(fsts_ST0)
#define gen_helper_fstl_ST0 MAP_GEN_HELPER_SOFT_HARD(fstl_ST0)
#define gen_helper_fist_ST0 MAP_GEN_HELPER_SOFT_HARD(fist_ST0)
#define gen_helper_fistl_ST0 MAP_GEN_HELPER_SOFT_HARD(fistl_ST0)
#define gen_helper_fistll_ST0 MAP_GEN_HELPER_SOFT_HARD(fistll_ST0)
#define gen_helper_fistt_ST0 MAP_GEN_HELPER_SOFT_HARD(fistt_ST0)
#define gen_helper_fisttl_ST0 MAP_GEN_HELPER_SOFT_HARD(fisttl_ST0)
#define gen_helper_fisttll_ST0 MAP_GEN_HELPER_SOFT_HARD(fisttll_ST0)
#define gen_helper_fldt_ST0 MAP_GEN_HELPER_SOFT_HARD(fldt_ST0)
#define gen_helper_fstt_ST0 MAP_GEN_HELPER_SOFT_HARD(fstt_ST0)
#define gen_helper_fpush MAP_GEN_HELPER_SOFT_HARD(fpush)
#define gen_helper_fpop MAP_GEN_HELPER_SOFT_HARD(fpop)
#define gen_helper_fdecstp MAP_GEN_HELPER_SOFT_HARD(fdecstp)
#define gen_helper_fincstp MAP_GEN_HELPER_SOFT_HARD(fincstp)
#define gen_helper_ffree_STN MAP_GEN_HELPER_SOFT_HARD(ffree_STN)
#define gen_helper_fmov_ST0_FT0 MAP_GEN_HELPER_SOFT_HARD(fmov_ST0_FT0)
#define gen_helper_fmov_FT0_STN MAP_GEN_HELPER_SOFT_HARD(fmov_FT0_STN)
#define gen_helper_fmov_ST0_STN MAP_GEN_HELPER_SOFT_HARD(fmov_ST0_STN)
#define gen_helper_fmov_STN_ST0 MAP_GEN_HELPER_SOFT_HARD(fmov_STN_ST0)
#define gen_helper_fxchg_ST0_STN MAP_GEN_HELPER_SOFT_HARD(fxchg_ST0_STN)
#define gen_helper_fcom_ST0_FT0 MAP_GEN_HELPER_SOFT_HARD(fcom_ST0_FT0)
#define gen_helper_fucom_ST0_FT0 MAP_GEN_HELPER_SOFT_HARD(fucom_ST0_FT0)
#define gen_helper_fcomi_ST0_FT0 MAP_GEN_HELPER_SOFT_HARD(fcomi_ST0_FT0)
#define gen_helper_fucomi_ST0_FT0 MAP_GEN_HELPER_SOFT_HARD(fucomi_ST0_FT0)
#define gen_helper_fadd_ST0_FT0 MAP_GEN_HELPER_SOFT_HARD(fadd_ST0_FT0)
#define gen_helper_fmul_ST0_FT0 MAP_GEN_HELPER_SOFT_HARD(fmul_ST0_FT0)
#define gen_helper_fsub_ST0_FT0 MAP_GEN_HELPER_SOFT_HARD(fsub_ST0_FT0)
#define gen_helper_fsubr_ST0_FT0 MAP_GEN_HELPER_SOFT_HARD(fsubr_ST0_FT0)
#define gen_helper_fdiv_ST0_FT0 MAP_GEN_HELPER_SOFT_HARD(fdiv_ST0_FT0)
#define gen_helper_fdivr_ST0_FT0 MAP_GEN_HELPER_SOFT_HARD(fdivr_ST0_FT0)
#define gen_helper_fadd_STN_ST0 MAP_GEN_HELPER_SOFT_HARD(fadd_STN_ST0)
#define gen_helper_fmul_STN_ST0 MAP_GEN_HELPER_SOFT_HARD(fmul_STN_ST0)
#define gen_helper_fsub_STN_ST0 MAP_GEN_HELPER_SOFT_HARD(fsub_STN_ST0)
#define gen_helper_fsubr_STN_ST0 MAP_GEN_HELPER_SOFT_HARD(fsubr_STN_ST0)
#define gen_helper_fdiv_STN_ST0 MAP_GEN_HELPER_SOFT_HARD(fdiv_STN_ST0)
#define gen_helper_fdivr_STN_ST0 MAP_GEN_HELPER_SOFT_HARD(fdivr_STN_ST0)
#define gen_helper_fchs_ST0 MAP_GEN_HELPER_SOFT_HARD(fchs_ST0)
#define gen_helper_fabs_ST0 MAP_GEN_HELPER_SOFT_HARD(fabs_ST0)
#define gen_helper_fxam_ST0 MAP_GEN_HELPER_SOFT_HARD(fxam_ST0)
#define gen_helper_fld1_ST0 MAP_GEN_HELPER_SOFT_HARD(fld1_ST0)
#define gen_helper_fldl2t_ST0 MAP_GEN_HELPER_SOFT_HARD(fldl2t_ST0)
#define gen_helper_fldl2e_ST0 MAP_GEN_HELPER_SOFT_HARD(fldl2e_ST0)
#define gen_helper_fldpi_ST0 MAP_GEN_HELPER_SOFT_HARD(fldpi_ST0)
#define gen_helper_fldlg2_ST0 MAP_GEN_HELPER_SOFT_HARD(fldlg2_ST0)
#define gen_helper_fldln2_ST0 MAP_GEN_HELPER_SOFT_HARD(fldln2_ST0)
#define gen_helper_fldz_ST0 MAP_GEN_HELPER_SOFT_HARD(fldz_ST0)
#define gen_helper_fldz_FT0 MAP_GEN_HELPER_SOFT_HARD(fldz_FT0)
#define gen_helper_fnstsw MAP_GEN_HELPER_SOFT_HARD(fnstsw)
#define gen_helper_fnstcw MAP_GEN_HELPER_SOFT_HARD(fnstcw)
#define gen_helper_fldcw MAP_GEN_HELPER_SOFT_HARD(fldcw)
#define gen_helper_fclex MAP_GEN_HELPER_SOFT_HARD(fclex)
#define gen_helper_fwait MAP_GEN_HELPER_SOFT_HARD(fwait)
#define gen_helper_fninit MAP_GEN_HELPER_SOFT_HARD(fninit)
#define gen_helper_fbld_ST0 MAP_GEN_HELPER_SOFT_HARD(fbld_ST0)
#define gen_helper_fbst_ST0 MAP_GEN_HELPER_SOFT_HARD(fbst_ST0)
#define gen_helper_f2xm1 MAP_GEN_HELPER_SOFT_HARD(f2xm1)
#define gen_helper_fyl2x MAP_GEN_HELPER_SOFT_HARD(fyl2x)
#define gen_helper_fptan MAP_GEN_HELPER_SOFT_HARD(fptan)
#define gen_helper_fpatan MAP_GEN_HELPER_SOFT_HARD(fpatan)
#define gen_helper_fxtract MAP_GEN_HELPER_SOFT_HARD(fxtract)
#define gen_helper_fprem1 MAP_GEN_HELPER_SOFT_HARD(fprem1)
#define gen_helper_fprem MAP_GEN_HELPER_SOFT_HARD(fprem)
#define gen_helper_fyl2xp1 MAP_GEN_HELPER_SOFT_HARD(fyl2xp1)
#define gen_helper_fsqrt MAP_GEN_HELPER_SOFT_HARD(fsqrt)
#define gen_helper_fsincos MAP_GEN_HELPER_SOFT_HARD(fsincos)
#define gen_helper_frndint MAP_GEN_HELPER_SOFT_HARD(frndint)
#define gen_helper_fscale MAP_GEN_HELPER_SOFT_HARD(fscale)
#define gen_helper_fsin MAP_GEN_HELPER_SOFT_HARD(fsin)
#define gen_helper_fcos MAP_GEN_HELPER_SOFT_HARD(fcos)
#define gen_helper_fstenv MAP_GEN_HELPER_SOFT_HARD(fstenv)
#define gen_helper_fldenv MAP_GEN_HELPER_SOFT_HARD(fldenv)
#define gen_helper_fsave MAP_GEN_HELPER_SOFT_HARD(fsave)
#define gen_helper_frstor MAP_GEN_HELPER_SOFT_HARD(frstor)
#endif /* defined(XBOX) && defined(__x86_64__) */
#define PREFIX_REPZ 0x01
#define PREFIX_REPNZ 0x02
#define PREFIX_LOCK 0x04
@ -8449,6 +8536,8 @@ void tcg_x86_init(void)
offsetof(CPUX86State, bnd_regs[i].ub),
bnd_regu_names[i]);
}
xemu_settings_get_bool(XEMU_SETTINGS_SYSTEM_HARD_FPU, &g_use_hard_fpu);
}
static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)

View File

@ -45,6 +45,7 @@ struct xemu_settings {
char *eeprom_path;
int memory;
int short_animation; // Boolean
int hard_fpu; // Boolean
// [audio]
int use_dsp; // Boolean
@ -107,6 +108,7 @@ struct config_offset_table {
[XEMU_SETTINGS_SYSTEM_EEPROM_PATH] = { CONFIG_TYPE_STRING, "system", "eeprom_path", offsetof(struct xemu_settings, eeprom_path), { .default_str = "" } },
[XEMU_SETTINGS_SYSTEM_MEMORY] = { CONFIG_TYPE_INT, "system", "memory", offsetof(struct xemu_settings, memory), { .default_int = 64 } },
[XEMU_SETTINGS_SYSTEM_SHORTANIM] = { CONFIG_TYPE_BOOL, "system", "shortanim", offsetof(struct xemu_settings, short_animation), { .default_bool = 0 } },
[XEMU_SETTINGS_SYSTEM_HARD_FPU] = { CONFIG_TYPE_BOOL, "system", "hard_fpu", offsetof(struct xemu_settings, hard_fpu), { .default_bool = 1 } },
[XEMU_SETTINGS_AUDIO_USE_DSP] = { CONFIG_TYPE_BOOL, "audio", "use_dsp", offsetof(struct xemu_settings, use_dsp), { .default_bool = 0 } },

View File

@ -36,6 +36,7 @@ enum xemu_settings_keys {
XEMU_SETTINGS_SYSTEM_DVD_PATH,
XEMU_SETTINGS_SYSTEM_MEMORY,
XEMU_SETTINGS_SYSTEM_SHORTANIM,
XEMU_SETTINGS_SYSTEM_HARD_FPU,
XEMU_SETTINGS_AUDIO_USE_DSP,
XEMU_SETTINGS_DISPLAY_SCALE,
XEMU_SETTINGS_DISPLAY_UI_SCALE,