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;
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;
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 {
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)) {
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);
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;
#endif
}
- if (currprefs.fpu_mode <= 0) {
+ if (!support_exceptions || jit_fpu()) {
// log message and exit
regs.fp_exp_pend = 0;
return;
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);
}
#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))
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
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;
#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))
// 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)) {
}
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)) {
#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);
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);
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);
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);
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);
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);
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 */
}
}
+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];
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();
#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]);
}
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();
regs.fpiar = 0;
regs.fpu_exp_state = 0;
+ get_features();
fpp_set_fpcr (0);
fpp_set_fpsr (0);
fpux_restore (NULL);
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
#endif
}
+static uae_u32 fp_get_support_flags(void)
+{
+ return 0;
+}
+
static void fp_clear_status(void)
{
#if 0
}
/* 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 */
/* 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;
}
};
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);
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);
}
}
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;
}
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
{
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
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;
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;
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;
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*);
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_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
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 };
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;
}
}
+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)
}
/* 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 */
// 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
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)
{
}
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)
{
}
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)
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)
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;
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;
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;