From: Toni Wilen Date: Tue, 1 May 2018 13:20:41 +0000 (+0300) Subject: Extended precision native FPU mode updates. X-Git-Tag: 4000~85 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=7711f3008fee992c83c0756b48779c05dfd5a307;p=francis%2Fwinuae.git Extended precision native FPU mode updates. --- diff --git a/cfgfile.cpp b/cfgfile.cpp index 3df845f2..0d801655 100644 --- a/cfgfile.cpp +++ b/cfgfile.cpp @@ -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 578da31c..aa270413 100644 --- 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 (®s.fp_result)) { + fpp_is_init(®s.fp_result); + if (fpp_is_nan(®s.fp_result)) { regs.fpsr |= FPSR_CC_NAN; } else if (fpp_is_zero(®s.fp_result)) { regs.fpsr |= FPSR_CC_Z; - } else if (fpp_is_infinity (®s.fp_result)) { + } else if (fpp_is_infinity(®s.fp_result)) { regs.fpsr |= FPSR_CC_I; } if (fpp_is_neg(®s.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(®s.fp_result); NotANumber = fpp_is_nan(®s.fp_result); N = fpp_is_neg(®s.fp_result); Z = fpp_is_zero(®s.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(®s.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); diff --git a/fpp_native.cpp b/fpp_native.cpp index 3bc1ee54..ea040041 100644 --- a/fpp_native.cpp +++ b/fpp_native.cpp @@ -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; diff --git a/fpp_softfloat.cpp b/fpp_softfloat.cpp index 97e1d195..fb894c83 100644 --- a/fpp_softfloat.cpp +++ b/fpp_softfloat.cpp @@ -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; diff --git a/include/fpp.h b/include/fpp.h index 7374d486..3b0a1ce5 100644 --- a/include/fpp.h +++ b/include/fpp.h @@ -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; diff --git a/od-win32/fpp_native_msvc_80bit.cpp b/od-win32/fpp_native_msvc_80bit.cpp index e9d6832e..c32d7a94 100644 --- a/od-win32/fpp_native_msvc_80bit.cpp +++ b/od-win32/fpp_native_msvc_80bit.cpp @@ -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; diff --git a/od-win32/fpux64_80.asm b/od-win32/fpux64_80.asm index 65d671f1..7ab820f0 100644 --- a/od-win32/fpux64_80.asm +++ b/od-win32/fpux64_80.asm @@ -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 diff --git a/od-win32/fpux86_80.asm b/od-win32/fpux86_80.asm index 459e2ab0..1e0a0062 100644 --- a/od-win32/fpux86_80.asm +++ b/od-win32/fpux86_80.asm @@ -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