]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Extended precision native FPU mode updates.
authorToni Wilen <twilen@winuae.net>
Tue, 1 May 2018 13:20:41 +0000 (16:20 +0300)
committerToni Wilen <twilen@winuae.net>
Tue, 1 May 2018 13:20:41 +0000 (16:20 +0300)
cfgfile.cpp
fpp.cpp
fpp_native.cpp
fpp_softfloat.cpp
include/fpp.h
od-win32/fpp_native_msvc_80bit.cpp
od-win32/fpux64_80.asm
od-win32/fpux86_80.asm

index 3df845f2b2178bb90f1bf595a67ca0cfa41ae24c..0d801655555007ab73b0697081ced30dbb080258 100644 (file)
@@ -7543,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_mode = 0;
+       p->fpu_mode = -1;
        p->m68k_speed = 0;
        p->cpu_compatible = 1;
        p->address_space_24 = 1;
diff --git a/fpp.cpp b/fpp.cpp
index 578da31c328f8969fac3002c85cf998cba227648..aa27041342e38c80e34b4fb0ea4499c4e59d8200 100644 (file)
--- a/fpp.cpp
+++ b/fpp.cpp
@@ -42,10 +42,14 @@ bool use_long_double = true;
 bool use_long_double = false;
 #endif
 
+static bool support_exceptions;
+static bool support_denormals;
+
 FPP_PRINT fpp_print;
 
-FPP_IS fpp_is_snan;
 FPP_IS fpp_unset_snan;
+FPP_IS fpp_is_init;
+FPP_IS fpp_is_snan;
 FPP_IS fpp_is_nan;
 FPP_IS fpp_is_infinity;
 FPP_IS fpp_is_zero;
@@ -56,6 +60,7 @@ FPP_IS fpp_is_unnormal;
 FPP_GET_STATUS fpp_get_status;
 FPP_CLEAR_STATUS fpp_clear_status;
 FPP_SET_MODE fpp_set_mode;
+FPP_SUPPORT_FLAGS fpp_get_support_flags;
 
 FPP_FROM_NATIVE fpp_from_native;
 FPP_TO_NATIVE fpp_to_native;
@@ -135,6 +140,11 @@ STATIC_INLINE int isinrom (void)
        return (munge24 (m68k_getpc ()) & 0xFFF80000) == 0xF80000 && !currprefs.mmu_model;
 }
 
