void fpuop_restore (uae_u32 opcode)
{
- int fpu_version = get_fpu_version (); // TODO: check version of stack frame
+ int fpu_version = get_fpu_version();
+ int frame_version;
uaecptr pc = m68k_getpc () - 2;
uae_u32 ad;
uae_u32 d;
d = x_get_long (ad);
ad += 4;
+ frame_version = (d >> 24) & 0xff;
+
if (currprefs.fpu_model == 68060) {
int ff = (d >> 8) & 0xff;
uae_u32 v = d & 0x7;
} else if (currprefs.fpu_model == 68040) {
- if ((d & 0xff000000) != 0) { // not null frame
+ if (frame_version == fpu_version) { // not null frame
uae_u32 frame_size = (d >> 16) & 0xff;
if (frame_size == 0x60) { // busy
opclass = (cmdreg1b >> 13) & 0x7; // just to be sure
- if (cusavepc == 0xFE && (opclass == 0 || opclass == 2)) {
- fpp_to_exten_fmovem(&dst, fsave_data.fpt[0], fsave_data.fpt[1], fsave_data.fpt[2]);
- fpp_denormalize(&dst, fpte15);
- fpp_to_exten_fmovem(&src, fsave_data.et[0], fsave_data.et[1], fsave_data.et[2]);
- fpp_denormalize(&src, et15);
+ if (cusavepc == 0xFE) {
+ if (opclass == 0 || opclass == 2) {
+ fpp_to_exten_fmovem(&dst, fsave_data.fpt[0], fsave_data.fpt[1], fsave_data.fpt[2]);
+ fpp_denormalize(&dst, fpte15);
+ fpp_to_exten_fmovem(&src, fsave_data.et[0], fsave_data.et[1], fsave_data.et[2]);
+ fpp_denormalize(&src, et15);
#if EXCEPTION_FPP
- uae_u32 tmpsrc[3], tmpdst[3];
- fpp_from_exten_fmovem(&src, &tmpsrc[0], &tmpsrc[1], &tmpsrc[2]);
- fpp_from_exten_fmovem(&dst, &tmpdst[0], &tmpdst[1], &tmpdst[2]);
- write_log (_T("FRESTORE src = %08X %08X %08X, dst = %08X %08X %08X, extra = %04X\n"),
- tmpsrc[0], tmpsrc[1], tmpsrc[2], tmpdst[0], tmpdst[1], tmpdst[2], cmdreg1b);
-#endif
- fpsr_clear_status();
-
- v = fp_arithmetic(&src, &dst, cmdreg1b);
-
- if (v)
- regs.fp[(cmdreg1b >> 7) & 7] = dst;
-
- fpsr_check_arithmetic_exception(0, &src, regs.fp_opword, cmdreg1b, regs.fp_ea);
+ uae_u32 tmpsrc[3], tmpdst[3];
+ fpp_from_exten_fmovem(&src, &tmpsrc[0], &tmpsrc[1], &tmpsrc[2]);
+ fpp_from_exten_fmovem(&dst, &tmpdst[0], &tmpdst[1], &tmpdst[2]);
+ write_log (_T("FRESTORE src = %08X %08X %08X, dst = %08X %08X %08X, extra = %04X\n"),
+ tmpsrc[0], tmpsrc[1], tmpsrc[2], tmpdst[0], tmpdst[1], tmpdst[2], cmdreg1b);
+#endif
+ fpsr_clear_status();
+
+ v = fp_arithmetic(&src, &dst, cmdreg1b);
+
+ if (v)
+ regs.fp[(cmdreg1b>>7)&7] = dst;
+
+ fpsr_check_arithmetic_exception(0, &src, regs.fp_opword, cmdreg1b, regs.fp_ea);
+ } else {
+ write_log (_T("FRESTORE resume of opclass %d instruction not supported!\n"), opclass);
+ }
}
- } else if((frame_size == 0x30 || frame_size == 0x28)) { // unimp
+ } else if (frame_size == 0x30 || frame_size == 0x28) { // unimp
// TODO: restore frame contents
ad += frame_size;
- } else if (frame_size != 0x00) { // not idle
-
- write_log (_T("FRESTORE invalid frame format %02X!\n"), frame_size);
+ } else if (frame_size == 0x00) { // idle
+ regs.fpu_state = 1;
+ regs.fpu_exp_state = 0;
+ } else {
+ write_log (_T("FRESTORE invalid frame size %02X!\n"), frame_size);
Exception(14);
return;
}
- } else { // null frame
+ } else if (frame_version == 0x00) { // null frame
fpu_null();
+ } else {
+ write_log (_T("FRESTORE invalid frame version %02X!\n"), frame_version);
+ Exception(14);
+ return;
}
} else {
// 6888x
- if ((d & 0xff000000) != 0) { // not null frame
+ if (frame_version == fpu_version) { // not null frame
uae_u32 biu_flags;
uae_u32 frame_size = (d >> 16) & 0xff;
uae_u32 biu_offset = frame_size - 4;
if ((biu_flags & 0x08000000) == 0x00000000) {
regs.fpu_exp_state = 2;
regs.fp_exp_pend = fpsr_get_vector(regs.fpsr & regs.fpcr & 0xff00);
+ } else {
+ regs.fpu_exp_state = 0;
+ regs.fp_exp_pend = 0;
}
} else if (frame_size == 0xB4 || frame_size == 0xD4) {
write_log (_T("FRESTORE of busy frame not supported\n"));
+ ad += frame_size;
} else {
- write_log (_T("FRESTORE invalid frame format %02X!\n"), frame_size);
-
+ write_log (_T("FRESTORE invalid frame size %02X!\n"), frame_size);
Exception(14);
return;
}
- } else { // null frame
+ } else if (frame_version == 0x00) { // null frame
fpu_null();
+ } else {
+ write_log (_T("FRESTORE invalid frame version %02X!\n"), frame_version);
+ Exception(14);
+ return;
}
}
m68k_areg (regs, opcode & 7) = ad;
fp_exception_pending(false);
-
}
static uaecptr fmovem2mem (uaecptr ad, uae_u32 list, int incr, int regdir)
float fp_1e0 = 1, fp_1e1 = 10, fp_1e2 = 100, fp_1e4 = 10000;
#endif
-static uae_u32 xhex_pi[] ={0x2168c235, 0xc90fdaa2, 0x4000};
-static uae_u32 xhex_l2_e[] ={0x5c17f0bc, 0xb8aa3b29, 0x3fff};
-static uae_u32 xhex_ln_2[] ={0xd1cf79ac, 0xb17217f7, 0x3ffe};
-static uae_u32 xhex_inf[] ={0x00000000, 0x00000000, 0x7fff};
-static uae_u32 xhex_nan[] ={0xffffffff, 0xffffffff, 0x7fff};
-static uae_u32 xhex_snan[] ={0xffffffff, 0xbfffffff, 0x7fff};
#ifdef USE_LONG_DOUBLE
-static long double *fp_pi = (long double *)xhex_pi;
-static long double *fp_exp_1 = (long double *)xhex_exp_1;
-static long double *fp_l2_e = (long double *)xhex_l2_e;
-static long double *fp_ln_2 = (long double *)xhex_ln_2;
-static long double *fp_ln_10 = (long double *)xhex_ln_10;
-static long double *fp_l10_2 = (long double *)xhex_l10_2;
-static long double *fp_l10_e = (long double *)xhex_l10_e;
-static long double *fp_1e16 = (long double *)xhex_1e16;
-static long double *fp_1e32 = (long double *)xhex_1e32;
-static long double *fp_1e64 = (long double *)xhex_1e64;
-static long double *fp_1e128 = (long double *)xhex_1e128;
-static long double *fp_1e256 = (long double *)xhex_1e256;
-static long double *fp_1e512 = (long double *)xhex_1e512;
-static long double *fp_1e1024 = (long double *)xhex_1e1024;
-static long double *fp_1e2048 = (long double *)xhex_1e2048;
-static long double *fp_1e4096 = (long double *)xhex_1e4096;
-static long double *fp_inf = (long double *)xhex_inf;
+static uae_u32 xhex_nan[] ={0xffffffff, 0xffffffff, 0x7fff};
static long double *fp_nan = (long double *)xhex_nan;
#else
-static uae_u32 dhex_pi[] ={0x54442D18, 0x400921FB};
-static uae_u32 dhex_exp_1[] ={0x8B145769, 0x4005BF0A};
-static uae_u32 dhex_l2_e[] ={0x652B82FE, 0x3FF71547};
-static uae_u32 dhex_ln_2[] ={0xFEFA39EF, 0x3FE62E42};
-static uae_u32 dhex_ln_10[] ={0xBBB55516, 0x40026BB1};
-static uae_u32 dhex_l10_2[] ={0x509F79FF, 0x3FD34413};
-static uae_u32 dhex_l10_e[] ={0x1526E50E, 0x3FDBCB7B};
-static uae_u32 dhex_1e16[] ={0x37E08000, 0x4341C379};
-static uae_u32 dhex_1e32[] ={0xB5056E17, 0x4693B8B5};
-static uae_u32 dhex_1e64[] ={0xE93FF9F5, 0x4D384F03};
-static uae_u32 dhex_1e128[] ={0xF9301D32, 0x5A827748};
-static uae_u32 dhex_1e256[] ={0x7F73BF3C, 0x75154FDD};
-static uae_u32 dhex_inf[] ={0x00000000, 0x7ff00000};
static uae_u32 dhex_nan[] ={0xffffffff, 0x7fffffff};
-static double *fp_pi = (double *)dhex_pi;
-static double *fp_exp_1 = (double *)dhex_exp_1;
-static double *fp_l2_e = (double *)dhex_l2_e;
-static double *fp_ln_2 = (double *)dhex_ln_2;
-static double *fp_ln_10 = (double *)dhex_ln_10;
-static double *fp_l10_2 = (double *)dhex_l10_2;
-static double *fp_l10_e = (double *)dhex_l10_e;
-static double *fp_1e16 = (double *)dhex_1e16;
-static double *fp_1e32 = (double *)dhex_1e32;
-static double *fp_1e64 = (double *)dhex_1e64;
-static double *fp_1e128 = (double *)dhex_1e128;
-static double *fp_1e256 = (double *)dhex_1e256;
-static double *fp_1e512 = (double *)dhex_inf;
-static double *fp_1e1024 = (double *)dhex_inf;
-static double *fp_1e2048 = (double *)dhex_inf;
-static double *fp_1e4096 = (double *)dhex_inf;
-static double *fp_inf = (double *)dhex_inf;
static double *fp_nan = (double *)dhex_nan;
#endif
static const double twoto32 = 4294967296.0;
/* Functions for rounding */
-static floatx80 fp_to_sgl(floatx80 a)
-{
- floatx80 v = floatx80_round32(a, &fs);
- v.high &= 0x7fff;
- v.high |= a.high & 0x7fff;
- return v;
-}
-
// round to float with extended precision exponent
static void fp_round32(fpdata *fpd)
{
fpd->fpx = floatx80_round_to_float64(fpd->fpx, &fs);
}
+#if 0
// round to selected precision
static void fp_round(fpdata *a)
{
break;
}
}
+#endif
/* Arithmetic functions */
exponent = f.high & 0x3FFF;
significand = f.low;
+ pack_int = 0;
pack_frac = 0;
len = kfactor; // SoftFloat saved len to kfactor variable
while (len > 0) {
}
}
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the extended double-precision floating-point value `a' is a
+| signaling NaN; otherwise returns 0.
+*----------------------------------------------------------------------------*/
+
+static inline flag floatx80_is_signaling_nan( floatx80 a )
+{
+ uint64_t aLow;
+
+ aLow = a.low & ~ LIT64( 0x4000000000000000 );
+ return
+ ( ( a.high & 0x7FFF ) == 0x7FFF )
+ && (uint64_t) ( aLow<<1 )
+ && ( a.low == aLow );
+
+}
+
/*----------------------------------------------------------------------------
| Returns the result of converting the extended double-precision floating-
| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
}
#endif
-/*----------------------------------------------------------------------------
-| Returns 1 if the extended double-precision floating-point value `a' is a
-| signaling NaN; otherwise returns 0.
-*----------------------------------------------------------------------------*/
-
-static flag floatx80_is_signaling_nan( floatx80 a )
-{
- uint64_t aLow;
-
- aLow = a.low & ~ LIT64( 0x4000000000000000 );
- return
- ( ( a.high & 0x7FFF ) == 0x7FFF )
- && (uint64_t) ( aLow<<1 )
- && ( a.low == aLow );
-
-}
-
// 28-12-2016: Added for Previous:
/*----------------------------------------------------------------------------
flag floatx80_lt( floatx80, floatx80, float_status *status);
#ifdef SOFTFLOAT_68K
-flag floatx80_is_zero( floatx80 );
-flag floatx80_is_infinity( floatx80 );
-flag floatx80_is_negative( floatx80 );
-flag floatx80_is_denormal( floatx80 );
-flag floatx80_is_unnormal( floatx80 );
-flag floatx80_is_normal( floatx80 );
-
// functions are in softfloat.c
floatx80 floatx80_move( floatx80 a, float_status *status );
floatx80 floatx80_abs( floatx80 a, float_status *status );
floatx80 packFloatx80( flag zSign, int32_t zExp, uint64_t zSig );
floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign, int32_t zExp, uint64_t zSig0, uint64_t zSig1, float_status *status);
-// functions are in softfloat-specialize.h
-floatx80 propagateFloatx80NaNOneArg( floatx80 a, float_status *status );
-floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b, float_status *status );
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision operations.
*----------------------------------------------------------------------------*/
floatx80 floatx80_mul(floatx80, floatx80, float_status *status);
floatx80 floatx80_div(floatx80, floatx80, float_status *status);
floatx80 floatx80_sqrt(floatx80, float_status *status);
-flag floatx80_is_signaling_nan(floatx80);
floatx80 floatx80_normalize(floatx80);
floatx80 floatx80_denormalize(floatx80, flag);
#define floatx80_half make_floatx80(0x3ffe, 0x8000000000000000LL)
#define floatx80_infinity make_floatx80(0x7fff, 0x8000000000000000LL)
-/*----------------------------------------------------------------------------
-| The pattern for a default generated extended double-precision NaN.
-*----------------------------------------------------------------------------*/
-floatx80 floatx80_default_nan(float_status *status);
-
#endif /* SOFTFLOAT_H */
| Methods for converting decimal floats to binary extended precision floats.
*----------------------------------------------------------------------------*/
-void round128to64(flag aSign, int32_t *aExp, uint64_t *aSig0, uint64_t *aSig1, float_status *status)
+static void round128to64(flag aSign, int32_t *aExp, uint64_t *aSig0, uint64_t *aSig1, float_status *status)
{
flag increment;
int32_t zExp;
*aSig1 = 0;
}
-void mul128by128round(int32_t *aExp, uint64_t *aSig0, uint64_t *aSig1, int32_t bExp, uint64_t bSig0, uint64_t bSig1, float_status *status)
+static void mul128by128round(int32_t *aExp, uint64_t *aSig0, uint64_t *aSig1, int32_t bExp, uint64_t bSig0, uint64_t bSig1, float_status *status)
{
int32_t zExp;
uint64_t zSig0, zSig1, zSig2, zSig3;
round128to64(0, aExp, aSig0, aSig1, status);
}
-void mul128by128(int32_t *aExp, uint64_t *aSig0, uint64_t *aSig1, int32_t bExp, uint64_t bSig0, uint64_t bSig1)
+static void mul128by128(int32_t *aExp, uint64_t *aSig0, uint64_t *aSig1, int32_t bExp, uint64_t bSig0, uint64_t bSig1)
{
int32_t zExp;
uint64_t zSig0, zSig1, zSig2, zSig3;
*aSig1 = zSig1;
}
-void div128by128(int32_t *paExp, uint64_t *paSig0, uint64_t *paSig1, int32_t bExp, uint64_t bSig0, uint64_t bSig1)
+static void div128by128(int32_t *paExp, uint64_t *paSig0, uint64_t *paSig1, int32_t bExp, uint64_t bSig0, uint64_t bSig1)
{
int32_t zExp, aExp;
uint64_t zSig0, zSig1, aSig0, aSig1;
#else
-void tentoint128(flag mSign, flag eSign, int32_t *aExp, uint64_t *aSig0, uint64_t *aSig1, int32_t scale, float_status *status)
+static void tentoint128(flag mSign, flag eSign, int32_t *aExp, uint64_t *aSig0, uint64_t *aSig1, int32_t scale, float_status *status)
{
int8_t save_rounding_mode;
int32_t mExp;
#endif
-int64_t tentointdec(int32_t scale)
+static int64_t tentointdec(int32_t scale)
{
uint64_t decM, decX;
}
-int64_t float128toint64(flag zSign, int32_t zExp, uint64_t zSig0, uint64_t zSig1, float_status *status)
+static int64_t float128toint64(flag zSign, int32_t zExp, uint64_t zSig0, uint64_t zSig1, float_status *status)
{
int8_t roundingMode;
flag roundNearestEven, increment;
return z;
}
-int32_t getDecimalExponent(int32_t aExp, uint64_t aSig)
+static int32_t getDecimalExponent(int32_t aExp, uint64_t aSig)
{
flag zSign;
int32_t zExp, shiftCount;