]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
MSVC 80-bit host FPU mode.
authorToni Wilen <twilen@winuae.net>
Sat, 28 Apr 2018 12:54:21 +0000 (15:54 +0300)
committerToni Wilen <twilen@winuae.net>
Sat, 28 Apr 2018 12:54:21 +0000 (15:54 +0300)
22 files changed:
cfgfile.cpp
fpp.cpp
fpp_native.cpp
fpp_softfloat.cpp
include/fpp.h
include/newcpu.h
include/options.h
include/sysdeps.h
jit/compemu_support.cpp
jit/compemu_support_codegen.cpp
main.cpp
newcpu.cpp
od-win32/asm.cmd
od-win32/fpp_native_msvc_80bit.cpp [new file with mode: 0644]
od-win32/fpux64_80.asm [new file with mode: 0644]
od-win32/fpux86_80.asm [new file with mode: 0644]
od-win32/resources/resource.h
od-win32/resources/winuae.rc
od-win32/sysconfig.h
od-win32/win32gui.cpp
od-win32/winuae_msvc15/winuae_msvc.vcxproj
od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters

index b5b8ed0150d3b8f1e5b4cf32e0c258212da09694..3df845f2b2178bb90f1bf595a67ca0cfa41ae24c 100644 (file)
@@ -2367,7 +2367,10 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type)
        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);
@@ -5140,7 +5143,6 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCH
                || 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
@@ -5241,6 +5243,19 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCH
                || 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)
@@ -7528,7 +7543,7 @@ void default_prefs (struct uae_prefs *p, bool reset, int type)
        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;
diff --git a/fpp.cpp b/fpp.cpp
index 7ceb305f227f9b82cb460390bf3a8b40b5bd3510..578da31c328f8969fac3002c85cf998cba227648 100644 (file)
--- a/fpp.cpp
+++ b/fpp.cpp
 
 #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;
@@ -346,7 +353,7 @@ STATIC_INLINE bool fp_is_dyadic(uae_u16 extra)
 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);
@@ -405,7 +412,7 @@ static uae_u32 fpsr_get_vector(uae_u32 exception)
 
 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;
@@ -427,7 +434,7 @@ static void fpsr_check_arithmetic_exception(uae_u32 mask, fpdata *src, uae_u32 o
 #endif 
                }
 
-               if (!currprefs.fpu_softfloat) {
+               if (currprefs.fpu_mode <= 0) {
                        // log message and exit
                        regs.fp_exp_pend = 0;
                        return;
@@ -588,7 +595,7 @@ static uae_u32 fpsr_make_status(void)
        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
@@ -607,7 +614,7 @@ static int fpsr_set_bsun(void)
        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;
@@ -1218,7 +1225,7 @@ static void fpu_null (void)
 // 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) {
@@ -1236,7 +1243,7 @@ static bool normalize_or_fault_if_no_denormal_support(uae_u16 opcode, uae_u16 ex
 }
 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) {
@@ -1266,7 +1273,7 @@ static bool fault_if_no_packed_support(uae_u16 opcode, uae_u16 extra, uaecptr ea
 // 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);
@@ -3055,8 +3062,13 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra)
        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;
@@ -3070,16 +3082,25 @@ void fpu_modechange(void)
 {
        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(&regs.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++) {
@@ -3105,14 +3126,25 @@ static void fpu_test(void)
 
 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;
index f7bccd5641d9df4898c4a3ee145413090727aeb5..3bc1ee546407db912f57e9636c886abd09a96b26 100644 (file)
@@ -1065,9 +1065,9 @@ static void fp_from_pack (fpdata *src, uae_u32 *wrd, int kfactor)
 
        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);
@@ -1241,12 +1241,12 @@ static void fp_to_pack (fpdata *fpd, uae_u32 *wrd, int dummy)
        *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);
 }
 
 
@@ -1269,9 +1269,6 @@ void fp_init_native(void)
        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;
 
index cf2b6d8b75d25437a45285e3df1f72494deaad5c..97e1d19598aa449933f1127c91288464c11ed5f2 100644 (file)
@@ -514,7 +514,7 @@ static void to_native(fptype *fp, fpdata *fpd)
                return;
        }
        if (fp_is_nan(fpd)) {
-#if USE_LONG_DOUBLE
+#ifdef USE_LONG_DOUBLE
                *fp = sqrtl(-1);
 #else
                *fp = sqrt(-1);
@@ -523,7 +523,7 @@ static void to_native(fptype *fp, fpdata *fpd)
        }
        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);
@@ -534,7 +534,7 @@ static void to_native(fptype *fp, fpdata *fpd)
        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);
@@ -568,7 +568,7 @@ static void from_native(fptype fp, fpdata *fpd)
        if (fp < 0.0)
                fp = -fp;
        
-#if USE_LONG_DOUBLE
+#ifdef USE_LONG_DOUBLE
         frac = frexpl (fp, &expon);
 #else
         frac = frexp (fp, &expon);
@@ -739,9 +739,6 @@ void fp_init_softfloat(void)
        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;
 
index b30c745596c5d1d9ca5ff8e4e52b142bfdc38106..7374d486f4dc6ebc0d879e1a4599ee9a69930c81 100644 (file)
 #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*);
@@ -72,9 +78,6 @@ extern FPP_GET_STATUS fpp_get_status;
 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;
 
index 208b7183908c62d708468cc4ea23f24a643a783a..8ceb3938d66e5b7f789ff8f2affc17eff7e3528f 100644 (file)
@@ -92,10 +92,8 @@ typedef uae_u8 flagtype;
 
 #ifdef USE_LONG_DOUBLE
 typedef long double fptype;
