From: Toni Wilen Date: Sun, 19 Mar 2017 17:06:38 +0000 (+0200) Subject: FPU packed decimal updates, should be 100% accurate now. X-Git-Tag: 3500~79 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=059db89267f9d4dc8713fb5e20059dce53882405;p=francis%2Fwinuae.git FPU packed decimal updates, should be 100% accurate now. --- diff --git a/fpp.cpp b/fpp.cpp index 8444eedb..afe15f78 100644 --- a/fpp.cpp +++ b/fpp.cpp @@ -10,6 +10,8 @@ #define __USE_ISOC9X /* We might be able to pick up a NaN */ +#define FPU_TEST 0 + #include #include #include @@ -2918,6 +2920,22 @@ void fpu_modechange(void) } } +#if FPU_TEST + +static void fpu_test(void) +{ + fpdata testp; + uae_u32 packed[3]; + + fpp_set_fpcr(0x30); + fpp_to_exten_fmovem(&testp, 0xB4000000, 0x80000000, 0x000003fc); + write_log(_T("INPUT: %s (%04x %16llx)\n"), fpp_print(&testp, -1), testp.fpx.high, testp.fpx.low); + fpp_from_pack(&testp, packed, 17); + fpp_to_pack(&testp, packed, 0); +} + +#endif + void fpu_reset (void) { if (currprefs.fpu_softfloat) { @@ -2938,6 +2956,11 @@ void fpu_reset (void) // reset precision fpp_set_mode(0x00000080 | 0x00000010); fpp_set_mode(0x00000000); + +#if FPU_TEST + fpu_test(); +#endif + } uae_u8 *restore_fpu (uae_u8 *src) @@ -3035,6 +3058,4 @@ uae_u8 *save_fpu (int *len, uae_u8 *dstptr) return dstbak; } -#ifdef _MSC_VER -#pragma fenv_access(off) -#endif + diff --git a/softfloat/SOFTFLOAT-MACROS.H b/softfloat/SOFTFLOAT-MACROS.H index a84956e6..55937eb8 100644 --- a/softfloat/SOFTFLOAT-MACROS.H +++ b/softfloat/SOFTFLOAT-MACROS.H @@ -484,7 +484,7 @@ static inline void ) { uint64_t z0, z1, z2; - int8_t borrow0, borrow1; + uint8_t borrow0, borrow1; z2 = a2 - b2; borrow1 = ( a2 < b2 ); diff --git a/softfloat/softfloat_decimal.cpp b/softfloat/softfloat_decimal.cpp index 9e1d3977..86956d03 100644 --- a/softfloat/softfloat_decimal.cpp +++ b/softfloat/softfloat_decimal.cpp @@ -55,7 +55,7 @@ void round128to64(flag aSign, int32_t *aExp, uint64_t *aSig0, uint64_t *aSig1, f ++zExp; zSig0 = LIT64(0x8000000000000000); } else { - zSig0 &= ~ (((int64_t) (zSig1<<1) == 0) & (status->float_rounding_mode == float_round_nearest_even)); + zSig0 &= ~ (((uint64_t) (zSig1<<1) == 0) & (status->float_rounding_mode == float_round_nearest_even)); } } else { if ( zSig0 == 0 ) zExp = 0; @@ -66,7 +66,7 @@ void round128to64(flag aSign, int32_t *aExp, uint64_t *aSig0, uint64_t *aSig1, f *aSig1 = 0; } -void mul128by128round(flag aSign, int32_t *aExp, uint64_t *aSig0, uint64_t *aSig1, int32_t bExp, uint64_t bSig0, uint64_t bSig1, float_status *status) +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; @@ -75,7 +75,7 @@ void mul128by128round(flag aSign, int32_t *aExp, uint64_t *aSig0, uint64_t *aSig zSig0 = *aSig0; zSig1 = *aSig1; - round128to64(aSign, &bExp, &bSig0, &bSig1, status); + round128to64(0, &bExp, &bSig0, &bSig1, status); zExp += bExp - 0x3FFE; mul128To256(zSig0, zSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3); @@ -88,7 +88,7 @@ void mul128by128round(flag aSign, int32_t *aExp, uint64_t *aSig0, uint64_t *aSig *aSig0 = zSig0; *aSig1 = zSig1; - round128to64(aSign, aExp, aSig0, aSig1, status); + 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) @@ -150,11 +150,65 @@ void div128by128(int32_t *paExp, uint64_t *paSig0, uint64_t *paSig1, int32_t bEx *paSig1 = zSig1; } -void tentoint128(flag aSign, int32_t *aExp, uint64_t *aSig0, uint64_t *aSig1, int32_t scale, float_status *status) +#if 0 + +void tentoint128(flag mSign, flag eSign, int32_t *aExp, uint64_t *aSig0, uint64_t *aSig1, int32_t scale, float_status *status) { - int32_t mExp; - uint64_t mSig0, mSig1; - + int32_t mExp; + uint64_t mSig0, mSig1; + + + *aExp = 0x3FFF; + *aSig0 = LIT64(0x8000000000000000); + *aSig1 = 0; + + mExp = 0x4002; + mSig0 = LIT64(0xA000000000000000); + mSig1 = 0; + + + while (scale) { + if (scale & 1) { + mul128by128round(aExp, aSig0, aSig1, mExp, mSig0, mSig1, status); + } + mul128by128(&mExp, &mSig0, &mSig1, mExp, mSig0, mSig1); + scale >>= 1; + } +} + +#else + +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; + uint64_t mSig0, mSig1; + + save_rounding_mode = status->float_rounding_mode; + switch (status->float_rounding_mode) { + case float_round_nearest_even: + break; + case float_round_down: + if (mSign != eSign) { + set_float_rounding_mode(float_round_up, status); + } + break; + case float_round_up: + if (mSign != eSign) { + set_float_rounding_mode(float_round_down, status); + } + break; + case float_round_to_zero: + if (eSign == 0) { + set_float_rounding_mode(float_round_down, status); + } else { + set_float_rounding_mode(float_round_up, status); + } + break; + default: + break; + } + *aExp = 0x3FFF; *aSig0 = LIT64(0x8000000000000000); *aSig1 = 0; @@ -165,13 +219,17 @@ void tentoint128(flag aSign, int32_t *aExp, uint64_t *aSig0, uint64_t *aSig1, in while (scale) { if (scale & 1) { - mul128by128round(aSign, aExp, aSig0, aSig1, mExp, mSig0, mSig1, status); + mul128by128round(aExp, aSig0, aSig1, mExp, mSig0, mSig1, status); } mul128by128(&mExp, &mSig0, &mSig1, mExp, mSig0, mSig1); scale >>= 1; } + + set_float_rounding_mode(save_rounding_mode, status); } +#endif + int64_t tentointdec(int32_t scale) { uint64_t decM, decX; @@ -299,7 +357,7 @@ floatx80 floatdecimal_to_floatx80(floatx80 a, float_status *status) zSig1 = 0; zSign = decSign; - tentoint128(zSign, &xExp, &xSig0, &xSig1, decExp, status); + tentoint128(decSign, decExpSign, &xExp, &xSig0, &xSig1, decExp, status); if (decExpSign) { div128by128(&zExp, &zSig0, &zSig1, xExp, xSig0, xSig1); @@ -403,7 +461,9 @@ try_again: decimal_log(_T("ISCALE = %i, LAMBDA = %i\n"),iscale, lambda); - tentoint128(0, &xExp, &xSig0, &xSig1, iscale, status); + tentoint128(lambda, 0, &xExp, &xSig0, &xSig1, iscale, status); + + decimal_log(_T("AFTER tentoint128: zExp = %04x, zSig0 = %16llx, zSig1 = %16llx\n"), xExp, xSig0, xSig1); zExp = aExp; zSig0 = aSig;