diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h index 7680193ebc..07698ea27f 100644 --- a/include/fpu/softfloat-types.h +++ b/include/fpu/softfloat-types.h @@ -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 diff --git a/target/i386/Makefile.objs b/target/i386/Makefile.objs index 0b93143e27..8b9a0b42d1 100644 --- a/target/i386/Makefile.objs +++ b/target/i386/Makefile.objs @@ -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 diff --git a/target/i386/fpu_helper.c b/target/i386/fpu_helper.c index 4ea73874d8..643edc51db 100644 --- a/target/i386/fpu_helper.c +++ b/target/i386/fpu_helper.c @@ -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 diff --git a/target/i386/fpu_helper_hard.c b/target/i386/fpu_helper_hard.c new file mode 100644 index 0000000000..ce4abe54f2 --- /dev/null +++ b/target/i386/fpu_helper_hard.c @@ -0,0 +1,4 @@ +#if defined(XBOX) && defined(__x86_64__) +#define USE_HARD_FPU 1 +#include "fpu_helper.c" +#endif diff --git a/target/i386/helper.h b/target/i386/helper.h index c2ae2f7e61..a5a7e7ad8b 100644 --- a/target/i386/helper.h +++ b/target/i386/helper.h @@ -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) diff --git a/target/i386/translate.c b/target/i386/translate.c index caea6f5fb1..b3b802d763 100644 --- a/target/i386/translate.c +++ b/target/i386/translate.c @@ -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) diff --git a/ui/xemu-settings.c b/ui/xemu-settings.c index 6fe65ab48d..223bee5727 100644 --- a/ui/xemu-settings.c +++ b/ui/xemu-settings.c @@ -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 } }, diff --git a/ui/xemu-settings.h b/ui/xemu-settings.h index 1e34b4925b..995439a292 100644 --- a/ui/xemu-settings.h +++ b/ui/xemu-settings.h @@ -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,