-#define LDPTR tbyte ptr
 #else
 typedef double fptype;
-#define LDPTR qword ptr
 #endif
 #endif
 
@@ -143,10 +141,25 @@ struct mmufixup
 };
 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
index b27fc80570162cf585a9870dd9c85722fc88858f..9cc6d02223fb19db2dd90258a361500a4e57a5da 100644 (file)
@@ -493,7 +493,7 @@ struct uae_prefs {
        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;
index a4507e2a94b6ca09c39c6d3ba3c9027caa4f13c9..3c276c4a5d2e893c5964705579487fc8355adca0 100644 (file)
@@ -470,6 +470,7 @@ extern void logging_init (void);
 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
index eaac9c286ccadc88ab8b4952fbce239956b8024b..54150c0ea7f876edfbafe0f0fc3dbd377ad71bee 100644 (file)
@@ -2195,11 +2195,11 @@ static void bt_l_ri_noclobber(RR4 r, IMM i)
 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;
        }
 }
@@ -2207,11 +2207,11 @@ static  void f_tomem(int r)
 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;
        }
 }
@@ -2315,11 +2315,11 @@ static  int f_alloc_reg(int r, int willclobber)
 
        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;
        }
index 86b4086ad8f0c6509018fba7631ed0414f6ef0ba..ee291618fb25355d1d24a18d64ebc67f67241fd0 100644 (file)
@@ -1967,24 +1967,24 @@ static void bt_l_ri_noclobber(R4 r, IMM i)
 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;
     }
 }
 
@@ -2089,11 +2089,11 @@ static  int f_alloc_reg(int r, int willclobber)
 
     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;
     }
@@ -6586,7 +6586,7 @@ void compiler_dumpstate(void)
        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");
index 8aefd56f3016f7eb6c33d0bfc89d03e89ab74b31..67cbfb9aa34695f70c54d450fbf31635e4787610 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -300,9 +300,9 @@ void fixup_cpu (struct uae_prefs *p)
                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
index 6d84fee4544e4502b35ad1203724f49ade540245..771bba612d135ef6de26c4ab91987341aa031f52 100644 (file)
@@ -1878,7 +1878,7 @@ static void build_cpufunctbl (void)
 
        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);
@@ -2054,7 +2054,7 @@ static int check_prefs_changed_cpu2(void)
                || 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
index 4a67210499a22c404eb78b9c65d7a7061dc1c380..8697e0c017b070cf82aedf6ca3583a699b17d92c 100644 (file)
@@ -1,6 +1,9 @@
-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
diff --git a/od-win32/fpp_native_msvc_80bit.cpp b/od-win32/fpp_native_msvc_80bit.cpp
new file mode 100644 (file)
index 0000000..e9d6832
--- /dev/null
@@ -0,0 +1,1231 @@
+/*
+* 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;
+}
diff --git a/od-win32/fpux64_80.asm b/od-win32/fpux64_80.asm
new file mode 100644 (file)
index 0000000..65d671f
--- /dev/null
@@ -0,0 +1,175 @@
+
+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
diff --git a/od-win32/fpux86_80.asm b/od-win32/fpux86_80.asm
new file mode 100644 (file)
index 0000000..459e2ab
--- /dev/null
@@ -0,0 +1,197 @@
+
+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
index a0fad723cb22a91b3df0430ea8164a5245d17951..03597b78dfdcab99d7632430d85d27c28ec97261 100644 (file)
 #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
index dc7185a34b1b5cbcdf9111dee2a6796a917d68b7..2d9141045a574566c2154712423ef272de7c5403 100644 (file)
@@ -279,9 +279,9 @@ BEGIN
     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,
@@ -314,10 +314,10 @@ BEGIN
     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
index 584f1daa5df1c9b0a7b483a1fbd1e9100e97328a..74d42a1a8b5c613578b60cb47a31dc6f4b3c74e1 100644 (file)
@@ -14,6 +14,7 @@
 #define GFXFILTER
 #define X86_MSVC_ASSEMBLY
 #define OPTIMIZED_FLAGS
+#define MSVC_LONG_DOUBLE
 #ifndef __i386__
 #define __i386__
 #endif
index 373d5cee367a605cb7cbbd8833d1f74c2df5a51d..648203f29fe702f8d5ea653fb9098a814efb31e6 100644 (file)
@@ -11604,33 +11604,33 @@ static void enable_for_cpudlg (HWND hDlg)
 #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);
@@ -11666,7 +11666,7 @@ static void values_to_cpudlg (HWND hDlg)
        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);
@@ -11726,7 +11726,6 @@ static void values_from_cpudlg (HWND hDlg)
        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;
@@ -11734,6 +11733,13 @@ static void values_from_cpudlg (HWND hDlg)
        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
@@ -11832,7 +11838,7 @@ static void values_from_cpudlg (HWND hDlg)
                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);
                }
@@ -11840,9 +11846,9 @@ static void values_from_cpudlg (HWND hDlg)
        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;
@@ -11918,6 +11924,11 @@ static INT_PTR CALLBACK CPUDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM l
                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;
index 99989db4423d160d88142f91f7d7050aeaeacd59..8dd17f68e9b8b660ca3fbfd1c585dcf19c15b3ae 100644 (file)
     <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>
index b7bff3648aba09e8f3317c8b450c910e6a199af9..a0b1beb04d26abc2a963592c35b56f7f496bccf5 100644 (file)
     <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