cfgfile_dwrite_bool (f, _T("fpu_no_unimplemented"), p->fpu_no_unimplemented);
cfgfile_dwrite_bool (f, _T("cpu_no_unimplemented"), p->int_no_unimplemented);
cfgfile_write_bool (f, _T("fpu_strict"), p->fpu_strict);
- cfgfile_dwrite_bool (f, _T("fpu_softfloat"), p->fpu_softfloat);
+ cfgfile_dwrite_bool (f, _T("fpu_softfloat"), p->fpu_mode > 0);
+#ifdef MSVC_LONG_DOUBLE
+ cfgfile_dwrite_bool(f, _T("fpu_msvc_long_double"), p->fpu_mode < 0);
+#endif
cfgfile_write_bool (f, _T("rtg_nocustom"), p->picasso96_nocustom);
cfgfile_write (f, _T("rtg_modes"), _T("0x%x"), p->picasso96_modeflags);
|| cfgfile_yesno (option, value, _T("serial_hardware_ctsrts"), &p->serial_hwctsrts)
|| cfgfile_yesno (option, value, _T("serial_direct"), &p->serial_direct)
|| cfgfile_yesno (option, value, _T("fpu_strict"), &p->fpu_strict)
- || cfgfile_yesno (option, value, _T("fpu_softfloat"), &p->fpu_softfloat)
|| cfgfile_yesno (option, value, _T("comp_nf"), &p->compnf)
|| cfgfile_yesno (option, value, _T("comp_constjump"), &p->comp_constjump)
#ifdef USE_JIT_FPU
|| cfgfile_string (option, value, _T("ghostscript_parameters"), p->ghostscript_parameters, sizeof p->ghostscript_parameters / sizeof (TCHAR)))
return 1;
+ if (cfgfile_yesno(option, value, _T("fpu_softfloat"), &dummybool)) {
+ if (dummybool)
+ p->fpu_mode = 1;
+ return 1;
+ }
+#ifdef MSVC_LONG_DOUBLE
+ if (cfgfile_yesno(option, value, _T("fpu_msvc_long_double"), &dummybool)) {
+ if (dummybool)
+ p->fpu_mode = -1;
+ return 1;
+ }
+#endif
+
if (cfgfile_string(option, value, _T("uaeboard_options"), tmpbuf, sizeof tmpbuf / sizeof(TCHAR))) {
TCHAR *s = cfgfile_option_get(value, _T("order"));
if (s)
p->fpu_no_unimplemented = false;
p->int_no_unimplemented = false;
p->fpu_strict = 0;
- p->fpu_softfloat = 0;
+ p->fpu_mode = 0;
p->m68k_speed = 0;
p->cpu_compatible = 1;
p->address_space_24 = 1;
#include "softfloat/softfloat.h"
+// global variable for JIT FPU
+#ifdef USE_LONG_DOUBLE
+bool use_long_double = true;
+#else
+bool use_long_double = false;
+#endif
+
FPP_PRINT fpp_print;
FPP_IS fpp_is_snan;
static bool fp_exception_pending(bool pre)
{
// first check for pending arithmetic exceptions
- if (currprefs.fpu_softfloat) {
+ if (currprefs.fpu_mode > 0) {
if (regs.fp_exp_pend) {
if (warned > 0) {
write_log (_T("FPU ARITHMETIC EXCEPTION (%d)\n"), regs.fp_exp_pend);
static void fpsr_check_arithmetic_exception(uae_u32 mask, fpdata *src, uae_u32 opcode, uae_u16 extra, uae_u32 ea)
{
- if (!currprefs.fpu_softfloat)
+ if (currprefs.fpu_mode <= 0)
return;
bool nonmaskable;
#endif
}
- if (!currprefs.fpu_softfloat) {
+ if (currprefs.fpu_mode <= 0) {
// log message and exit
regs.fp_exp_pend = 0;
return;
if (regs.fpsr & (FPSR_OVFL | FPSR_INEX2 | FPSR_INEX1))
regs.fpsr |= FPSR_AE_INEX; // INEX = INEX1 || INEX2 || OVFL
- if (!currprefs.fpu_softfloat)
+ if (currprefs.fpu_mode <= 0)
return 0;
// return exceptions that interrupt calculation
if (regs.fpcr & FPSR_BSUN) {
// logging only so far
write_log (_T("FPU exception: BSUN! (FPSR: %08x, FPCR: %04x)\n"), regs.fpsr, regs.fpcr);
- if (currprefs.fpu_softfloat) {
+ if (currprefs.fpu_mode > 0) {
regs.fp_exp_pend = fpsr_get_vector(FPSR_BSUN);
fp_exception_pending(true);
return 1;
// 68040/060 does not support denormals
static bool normalize_or_fault_if_no_denormal_support(uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr oldpc, fpdata *src)
{
- if (!currprefs.fpu_softfloat)
+ if (currprefs.fpu_mode <= 0)
return false;
if (fpp_is_unnormal(src) || fpp_is_denormal(src)) {
if (currprefs.cpu_model >= 68040 && currprefs.fpu_model && currprefs.fpu_no_unimplemented) {
}
static bool normalize_or_fault_if_no_denormal_support_dst(uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr oldpc, fpdata *dst, fpdata *src)
{
- if (!currprefs.fpu_softfloat)
+ if (currprefs.fpu_mode <= 0)
return false;
if (fpp_is_unnormal(dst) || fpp_is_denormal(dst)) {
if (currprefs.cpu_model >= 68040 && currprefs.fpu_model && currprefs.fpu_no_unimplemented) {
// 68040 does not support move to integer format
static bool fault_if_68040_integer_nonmaskable(uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr oldpc, fpdata *src)
{
- if (currprefs.cpu_model == 68040 && currprefs.fpu_model && currprefs.fpu_softfloat) {
+ if (currprefs.cpu_model == 68040 && currprefs.fpu_model && currprefs.fpu_mode > 0) {
fpsr_make_status();
if (regs.fpsr & (FPSR_SNAN | FPSR_OPERR)) {
fpsr_check_arithmetic_exception(FPSR_SNAN | FPSR_OPERR, src, opcode, extra, ea);
fpu_noinst (opcode, pc);
}
+static bool plop;
+
void fpuop_arithmetic (uae_u32 opcode, uae_u16 extra)
{
+ if (plop)
+ write_log(_T("%04x %04x %08x\n"), opcode, extra, M68K_GETPC);
+
regs.fpu_state = 1;
regs.fp_exception = false;
fpu_mmu_fixup = false;
{
uae_u32 temp_ext[8][3];
- if (currprefs.fpu_softfloat == changed_prefs.fpu_softfloat)
+ if (currprefs.fpu_mode == changed_prefs.fpu_mode)
return;
- currprefs.fpu_softfloat = changed_prefs.fpu_softfloat;
+ currprefs.fpu_mode = changed_prefs.fpu_mode;
+ set_cpu_caches(true);
for (int i = 0; i < 8; i++) {
fpp_from_exten_fmovem(®s.fp[i], &temp_ext[i][0], &temp_ext[i][1], &temp_ext[i][2]);
}
- if (currprefs.fpu_softfloat) {
+ if (currprefs.fpu_mode > 0) {
fp_init_softfloat();
+#ifdef MSVC_LONG_DOUBLE
+ } else if (currprefs.fpu_mode < 0) {
+ use_long_double = true;
+ fp_init_native_80();
+#endif
} else {
+#ifdef MSVC_LONG_DOUBLE
+ use_long_double = false;
+#endif
fp_init_native();
}
for (int i = 0; i < 8; i++) {
void fpu_reset (void)
{
- if (currprefs.fpu_softfloat) {
+ if (currprefs.fpu_mode > 0) {
fp_init_softfloat();
+#ifdef MSVC_LONG_DOUBLE
+ } else if (currprefs.fpu_mode < 0) {
+ use_long_double = true;
+ fp_init_native_80();
+#endif
} else {
+#ifdef MSVC_LONG_DOUBLE
+ use_long_double = false;
+#endif
fp_init_native();
}
#if defined(CPU_i386) || defined(CPU_x86_64)
init_fpucw_x87();
+#ifdef MSVC_LONG_DOUBLE
+ init_fpucw_x87_80();
+#endif
#endif
regs.fpiar = 0;
wrd[0] = wrd[1] = wrd[2] = 0;
- fpp_to_native(&fp, src);
+ fp_to_native(&fp, src);
-#if USE_LONG_DOUBLE
+#ifdef USE_LONG_DOUBLE
sprintf (str, "%#.17Le", fp);
#else
sprintf (str, "%#.17e", fp);
*cp++ = ((wrd[0] >> 20) & 0xf) + '0';
*cp++ = ((wrd[0] >> 16) & 0xf) + '0';
*cp = 0;
-#if USE_LONG_DOUBLE
+#ifdef USE_LONG_DOUBLE
sscanf (str, "%Le", &d);
#else
sscanf (str, "%le", &d);
#endif
- fpp_from_native(d, fpd);
+ fp_from_native(d, fpd);
}
fpp_clear_status = fp_clear_status;
fpp_set_mode = fp_set_mode;
- fpp_from_native = fp_from_native;
- fpp_to_native = fp_to_native;
-
fpp_to_int = fp_to_int;
fpp_from_int = fp_from_int;
return;
}
if (fp_is_nan(fpd)) {
-#if USE_LONG_DOUBLE
+#ifdef USE_LONG_DOUBLE
*fp = sqrtl(-1);
#else
*fp = sqrt(-1);
}
if (fp_is_infinity(fpd)) {
double zero = 0.0;
-#if USE_LONG_DOUBLE
+#ifdef USE_LONG_DOUBLE
*fp = fp_is_neg(fpd) ? logl(0.0) : (1.0 / zero);
#else
*fp = fp_is_neg(fpd) ? log(0.0) : (1.0 / zero);
frac = (fptype)fpd->fpx.low / (fptype)(twoto32 * 2147483648.0);
if (fp_is_neg(fpd))
frac = -frac;
-#if USE_LONG_DOUBLE
+#ifdef USE_LONG_DOUBLE
*fp = ldexpl (frac, expon - 16383);
#else
*fp = ldexp (frac, expon - 16383);
if (fp < 0.0)
fp = -fp;
-#if USE_LONG_DOUBLE
+#ifdef USE_LONG_DOUBLE
frac = frexpl (fp, &expon);
#else
frac = frexp (fp, &expon);
fpp_clear_status = fp_clear_status;
fpp_set_mode = fp_set_mode;
- fpp_from_native = from_native;
- fpp_to_native = to_native;
-
fpp_to_int = to_int;
fpp_from_int = from_int;
#define FPSR_INEX1 0x00000100
extern void fp_init_native(void);
+#ifdef MSVC_LONG_DOUBLE
+extern void fp_init_native_80(void);
+#endif
extern void fp_init_softfloat(void);
extern void fpsr_set_exception(uae_u32 exception);
extern void fpu_modechange(void);
#if defined(CPU_i386) || defined(CPU_x86_64)
extern void init_fpucw_x87(void);
+#ifdef MSVC_LONG_DOUBLE
+extern void init_fpucw_x87_80(void);
+#endif
#endif
typedef void (*FPP_ABQS)(fpdata*, fpdata*, uae_u64*, uae_u8*);
extern FPP_CLEAR_STATUS fpp_clear_status;
extern FPP_SET_MODE fpp_set_mode;
-extern FPP_FROM_NATIVE fpp_from_native;
-extern FPP_TO_NATIVE fpp_to_native;
-
extern FPP_TO_INT fpp_to_int;
extern FPP_FROM_INT fpp_from_int;
#ifdef USE_LONG_DOUBLE
typedef long double fptype;
-#define LDPTR tbyte ptr
#else
typedef double fptype;
-#define LDPTR qword ptr
#endif
#endif
};
extern struct mmufixup mmufixup[2];
+#ifdef MSVC_LONG_DOUBLE
+typedef struct {
+ uae_u64 m;
+ uae_u16 e;
+ uae_u16 dummy;
+} fprawtype;
+#endif
+
typedef struct
{
floatx80 fpx;
+#ifdef MSVC_LONG_DOUBLE
+ union {
+ fptype fp;
+ fprawtype rfp;
+ };
+#else
fptype fp;
+#endif
} fpdata;
struct regstruct
bool comp_constjump;
int cachesize;
bool fpu_strict;
- bool fpu_softfloat;
+ int fpu_mode;
struct monconfig gfx_monitor[MAX_AMIGADISPLAYS];
int gfx_framerate, gfx_autoframerate;
extern FILE *log_open (const TCHAR *name, int append, int bootlog, TCHAR*);
extern void log_close (FILE *f);
+extern bool use_long_double;
#ifndef O_BINARY
#define O_BINARY 0
static void f_tomem(int r)
{
if (live.fate[r].status==DIRTY) {
-#if defined(USE_LONG_DOUBLE)
- raw_fmov_ext_mr((uintptr)live.fate[r].mem,live.fate[r].realreg);
-#else
- raw_fmov_mr((uintptr)live.fate[r].mem,live.fate[r].realreg);
-#endif
+ if (use_long_double) {
+ raw_fmov_ext_mr((uintptr)live.fate[r].mem, live.fate[r].realreg);
+ } else {
+ raw_fmov_mr((uintptr)live.fate[r].mem, live.fate[r].realreg);
+ }
live.fate[r].status=CLEAN;
}
}
static void f_tomem_drop(int r)
{
if (live.fate[r].status==DIRTY) {
-#if defined(USE_LONG_DOUBLE)
- raw_fmov_ext_mr_drop((uintptr)live.fate[r].mem,live.fate[r].realreg);
-#else
- raw_fmov_mr_drop((uintptr)live.fate[r].mem,live.fate[r].realreg);
-#endif
+ if (use_long_double) {
+ raw_fmov_ext_mr_drop((uintptr)live.fate[r].mem, live.fate[r].realreg);
+ } else {
+ raw_fmov_mr_drop((uintptr)live.fate[r].mem, live.fate[r].realreg);
+ }
live.fate[r].status=INMEM;
}
}
if (!willclobber) {
if (live.fate[r].status!=UNDEF) {
-#if defined(USE_LONG_DOUBLE)
- raw_fmov_ext_rm(bestreg,(uintptr)live.fate[r].mem);
-#else
- raw_fmov_rm(bestreg,(uintptr)live.fate[r].mem);
-#endif
+ if (use_long_double) {
+ raw_fmov_ext_rm(bestreg, (uintptr)live.fate[r].mem);
+ } else {
+ raw_fmov_rm(bestreg, (uintptr)live.fate[r].mem);
+ }
}
live.fate[r].status=CLEAN;
}
static void f_tomem(int r)
{
if (live.fate[r].status==DIRTY) {
-#if USE_LONG_DOUBLE
- raw_fmov_ext_mr((uintptr)live.fate[r].mem,live.fate[r].realreg);
-#else
- raw_fmov_mr((uintptr)live.fate[r].mem,live.fate[r].realreg);
-#endif
- live.fate[r].status=CLEAN;
+ if (use_long_double) {
+ raw_fmov_ext_mr((uintptr)live.fate[r].mem, live.fate[r].realreg);
+ } else {
+ raw_fmov_mr((uintptr)live.fate[r].mem, live.fate[r].realreg);
+ }
+ live.fate[r].status=CLEAN;
}
}
static void f_tomem_drop(int r)
{
- if (live.fate[r].status==DIRTY) {
-#if USE_LONG_DOUBLE
- raw_fmov_ext_mr_drop((uintptr)live.fate[r].mem,live.fate[r].realreg);
-#else
- raw_fmov_mr_drop((uintptr)live.fate[r].mem,live.fate[r].realreg);
-#endif
- live.fate[r].status=INMEM;
+ if (live.fate[r].status == DIRTY) {
+ if (use_long_double) {
+ raw_fmov_ext_mr_drop((uintptr)live.fate[r].mem, live.fate[r].realreg);
+ } else {
+ raw_fmov_mr_drop((uintptr)live.fate[r].mem, live.fate[r].realreg);
+ }
+ live.fate[r].status=INMEM;
}
}
if (!willclobber) {
if (live.fate[r].status!=UNDEF) {
-#if USE_LONG_DOUBLE
- raw_fmov_ext_rm(bestreg,(uintptr)live.fate[r].mem);
-#else
- raw_fmov_rm(bestreg,(uintptr)live.fate[r].mem);
-#endif
+ if (use_long_double) {
+ raw_fmov_ext_rm(bestreg, (uintptr)live.fate[r].mem);
+ } else {
+ raw_fmov_rm(bestreg, (uintptr)live.fate[r].mem);
+ }
}
live.fate[r].status=CLEAN;
}
write_log("\n");
write_log("### M68k processor state\n");
- m68k_dumpstate(0);
+ m68k_dumpstate(NULL, 0xffffffff);
write_log("\n");
write_log("### Block in Mac address space\n");
error_log (_T("JIT is not compatible with unimplemented CPU/FPU instruction emulation."));
p->fpu_no_unimplemented = p->int_no_unimplemented = false;
}
- if (p->cachesize && p->compfpu && p->fpu_softfloat) {
+ if (p->cachesize && p->compfpu && p->fpu_mode > 0) {
error_log (_T("JIT FPU emulation is not compatible with softfloat FPU emulation."));
- p->fpu_softfloat = false;
+ p->fpu_mode = 0;
}
#if 0
write_log(_T("CPU=%d, FPU=%d%s, MMU=%d, JIT%s=%d."),
currprefs.cpu_model,
- currprefs.fpu_model, currprefs.fpu_model ? (currprefs.fpu_softfloat ? _T(" (softfloat)") : _T(" (host)")) : _T(""),
+ currprefs.fpu_model, currprefs.fpu_model ? (currprefs.fpu_mode > 0 ? _T(" (softfloat)") : (currprefs.fpu_mode < 0 ? _T(" (host 80b)") : _T(" (host 64b)"))) : _T(""),
currprefs.mmu_model,
currprefs.cachesize ? (currprefs.compfpu ? _T("=CPU/FPU") : _T("=CPU")) : _T(""),
currprefs.cachesize);
|| currprefs.cpu_compatible != changed_prefs.cpu_compatible
|| currprefs.cpu_cycle_exact != changed_prefs.cpu_cycle_exact
|| currprefs.cpu_memory_cycle_exact != changed_prefs.cpu_memory_cycle_exact
- || currprefs.fpu_softfloat != changed_prefs.fpu_softfloat) {
+ || currprefs.fpu_mode != changed_prefs.fpu_mode) {
cpu_prefs_changed_flag |= 1;
}
if (changed
-nasm -O1 -f win32 hq2x32.asm
-nasm -O1 -f win32 hq3x32.asm
-nasm -O1 -f win32 hq4x32.asm
-nasm -O1 -f win32 hq2x16.asm
-nasm -O1 -f win32 hq3x16.asm
-nasm -O1 -f win32 hq4x16.asm
+nasm -f win32 fpux86_80.asm
+nasm -f win64 fpux64_80.asm
+
+nasm -w-orphan-labels -f win32 hq2x32.asm
+nasm -w-orphan-labels -f win32 hq3x32.asm
+nasm -w-orphan-labels -f win32 hq4x32.asm
+nasm -w-orphan-labels -f win32 hq2x16.asm
+nasm -w-orphan-labels -f win32 hq3x16.asm
+nasm -w-orphan-labels -f win32 hq4x16.asm
--- /dev/null
+/*
+* UAE - The Un*x Amiga Emulator
+*
+* MC68881/68882/68040/68060 FPU emulation
+*
+* Native FPU, MSVC 80-bit hack
+*/
+
+#include <math.h>
+#include <float.h>
+#include <fenv.h>
+
+#include "sysconfig.h"
+#include "sysdeps.h"
+
+#define USE_HOST_ROUNDING 1
+
+#include "options.h"
+#include "memory.h"
+#include "newcpu.h"
+#include "fpp.h"
+#include "uae/attributes.h"
+#include "uae/vm.h"
+#include "newcpu.h"
+#include "softfloat/softfloat-specialize.h"
+
+extern "C"
+{
+ extern void _cdecl xfp_fldcw(uae_u16*);
+ extern void _cdecl xfp_int(void*, void*);
+ extern void _cdecl xfp_mov(void*, void*);
+ extern void _cdecl xfp_div(void*, void*);
+ extern void _cdecl xfp_mul(void*, void*);
+ extern void _cdecl xfp_abs(void*, void*);
+ extern void _cdecl xfp_neg(void*, void*);
+ extern void _cdecl xfp_add(void*, void*);
+ extern void _cdecl xfp_sub(void*, void*);
+ extern void _cdecl xfp_sqrt(void*, void*);
+ extern void _cdecl xfp_sin(void*, void*);
+ extern void _cdecl xfp_cos(void*, void*);
+ extern void _cdecl xfp_to_single(void*, uae_u32*);
+ extern void _cdecl xfp_from_single(void*, uae_u32*);
+ extern void _cdecl xfp_to_double(void*, uae_u32*);
+ extern void _cdecl xfp_from_double(void*, uae_u32*);
+ extern void _cdecl xfp_from_int(void*, uae_s32*);
+ extern void _cdecl xfp_to_int(void*, uae_s64*);
+ extern void _cdecl xfp_round_single(void*, void*);
+ extern void _cdecl xfp_round_double(void*, void*);
+ extern void _cdecl xfp_x_to_double(void*, fptype*);
+ extern void _cdecl xfp_x_from_double(void*, fptype*);
+ extern uae_u16 _cdecl xfp_get_status(void);
+ extern void _cdecl xfp_clear_status(void);
+}
+static uae_u16 fpx_mode = 0x107f;
+
+static uae_u32 xhex_nan[] ={0xffffffff, 0xffffffff, 0x7fff};
+static long double *fp_nan = (long double *)xhex_nan;
+
+#define FPCR_ROUNDING_MODE 0x00000030
+#define FPCR_ROUND_NEAR 0x00000000
+#define FPCR_ROUND_ZERO 0x00000010
+#define FPCR_ROUND_MINF 0x00000020
+#define FPCR_ROUND_PINF 0x00000030
+
+#define FPCR_ROUNDING_PRECISION 0x000000c0
+#define FPCR_PRECISION_SINGLE 0x00000040
+#define FPCR_PRECISION_DOUBLE 0x00000080
+#define FPCR_PRECISION_EXTENDED 0x00000000
+
+static struct float_status fs;
+static uae_u32 fpu_mode_control = 0;
+static int fpu_prec;
+static int temp_prec;
+
+static void fp_set_mode(uae_u32 m68k_cw)
+{
+ // RN, RZ, RM, RP
+ static const uae_u16 fp87_round[4] = { 0 << 10, 3 << 10, 1 << 10, 2 << 10 };
+ // Extend X, Single S, Double D, Undefined (Double)
+ static const uae_u16 fp87_prec[4] = { 3 << 8, 0 << 8, 2 << 8, 2 << 8 };
+
+ int round = (m68k_cw >> 4) & 3;
+ int prec = (m68k_cw >> 6) & 3;
+
+ fpx_mode = fp87_round[round] | fp87_prec[prec] | 0x107f;
+ xfp_fldcw(&fpx_mode);
+}
+
+/* The main motivation for dynamically creating an x86(-64) function in
+* memory is because MSVC (x64) does not allow you to use inline assembly,
+* and the x86-64 versions of _control87/_controlfp functions only modifies
+* SSE2 registers. */
+
+static uae_u16 x87_cw = 0;
+static uae_u8 *x87_fldcw_code = NULL;
+typedef void (uae_cdecl *x87_fldcw_function)(void);
+
+void init_fpucw_x87_80(void)
+{
+ if (x87_fldcw_code) {
+ return;
+ }
+ x87_fldcw_code = (uae_u8 *)uae_vm_alloc(uae_vm_page_size(), UAE_VM_32BIT, UAE_VM_READ_WRITE_EXECUTE);
+ uae_u8 *c = x87_fldcw_code;
+ /* mov eax,0x0 */
+ *(c++) = 0xb8;
+ *(c++) = 0x00;
+ *(c++) = 0x00;
+ *(c++) = 0x00;
+ *(c++) = 0x00;
+#ifdef CPU_x86_64
+ /* Address override prefix */
+ *(c++) = 0x67;
+#endif
+ /* fldcw WORD PTR [eax+addr] */
+ *(c++) = 0xd9;
+ *(c++) = 0xa8;
+ *(c++) = (((uintptr_t)&x87_cw)) & 0xff;
+ *(c++) = (((uintptr_t)&x87_cw) >> 8) & 0xff;
+ *(c++) = (((uintptr_t)&x87_cw) >> 16) & 0xff;
+ *(c++) = (((uintptr_t)&x87_cw) >> 24) & 0xff;
+ /* ret */
+ *(c++) = 0xc3;
+ /* Write-protect the function */
+ uae_vm_protect(x87_fldcw_code, uae_vm_page_size(), UAE_VM_READ_EXECUTE);
+}
+
+static void native_set_fpucw(uae_u32 m68k_cw)
+{
+ static int ex = 0;
+ // RN, RZ, RM, RP
+ static const unsigned int fp87_round[4] = { _RC_NEAR, _RC_CHOP, _RC_DOWN, _RC_UP };
+ // Extend X, Single S, Double D, Undefined
+ static const unsigned int fp87_prec[4] = { _PC_53, _PC_24, _PC_53, _PC_53 };
+ int round = (m68k_cw >> 4) & 3;
+#ifdef WIN64
+ // x64 only sets SSE2, must also call x87_fldcw_code() to set FPU rounding mode.
+ _controlfp(ex | fp87_round[round], _MCW_RC);
+#else
+ int prec = (m68k_cw >> 6) & 3;
+ // x86 sets both FPU and SSE2 rounding mode, don't need x87_fldcw_code()
+ _control87(ex | fp87_round[round] | fp87_prec[prec], _MCW_RC | _MCW_PC);
+ return;
+#endif
+ static const uae_u16 x87_cw_tab[] = {
+ 0x127f, 0x1e7f, 0x167f, 0x1a7f, /* Double */
+ 0x107f, 0x1c7f, 0x147f, 0x187f, /* Single */
+ 0x127f, 0x1e7f, 0x167f, 0x1a7f, /* Double */
+ 0x127f, 0x1e7f, 0x167f, 0x1a7f, /* undefined (Double) */
+ };
+ x87_cw = x87_cw_tab[(m68k_cw >> 4) & 0xf];
+ ((x87_fldcw_function)x87_fldcw_code)();
+}
+
+/* Functions for setting host/library modes and getting status */
+static void fp_set_mode_native(uae_u32 mode_control)
+{
+ if (mode_control == fpu_mode_control)
+ return;
+ switch (mode_control & FPCR_ROUNDING_PRECISION) {
+ case FPCR_PRECISION_EXTENDED: // X
+ fpu_prec = 80;
+ break;
+ case FPCR_PRECISION_SINGLE: // S
+ fpu_prec = 32;
+ break;
+ case FPCR_PRECISION_DOUBLE: // D
+ default: // undefined
+ fpu_prec = 64;
+ break;
+ }
+#if USE_HOST_ROUNDING
+ if ((mode_control & FPCR_ROUNDING_MODE) != (fpu_mode_control & FPCR_ROUNDING_MODE)) {
+ switch (mode_control & FPCR_ROUNDING_MODE) {
+ case FPCR_ROUND_NEAR: // to neareset
+ fesetround(FE_TONEAREST);
+ break;
+ case FPCR_ROUND_ZERO: // to zero
+ fesetround(FE_TOWARDZERO);
+ break;
+ case FPCR_ROUND_MINF: // to minus
+ fesetround(FE_DOWNWARD);
+ break;
+ case FPCR_ROUND_PINF: // to plus
+ fesetround(FE_UPWARD);
+ break;
+ }
+ }
+ native_set_fpucw(mode_control);
+#endif
+ fpu_mode_control = mode_control;
+}
+
+
+static bool xfp_changed;
+static bool native_changed;
+
+static void xfp_resetprec(void)
+{
+ if (xfp_changed)
+ xfp_fldcw(&fpx_mode);
+}
+static void xfp_setprec(int prec)
+{
+ uae_u16 v = fpx_mode;
+ // clear precision fields
+ v &= ~(3 << 8);
+ switch (prec)
+ {
+ case 0:
+ break;
+ case 32:
+ v |= 2 << 8;
+ break;
+ default:
+ case 64:
+ v |= 3 << 8;
+ break;
+ }
+ if (v != fpx_mode) {
+ xfp_fldcw(&v);
+ xfp_changed = true;
+ } else {
+ xfp_changed = false;
+ }
+}
+
+// Must use default precision/rounding mode when calling C-library math functions.
+static void fp_normal_prec(void)
+{
+ if ((fpu_mode_control & FPCR_ROUNDING_PRECISION) != FPCR_PRECISION_DOUBLE || (fpu_mode_control & FPCR_ROUNDING_MODE) != FPCR_ROUND_NEAR) {
+ fp_set_mode_native(FPCR_PRECISION_DOUBLE | FPCR_ROUND_NEAR);
+ native_changed = true;
+ } else {
+ native_changed = false;
+ }
+}
+
+static void fp_reset_normal_prec(void)
+{
+ if (native_changed) {
+ fp_set_mode_native(temp_prec);
+ xfp_fldcw(&fpx_mode);
+ }
+}
+
+static void fp_get_status(uae_u32 *status)
+{
+ uae_u16 st = xfp_get_status();
+
+ if (st & (1 << 5))
+ *status |= FPSR_INEX2;
+ if (st & (1 << 4))
+ *status |= FPSR_UNFL;
+ if (st & (1 << 3))
+ *status |= FPSR_OVFL;
+ if (st & (1 << 2))
+ *status |= FPSR_DZ;
+}
+
+static void fp_clear_status(void)
+{
+ xfp_clear_status();
+}
+
+static void toxnative(fpdata *fpd, fptype *fp)
+{
+ xfp_x_to_double(&fpd->rfp, fp);
+}
+static void fromxnative(fptype *fp, fpdata *fpd)
+{
+ xfp_x_from_double(&fpd->rfp, fp);
+ fp_clear_status();
+}
+
+static void xfp_to_softfloat(fpdata *fpd)
+{
+ fpd->fpx.high = fpd->rfp.e;
+ fpd->fpx.low = fpd->rfp.m;
+}
+static void xfp_from_softfloat(fpdata *fpd)
+{
+ fpd->rfp.e = fpd->fpx.high;
+ fpd->rfp.m = fpd->fpx.low;
+}
+
+/* Functions for detecting float type */
+static bool fp_is_snan(fpdata *fpd)
+{
+ return 0; /* FIXME: how to detect SNAN */
+}
+static bool fp_unset_snan(fpdata *fpd)
+{
+ /* FIXME: how to unset SNAN */
+ return 0;
+}
+static bool fp_is_nan (fpdata *fpd)
+{
+ xfp_to_softfloat(fpd);
+ return floatx80_is_nan(fpd->fpx);
+}
+static bool fp_is_infinity (fpdata *fpd)
+{
+ xfp_to_softfloat(fpd);
+ return floatx80_is_infinity(fpd->fpx);
+}
+static bool fp_is_zero(fpdata *fpd)
+{
+ xfp_to_softfloat(fpd);
+ return floatx80_is_zero(fpd->fpx);
+}
+static bool fp_is_neg(fpdata *fpd)
+{
+ xfp_to_softfloat(fpd);
+ return floatx80_is_negative(fpd->fpx);
+}
+static bool fp_is_denormal(fpdata *fpd)
+{
+ return false;
+ //return (isnormal(fpd->fp) == 0); /* FIXME: how to differ denormal/unnormal? */
+}
+static bool fp_is_unnormal(fpdata *fpd)
+{
+ return false;
+ //return (isnormal(fpd->fp) == 0); /* FIXME: how to differ denormal/unnormal? */
+}
+
+/* Functions for converting between float formats */
+/* FIXME: how to preserve/fix denormals and unnormals? */
+
+static void fp_to_native(fptype *fp, fpdata *fpd)
+{
+ toxnative(fpd, fp);
+}
+static void fp_from_native(fptype fp, fpdata *fpd)
+{
+ fromxnative(&fp, fpd);
+}
+
+static void fp_to_single(fpdata *fpd, uae_u32 wrd1)
+{
+ xfp_to_single(&fpd->rfp, &wrd1);
+}
+static uae_u32 fp_from_single(fpdata *fpd)
+{
+ uae_u32 v;
+ xfp_from_single(&fpd->rfp, &v);
+ return v;
+}
+
+static void fp_to_double(fpdata *fpd, uae_u32 wrd1, uae_u32 wrd2)
+{
+ uae_u32 v[2] = { wrd2, wrd1 };
+ xfp_to_double(&fpd->rfp, v);
+}
+static void fp_from_double(fpdata *fpd, uae_u32 *wrd1, uae_u32 *wrd2)
+{
+ uae_u32 v[2];
+ xfp_from_double(&fpd->rfp, v);
+ *wrd1 = v[1];
+ *wrd2 = v[0];
+}
+static void fp_to_exten(fpdata *fpd, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
+{
+ fpd->rfp.m = ((uae_u64)wrd2 << 32) | wrd3;
+ fpd->rfp.e = wrd1 >> 16;
+}
+static void fp_from_exten(fpdata *fpd, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3)
+{
+ *wrd3 = (uae_u32)fpd->rfp.m;
+ *wrd2 = fpd->rfp.m >> 32;
+ *wrd1 = (uae_u32)fpd->rfp.e << 16;
+}
+
+static uae_s64 fp_to_int(fpdata *src, int size)
+{
+ static const fptype fxsizes1[6] =
+ {
+ -128.0, 127.0,
+ -32768.0, 32767.0,
+ -2147483648.0, 2147483647.0
+ };
+ static const uae_s64 fxsizes2[6] =
+ {
+ -128, 127,
+ -32768, 32767,
+ -2147483648LL, 2147483647
+ };
+ // x86 FPU returns infinity if conversion to integer is out
+ // of range so convert to double first, then do range check
+ fptype d;
+ xfp_x_to_double(&src->rfp, &d);
+ if (d < fxsizes1[size * 2 + 0]) {
+ return fxsizes2[size * 2 + 0];
+ } if (d > fxsizes1[size * 2 + 1]) {
+ return fxsizes2[size * 2 + 1];
+ }
+ uae_s64 v;
+ xfp_to_int(&src->rfp, &v);
+ return v;
+}
+static void fp_from_int(fpdata *fpd, uae_s32 src)
+{
+ xfp_from_int(&fpd->rfp, &src);
+}
+
+/* Functions for rounding */
+
+// round to float with extended precision exponent
+static void fp_round32(fpdata *fpd)
+{
+ int expon;
+ float mant;
+ fptype fp;
+ toxnative(fpd, &fp);
+ fp_normal_prec();
+ mant = (float)(frexpl(fp, &expon) * 2.0);
+ fp = ldexpl((fptype)mant, expon - 1);
+ fp_reset_normal_prec();
+ fromxnative(&fp, fpd);
+}
+
+// round to double with extended precision exponent
+static void fp_round64(fpdata *fpd)
+{
+ int expon;
+ double mant;
+ fptype fp;
+ toxnative(fpd, &fp);
+ fp_normal_prec();
+ mant = (double)(frexpl(fp, &expon) * 2.0);
+ fp = ldexpl((fptype)mant, expon - 1);
+ fp_reset_normal_prec();
+ fromxnative(&fp, fpd);
+}
+
+// round to float
+static void fp_round_single(fpdata *fpd)
+{
+ xfp_round_single(&fpd->rfp, &fpd->rfp);
+}
+
+// round to double
+static void fp_round_double(fpdata *fpd)
+{
+ xfp_round_double(&fpd->rfp, &fpd->rfp);
+}
+
+static const TCHAR *fp_print(fpdata *fpd, int mode)
+{
+ static TCHAR fsout[32];
+ bool n;
+ fptype fp;
+
+ if (mode < 0) {
+ uae_u32 w1, w2, w3;
+ fp_from_exten(fpd, &w1, &w2, &w3);
+ _stprintf(fsout, _T("%04X-%08X-%08X"), w1 >> 16, w2, w3);
+ return fsout;
+ }
+ toxnative(fpd, &fp);
+ fp_normal_prec();
+
+ n = signbit(fp) ? 1 : 0;
+
+ if(isinf(fp)) {
+ _stprintf(fsout, _T("%c%s"), n ? '-' : '+', _T("inf"));
+ } else if(isnan(fp)) {
+ _stprintf(fsout, _T("%c%s"), n ? '-' : '+', _T("nan"));
+ } else {
+ if(n)
+ fpd->fp *= -1.0;
+ _stprintf(fsout, _T("#%e"), fp);
+ }
+ fp_reset_normal_prec();
+ if (mode == 0 || mode > _tcslen(fsout))
+ return fsout;
+ fsout[mode] = 0;
+ return fsout;
+}
+
+static void fp_round_prec(fpdata *fpd, int prec)
+{
+ if (prec == 64) {
+ fp_round_double(fpd);
+ } else if (prec == 32) {
+ fp_round_single(fpd);
+ }
+}
+
+static void fp_round(fpdata *fpd)
+{
+ if (!currprefs.fpu_strict)
+ return;
+ fp_round_prec(fpd, fpu_prec);
+}
+
+/* Arithmetic functions */
+
+static void fp_move(fpdata *a, fpdata *b, int prec)
+{
+ xfp_setprec(prec);
+ xfp_mov(&a->rfp, &b->rfp);
+ xfp_resetprec();
+}
+
+static void fp_int(fpdata *a, fpdata *b)
+{
+ xfp_int(&a->rfp, &b->rfp);
+}
+
+static void fp_getexp(fpdata *a, fpdata *b)
+{
+ int expon;
+ fptype aa, bb;
+ toxnative(b, &bb);
+ fp_normal_prec();
+ frexpl(bb, &expon);
+ aa = (fptype) (expon - 1);
+ fp_reset_normal_prec();
+ fromxnative(&aa, a);
+}
+static void fp_getman(fpdata *a, fpdata *b)
+{
+ int expon;
+ fptype aa, bb;
+ toxnative(b, &bb);
+ fp_normal_prec();
+ aa = frexpl(bb, &expon) * 2.0;
+ fp_reset_normal_prec();
+ fromxnative(&aa, a);
+}
+static void fp_div(fpdata *a, fpdata *b, int prec)
+{
+ xfp_setprec(prec);
+ xfp_div(&a->rfp, &b->rfp);
+ xfp_resetprec();
+}
+static void fp_mod(fpdata *a, fpdata *b, uae_u64 *q, uae_u8 *s)
+{
+ fptype quot;
+ fptype aa, bb;
+ toxnative(a, &aa);
+ toxnative(b, &bb);
+#if USE_HOST_ROUNDING
+ quot = truncl(aa / bb);
+#else
+ quot = fp_round_to_zero(aa / bb);
+#endif
+ if (quot < 0.0) {
+ *s = 1;
+ quot = -quot;
+ } else {
+ *s = 0;
+ }
+ *q = (uae_u64)quot;
+ aa = fmodl(aa, bb);
+ fromxnative(&aa, a);
+}
+
+static void fp_rem(fpdata *a, fpdata *b, uae_u64 *q, uae_u8 *s)
+{
+ fptype quot;
+ fptype aa, bb;
+ toxnative(a, &aa);
+ toxnative(b, &bb);
+#if USE_HOST_ROUNDING
+ quot = roundl(aa / bb);
+#else
+ quot = fp_round_to_nearest(aa / bb);
+#endif
+ if (quot < 0.0) {
+ *s = 1;
+ quot = -quot;
+ } else {
+ *s = 0;
+ }
+ *q = (uae_u64)quot;
+ aa = remainderl(aa, bb);
+ fromxnative(&aa, a);
+}
+
+static void fp_scale(fpdata *a, fpdata *b)
+{
+ fptype aa, bb;
+ toxnative(a, &aa);
+ toxnative(b, &bb);
+ fp_normal_prec();
+ aa = ldexpl(aa, (int)bb);
+ fp_reset_normal_prec();
+ fromxnative(&aa, a);
+}
+
+static void fp_sinh(fpdata *a, fpdata *b)
+{
+ fptype aa, bb;
+ toxnative(b, &bb);
+ fp_normal_prec();
+ aa = sinhl(bb);
+ fp_reset_normal_prec();
+ fromxnative(&aa, a);
+}
+static void fp_intrz(fpdata *a, fpdata *b)
+{
+ if ((fpx_mode & (3 << 10)) == (3 << 10)) {
+ xfp_int(&a->rfp, &b->rfp);
+ } else {
+ uae_u16 old = fpx_mode;
+ uae_u16 s = fpx_mode | (3 << 10);
+ xfp_fldcw(&s);
+ xfp_int(&a->rfp, &b->rfp);
+ xfp_fldcw(&old);
+ }
+}
+static void fp_sqrt(fpdata *a, fpdata *b, int prec)
+{
+ xfp_setprec(prec);
+ xfp_sqrt(&a->rfp, &b->rfp);
+ xfp_resetprec();
+}
+static void fp_lognp1(fpdata *a, fpdata *b)
+{
+ fptype aa, bb;
+ toxnative(b, &bb);
+ fp_normal_prec();
+ aa = log1pl(bb);
+ fp_reset_normal_prec();
+ fromxnative(&aa, a);
+}
+static void fp_etoxm1(fpdata *a, fpdata *b)
+{
+ fptype aa, bb;
+ toxnative(b, &bb);
+ fp_normal_prec();
+ aa = expm1l(bb);
+ fp_reset_normal_prec();
+ fromxnative(&aa, a);
+}
+static void fp_tanh(fpdata *a, fpdata *b)
+{
+ fptype aa, bb;
+ toxnative(b, &bb);
+ fp_normal_prec();
+ a->fp = tanhl(b->fp);
+ fp_reset_normal_prec();
+ fp_round(a);
+ fromxnative(&aa, a);
+}
+static void fp_atan(fpdata *a, fpdata *b)
+{
+ fptype aa, bb;
+ toxnative(b, &bb);
+ fp_normal_prec();
+ aa = atanl(bb);
+ fp_reset_normal_prec();
+ fromxnative(&aa, a);
+}
+static void fp_atanh(fpdata *a, fpdata *b)
+{
+ fptype aa, bb;
+ toxnative(b, &bb);
+ fp_normal_prec();
+ aa = atanhl(bb);
+ fp_reset_normal_prec();
+ fromxnative(&aa, a);
+}
+static void fp_sin(fpdata *a, fpdata *b)
+{
+ xfp_sin(&a->rfp, &b->rfp);
+}
+static void fp_asin(fpdata *a, fpdata *b)
+{
+ fptype aa, bb;
+ toxnative(b, &bb);
+ fp_normal_prec();
+ aa = asinl(bb);
+ fp_reset_normal_prec();
+ fromxnative(&aa, a);
+}
+static void fp_tan(fpdata *a, fpdata *b)
+{
+ fptype aa, bb;
+ toxnative(b, &bb);
+ fp_normal_prec();
+ aa = tanl(bb);
+ fp_reset_normal_prec();
+ fromxnative(&aa, a);
+}
+static void fp_etox(fpdata *a, fpdata *b)
+{
+ fptype aa, bb;
+ toxnative(b, &bb);
+ fp_normal_prec();
+ aa = expl(bb);
+ fp_reset_normal_prec();
+ fromxnative(&aa, a);
+}
+static void fp_twotox(fpdata *a, fpdata *b)
+{
+ fptype aa, bb;
+ toxnative(b, &bb);
+ fp_normal_prec();
+ aa = powl(2.0, bb);
+ fp_reset_normal_prec();
+ fromxnative(&aa, a);
+}
+static void fp_tentox(fpdata *a, fpdata *b)
+{
+ fptype aa, bb;
+ toxnative(b, &bb);
+ fp_normal_prec();
+ aa = powl(10.0, bb);
+ fp_reset_normal_prec();
+ fromxnative(&aa, a);
+}
+static void fp_logn(fpdata *a, fpdata *b)
+{
+ fptype aa, bb;
+ toxnative(b, &bb);
+ fp_normal_prec();
+ aa = logl(bb);
+ fp_reset_normal_prec();
+ fromxnative(&aa, a);
+}
+static void fp_log10(fpdata *a, fpdata *b)
+{
+ fptype aa, bb;
+ toxnative(b, &bb);
+ fp_normal_prec();
+ aa = log10l(bb);
+ fp_reset_normal_prec();
+ fromxnative(&aa, a);
+}
+static void fp_log2(fpdata *a, fpdata *b)
+{
+ fptype aa, bb;
+ toxnative(b, &bb);
+ fp_normal_prec();
+ aa = log2l(bb);
+ fp_reset_normal_prec();
+ fromxnative(&aa, a);
+}
+static void fp_abs(fpdata *a, fpdata *b, int prec)
+{
+ xfp_setprec(prec);
+ xfp_abs(&a->rfp, &b->rfp);
+ xfp_resetprec();
+}
+static void fp_cosh(fpdata *a, fpdata *b)
+{
+ fptype aa, bb;
+ toxnative(b, &bb);
+ fp_normal_prec();
+ aa = coshl(bb);
+ fp_reset_normal_prec();
+ fromxnative(&aa, a);
+}
+static void fp_neg(fpdata *a, fpdata *b, int prec)
+{
+ xfp_setprec(prec);
+ xfp_neg(&a->rfp, &b->rfp);
+ xfp_resetprec();
+}
+static void fp_acos(fpdata *a, fpdata *b)
+{
+ fptype aa, bb;
+ toxnative(b, &bb);
+ fp_normal_prec();
+ aa = acosl(bb);
+ fp_reset_normal_prec();
+ fromxnative(&aa, a);
+}
+static void fp_cos(fpdata *a, fpdata *b)
+{
+ xfp_cos(&a->rfp, &b->rfp);
+}
+static void fp_sub(fpdata *a, fpdata *b, int prec)
+{
+ xfp_setprec(prec);
+ xfp_sub(&a->rfp, &b->rfp);
+ xfp_resetprec();
+}
+static void fp_add(fpdata *a, fpdata *b, int prec)
+{
+ xfp_setprec(prec);
+ xfp_add(&a->rfp, &b->rfp);
+ xfp_resetprec();
+}
+static void fp_mul(fpdata *a, fpdata *b, int prec)
+{
+ xfp_setprec(prec);
+ xfp_mul(&a->rfp, &b->rfp);
+ xfp_resetprec();
+}
+static void fp_sglmul(fpdata *a, fpdata *b)
+{
+ float mant;
+ int expon;
+
+ xfp_mul(&a->rfp, &b->rfp);
+
+ fptype aa;
+ toxnative(a, &aa);
+ fp_normal_prec();
+
+ mant = (float)(frexpl(aa, &expon) * 2.0);
+ aa = ldexpl((fptype)mant, expon - 1);
+
+ fp_reset_normal_prec();
+ fromxnative(&aa, a);
+}
+static void fp_sgldiv(fpdata *a, fpdata *b)
+{
+ float mant;
+ int expon;
+
+ xfp_div(&a->rfp, &b->rfp);
+
+ fptype aa;
+ toxnative(a, &aa);
+ fp_normal_prec();
+
+ mant = (float)(frexpl(aa, &expon) * 2.0);
+ aa = ldexpl((fptype)mant, expon - 1);
+
+ fp_reset_normal_prec();
+ fromxnative(&aa, a);
+}
+
+static void fp_normalize(fpdata *a)
+{
+}
+
+static void fp_cmp(fpdata *a, fpdata *b)
+{
+ xfp_setprec(64);
+ fptype v = 1.0;
+ if (currprefs.fpu_strict) {
+ bool xvset = false;
+ bool a_neg = fpp_is_neg(a);
+ bool b_neg = fpp_is_neg(b);
+ bool a_inf = fpp_is_infinity(a);
+ bool b_inf = fpp_is_infinity(b);
+ bool a_zero = fpp_is_zero(a);
+ bool b_zero = fpp_is_zero(b);
+ bool a_nan = fpp_is_nan(a);
+ bool b_nan = fpp_is_nan(b);
+
+ if (a_nan || b_nan) {
+ // FCMP never returns N + NaN
+ a->rfp.m = ((uae_u64)xhex_nan[0] << 32) | xhex_nan[1];
+ a->rfp.e = xhex_nan[2];
+ xvset = true;
+ } else if (a_zero && b_zero) {
+ if ((a_neg && b_neg) || (a_neg && !b_neg))
+ v = -0.0;
+ else
+ v = 0.0;
+ } else if (a_zero && b_inf) {
+ if (!b_neg)
+ v = -1.0;
+ else
+ v = 1.0;
+ } else if (a_inf && b_zero) {
+ if (!a_neg)
+ v = -1.0;
+ else
+ v = 1.0;
+ } else if (a_inf && b_inf) {
+ if (a_neg == b_neg)
+ v = 0.0;
+ if ((a_neg && b_neg) || (a_neg && !b_neg))
+ v = -v;
+ } else if (a_inf) {
+ if (a_neg)
+ v = -1.0;
+ } else if (b_inf) {
+ if (!b_neg)
+ v = -1.0;
+ } else {
+ xfp_sub(&a->rfp, &b->rfp);
+ xvset = true;
+ }
+ if (!xvset)
+ xfp_x_from_double(&a->rfp, &v);
+ } else {
+ xfp_sub(&a->rfp, &b->rfp);
+ }
+ fp_clear_status();
+ xfp_resetprec();
+}
+
+static void fp_tst(fpdata *a, fpdata *b)
+{
+ a->rfp.m = b->rfp.m;
+ a->rfp.e = b->rfp.e;
+}
+
+/* Functions for returning exception state data */
+
+static void fp_get_internal_overflow(fpdata *fpd)
+{
+ fpd->rfp.m = 0;
+ fpd->rfp.e = 0;
+}
+static void fp_get_internal_underflow(fpdata *fpd)
+{
+ fpd->rfp.m = 0;
+ fpd->rfp.e = 0;
+}
+static void fp_get_internal_round_all(fpdata *fpd)
+{
+ fpd->rfp.m = 0;
+ fpd->rfp.e = 0;
+}
+static void fp_get_internal_round(fpdata *fpd)
+{
+ fpd->rfp.m = 0;
+ fpd->rfp.e = 0;
+}
+static void fp_get_internal_round_exten(fpdata *fpd)
+{
+ fpd->rfp.m = 0;
+ fpd->rfp.e = 0;
+}
+static void fp_get_internal(fpdata *fpd)
+{
+ fpd->rfp.m = 0;
+ fpd->rfp.e = 0;
+}
+static uae_u32 fp_get_internal_grs(void)
+{
+ return 0;
+}
+
+/* Function for denormalizing */
+static void fp_denormalize(fpdata *fpd, int esign)
+{
+}
+
+static void fp_from_pack (fpdata *src, uae_u32 *wrd, int kfactor)
+{
+ int i, j, t;
+ int exp;
+ int ndigits;
+ char *cp, *strp;
+ char str[100];
+ fptype fp;
+
+ if (fpp_is_nan (src)) {
+ // copy bit by bit, handle signaling nan
+ fpp_from_exten(src, &wrd[0], &wrd[1], &wrd[2]);
+ return;
+ }
+ if (fpp_is_infinity (src)) {
+ // extended exponent and all 0 packed fraction
+ fpp_from_exten(src, &wrd[0], &wrd[1], &wrd[2]);
+ wrd[1] = wrd[2] = 0;
+ return;
+ }
+
+ wrd[0] = wrd[1] = wrd[2] = 0;
+
+ fp_to_native(&fp, src);
+ fp_normal_prec();
+
+ sprintf (str, "%#.17e", fp);
+
+ // get exponent
+ cp = str;
+ while (*cp != 'e') {
+ if (*cp == 0)
+ return;
+ cp++;
+ }
+ cp++;
+ if (*cp == '+')
+ cp++;
+ exp = atoi (cp);
+
+ // remove trailing zeros
+ cp = str;
+ while (*cp != 'e') {
+ cp++;
+ }
+ cp[0] = 0;
+ cp--;
+ while (cp > str && *cp == '0') {
+ *cp = 0;
+ cp--;
+ }
+
+ cp = str;
+ // get sign
+ if (*cp == '-') {
+ cp++;
+ wrd[0] = 0x80000000;
+ } else if (*cp == '+') {
+ cp++;
+ }
+ strp = cp;
+
+ if (kfactor <= 0) {
+ ndigits = abs (exp) + (-kfactor) + 1;
+ } else {
+ if (kfactor > 17) {
+ kfactor = 17;
+ fpsr_set_exception(FPSR_OPERR);
+ }
+ ndigits = kfactor;
+ }
+
+ if (ndigits < 0)
+ ndigits = 0;
+ if (ndigits > 16)
+ ndigits = 16;
+
+ // remove decimal point
+ strp[1] = strp[0];
+ strp++;
+ // add trailing zeros
+ i = strlen (strp);
+ cp = strp + i;
+ while (i < ndigits) {
+ *cp++ = '0';
+ i++;
+ }
+ i = ndigits + 1;
+ while (i < 17) {
+ strp[i] = 0;
+ i++;
+ }
+ *cp = 0;
+ i = ndigits - 1;
+ // need to round?
+ if (i >= 0 && strp[i + 1] >= '5') {
+ while (i >= 0) {
+ strp[i]++;
+ if (strp[i] <= '9')
+ break;
+ if (i == 0) {
+ strp[i] = '1';
+ exp++;
+ } else {
+ strp[i] = '0';
+ }
+ i--;
+ }
+ }
+ strp[ndigits] = 0;
+
+ // store first digit of mantissa
+ cp = strp;
+ wrd[0] |= *cp++ - '0';
+
+ // store rest of mantissa
+ for (j = 1; j < 3; j++) {
+ for (i = 0; i < 8; i++) {
+ wrd[j] <<= 4;
+ if (*cp >= '0' && *cp <= '9')
+ wrd[j] |= *cp++ - '0';
+ }
+ }
+
+ // exponent
+ if (exp < 0) {
+ wrd[0] |= 0x40000000;
+ exp = -exp;
+ }
+ if (exp > 9999) // ??
+ exp = 9999;
+ if (exp > 999) {
+ int d = exp / 1000;
+ wrd[0] |= d << 12;
+ exp -= d * 1000;
+ fpsr_set_exception(FPSR_OPERR);
+ }
+ i = 100;
+ t = 0;
+ while (i >= 1) {
+ int d = exp / i;
+ t <<= 4;
+ t |= d;
+ exp -= d * i;
+ i /= 10;
+ }
+ wrd[0] |= t << 16;
+ fp_reset_normal_prec();
+}
+
+static void fp_to_pack (fpdata *fpd, uae_u32 *wrd, int dummy)
+{
+ fptype d;
+ char *cp;
+ char str[100];
+
+ if (((wrd[0] >> 16) & 0x7fff) == 0x7fff) {
+ // infinity has extended exponent and all 0 packed fraction
+ // nans are copies bit by bit
+ fpp_to_exten(fpd, wrd[0], wrd[1], wrd[2]);
+ return;
+ }
+ if (!(wrd[0] & 0xf) && !wrd[1] && !wrd[2]) {
+ // exponent is not cared about, if mantissa is zero
+ wrd[0] &= 0x80000000;
+ fpp_to_exten(fpd, wrd[0], wrd[1], wrd[2]);
+ return;
+ }
+
+ fp_normal_prec();
+ cp = str;
+ if (wrd[0] & 0x80000000)
+ *cp++ = '-';
+ *cp++ = (wrd[0] & 0xf) + '0';
+ *cp++ = '.';
+ *cp++ = ((wrd[1] >> 28) & 0xf) + '0';
+ *cp++ = ((wrd[1] >> 24) & 0xf) + '0';
+ *cp++ = ((wrd[1] >> 20) & 0xf) + '0';
+ *cp++ = ((wrd[1] >> 16) & 0xf) + '0';
+ *cp++ = ((wrd[1] >> 12) & 0xf) + '0';
+ *cp++ = ((wrd[1] >> 8) & 0xf) + '0';
+ *cp++ = ((wrd[1] >> 4) & 0xf) + '0';
+ *cp++ = ((wrd[1] >> 0) & 0xf) + '0';
+ *cp++ = ((wrd[2] >> 28) & 0xf) + '0';
+ *cp++ = ((wrd[2] >> 24) & 0xf) + '0';
+ *cp++ = ((wrd[2] >> 20) & 0xf) + '0';
+ *cp++ = ((wrd[2] >> 16) & 0xf) + '0';
+ *cp++ = ((wrd[2] >> 12) & 0xf) + '0';
+ *cp++ = ((wrd[2] >> 8) & 0xf) + '0';
+ *cp++ = ((wrd[2] >> 4) & 0xf) + '0';
+ *cp++ = ((wrd[2] >> 0) & 0xf) + '0';
+ *cp++ = 'E';
+ if (wrd[0] & 0x40000000)
+ *cp++ = '-';
+ *cp++ = ((wrd[0] >> 24) & 0xf) + '0';
+ *cp++ = ((wrd[0] >> 20) & 0xf) + '0';
+ *cp++ = ((wrd[0] >> 16) & 0xf) + '0';
+ *cp = 0;
+ sscanf (str, "%le", &d);
+ fp_reset_normal_prec();
+ fp_from_native(d, fpd);
+}
+
+
+void fp_init_native_80(void)
+{
+ set_floatx80_rounding_precision(80, &fs);
+ set_float_rounding_mode(float_round_to_zero, &fs);
+
+ fpp_print = fp_print;
+ fpp_is_snan = fp_is_snan;
+ fpp_unset_snan = fp_unset_snan;
+ fpp_is_nan = fp_is_nan;
+ fpp_is_infinity = fp_is_infinity;
+ fpp_is_zero = fp_is_zero;
+ fpp_is_neg = fp_is_neg;
+ fpp_is_denormal = fp_is_denormal;
+ fpp_is_unnormal = fp_is_unnormal;
+
+ fpp_get_status = fp_get_status;
+ fpp_clear_status = fp_clear_status;
+ fpp_set_mode = fp_set_mode;
+
+ fpp_to_int = fp_to_int;
+ fpp_from_int = fp_from_int;
+
+ fpp_to_pack = fp_to_pack;
+ fpp_from_pack = fp_from_pack;
+
+ fpp_to_single = fp_to_single;
+ fpp_from_single = fp_from_single;
+ fpp_to_double = fp_to_double;
+ fpp_from_double = fp_from_double;
+ fpp_to_exten = fp_to_exten;
+ fpp_from_exten = fp_from_exten;
+ fpp_to_exten_fmovem = fp_to_exten;
+ fpp_from_exten_fmovem = fp_from_exten;
+
+ fpp_round_single = fp_round_single;
+ fpp_round_double = fp_round_double;
+ fpp_round32 = fp_round32;
+ fpp_round64 = fp_round64;
+
+ fpp_normalize = fp_normalize;
+ fpp_denormalize = fp_denormalize;
+ fpp_get_internal_overflow = fp_get_internal_overflow;
+ fpp_get_internal_underflow = fp_get_internal_underflow;
+ fpp_get_internal_round_all = fp_get_internal_round_all;
+ fpp_get_internal_round = fp_get_internal_round;
+ fpp_get_internal_round_exten = fp_get_internal_round_exten;
+ fpp_get_internal = fp_get_internal;
+ fpp_get_internal_grs = fp_get_internal_grs;
+
+ fpp_int = fp_int;
+ fpp_sinh = fp_sinh;
+ fpp_intrz = fp_intrz;
+ fpp_sqrt = fp_sqrt;
+ fpp_lognp1 = fp_lognp1;
+ fpp_etoxm1 = fp_etoxm1;
+ fpp_tanh = fp_tanh;
+ fpp_atan = fp_atan;
+ fpp_atanh = fp_atanh;
+ fpp_sin = fp_sin;
+ fpp_asin = fp_asin;
+ fpp_tan = fp_tan;
+ fpp_etox = fp_etox;
+ fpp_twotox = fp_twotox;
+ fpp_tentox = fp_tentox;
+ fpp_logn = fp_logn;
+ fpp_log10 = fp_log10;
+ fpp_log2 = fp_log2;
+ fpp_abs = fp_abs;
+ fpp_cosh = fp_cosh;
+ fpp_neg = fp_neg;
+ fpp_acos = fp_acos;
+ fpp_cos = fp_cos;
+ fpp_getexp = fp_getexp;
+ fpp_getman = fp_getman;
+ fpp_div = fp_div;
+ fpp_mod = fp_mod;
+ fpp_add = fp_add;
+ fpp_mul = fp_mul;
+ fpp_rem = fp_rem;
+ fpp_scale = fp_scale;
+ fpp_sub = fp_sub;
+ fpp_sgldiv = fp_sgldiv;
+ fpp_sglmul = fp_sglmul;
+ fpp_cmp = fp_cmp;
+ fpp_tst = fp_tst;
+ fpp_move = fp_move;
+}
--- /dev/null
+
+global xfp_int
+global xfp_mov
+global xfp_fldcw
+global xfp_to_single
+global xfp_from_single
+global xfp_to_double
+global xfp_from_double
+global xfp_from_int
+global xfp_to_int
+global xfp_x_to_double
+global xfp_x_from_double
+global xfp_round_single
+global xfp_round_double
+
+global xfp_div
+global xfp_mul
+global xfp_abs
+global xfp_neg
+global xfp_add
+global xfp_sub
+global xfp_sqrt
+global xfp_sin
+global xfp_cos
+global xfp_get_status
+global xfp_clear_status
+
+section .text
+
+bits 64
+
+%macro loadfp1 0
+ fld tword[rdx]
+%endmacro
+
+%macro loadfp2 0
+ fld tword[rcx]
+ fld tword[rdx]
+%endmacro
+
+%macro storefp 0
+ fstp tword[rcx]
+%endmacro
+
+
+xfp_fldcw:
+ fldcw word[rcx]
+ ret
+
+xfp_get_status:
+ fnstsw ax
+ ret
+
+xfp_clear_status:
+ fnclex
+ ret
+
+xfp_int:
+ loadfp1
+ frndint
+ storefp
+ ret
+
+xfp_x_to_double:
+ fld tword[rcx]
+ fstp qword[rdx]
+ ret
+
+xfp_x_from_double:
+ fld qword[rdx]
+ fstp tword[rcx]
+ ret
+
+xfp_round_single:
+ fld tword[rdx]
+ fstp dword[rcx]
+ fld dword[rcx]
+ fstp tword[rcx]
+ ret
+
+xfp_round_double:
+ fld tword[rdx]
+ fstp qword[rcx]
+ fld qword[rcx]
+ fstp tword[rcx]
+ ret
+
+xfp_to_single:
+ fld dword[rdx]
+ fstp tword[rcx]
+ ret
+
+xfp_from_single:
+ fld tword[rcx]
+ fstp dword[rdx]
+ ret
+
+xfp_to_double:
+ fld qword[rdx]
+ fstp tword[rcx]
+ ret
+
+xfp_from_double:
+ fld tword[rcx]
+ fstp qword[rdx]
+ ret
+
+xfp_to_int:
+ fld tword[rcx]
+ fistp qword[rdx]
+ ret
+
+xfp_from_int:
+ fild dword[rdx]
+ fstp tword[rcx]
+ ret
+
+xfp_mov:
+ loadfp1
+ storefp
+ ret
+
+xfp_add:
+ loadfp2
+ faddp
+ storefp
+ ret
+
+xfp_sub:
+ loadfp2
+ fsubp
+ storefp
+ ret
+
+xfp_div:
+ loadfp2
+ fdivp
+ storefp
+ ret
+
+xfp_mul:
+ loadfp2
+ fmulp
+ storefp
+ ret
+
+xfp_sqrt:
+ loadfp1
+ fsqrt
+ storefp
+ ret
+
+xfp_neg:
+ loadfp1
+ fchs
+ storefp
+ ret
+
+xfp_abs:
+ loadfp1
+ fabs
+ storefp
+ ret
+
+xfp_cos:
+ loadfp1
+ fcos
+ storefp
+ ret
+
+xfp_sin:
+ loadfp1
+ fsin
+ storefp
+ ret
--- /dev/null
+
+global _xfp_int
+global _xfp_mov
+global _xfp_fldcw
+global _xfp_to_single
+global _xfp_from_single
+global _xfp_to_double
+global _xfp_from_double
+global _xfp_from_int
+global _xfp_to_int
+global _xfp_x_to_double
+global _xfp_x_from_double
+global _xfp_round_single
+global _xfp_round_double
+
+global _xfp_div
+global _xfp_mul
+global _xfp_abs
+global _xfp_neg
+global _xfp_add
+global _xfp_sub
+global _xfp_sqrt
+global _xfp_sin
+global _xfp_cos
+global _xfp_get_status
+global _xfp_clear_status
+
+section .text
+
+%macro loadfp1 0
+ mov eax,[esp+4]
+ mov ecx,[esp+8]
+ fld tword[ecx]
+%endmacro
+
+%macro loadfp2 0
+ mov eax,[esp+4]
+ mov ecx,[esp+8]
+ fld tword[eax]
+ fld tword[ecx]
+%endmacro
+
+%macro storefp 0
+ fstp tword[eax]
+%endmacro
+
+_xfp_fldcw:
+ mov eax,[esp+4]
+ fldcw word[eax]
+ ret
+
+_xfp_get_status:
+ fnstsw ax
+ ret
+
+_xfp_clear_status:
+ fnclex
+ ret
+
+_xfp_int:
+ loadfp1
+ frndint
+ storefp
+ ret
+
+_xfp_x_to_double:
+ mov ecx,[esp+4]
+ fld tword[ecx]
+ mov eax,[esp+8]
+ fstp qword[eax]
+ ret
+
+_xfp_x_from_double:
+ mov eax,[esp+8]
+ fld qword[eax]
+ mov ecx,[esp+4]
+ fstp tword[ecx]
+ ret
+
+_xfp_round_single:
+ mov ecx,[esp+8]
+ fld tword[ecx]
+ mov eax,[esp+4]
+ fstp dword[eax]
+ fld dword[eax]
+ fstp tword[eax]
+ ret
+
+_xfp_round_double:
+ mov ecx,[esp+8]
+ fld tword[ecx]
+ mov eax,[esp+4]
+ fstp qword[eax]
+ fld qword[eax]
+ fstp tword[eax]
+ ret
+
+_xfp_to_single:
+ mov ecx,[esp+8]
+ mov eax,[esp+4]
+ fld dword[ecx]
+ fstp tword[eax]
+ ret
+
+_xfp_from_single:
+ mov eax,[esp+4]
+ mov ecx,[esp+8]
+ fld tword[eax]
+ fstp dword[ecx]
+ ret
+
+_xfp_to_double:
+ mov ecx,[esp+8]
+ mov eax,[esp+4]
+ fld qword[ecx]
+ fstp tword[eax]
+ ret
+
+_xfp_from_double:
+ mov eax,[esp+4]
+ mov ecx,[esp+8]
+ fld tword[eax]
+ fstp qword[ecx]
+ ret
+
+_xfp_to_int:
+ mov eax,[esp+4]
+ mov ecx,[esp+8]
+ fld tword[eax]
+ fistp qword[ecx]
+ ret
+
+_xfp_from_int:
+ mov eax,[esp+4]
+ mov ecx,[esp+8]
+ fild dword[ecx]
+ fstp tword[eax]
+ ret
+
+_xfp_mov:
+ loadfp1
+ storefp
+ ret
+
+_xfp_add:
+ loadfp2
+ faddp
+ storefp
+ ret
+
+_xfp_sub:
+ loadfp2
+ fsubp
+ storefp
+ ret
+
+_xfp_div:
+ loadfp2
+ fdivp
+ storefp
+ ret
+
+_xfp_mul:
+ loadfp2
+ fmulp
+ storefp
+ ret
+
+_xfp_sqrt:
+ loadfp1
+ fsqrt
+ storefp
+ ret
+
+_xfp_neg:
+ loadfp1
+ fchs
+ storefp
+ ret
+
+_xfp_abs:
+ loadfp1
+ fabs
+ storefp
+ ret
+
+_xfp_cos:
+ loadfp1
+ fcos
+ storefp
+ ret
+
+_xfp_sin:
+ loadfp1
+ fsin
+ storefp
+ ret
#define IDC_16BIT 1231
#define IDC_PPC_CPUIDLE 1231
#define IDC_11KHZ 1232
-#define IDC_FPU_SOFTFLOAT 1232
+#define IDC_FPU_MODE 1232
#define IDC_22KHZ 1233
#define IDC_SPEED_x86 1233
#define IDC_44KHZ 1234
CONTROL "68882",IDC_FPU2,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,8,249,87,10
CONTROL "CPU internal",IDC_FPU3,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,8,262,93,10
CONTROL "More compatible [] More compatible but slower FPU emulation.",IDC_COMPATIBLE_FPU,
- "Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,8,276,117,10
+ "Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,8,275,117,10
CONTROL "Unimplemented FPU emu [] Emulate FPU unimplemented instructions",IDC_FPU_UNIMPLEMENTED,
- "Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,8,289,116,10
+ "Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,8,287,116,10
GROUPBOX "CPU Emulation Speed",IDC_STATIC,136,1,258,97
CONTROL "Fastest possible",IDC_CS_HOST,"Button",BS_AUTORADIOBUTTON | BS_LEFT | WS_GROUP | WS_TABSTOP,143,19,195,10
CONTROL "Approximate A500/A1200 or cycle-exact",IDC_CS_68000,
CONTROL "Direct",IDC_TRUST0,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,143,299,72,10
CONTROL "Indirect",IDC_TRUST1,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,221,299,72,10
CONTROL "No flags",IDC_NOFLAGS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,299,299,68,11
- CONTROL "Softfloat FPU emulation",IDC_FPU_SOFTFLOAT,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,8,302,115,10
GROUPBOX "MMU",IDC_STATIC,2,168,129,42,BS_LEFT
CONTROL "Data cache emulation [] 68030, 040 and 060 optional data cache emulation. Requires More compatible option.",IDC_CPUDATACACHE,
"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,8,123,119,12
+ COMBOBOX IDC_FPU_MODE,7,299,112,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
END
IDD_FLOPPY DIALOGEX 0, 0, 396, 261
#define GFXFILTER
#define X86_MSVC_ASSEMBLY
#define OPTIMIZED_FLAGS
+#define MSVC_LONG_DOUBLE
#ifndef __i386__
#define __i386__
#endif
#endif
enable = jitenable && workprefs.cachesize;
- ew (hDlg, IDC_TRUST0, enable);
- ew (hDlg, IDC_TRUST1, enable);
- ew (hDlg, IDC_HARDFLUSH, enable);
- ew (hDlg, IDC_CONSTJUMP, enable);
- ew (hDlg, IDC_JITFPU, enable);
- ew (hDlg, IDC_NOFLAGS, enable);
- ew (hDlg, IDC_CS_CACHE_TEXT, enable);
- ew (hDlg, IDC_CACHE, enable);
- ew (hDlg, IDC_JITENABLE, jitenable);
- ew (hDlg, IDC_COMPATIBLE, !workprefs.cpu_memory_cycle_exact && !(workprefs.cachesize && workprefs.cpu_model >= 68040));
- ew (hDlg, IDC_COMPATIBLE_FPU, workprefs.fpu_model > 0);
- ew (hDlg, IDC_FPU_UNIMPLEMENTED, workprefs.fpu_model && !workprefs.cachesize);
- ew (hDlg, IDC_FPU_SOFTFLOAT, workprefs.fpu_model && (!workprefs.compfpu || !workprefs.cachesize));
- ew (hDlg, IDC_CPU_UNIMPLEMENTED, workprefs.cpu_model == 68060 && !workprefs.cachesize);
+ ew(hDlg, IDC_FPU_MODE, workprefs.fpu_model != 0);
+ ew(hDlg, IDC_TRUST0, enable);
+ ew(hDlg, IDC_TRUST1, enable);
+ ew(hDlg, IDC_HARDFLUSH, enable);
+ ew(hDlg, IDC_CONSTJUMP, enable);
+ ew(hDlg, IDC_JITFPU, enable);
+ ew(hDlg, IDC_NOFLAGS, enable);
+ ew(hDlg, IDC_CS_CACHE_TEXT, enable);
+ ew(hDlg, IDC_CACHE, enable);
+ ew(hDlg, IDC_JITENABLE, jitenable);
+ ew(hDlg, IDC_COMPATIBLE, !workprefs.cpu_memory_cycle_exact && !(workprefs.cachesize && workprefs.cpu_model >= 68040));
+ ew(hDlg, IDC_COMPATIBLE_FPU, workprefs.fpu_model > 0);
+ ew(hDlg, IDC_FPU_UNIMPLEMENTED, workprefs.fpu_model && !workprefs.cachesize);
+ ew(hDlg, IDC_CPU_UNIMPLEMENTED, workprefs.cpu_model == 68060 && !workprefs.cachesize);
#if 0
- ew (hDlg, IDC_CPU_MULTIPLIER, workprefs.cpu_cycle_exact);
+ ew(hDlg, IDC_CPU_MULTIPLIER, workprefs.cpu_cycle_exact);
#endif
- ew (hDlg, IDC_CPU_FREQUENCY, workprefs.cpu_cycle_exact && workprefs.m68k_speed >= 0);
- ew (hDlg, IDC_CPU_FREQUENCY2, workprefs.cpu_cycle_exact && !workprefs.cpu_clock_multiplier && workprefs.m68k_speed >= 0);
+ ew(hDlg, IDC_CPU_FREQUENCY, workprefs.cpu_cycle_exact && workprefs.m68k_speed >= 0);
+ ew(hDlg, IDC_CPU_FREQUENCY2, workprefs.cpu_cycle_exact && !workprefs.cpu_clock_multiplier && workprefs.m68k_speed >= 0);
- ew (hDlg, IDC_FPU1, workprefs.cpu_model < 68040 && (workprefs.cpu_model >= 68020 || !workprefs.cpu_compatible));
- ew (hDlg, IDC_FPU2, workprefs.cpu_model < 68040 && (workprefs.cpu_model >= 68020 || !workprefs.cpu_compatible));
- ew (hDlg, IDC_FPU3, workprefs.cpu_model >= 68040);
- ew (hDlg, IDC_MMUENABLEEC, workprefs.cpu_model >= 68030 && workprefs.cachesize == 0);
- ew (hDlg, IDC_MMUENABLE, workprefs.cpu_model >= 68030 && workprefs.cachesize == 0);
- ew (hDlg, IDC_CPUDATACACHE, workprefs.cpu_model >= 68030 && workprefs.cachesize == 0 && workprefs.cpu_compatible);
- ew (hDlg, IDC_CPU_PPC, workprefs.cpu_model >= 68040 && (workprefs.ppc_mode == 1 || (workprefs.ppc_mode == 0 && !is_ppc_cpu(&workprefs))));
+ ew(hDlg, IDC_FPU1, workprefs.cpu_model < 68040 && (workprefs.cpu_model >= 68020 || !workprefs.cpu_compatible));
+ ew(hDlg, IDC_FPU2, workprefs.cpu_model < 68040 && (workprefs.cpu_model >= 68020 || !workprefs.cpu_compatible));
+ ew(hDlg, IDC_FPU3, workprefs.cpu_model >= 68040);
+ ew(hDlg, IDC_MMUENABLEEC, workprefs.cpu_model >= 68030 && workprefs.cachesize == 0);
+ ew(hDlg, IDC_MMUENABLE, workprefs.cpu_model >= 68030 && workprefs.cachesize == 0);
+ ew(hDlg, IDC_CPUDATACACHE, workprefs.cpu_model >= 68030 && workprefs.cachesize == 0 && workprefs.cpu_compatible);
+ ew(hDlg, IDC_CPU_PPC, workprefs.cpu_model >= 68040 && (workprefs.ppc_mode == 1 || (workprefs.ppc_mode == 0 && !is_ppc_cpu(&workprefs))));
SendDlgItemMessage(hDlg, IDC_SPEED, TBM_SETRANGE, TRUE, workprefs.m68k_speed < 0 || (workprefs.cpu_memory_cycle_exact && !workprefs.cpu_cycle_exact) ? MAKELONG(-9, 0) : MAKELONG(-9, 50));
SendDlgItemMessage(hDlg, IDC_SPEED, TBM_SETPAGESIZE, 0, 1);
CheckDlgButton (hDlg, IDC_CPUDATACACHE, workprefs.cpu_data_cache);
CheckDlgButton (hDlg, IDC_COMPATIBLE_FPU, workprefs.fpu_strict);
CheckDlgButton (hDlg, IDC_FPU_UNIMPLEMENTED, !workprefs.fpu_no_unimplemented || workprefs.cachesize);
- CheckDlgButton (hDlg, IDC_FPU_SOFTFLOAT, workprefs.fpu_softfloat);
+ SendDlgItemMessage(hDlg, IDC_FPU_MODE, CB_SETCURSEL, workprefs.fpu_mode < 0 ? 1 : (workprefs.fpu_mode > 0 ? 2 : 0), 0);
CheckDlgButton (hDlg, IDC_CPU_UNIMPLEMENTED, !workprefs.int_no_unimplemented || workprefs.cachesize);
SendDlgItemMessage (hDlg, IDC_CPUIDLE, TBM_SETPOS, TRUE, workprefs.cpu_idle == 0 ? 0 : 12 - workprefs.cpu_idle / 15);
SendDlgItemMessage (hDlg, IDC_PPC_CPUIDLE, TBM_SETPOS, TRUE, workprefs.ppc_cpu_idle);
workprefs.cpu_compatible = workprefs.cpu_memory_cycle_exact | (ischecked (hDlg, IDC_COMPATIBLE) ? 1 : 0);
workprefs.fpu_strict = ischecked (hDlg, IDC_COMPATIBLE_FPU) ? 1 : 0;
workprefs.fpu_no_unimplemented = ischecked (hDlg, IDC_FPU_UNIMPLEMENTED) ? 0 : 1;
- workprefs.fpu_softfloat = ischecked (hDlg, IDC_FPU_SOFTFLOAT) ? 1 : 0;
workprefs.int_no_unimplemented = ischecked (hDlg, IDC_CPU_UNIMPLEMENTED) ? 0 : 1;
workprefs.address_space_24 = ischecked (hDlg, IDC_COMPATIBLE24) ? 1 : 0;
workprefs.m68k_speed = ischecked (hDlg, IDC_CS_HOST) ? -1 : 0;
if (workprefs.m68k_speed_throttle > 0 && workprefs.m68k_speed < 0)
workprefs.m68k_speed_throttle = 0;
workprefs.x86_speed_throttle = SendMessage(GetDlgItem(hDlg, IDC_SPEED_x86), TBM_GETPOS, 0, 0) * 100;
+ idx = SendDlgItemMessage(hDlg, IDC_FPU_MODE, CB_GETCURSEL, 0, 0);
+ if (idx == 0)
+ workprefs.fpu_mode = 0;
+ if (idx == 1)
+ workprefs.fpu_mode = -1;
+ if (idx == 2)
+ workprefs.fpu_mode = 1;
newcpu = ischecked (hDlg, IDC_CPU0) ? 68000
: ischecked (hDlg, IDC_CPU1) ? 68010
workprefs.comptrustword = trust_prev;
workprefs.comptrustlong = trust_prev;
workprefs.comptrustnaddr = trust_prev;
- if (workprefs.fpu_softfloat) {
+ if (workprefs.fpu_mode > 0) {
workprefs.compfpu = false;
setchecked(hDlg, IDC_JITFPU, false);
}
if (!workprefs.cachesize) {
setchecked (hDlg, IDC_JITENABLE, false);
}
- if (workprefs.cachesize && workprefs.compfpu && workprefs.fpu_softfloat) {
- workprefs.fpu_softfloat = false;
- setchecked(hDlg, IDC_FPU_SOFTFLOAT, false);
+ if (workprefs.cachesize && workprefs.compfpu && workprefs.fpu_mode > 0) {
+ workprefs.fpu_mode = 0;
+ SendDlgItemMessage(hDlg, IDC_FPU_MODE, CB_SETCURSEL, 0, 0);
}
if (oldcache == 0 && workprefs.cachesize > 0) {
canbang = 1;
SendDlgItemMessage (hDlg, IDC_CPU_FREQUENCY, CB_ADDSTRING, 0, (LPARAM)_T("8x"));
SendDlgItemMessage (hDlg, IDC_CPU_FREQUENCY, CB_ADDSTRING, 0, (LPARAM)_T("Custom"));
+ SendDlgItemMessage(hDlg, IDC_FPU_MODE, CB_RESETCONTENT, 0, 0);
+ SendDlgItemMessage(hDlg, IDC_FPU_MODE, CB_ADDSTRING, 0, (LPARAM)_T("Host (64-bit)"));
+ SendDlgItemMessage(hDlg, IDC_FPU_MODE, CB_ADDSTRING, 0, (LPARAM)_T("Host (80-bit)"));
+ SendDlgItemMessage(hDlg, IDC_FPU_MODE, CB_ADDSTRING, 0, (LPARAM)_T("Softfloat (80-bit)"));
+
idx = 4;
if (workprefs.cpu_clock_multiplier >= 1 << 8) {
idx = 0;
<ClCompile Include="..\direct3d11.cpp" />
<ClCompile Include="..\driveclick_win32.cpp" />
<ClCompile Include="..\dxwrap.cpp" />
+ <ClCompile Include="..\fpp_native_msvc_80bit.cpp" />
<ClCompile Include="..\fsdb_mywin32.cpp" />
<ClCompile Include="..\fsdb_win32.cpp" />
<ClCompile Include="..\FX11\d3dxGlobal.cpp" />
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='FullRelease|x64'">4.0_level_9_1</ShaderModel>
</FxCompile>
</ItemGroup>
+ <ItemGroup>
+ <Object Include="..\fpux64_80.obj">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Test|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='FullRelease|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Test|x64'">false</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='FullRelease|x64'">false</ExcludedFromBuild>
+ </Object>
+ <Object Include="..\fpux86_80.obj">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Test|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='FullRelease|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Test|Win32'">false</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='FullRelease|Win32'">false</ExcludedFromBuild>
+ </Object>
+ </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<ClCompile Include="..\..\casablanca.cpp">
<Filter>common</Filter>
</ClCompile>
+ <ClCompile Include="..\fpp_native_msvc_80bit.cpp">
+ <Filter>win32</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\resources\35floppy.ico">
<Filter>win32\Shaders</Filter>
</FxCompile>
</ItemGroup>
+ <ItemGroup>
+ <Object Include="..\fpux86_80.obj" />
+ <Object Include="..\fpux64_80.obj" />
+ </ItemGroup>
</Project>
\ No newline at end of file