From: Toni Wilen Date: Mon, 13 Mar 2017 17:44:53 +0000 (+0200) Subject: Packed decimal support. X-Git-Tag: 3500~84 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=00ac1eaf4d7d08c5c9288f2d3d6a9ea647c3827d;p=francis%2Fwinuae.git Packed decimal support. --- diff --git a/fpp.cpp b/fpp.cpp index 2daea2d5..7e38ccfb 100644 --- a/fpp.cpp +++ b/fpp.cpp @@ -1183,6 +1183,17 @@ static void to_pack (fpdata *fpd, uae_u32 *wrd) #endif +#if 1 + +void from_pack_softfloat (fpdata *fp, uae_u32 *wrd, int kfactor); + +static void from_pack (fpdata *fpd, uae_u32 *wrd, int kfactor) +{ + from_pack_softfloat(fpd, wrd, kfactor); +} + +#else + static void from_pack (fpdata *src, uae_u32 *wrd, int kfactor) { int i, j, t; @@ -1335,6 +1346,8 @@ static void from_pack (fpdata *src, uae_u32 *wrd, int kfactor) wrd[0] |= t << 16; } +#endif + // 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) { diff --git a/fpp_softfloat.cpp b/fpp_softfloat.cpp index a51c65bf..c1cd413c 100644 --- a/fpp_softfloat.cpp +++ b/fpp_softfloat.cpp @@ -88,6 +88,8 @@ static void fp_get_status(uae_u32 *status) *status |= FPSR_UNFL; if (fs.float_exception_flags & float_flag_inexact) *status |= FPSR_INEX2; + if (fs.float_exception_flags & float_flag_decimal) + *status |= FPSR_INEX1; } STATIC_INLINE void fp_clear_status(void) { @@ -754,8 +756,6 @@ static void fp_normalize(fpdata *a) a->fpx = floatx80_normalize(a->fpx); } -static float_status fsp; - void to_pack_softfloat (fpdata *fp, uae_u32 *wrd) { uae_s32 exp = 0; @@ -814,7 +814,8 @@ void to_pack_softfloat (fpdata *fp, uae_u32 *wrd) mant += (pack_frac >> (60 - i * 4)) & 0xF; } - +#if 1 + if (pack_sm) { mant = -mant; } @@ -874,20 +875,20 @@ void to_pack_softfloat (fpdata *fp, uae_u32 *wrd) while (exp) { if (exp & 1) { - a = floatx80_mul(a, m, &fsp); + a = floatx80_mul(a, m, &fs); } - m = floatx80_mul(m, m, &fsp); + m = floatx80_mul(m, m, &fs); exp >>= 1; } if (pack_se) { - z = floatx80_div(z, a, &fsp); + z = floatx80_div(z, a, &fs); } else { - z = floatx80_mul(z, a, &fsp); + z = floatx80_mul(z, a, &fs); } - +#if 0 write_log(_T("z = %s\n"), fp_printx80(&z, 0)); write_log(_T("m = %s\n"), fp_printx80(&m, 0)); write_log(_T("a = %s\n"), fp_printx80(&a, 0)); @@ -895,15 +896,95 @@ void to_pack_softfloat (fpdata *fp, uae_u32 *wrd) write_log(_T("zerocount = %i\n"), zerocount); write_log(_T("multiplier = %llu\n"), multiplier); +#endif fp->fpx = z; + + /* TODO: set inex1 and restore rounding mode */ + // if mul/div caused inex2 --> set inex1 + +#else + + floatx80 f; + f.high = exp & 0x3FFF; + f.high |= pack_se ? 0x4000 : 0; + f.high |= pack_sm ? 0x8000 : 0; + f.low = mant; + + fp->fpx = floatdecimal_to_floatx80(f, &fsp); + +#endif + if (!currprefs.fpu_softfloat) { to_native(&fp->fp, fp); } - /* TODO: set inex1 and restore rounding mode */ - // if mul/div caused inex2 --> set inex1 +} + +void from_pack_softfloat (fpdata *src, uae_u32 *wrd, int kfactor) +{ + floatx80 a; + fpdata fpd; + + if (!currprefs.fpu_softfloat) { + from_native(src->fp, &fpd); + } else { + fpd.fpx = src->fpx; + } + a = fpd.fpx; + + floatx80 f = floatx80_to_floatdecimal(a, &kfactor, &fs); + + uae_u32 pack_exp = 0; // packed exponent + uae_u32 pack_exp4 = 0; + uae_u32 pack_int = 0; // packed integer part + uae_u64 pack_frac = 0; // packed fraction + uae_u32 pack_se = 0; // sign of packed exponent + uae_u32 pack_sm = 0; // sign of packed significand + + uae_u32 exponent = f.high & 0x3FFF; + uae_u64 significand = f.low; + + uae_s32 len = kfactor; // SoftFloat saved len to kfactor variable + + uae_u64 digit; + pack_frac = 0; + while (len > 0) { + len--; + digit = significand % 10; + significand /= 10; + if (len == 0) { + pack_int = digit; + } else { + pack_frac |= digit << (64 - len * 4); + } + } + + digit = exponent / 1000; + exponent -= digit * 1000; + pack_exp4 = digit; + digit = exponent / 100; + exponent -= digit * 100; + pack_exp = digit << 8; + digit = exponent / 10; + exponent -= digit * 10; + pack_exp |= digit << 4; + pack_exp |= exponent; + + pack_se = f.high & 0x4000; + pack_sm = f.high & 0x8000; + + wrd[0] = pack_exp << 16; + wrd[0] |= pack_exp4 << 12; + wrd[0] |= pack_int; + wrd[0] |= pack_se ? 0x40000000 : 0; + wrd[0] |= pack_sm ? 0x80000000 : 0; + + wrd[1] = pack_frac >> 32; + wrd[2] = pack_frac & 0xffffffff; + + //printf("PACKED = %08x %08x %08x\n",wrd[0],wrd[1],wrd[2]); } void fp_init_softfloat(void) @@ -911,8 +992,6 @@ void fp_init_softfloat(void) float_status fsx = { 0 }; set_floatx80_rounding_precision(80, &fsx); set_float_rounding_mode(float_round_to_zero, &fsx); - set_floatx80_rounding_precision(80, &fsp); - set_float_rounding_mode(float_round_to_zero, &fsp); fpp_print = fp_print; fpp_is_snan = fp_is_snan; diff --git a/softfloat/softfloat.cpp b/softfloat/softfloat.cpp index 90a3bbaa..3c039e5f 100644 --- a/softfloat/softfloat.cpp +++ b/softfloat/softfloat.cpp @@ -3464,6 +3464,101 @@ floatx80 floatx80_move( floatx80 a, float_status *status ) #endif // End of addition for Previous +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is +| equal to the corresponding value `b', and 0 otherwise. The comparison is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +flag floatx80_eq( floatx80 a, floatx80 b, float_status *status ) +{ + if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) + && (uint64_t) ( extractFloatx80Frac( a )<<1 ) ) + || ( ( extractFloatx80Exp( b ) == 0x7FFF ) + && (uint64_t) ( extractFloatx80Frac( b )<<1 ) ) + ) { + if ( floatx80_is_signaling_nan( a ) + || floatx80_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid, status ); + } + return 0; + } + return + ( a.low == b.low ) + && ( ( a.high == b.high ) + || ( ( a.low == 0 ) + && ( (uint16_t) ( ( a.high | b.high )<<1 ) == 0 ) ) + ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is +| less than or equal to the corresponding value `b', and 0 otherwise. The +| comparison is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag floatx80_le( floatx80 a, floatx80 b, float_status *status ) +{ + flag aSign, bSign; + + if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) + && (uint64_t) ( extractFloatx80Frac( a )<<1 ) ) + || ( ( extractFloatx80Exp( b ) == 0x7FFF ) + && (uint64_t) ( extractFloatx80Frac( b )<<1 ) ) + ) { + float_raise( float_flag_invalid, status ); + return 0; + } + aSign = extractFloatx80Sign( a ); + bSign = extractFloatx80Sign( b ); + if ( aSign != bSign ) { + return + aSign + || ( ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + == 0 ); + } + return + aSign ? le128( b.high, b.low, a.high, a.low ) + : le128( a.high, a.low, b.high, b.low ); +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is +| less than the corresponding value `b', and 0 otherwise. The comparison +| is performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +flag floatx80_lt( floatx80 a, floatx80 b, float_status *status ) +{ + flag aSign, bSign; + + if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) + && (uint64_t) ( extractFloatx80Frac( a )<<1 ) ) + || ( ( extractFloatx80Exp( b ) == 0x7FFF ) + && (uint64_t) ( extractFloatx80Frac( b )<<1 ) ) + ) { + float_raise( float_flag_invalid, status ); + return 0; + } + aSign = extractFloatx80Sign( a ); + bSign = extractFloatx80Sign( b ); + if ( aSign != bSign ) { + return + aSign + && ( ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + != 0 ); + } + return + aSign ? lt128( b.high, b.low, a.high, a.low ) + : lt128( a.high, a.low, b.high, b.low ); + +} + + /*---------------------------------------------------------------------------- | Returns the result of converting the 64-bit two's complement integer `a' | to the extended double-precision floating-point format. The conversion diff --git a/softfloat/softfloat.h b/softfloat/softfloat.h index 17bc9377..5ae05c60 100644 --- a/softfloat/softfloat.h +++ b/softfloat/softfloat.h @@ -188,15 +188,14 @@ enum { | Software IEC/IEEE floating-point exception flags. *----------------------------------------------------------------------------*/ enum { - float_flag_invalid = 1, - float_flag_denormal = 2, - float_flag_divbyzero = 4, - float_flag_overflow = 8, - float_flag_underflow = 16, - float_flag_inexact = 32, - float_flag_signaling = 64 -// float_flag_input_denormal = 64, -// float_flag_output_denormal = 128 + float_flag_invalid = 0x01, + float_flag_denormal = 0x02, + float_flag_divbyzero = 0x04, + float_flag_overflow = 0x08, + float_flag_underflow = 0x10, + float_flag_inexact = 0x20, + float_flag_signaling = 0x40, + float_flag_decimal = 0x80 }; /*---------------------------------------------------------------------------- @@ -383,11 +382,12 @@ int8_t floatx80_to_int8(floatx80, float_status *status); #endif int32_t floatx80_to_int32_round_to_zero(floatx80, float_status *status); int64_t floatx80_to_int64(floatx80, float_status *status); -int64_t floatx80_to_int64_round_to_zero(floatx80, float_status *status); float32 floatx80_to_float32(floatx80, float_status *status); float64 floatx80_to_float64(floatx80, float_status *status); #ifdef SOFTFLOAT_68K floatx80 floatx80_to_floatx80( floatx80, float_status *status); +floatx80 floatdecimal_to_floatx80(floatx80, float_status *status); +floatx80 floatx80_to_floatdecimal(floatx80, int32_t*, float_status *status); #endif uint64_t extractFloatx80Frac( floatx80 a ); @@ -400,6 +400,10 @@ floatx80 floatx80_round_to_float64( floatx80, float_status *status ); floatx80 floatx80_round32( floatx80, float_status *status); floatx80 floatx80_round64( floatx80, float_status *status); +flag floatx80_eq( floatx80, floatx80, float_status *status); +flag floatx80_le( floatx80, floatx80, float_status *status); +flag floatx80_lt( floatx80, floatx80, float_status *status); + #ifdef SOFTFLOAT_68K flag floatx80_is_zero( floatx80 ); flag floatx80_is_infinity( floatx80 ); diff --git a/softfloat/softfloat_decimal.cpp b/softfloat/softfloat_decimal.cpp new file mode 100644 index 00000000..0de1f951 --- /dev/null +++ b/softfloat/softfloat_decimal.cpp @@ -0,0 +1,429 @@ +/*============================================================================ + +This C source file is an extension to the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2a. + +=============================================================================*/ + +#include + +#include "softfloat.h" +#include "softfloat-macros.h" +#include "softfloat/softfloat-specialize.h" + +/*---------------------------------------------------------------------------- +| Methods for converting decimal floats to binary extended precision floats. +*----------------------------------------------------------------------------*/ + +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; + + zExp = *aExp; + zSig0 = *aSig0; + zSig1 = *aSig1; + + zExp += bExp - 0x3FFE; + mul128To256(zSig0, zSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3); + zSig1 |= (zSig2 | zSig3) != 0; + if ( 0 < (int64_t) zSig0 ) { + shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 ); + --zExp; + } + *aExp = zExp; + *aSig0 = zSig0; + *aSig1 = zSig1; +} + +void div128by128(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; + uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3; + + zExp = *aExp; + zSig0 = *aSig0; + zSig1 = *aSig1; + + zExp -= bExp - 0x3FFE; + rem1 = 0; + if ( le128( bSig0, bSig1, zSig0, zSig1 ) ) { + shift128Right( zSig0, zSig1, 1, &zSig0, &zSig1 ); + ++zExp; + } + zSig0 = estimateDiv128To64( zSig0, zSig1, bSig0 ); + mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 ); + sub192( zSig0, zSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 ); + while ( (int64_t) rem0 < 0 ) { + --zSig0; + add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 ); + } + zSig1 = estimateDiv128To64( rem1, rem2, bSig0 ); + if ( ( zSig1 & 0x3FFF ) <= 4 ) { + mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 ); + sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 ); + while ( (int64_t) rem1 < 0 ) { + --zSig1; + add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 ); + } + zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); + } + + *aExp = zExp; + *aSig0 = zSig0; + *aSig1 = zSig1; +} + +/*---------------------------------------------------------------------------- +| Decimal to binary +*----------------------------------------------------------------------------*/ + +floatx80 floatdecimal_to_floatx80(floatx80 a, float_status *status) +{ + flag decSign, zSign, decExpSign, increment; + int32_t decExp, zExp, mExp, xExp, shiftCount; + uint64_t decSig, zSig0, zSig1, mSig0, mSig1, xSig0, xSig1; + + decSign = extractFloatx80Sign(a); + decExp = extractFloatx80Exp(a); + decSig = extractFloatx80Frac(a); + + if (decExp == 0x7FFF) return a; + + if (decExp == 0 && decSig == 0) return a; + + decExpSign = (decExp >> 14) & 1; + decExp &= 0x3FFF; + + shiftCount = countLeadingZeros64( decSig ); + zExp = 0x403E - shiftCount; + zSig0 = decSig << shiftCount; + zSig1 = 0; + zSign = decSign; + + mExp = 0x4002; + mSig0 = LIT64(0xA000000000000000); + mSig1 = 0; + xExp = 0x3FFF; + xSig0 = LIT64(0x8000000000000000); + + while (decExp) { + if (decExp & 1) { + mul128by128(&xExp, &xSig0, &xSig1, mExp, mSig0, mSig1); + } + mul128by128(&mExp, &mSig0, &mSig1, mExp, mSig0, mSig1); + decExp >>= 1; + } + + if (decExpSign) { + div128by128(&zExp, &zSig0, &zSig1, xExp, xSig0, xSig1); + } else { + mul128by128(&zExp, &zSig0, &zSig1, xExp, xSig0, xSig1); + } + + increment = ( (int64_t) zSig1 < 0 ); + if (status->float_rounding_mode != float_round_nearest_even) { + if (status->float_rounding_mode == float_round_to_zero) { + increment = 0; + } else { + if (zSign) { + increment = (status->float_rounding_mode == float_round_down) && zSig1; + } else { + increment = (status->float_rounding_mode == float_round_up) && zSig1; + } + } + } + if (zSig1) float_raise(float_flag_decimal, status); + + if (increment) { + ++zSig0; + if (zSig0 == 0) { + ++zExp; + zSig0 = LIT64(0x8000000000000000); + } else { + zSig0 &= ~ (((uint64_t) (zSig1<<1) == 0) & (status->float_rounding_mode == float_round_nearest_even)); + } + } else { + if ( zSig0 == 0 ) zExp = 0; + } + return packFloatx80( zSign, zExp, zSig0 ); + +} + +/*---------------------------------------------------------------------------- + | Binary to decimal + *----------------------------------------------------------------------------*/ + +floatx80 floatx80_to_floatdecimal(floatx80 a, int32_t *k, float_status *status) +{ + flag aSign; + int32_t aExp; + uint64_t aSig; + + flag decSign; + int32_t decExp, zExp, mExp, xExp; + uint64_t decSig, zSig0, zSig1, mSig0, mSig1, xSig0, xSig1; + + aSign = extractFloatx80Sign(a); + aExp = extractFloatx80Exp(a); + aSig = extractFloatx80Frac(a); + + if (aExp == 0x7FFF) { + if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status); + return a; + } + + if (aExp == 0) { + if (aSig == 0) return packFloatx80(aSign, 0, 0); + normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + } + + int32_t kfactor = *k; + + int32_t ilog, len; + + flag bSign; + + + + floatx80 b; + floatx80 c; + floatx80 one = int32_to_floatx80(1); + floatx80 log2 = packFloatx80(0, 0x3FFD, LIT64(0x9A209A84FBCFF798)); + floatx80 log2up1 = packFloatx80(0, 0x3FFD, LIT64(0x9A209A84FBCFF799)); + + + if (aExp < 0) { + ilog = -4933; + } else { + b = packFloatx80(0, 0x3FFF, aSig); + c = int32_to_floatx80(aExp - 0x3FFF); + b = floatx80_add(b, c, status); + b = floatx80_sub(b, one, status); + bSign = extractFloatx80Sign(b); + if (bSign) { + b = floatx80_mul(b, log2up1, status); + } else { + b = floatx80_mul(b, log2, status); + } + ilog = floatx80_to_int32(b, status); + } + + bool ictr = false; + +try_again: + //printf("ILOG = %i\n",ilog); + + if (kfactor > 0) { + if (kfactor > 17) { + kfactor = 17; + float_raise(float_flag_invalid, status); + } + len = kfactor; + } else { + len = ilog + 1 - kfactor; + if (len > 17) { + len = 17; + } + if (len < 1) { + len = 1; + } + } + + //printf("LEN = %i\n",len); + + if (kfactor <= 0 && kfactor > ilog) { + ilog = kfactor; + //printf("ILOG is kfactor = %i\n",ilog); + } + + flag lambda = 0; + int iscale = ilog + 1 - len; + + if (iscale < 0) { + lambda = 1; +#if 0 + if (iscale <= -4908) { // do we need this? + iscale += 24; + temp_for_a9 = 24; + } +#endif + iscale = -iscale; + } + + //printf("ISCALE = %i, LAMDA = %i\n",iscale,lambda); + + mExp = 0x4002; + mSig0 = LIT64(0xA000000000000000); + mSig1 = 0; + xExp = 0x3FFF; + xSig0 = LIT64(0x8000000000000000); + xSig1 = 0; + + while (iscale) { + if (iscale & 1) { + mul128by128(&xExp, &xSig0, &xSig1, mExp, mSig0, mSig1); + } + mul128by128(&mExp, &mSig0, &mSig1, mExp, mSig0, mSig1); + iscale >>= 1; + } + + zExp = aExp; + zSig0 = aSig; + zSig1 = 0; + + if (lambda) { + mul128by128(&zExp, &zSig0, &zSig1, xExp, xSig0, xSig1); + } else { + div128by128(&zExp, &zSig0, &zSig1, xExp, xSig0, xSig1); + } + if (zSig1) zSig0 |= 1; + + floatx80 z = packFloatx80(aSign, zExp, zSig0); + z = floatx80_round_to_int(z, status); + zSig0 = extractFloatx80Frac(z); + zExp = extractFloatx80Exp(z); + zSig1 = 0; + + if (ictr == false) { + int lentemp = len - 1; + + mExp = 0x4002; + mSig0 = LIT64(0xA000000000000000); + mSig1 = 0; + xExp = 0x3FFF; + xSig0 = LIT64(0x8000000000000000); + xSig1 = 0; + + while (lentemp) { + if (lentemp & 1) { + mul128by128(&xExp, &xSig0, &xSig1, mExp, mSig0, mSig1); + } + mul128by128(&mExp, &mSig0, &mSig1, mExp, mSig0, mSig1); + lentemp >>= 1; + } + + zSig0 = extractFloatx80Frac(z); + zExp = extractFloatx80Exp(z); + + if (zExp < xExp || ((zExp == xExp) && lt128(zSig0, 0, xSig0, xSig1))) { // z < x + ilog -= 1; + ictr = true; + mul128by128(&xExp, &xSig0, &xSig1, 0x4002, LIT64(0xA000000000000000), 0); + goto try_again; + } + + mul128by128(&xExp, &xSig0, &xSig1, 0x4002, LIT64(0xA000000000000000), 0); + + if (zExp > xExp || ((zExp == xExp) && lt128(xSig0, xSig1, zSig0, 0))) { // z > x + ilog += 1; + ictr = true; + goto try_again; + } + } else { + int lentemp = len; + + mExp = 0x4002; + mSig0 = LIT64(0xA000000000000000); + mSig1 = 0; + xExp = 0x3FFF; + xSig0 = LIT64(0x8000000000000000); + xSig1 = 0; + + while (lentemp) { + if (lentemp & 1) { + mul128by128(&xExp, &xSig0, &xSig1, mExp, mSig0, mSig1); + } + mul128by128(&mExp, &mSig0, &mSig1, mExp, mSig0, mSig1); + lentemp >>= 1; + } + + if (eq128(zSig0, 0, xSig0, xSig1)) { + div128by128(&zExp, &zSig0, &zSig1, 0x4002, LIT64(0xA000000000000000), 0); + ilog += 1; + len += 1; + mul128by128(&xExp, &xSig0, &xSig1, 0x4002, LIT64(0xA000000000000000), 0); + } + } + + if (zSig1) zSig0 |= 1; + + z = packFloatx80(0, zExp, zSig0); + + decSign = aSign; + decSig = floatx80_to_int64(z, status); + decExp = (ilog < 0) ? -ilog : ilog; + if (decExp > 999) { + float_raise(float_flag_invalid, status); + } + if (ilog < 0) decExp |= 0x4000; + + *k = len; + + return packFloatx80(decSign, decExp, decSig); +#if 0 + printf("abs(Yint) = %s\n",fp_print(&zint)); + + uae_u64 significand = floatx80_to_int64(zint); + + printf("Mantissa = %lli\n",significand); + + printf("Exponent = %i\n",ilog); + + uae_s32 exp = ilog; + + uae_u32 pack_exp = 0; // packed exponent + uae_u32 pack_exp4 = 0; + uae_u32 pack_int = 0; // packed integer part + uae_u64 pack_frac = 0; // packed fraction + uae_u32 pack_se = 0; // sign of packed exponent + uae_u32 pack_sm = 0; // sign of packed significand + + if (exp < 0) { + exp = -exp; + pack_se = 1; + } + + uae_u64 digit; + pack_frac = 0; + while (len > 0) { + len--; + digit = significand % 10; + significand /= 10; + if (len == 0) { + pack_int = digit; + } else { + pack_frac |= digit << (64 - len * 4); + } + } + printf("PACKED FRACTION = %02x.%16llx\n",pack_int, pack_frac); + + if (exp > 999) { + digit = exp / 1000; + exp -= digit * 1000; + pack_exp4 = digit; + // OPERR + } + digit = exp / 100; + exp -= digit * 100; + pack_exp = digit << 8; + digit = exp / 10; + exp -= digit * 10; + pack_exp |= digit << 4; + pack_exp |= exp; + + pack_sm = aSign; + + wrd[0] = pack_exp << 16; + wrd[0] |= pack_exp4 << 12; + wrd[0] |= pack_int; + wrd[0] |= pack_se ? 0x40000000 : 0; + wrd[0] |= pack_sm ? 0x80000000 : 0; + + wrd[1] = pack_frac >> 32; + wrd[2] = pack_frac & 0xffffffff; + + printf("PACKED = %08x %08x %08x\n",wrd[0],wrd[1],wrd[2]); +#endif +}