+static bool jit_fpu(void)
+{
+       return currprefs.cachesize && currprefs.compfpu;
+}
+
 static int warned = 100;
 
 struct fpp_cr_entry {
@@ -331,6 +341,7 @@ static void reset_fsave_data(void)
 
 static uae_u32 get_ftag(fpdata *src, int size)
 {
+       fpp_is_init(src);
        if (fpp_is_zero(src)) {
                return 1; // ZERO
        } else if (fpp_is_unnormal(src) || fpp_is_denormal(src)) {
@@ -353,7 +364,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_mode > 0) {
+       if (support_exceptions && !jit_fpu()) {
                if (regs.fp_exp_pend) {
                        if (warned > 0) {
                                write_log (_T("FPU ARITHMETIC EXCEPTION (%d)\n"), regs.fp_exp_pend);
@@ -412,7 +423,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_mode <= 0)
+       if (!support_exceptions || jit_fpu())
                return;
 
        bool nonmaskable;
@@ -434,7 +445,7 @@ static void fpsr_check_arithmetic_exception(uae_u32 mask, fpdata *src, uae_u32 o
 #endif 
                }
 
-               if (currprefs.fpu_mode <= 0) {
+               if (!support_exceptions || jit_fpu()) {
                        // log message and exit
                        regs.fp_exp_pend = 0;
                        return;
@@ -498,6 +509,7 @@ static void fpsr_check_arithmetic_exception(uae_u32 mask, fpdata *src, uae_u32 o
                                fsave_data.t = 1;
                                fsave_data.wbte15 = (regs.fp_exp_pend == 51 || regs.fp_exp_pend == 54) ? 1 : 0; // UNFL, SNAN
 
+                               fpp_is_init(src);
                                if (fpp_is_snan(src)) {
                                        fpp_unset_snan(src);
                                }
@@ -557,11 +569,12 @@ static void fpsr_set_result(fpdata *result)
 #endif
        // condition code byte
        regs.fpsr &= 0x00fffff8; // clear cc
-       if (fpp_is_nan (result)) {
+       fpp_is_init(result);
+       if (fpp_is_nan(result)) {
                regs.fpsr |= FPSR_CC_NAN;
        } else if (fpp_is_zero(result)) {
                regs.fpsr |= FPSR_CC_Z;
-       } else if (fpp_is_infinity (result)) {
+       } else if (fpp_is_infinity(result)) {
                regs.fpsr |= FPSR_CC_I;
        }
        if (fpp_is_neg(result))
@@ -595,7 +608,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_mode <= 0)
+       if (!support_exceptions || jit_fpu())
                return 0;
 
        // return exceptions that interrupt calculation
@@ -614,7 +627,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_mode > 0) {
+               if (support_exceptions && !jit_fpu()) {
                        regs.fp_exp_pend = fpsr_get_vector(FPSR_BSUN);
                        fp_exception_pending(true);
                        return 1;
@@ -640,11 +653,12 @@ uae_u32 fpp_get_fpsr (void)
 #ifdef JIT
        if (currprefs.cachesize && currprefs.compfpu) {
                regs.fpsr &= 0x00fffff8; // clear cc
-               if (fpp_is_nan (&regs.fp_result)) {
+               fpp_is_init(&regs.fp_result);
+               if (fpp_is_nan(&regs.fp_result)) {
                        regs.fpsr |= FPSR_CC_NAN;
                } else if (fpp_is_zero(&regs.fp_result)) {
                        regs.fpsr |= FPSR_CC_Z;
-               } else if (fpp_is_infinity (&regs.fp_result)) {
+               } else if (fpp_is_infinity(&regs.fp_result)) {
                        regs.fpsr |= FPSR_CC_I;
                }
                if (fpp_is_neg(&regs.fp_result))
@@ -1225,8 +1239,9 @@ 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_mode <= 0)
+       if (!support_denormals)
                return false;
+       fpp_is_init(src);
        if (fpp_is_unnormal(src) || fpp_is_denormal(src)) {
                if (currprefs.cpu_model >= 68040 && currprefs.fpu_model && currprefs.fpu_no_unimplemented) {
                        if (fpp_is_zero(src)) {
@@ -1243,8 +1258,9 @@ 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_mode <= 0)
+       if (!support_denormals)
                return false;
+       fpp_is_init(dst);
        if (fpp_is_unnormal(dst) || fpp_is_denormal(dst)) {
                if (currprefs.cpu_model >= 68040 && currprefs.fpu_model && currprefs.fpu_no_unimplemented) {
                        if (fpp_is_zero(dst)) {
@@ -1736,6 +1752,7 @@ int fpp_cond (int condition)
 #ifdef JIT
        if (currprefs.cachesize && currprefs.compfpu) {
                // JIT reads and writes regs.fpu_result
+               fpp_is_init(&regs.fp_result);
                NotANumber = fpp_is_nan(&regs.fp_result);
                N = fpp_is_neg(&regs.fp_result);
                Z = fpp_is_zero(&regs.fp_result);
@@ -2571,13 +2588,13 @@ static bool fp_arithmetic(fpdata *src, fpdata *dst, int extra)
        switch (extra & 0x7f)
        {
                case 0x00: /* FMOVE */
-                       fpp_move(dst, src, 0);
+                       fpp_move(dst, src, PREC_NORMAL);
                        break;
                case 0x40: /* FSMOVE */
-                       fpp_move(dst, src, 32);
+                       fpp_move(dst, src, PREC_FLOAT);
                        break;
                case 0x44: /* FDMOVE */
-                       fpp_move(dst, src, 64);
+                       fpp_move(dst, src, PREC_DOUBLE);
                        break;
                case 0x01: /* FINT */
                        fpp_int(dst, src);
@@ -2589,13 +2606,13 @@ static bool fp_arithmetic(fpdata *src, fpdata *dst, int extra)
                        fpp_intrz(dst, src);
                        break;
                case 0x04: /* FSQRT */
-                       fpp_sqrt(dst, src, 0);
+                       fpp_sqrt(dst, src, PREC_NORMAL);
                        break;
                case 0x41: /* FSSQRT */
-                       fpp_sqrt(dst, src,  32);
+                       fpp_sqrt(dst, src, PREC_FLOAT);
                        break;
                case 0x45: /* FDSQRT */
-                       fpp_sqrt(dst, src, 64);
+                       fpp_sqrt(dst, src, PREC_DOUBLE);
                        break;
                case 0x06: /* FLOGNP1 */
                        fpp_lognp1(dst, src);
@@ -2640,25 +2657,25 @@ static bool fp_arithmetic(fpdata *src, fpdata *dst, int extra)
                        fpp_log2(dst, src);
                        break;
                case 0x18: /* FABS */
-                       fpp_abs(dst, src, 0);
+                       fpp_abs(dst, src, PREC_NORMAL);
                        break;
                case 0x58: /* FSABS */
-                       fpp_abs(dst, src, 32);
+                       fpp_abs(dst, src, PREC_FLOAT);
                        break;
                case 0x5c: /* FDABS */
-                       fpp_abs(dst, src, 64);
+                       fpp_abs(dst, src, PREC_DOUBLE);
                        break;
                case 0x19: /* FCOSH */
                        fpp_cosh(dst, src);
                        break;
                case 0x1a: /* FNEG */
-                       fpp_neg(dst, src, 0);
+                       fpp_neg(dst, src, PREC_NORMAL);
                        break;
                case 0x5a: /* FSNEG */
-                       fpp_neg(dst, src, 32);
+                       fpp_neg(dst, src, PREC_FLOAT);
                        break;
                case 0x5e: /* FDNEG */
-                       fpp_neg(dst, src, 64);
+                       fpp_neg(dst, src, PREC_DOUBLE);
                        break;
                case 0x1c: /* FACOS */
                        fpp_acos(dst, src);
@@ -2673,13 +2690,13 @@ static bool fp_arithmetic(fpdata *src, fpdata *dst, int extra)
                        fpp_getman(dst, src);
                        break;
                case 0x20: /* FDIV */
-                       fpp_div(dst, src, 0);
+                       fpp_div(dst, src, PREC_NORMAL);
                        break;
                case 0x60: /* FSDIV */
-                       fpp_div(dst, src, 32);
+                       fpp_div(dst, src, PREC_FLOAT);
                        break;
                case 0x64: /* FDDIV */
-                       fpp_div(dst, src, 64);
+                       fpp_div(dst, src, PREC_DOUBLE);
                        break;
                case 0x21: /* FMOD */
                        fpsr_get_quotient(&q, &s);
@@ -2687,22 +2704,22 @@ static bool fp_arithmetic(fpdata *src, fpdata *dst, int extra)
                        fpsr_set_quotient(q, s);
                        break;
                case 0x22: /* FADD */
-                       fpp_add(dst, src, 0);
+                       fpp_add(dst, src, PREC_NORMAL);
                        break;
                case 0x62: /* FSADD */
-                       fpp_add(dst, src, 32);
+                       fpp_add(dst, src, PREC_FLOAT);
                        break;
                case 0x66: /* FDADD */
-                       fpp_add(dst, src, 64);
+                       fpp_add(dst, src, PREC_DOUBLE);
                        break;
                case 0x23: /* FMUL */
-                       fpp_mul(dst, src, 0);
+                       fpp_mul(dst, src, PREC_NORMAL);
                        break;
                case 0x63: /* FSMUL */
-                       fpp_mul(dst, src, 32);
+                       fpp_mul(dst, src, PREC_FLOAT);
                        break;
                case 0x67: /* FDMUL */
-                       fpp_mul(dst, src, 64);
+                       fpp_mul(dst, src, PREC_DOUBLE);
                        break;
                case 0x24: /* FSGLDIV */
                        fpp_sgldiv(dst, src);
@@ -2719,13 +2736,13 @@ static bool fp_arithmetic(fpdata *src, fpdata *dst, int extra)
                        fpp_sglmul(dst, src);
                        break;
                case 0x28: /* FSUB */
-                       fpp_sub(dst, src, 0);
+                       fpp_sub(dst, src, PREC_NORMAL);
                        break;
                case 0x68: /* FSSUB */
-                       fpp_sub(dst, src, 32);
+                       fpp_sub(dst, src, PREC_FLOAT);
                        break;
                case 0x6c: /* FDSUB */
-                       fpp_sub(dst, src, 64);
+                       fpp_sub(dst, src, PREC_DOUBLE);
                        break;
                case 0x30: /* FSINCOS */
                case 0x31: /* FSINCOS */
@@ -3078,6 +3095,17 @@ void fpuop_arithmetic (uae_u32 opcode, uae_u16 extra)
        }
 }
 
+static void get_features(void)
+{
+       support_exceptions = (fpp_get_support_flags() & FPU_FEATURE_EXCEPTIONS) != 0;
+       support_denormals = (fpp_get_support_flags() & FPU_FEATURE_DENORMALS) != 0;
+}
+
+void fpu_clearstatus(void)
+{
+       fpp_clear_status();
+}
+
 void fpu_modechange(void)
 {
        uae_u32 temp_ext[8][3];
@@ -3093,6 +3121,7 @@ void fpu_modechange(void)
        if (currprefs.fpu_mode > 0) {
                fp_init_softfloat();
 #ifdef MSVC_LONG_DOUBLE
+               use_long_double = false;
        } else if (currprefs.fpu_mode < 0) {
                use_long_double = true;
                fp_init_native_80();
@@ -3103,6 +3132,7 @@ void fpu_modechange(void)
 #endif
                fp_init_native();
        }
+       get_features();
        for (int i = 0; i < 8; i++) {
                fpp_to_exten_fmovem(&regs.fp[i], temp_ext[i][0], temp_ext[i][1], temp_ext[i][2]);
        }
@@ -3129,6 +3159,7 @@ void fpu_reset (void)
        if (currprefs.fpu_mode > 0) {
                fp_init_softfloat();
 #ifdef MSVC_LONG_DOUBLE
+               use_long_double = false;
        } else if (currprefs.fpu_mode < 0) {
                use_long_double = true;
                fp_init_native_80();
@@ -3149,6 +3180,7 @@ void fpu_reset (void)
 
        regs.fpiar = 0;
        regs.fpu_exp_state = 0;
+       get_features();
        fpp_set_fpcr (0);
        fpp_set_fpsr (0);
        fpux_restore (NULL);
index 3bc1ee546407db912f57e9636c886abd09a96b26..ea040041b1da61f7faead126ef00d1efe046460a 100644 (file)
@@ -168,14 +168,14 @@ static void fp_set_mode(uae_u32 mode_control)
                return;
     switch(mode_control & FPCR_ROUNDING_PRECISION) {
         case FPCR_PRECISION_EXTENDED: // X
-                       fpu_prec = 80;
+                       fpu_prec = PREC_EXTENDED;
             break;
         case FPCR_PRECISION_SINGLE:   // S
-                       fpu_prec = 32;
+                       fpu_prec = PREC_FLOAT;
             break;
         case FPCR_PRECISION_DOUBLE:   // D
         default:                      // undefined
-                       fpu_prec = 64;
+                       fpu_prec = PREC_DOUBLE;
             break;
     }
 #if USE_HOST_ROUNDING
@@ -222,6 +222,11 @@ static void fp_get_status(uae_u32 *status)
 #endif
 }
 
+static uae_u32 fp_get_support_flags(void)
+{
+       return 0;
+}
+
 static void fp_clear_status(void)
 {
 #if 0
@@ -230,6 +235,10 @@ static void fp_clear_status(void)
 }
 
 /* Functions for detecting float type */
+static bool fp_is_init(fpdata *fpd)
+{
+       return false;
+}
 static bool fp_is_snan(fpdata *fpd)
 {
     return 0; /* FIXME: how to detect SNAN */
@@ -239,11 +248,11 @@ static bool fp_unset_snan(fpdata *fpd)
     /* FIXME: how to unset SNAN */
        return 0;
 }
-static bool fp_is_nan (fpdata *fpd)
+static bool fp_is_nan(fpdata *fpd)
 {
     return isnan(fpd->fp) != 0;
 }
-static bool fp_is_infinity (fpdata *fpd)
+static bool fp_is_infinity(fpdata *fpd)
 {
     return isinf(fpd->fp) != 0;
 }
@@ -458,6 +467,7 @@ static uae_s64 fp_to_int(fpdata *src, int size)
     };
 
        fptype fp = src->fp;
+       fp_is_init(src);
        if (fp_is_nan(src)) {
                uae_u32 w1, w2, w3;
                fp_from_exten(src, &w1, &w2, &w3);
@@ -580,9 +590,9 @@ static const TCHAR *fp_print(fpdata *fpd, int mode)
 
 static void fp_round_prec(fpdata *fpd, int prec)
 {
-       if (prec == 64) {
+       if (prec == PREC_DOUBLE) {
                fp_round_double(fpd);
-       } else if (prec == 32) {
+       } else if (prec == PREC_FLOAT) {
                fp_round_single(fpd);
        }
 }
@@ -603,14 +613,14 @@ static void fp_set_prec(int prec)
                fpu_mode_control &= ~FPCR_ROUNDING_PRECISION;
                switch (prec)
                {
-                       case 80:
+                       case PREC_EXTENDED:
                        fpu_mode_control |= FPCR_PRECISION_EXTENDED;
                        break;
-                       case 64:
+                       case PREC_DOUBLE:
                        default:
                        fpu_mode_control |= FPCR_PRECISION_DOUBLE;
                        break;
-                       case 32:
+                       case PREC_FLOAT:
                        fpu_mode_control |= FPCR_PRECISION_SINGLE;
                        break;
                }
@@ -625,7 +635,7 @@ static void fp_reset_prec(fpdata *fpd)
        fp_set_mode(temp_fpu_mode_control);
 #else
        int prec = temp_prec;
-       if (temp_prec == 0)
+       if (temp_prec == PREC_NORMAL)
                prec = fpu_prec;
        fp_round_prec(fpd, prec);
 #endif
@@ -952,14 +962,16 @@ static void fp_cmp(fpdata *a, fpdata *b)
 {
        fptype v = 1.0;
        if (currprefs.fpu_strict) {
-               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);
+               fp_is_init(a);
+               bool a_neg = fp_is_neg(a);
+               bool a_inf = fp_is_infinity(a);
+               bool a_zero = fp_is_zero(a);
+               bool a_nan = fp_is_nan(a);
+               fp_is_init(b);
+               bool b_neg = fp_is_neg(b);
+               bool b_inf = fp_is_infinity(b);
+               bool b_zero = fp_is_zero(b);
+               bool b_nan = fp_is_nan(b);
 
                if (a_nan || b_nan) {
                        // FCMP never returns N + NaN
@@ -1051,12 +1063,13 @@ static void fp_from_pack (fpdata *src, uae_u32 *wrd, int kfactor)
        char str[100];
        fptype fp;
 
-   if (fpp_is_nan (src)) {
+       fp_is_init(src);
+   if (fp_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)) {
+    if (fp_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;
@@ -1256,8 +1269,10 @@ void fp_init_native(void)
        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_init = fp_is_init;
+       fpp_is_snan = fp_is_snan;
        fpp_is_nan = fp_is_nan;
        fpp_is_infinity = fp_is_infinity;
        fpp_is_zero = fp_is_zero;
@@ -1268,6 +1283,7 @@ void fp_init_native(void)
        fpp_get_status = fp_get_status;
        fpp_clear_status = fp_clear_status;
        fpp_set_mode = fp_set_mode;
+       fpp_get_support_flags = fp_get_support_flags;
 
        fpp_to_int = fp_to_int;
        fpp_from_int = fp_from_int;
index 97e1d19598aa449933f1127c91288464c11ed5f2..fb894c83ec98038a91becd5d0e3a5a7b8be096b4 100644 (file)
@@ -91,11 +91,16 @@ static void fp_get_status(uae_u32 *status)
        if (fs.float_exception_flags & float_flag_decimal)
                *status |= FPSR_INEX1;
 }
+
 STATIC_INLINE void fp_clear_status(void)
 {
        fs.float_exception_flags = 0;
 }
 
+static uae_u32 fp_get_support_flags(void)
+{
+       return FPU_FEATURE_EXCEPTIONS | FPU_FEATURE_DENORMALS;
+}
 
 static const TCHAR *fp_printx80(floatx80 *fx, int mode)
 {
@@ -141,6 +146,10 @@ static const TCHAR *fp_print(fpdata *fpd, int mode)
 }
 
 /* Functions for detecting float type */
+static bool fp_is_init(fpdata *fpd)
+{
+       return false;
+}
 static bool fp_is_snan(fpdata *fpd)
 {
        return floatx80_is_signaling_nan(fpd->fpx) != 0;
@@ -148,13 +157,13 @@ static bool fp_is_snan(fpdata *fpd)
 static bool fp_unset_snan(fpdata *fpd)
 {
        fpd->fpx.low |= LIT64(0x4000000000000000);
-       return 0;
+       return false;
 }
-static bool fp_is_nan (fpdata *fpd)
+static bool fp_is_nan(fpdata *fpd)
 {
        return floatx80_is_any_nan(fpd->fpx) != 0;
 }
-static bool fp_is_infinity (fpdata *fpd)
+static bool fp_is_infinity(fpdata *fpd)
 {
        return floatx80_is_infinity(fpd->fpx) != 0;
 }
@@ -365,15 +374,15 @@ static void fp_tst(fpdata *a, fpdata *b)
        a->fpx = floatx80_tst(b->fpx, &fs);
 }
 
+static const uint8_t prectable[] = { 0, 32, 64, 80 };
+
 #define SETPREC \
        uint8_t oldprec = fs.floatx80_rounding_precision; \
-       if (prec > 0) \
-               set_floatx80_rounding_precision(prec, &fs);
+       if (prec > PREC_NORMAL) \
+               set_floatx80_rounding_precision(prectable[prec], &fs);
 
 #define RESETPREC \
-       if (prec > 0) \
-               set_floatx80_rounding_precision(oldprec, &fs);
-
+       set_floatx80_rounding_precision(oldprec, &fs);
 
 /* Functions with fixed precision */
 static void fp_move(fpdata *a, fpdata *b, int prec)
@@ -509,6 +518,7 @@ static void to_native(fptype *fp, fpdata *fpd)
        
        expon = fpd->fpx.high & 0x7fff;
        
+       fp_is_init(fpd);
        if (fp_is_zero(fpd)) {
                *fp = fp_is_neg(fpd) ? -0.0 : +0.0;
                return;
@@ -726,8 +736,10 @@ void fp_init_softfloat(void)
        set_float_rounding_mode(float_round_to_zero, &fsx);
 
        fpp_print = fp_print;
-       fpp_is_snan = fp_is_snan;
        fpp_unset_snan = fp_unset_snan;
+
+       fpp_is_init = fp_is_init;
+       fpp_is_snan = fp_is_snan;
        fpp_is_nan = fp_is_nan;
        fpp_is_infinity = fp_is_infinity;
        fpp_is_zero = fp_is_zero;
@@ -738,6 +750,7 @@ void fp_init_softfloat(void)
        fpp_get_status = fp_get_status;
        fpp_clear_status = fp_clear_status;
        fpp_set_mode = fp_set_mode;
+       fpp_get_support_flags = fp_get_support_flags;
 
        fpp_to_int = to_int;
        fpp_from_int = from_int;
index 7374d486f4dc6ebc0d879e1a4599ee9a69930c81..3b0a1ce5fd9ec2722ba6fce07fc9b5c5d8af60e8 100644 (file)
@@ -23,6 +23,7 @@ extern void fp_init_native_80(void);
 extern void fp_init_softfloat(void);
 extern void fpsr_set_exception(uae_u32 exception);
 extern void fpu_modechange(void);
+extern void fpu_clearstatus(void);
 
 #if defined(CPU_i386) || defined(CPU_x86_64)
 extern void init_fpucw_x87(void);
@@ -31,6 +32,14 @@ extern void init_fpucw_x87_80(void);
 #endif
 #endif
 
+#define PREC_NORMAL 0
+#define PREC_FLOAT 1
+#define PREC_DOUBLE 2
+#define PREC_EXTENDED 3
+
+#define FPU_FEATURE_EXCEPTIONS 1
+#define FPU_FEATURE_DENORMALS 2
+
 typedef void (*FPP_ABQS)(fpdata*, fpdata*, uae_u64*, uae_u8*);
 typedef void (*FPP_AB)(fpdata*, fpdata*);
 typedef void (*FPP_ABP)(fpdata*, fpdata*, int);
@@ -40,6 +49,7 @@ typedef bool (*FPP_IS)(fpdata*);
 typedef void (*FPP_SET_MODE)(uae_u32);
 typedef void (*FPP_GET_STATUS)(uae_u32*);
 typedef void (*FPP_CLEAR_STATUS)(void);
+typedef uae_u32 (*FPP_SUPPORT_FLAGS)(void);
 
 typedef void (*FPP_FROM_NATIVE)(fptype, fpdata*);
 typedef void (*FPP_TO_NATIVE)(fptype*, fpdata*);
@@ -65,8 +75,9 @@ typedef void (*FPP_DENORMALIZE)(fpdata*,int);
 
 extern FPP_PRINT fpp_print;
 
-extern FPP_IS fpp_is_snan;
 extern FPP_IS fpp_unset_snan;
+extern FPP_IS fpp_is_init;
+extern FPP_IS fpp_is_snan;
 extern FPP_IS fpp_is_nan;
 extern FPP_IS fpp_is_infinity;
 extern FPP_IS fpp_is_zero;
@@ -77,6 +88,7 @@ extern FPP_IS fpp_is_unnormal;
 extern FPP_GET_STATUS fpp_get_status;
 extern FPP_CLEAR_STATUS fpp_clear_status;
 extern FPP_SET_MODE fpp_set_mode;
+extern FPP_SUPPORT_FLAGS fpp_get_support_flags;
 
 extern FPP_TO_INT fpp_to_int;
 extern FPP_FROM_INT fpp_from_int;
index e9d6832ec0b179c8333250310fe3331039d2603d..c32d7a94be3963898c55173d64ca69b703445ca4 100644 (file)
@@ -36,8 +36,12 @@ extern "C"
        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_tan(void*, void*);
+       extern void _cdecl xfp_atan(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*);
@@ -48,6 +52,7 @@ extern "C"
        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);
 }
@@ -71,19 +76,25 @@ static struct float_status fs;
 static uae_u32 fpu_mode_control = 0;
 static int fpu_prec;
 static int temp_prec;
+static uae_u16 fp_status;
 
 static void fp_set_mode(uae_u32 m68k_cw)
 {
-       // RN, RZ, RM, RP
+       // RN, RZ, RD, RU
        static const uae_u16 fp87_round[4] = { 0 << 10, 3 << 10, 1 << 10, 2 << 10 };
+       static const uae_u16 sw_round[4] = { float_round_nearest_even, float_round_to_zero, float_round_down, float_round_up };
        // Extend X, Single S, Double D, Undefined (Double)
        static const uae_u16 fp87_prec[4] = { 3 << 8, 0 << 8, 2 << 8, 2 << 8 };
+       static const uae_u16 sw_prec[4] = { 80, 64, 32, 64 };
 
        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);
+       set_float_rounding_mode(sw_round[round], &fs);
+       set_floatx80_rounding_precision(sw_prec[prec], &fs);
+
 }
 
 /* The main motivation for dynamically creating an x86(-64) function in
@@ -128,7 +139,7 @@ void init_fpucw_x87_80(void)
 static void native_set_fpucw(uae_u32 m68k_cw)
 {
        static int ex = 0;
-       // RN, RZ, RM, RP
+       // RN, RZ, RD, RU
        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 };
@@ -194,31 +205,32 @@ static void fp_set_mode_native(uae_u32 mode_control)
 
 static bool xfp_changed;
 static bool native_changed;
+static uint8_t xfp_swprec;
 
 static void xfp_resetprec(void)
 {
-       if (xfp_changed)
+       if (xfp_changed) {
                xfp_fldcw(&fpx_mode);
+               set_floatx80_rounding_precision(xfp_swprec, &fs);
+               xfp_changed = false;
+       }
 }
+
 static void xfp_setprec(int prec)
 {
+       // normal, float, double, extended
+       static const uae_u16 prectable[] = { 0, 0 << 8, 2 << 8, 3 << 8 };
+       static const uint8_t sfprectable[] = { 32, 64, 0 };
+       if (prec == PREC_NORMAL)
+               return;
        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;
-       }
+       v |= prectable[prec];
        if (v != fpx_mode) {
                xfp_fldcw(&v);
+               xfp_swprec = fs.floatx80_rounding_precision;
+               set_floatx80_rounding_precision(sfprectable[prec], &fs);
                xfp_changed = true;
        } else {
                xfp_changed = false;
@@ -244,23 +256,30 @@ static void fp_reset_normal_prec(void)
        }
 }
 
+static uae_u32 fp_get_support_flags(void)
+{
+       return FPU_FEATURE_EXCEPTIONS;
+}
+
 static void fp_get_status(uae_u32 *status)
 {
        uae_u16 st = xfp_get_status();
 
-       if (st & (1 << 5))
+       if (st & (1 << 5)) // P
                *status |= FPSR_INEX2;
-       if (st & (1 << 4))
+       if (st & (1 << 4)) // U
                *status |= FPSR_UNFL;
-       if (st & (1 << 3))
+       if (st & (1 << 3)) // O
                *status |= FPSR_OVFL;
-       if (st & (1 << 2))
+       if (st & (1 << 2)) // Z
                *status |= FPSR_DZ;
+       *status |= fp_status;
 }
 
 static void fp_clear_status(void)
 {
        xfp_clear_status();
+       fp_status = 0;
 }
 
 static void toxnative(fpdata *fpd, fptype *fp)
@@ -285,44 +304,43 @@ static void xfp_from_softfloat(fpdata *fpd)
 }
 
 /* Functions for detecting float type */
+static bool fp_is_init(fpdata *fpd)
+{
+       xfp_to_softfloat(fpd);
+       return 0;
+}
 static bool fp_is_snan(fpdata *fpd)
 {
-    return 0; /* FIXME: how to detect SNAN */
+       return floatx80_is_signaling_nan(fpd->fpx) != 0;
 }
 static bool fp_unset_snan(fpdata *fpd)
 {
-    /* FIXME: how to unset SNAN */
+       fpd->rfp.m |= LIT64(0x4000000000000000);
        return 0;
 }
-static bool fp_is_nan (fpdata *fpd)
+static bool fp_is_nan(fpdata *fpd)
 {
-       xfp_to_softfloat(fpd);
        return floatx80_is_nan(fpd->fpx);
 }
-static bool fp_is_infinity (fpdata *fpd)
+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? */
+       return floatx80_is_denormal(fpd->fpx);
 }
 static bool fp_is_unnormal(fpdata *fpd)
 {
-       return false;
-    //return (isnormal(fpd->fp) == 0); /* FIXME: how to differ denormal/unnormal? */
+       return floatx80_is_unnormal(fpd->fpx);
 }
 
 /* Functions for converting between float formats */
@@ -409,29 +427,17 @@ static void fp_from_int(fpdata *fpd, uae_s32 src)
 // 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);
+       xfp_to_softfloat(fpd);
+       fpd->fpx = floatx80_round32(fpd->fpx, &fs);
+       xfp_from_softfloat(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);
+       xfp_to_softfloat(fpd);
+       fpd->fpx = floatx80_round64(fpd->fpx, &fs);
+       xfp_from_softfloat(fpd);
 }
 
 // round to float
@@ -511,24 +517,15 @@ static void fp_int(fpdata *a, fpdata *b)
 
 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);
+       xfp_to_softfloat(b);
+       a->fpx = floatx80_getexp(b->fpx, &fs);
+       xfp_from_softfloat(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);
+       xfp_to_softfloat(b);
+       a->fpx = floatx80_getman(b->fpx, &fs);
+       xfp_from_softfloat(a);
 }
 static void fp_div(fpdata *a, fpdata *b, int prec)
 {
@@ -538,237 +535,155 @@ static void fp_div(fpdata *a, fpdata *b, int prec)
 }
 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);
+       xfp_to_softfloat(a);
+       xfp_to_softfloat(b);
+       a->fpx = floatx80_mod(a->fpx, b->fpx, q, s, &fs);
+       xfp_from_softfloat(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);
+       xfp_to_softfloat(a);
+       xfp_to_softfloat(b);
+       a->fpx = floatx80_rem(a->fpx, b->fpx, q, s, &fs);
+       xfp_from_softfloat(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);
+       xfp_to_softfloat(a);
+       xfp_to_softfloat(b);
+       a->fpx = floatx80_scale(a->fpx, b->fpx, &fs);
+       xfp_from_softfloat(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();
+       xfp_to_softfloat(b);
+       a->fpx = floatx80_sinh(b->fpx, &fs);
+       xfp_from_softfloat(a);
 }
 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);
+       xfp_to_softfloat(b);
+       a->fpx = floatx80_lognp1(b->fpx, &fs);
+       xfp_from_softfloat(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);
+       xfp_to_softfloat(b);
+       a->fpx = floatx80_etoxm1(b->fpx, &fs);
+       xfp_from_softfloat(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);
+       xfp_to_softfloat(b);
+       a->fpx = floatx80_tanh(b->fpx, &fs);
+       xfp_from_softfloat(a);
 }
 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);
+       xfp_to_softfloat(b);
+       a->fpx = floatx80_asin(b->fpx, &fs);
+       xfp_from_softfloat(a);
 }
-static void fp_tan(fpdata *a, fpdata *b)
+static void fp_atanh(fpdata *a, fpdata *b)
 {
-       fptype aa, bb;
-       toxnative(b, &bb);
-       fp_normal_prec();
-       aa = tanl(bb);
-       fp_reset_normal_prec();
-       fromxnative(&aa, a);
+       xfp_to_softfloat(b);
+       a->fpx = floatx80_atanh(b->fpx, &fs);
+       xfp_from_softfloat(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);
+       xfp_to_softfloat(b);
+       a->fpx = floatx80_etox(b->fpx, &fs);
+       xfp_from_softfloat(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);
+       xfp_to_softfloat(b);
+       a->fpx = floatx80_twotox(b->fpx, &fs);
+       xfp_from_softfloat(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);
+       xfp_to_softfloat(b);
+       a->fpx = floatx80_tentox(b->fpx, &fs);
+       xfp_from_softfloat(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);
+       xfp_to_softfloat(b);
+       a->fpx = floatx80_logn(b->fpx, &fs);
+       xfp_from_softfloat(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);
+       xfp_to_softfloat(b);
+       a->fpx = floatx80_log10(b->fpx, &fs);
+       xfp_from_softfloat(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);
+       xfp_to_softfloat(b);
+       a->fpx = floatx80_log2(b->fpx, &fs);
+       xfp_from_softfloat(a);
 }
-static void fp_abs(fpdata *a, fpdata *b, int prec)
+static void fp_cosh(fpdata *a, fpdata *b)
+{
+       xfp_to_softfloat(b);
+       a->fpx = floatx80_cosh(b->fpx, &fs);
+       xfp_from_softfloat(a);
+}
+static void fp_acos(fpdata *a, fpdata *b)
+{
+       xfp_to_softfloat(b);
+       a->fpx = floatx80_acos(b->fpx, &fs);
+       xfp_from_softfloat(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_abs(&a->rfp, &b->rfp);
+       xfp_sqrt(&a->rfp, &b->rfp);
        xfp_resetprec();
 }
-static void fp_cosh(fpdata *a, fpdata *b)
+static void fp_atan(fpdata *a, fpdata *b)
 {
-       fptype aa, bb;
-       toxnative(b, &bb);
-       fp_normal_prec();
-       aa = coshl(bb);
-       fp_reset_normal_prec();
-       fromxnative(&aa, a);
+       xfp_atan(&a->rfp, &b->rfp);
 }
-static void fp_neg(fpdata *a, fpdata *b, int prec)
+static void fp_sin(fpdata *a, fpdata *b)
+{
+       xfp_sin(&a->rfp, &b->rfp);
+}
+static void fp_tan(fpdata *a, fpdata *b)
+{
+       xfp_tan(&a->rfp, &b->rfp);
+}
+
+static void fp_abs(fpdata *a, fpdata *b, int prec)
 {
        xfp_setprec(prec);
-       xfp_neg(&a->rfp, &b->rfp);
+       xfp_abs(&a->rfp, &b->rfp);
        xfp_resetprec();
 }
-static void fp_acos(fpdata *a, fpdata *b)
+static void fp_neg(fpdata *a, fpdata *b, int prec)
 {
-       fptype aa, bb;
-       toxnative(b, &bb);
-       fp_normal_prec();
-       aa = acosl(bb);
-       fp_reset_normal_prec();
-       fromxnative(&aa, a);
+       xfp_setprec(prec);
+       xfp_neg(&a->rfp, &b->rfp);
+       xfp_resetprec();
 }
 static void fp_cos(fpdata *a, fpdata *b)
 {
@@ -794,37 +709,21 @@ static void fp_mul(fpdata *a, fpdata *b, int prec)
 }
 static void fp_sglmul(fpdata *a, fpdata *b)
 {
-    float mant;
-    int expon;
-
+       xfp_setprec(PREC_EXTENDED);
+       a->rfp.m &= 0xFFFFFF0000000000;
+       b->rfp.m &= 0xFFFFFF0000000000;
        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);
+       fpdata fpx = *a;
+       fp_round32(a);
+       if (fpx.rfp.m != a->rfp.m)
+               fp_status |= FPSR_INEX2;
+       xfp_resetprec();
 }
 static void fp_sgldiv(fpdata *a, fpdata *b)
 {
-    float mant;
-    int expon;
-
+       xfp_setprec(PREC_FLOAT);
        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);
+       xfp_resetprec();
 }
 
 static void fp_normalize(fpdata *a)
@@ -833,61 +732,17 @@ 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);
+               xfp_to_softfloat(a);
+               xfp_to_softfloat(b);
+               a->fpx = floatx80_cmp(a->fpx, b->fpx, &fs);
+               xfp_from_softfloat(a);
        } else {
+               xfp_setprec(64);
                xfp_sub(&a->rfp, &b->rfp);
+               xfp_resetprec();
        }
        fp_clear_status();
-       xfp_resetprec();
 }
 
 static void fp_tst(fpdata *a, fpdata *b)
@@ -947,12 +802,13 @@ static void fp_from_pack (fpdata *src, uae_u32 *wrd, int kfactor)
        char str[100];
        fptype fp;
 
-   if (fpp_is_nan (src)) {
+       fp_is_init(src);
+   if (fp_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)) {
+    if (fp_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;
@@ -1148,8 +1004,10 @@ void fp_init_native_80(void)
        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_init = fp_is_init;
+       fpp_is_snan = fp_is_snan;
        fpp_is_nan = fp_is_nan;
        fpp_is_infinity = fp_is_infinity;
        fpp_is_zero = fp_is_zero;
@@ -1160,6 +1018,7 @@ void fp_init_native_80(void)
        fpp_get_status = fp_get_status;
        fpp_clear_status = fp_clear_status;
        fpp_set_mode = fp_set_mode;
+       fpp_get_support_flags = fp_get_support_flags;
 
        fpp_to_int = fp_to_int;
        fpp_from_int = fp_from_int;
index 65d671f1fa2c0302545b627f42f9f6b54b00db41..7ab820f09c9a7c4bda99c8291e4ea86a2d0ef7c7 100644 (file)
@@ -20,8 +20,12 @@ global xfp_neg
 global xfp_add
 global xfp_sub
 global xfp_sqrt
+
 global xfp_sin
 global xfp_cos
+global xfp_tan
+global xfp_atan
+
 global xfp_get_status
 global xfp_clear_status
 
@@ -173,3 +177,15 @@ xfp_sin:
        fsin
        storefp
        ret
+
+xfp_tan:
+       loadfp1
+       fptan
+       storefp
+       ret
+
+xfp_atan:
+       loadfp1
+       fpatan
+       storefp
+       ret
index 459e2ab0941a3f5cde301e6811b7bf7c9a32b986..1e0a0062c0e06796e6d88c683634541cdd2b4594 100644 (file)
@@ -20,8 +20,12 @@ global _xfp_neg
 global _xfp_add
 global _xfp_sub
 global _xfp_sqrt
+
 global _xfp_sin
 global _xfp_cos
+global _xfp_tan
+global _xfp_atan
+
 global _xfp_get_status
 global _xfp_clear_status
 
@@ -195,3 +199,15 @@ _xfp_sin:
        fsin
        storefp
        ret
+
+_xfp_tan:
+       loadfp1
+       fptan
+       storefp
+       ret
+
+_xfp_atan:
+       loadfp1
+       fpatan
+       storefp
+       ret