From 70718f506e0f215b73beb08c645ab30ed1002822 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 9 Apr 2012 06:03:25 +0000 Subject: [PATCH] SoftFloat changes for last CL and x07 tape format from MESS (no whatsnew) --- .gitattributes | 3 + src/lib/formats/x07_cas.c | 170 ++++++++++++ src/lib/formats/x07_cas.h | 16 ++ src/lib/softfloat/fyl2x.c | 490 ++++++++++++++++++++++++++++++++++ src/lib/softfloat/softfloat.c | 4 +- src/lib/softfloat/softfloat.h | 8 + 6 files changed, 690 insertions(+), 1 deletion(-) create mode 100644 src/lib/formats/x07_cas.c create mode 100644 src/lib/formats/x07_cas.h create mode 100644 src/lib/softfloat/fyl2x.c diff --git a/.gitattributes b/.gitattributes index 76d67d0c634..ceea9d8bfeb 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1601,6 +1601,8 @@ src/lib/formats/vtech1_dsk.c svneol=native#text/plain src/lib/formats/vtech1_dsk.h svneol=native#text/plain src/lib/formats/wavfile.c svneol=native#text/plain src/lib/formats/wavfile.h svneol=native#text/plain +src/lib/formats/x07_cas.c svneol=native#text/plain +src/lib/formats/x07_cas.h svneol=native#text/plain src/lib/formats/x1_tap.c svneol=native#text/plain src/lib/formats/x1_tap.h svneol=native#text/plain src/lib/formats/z80ne_dsk.c svneol=native#text/plain @@ -1800,6 +1802,7 @@ src/lib/libjpeg/libjpeg.txt svneol=native#text/plain src/lib/softfloat/README.txt svneol=native#text/plain src/lib/softfloat/fpu_constant.h svneol=native#text/plain src/lib/softfloat/fsincos.c svneol=native#text/plain +src/lib/softfloat/fyl2x.c svneol=native#text/plain src/lib/softfloat/mamesf.h svneol=native#text/plain src/lib/softfloat/milieu.h svneol=native#text/plain src/lib/softfloat/softfloat-macros svneol=native#text/plain diff --git a/src/lib/formats/x07_cas.c b/src/lib/formats/x07_cas.c new file mode 100644 index 00000000000..8765dea4f61 --- /dev/null +++ b/src/lib/formats/x07_cas.c @@ -0,0 +1,170 @@ +/******************************************************************** + + Support for Canon X-07 cassette images + +********************************************************************/ + +#include "x07_cas.h" + +#define WAVEENTRY_LOW -32768 +#define WAVEENTRY_HIGH 32767 + +#define X07_WAV_FREQUENCY 4800 +#define X07_TIMER_FREQUENCY 1200 +#define X07_BIT_LENGTH (X07_WAV_FREQUENCY/X07_TIMER_FREQUENCY) +#define X07_HEADER_BYTES 16 + +// image size +static int x07_image_size; + +static int x07_put_samples(INT16 *buffer, int sample_pos, int count, int level) +{ + if (buffer) + { + for (int i=0; i>i) & 0x01); + + /* stop */ + samples += x07_output_bit (buffer, sample_pos + samples, 1); + samples += x07_output_bit (buffer, sample_pos + samples, 1); + samples += x07_output_bit (buffer, sample_pos + samples, 1); + + return samples; +} + +static int x07_handle_cassette(INT16 *buffer, const UINT8 *bytes) +{ + int sample_count = 0; + int img_start = 0; + + /* start */ + for (int i=0; i>15; + +} + +/*---------------------------------------------------------------------------- +| Takes extended double-precision floating-point NaN `a' and returns the +| appropriate NaN result. If `a' is a signaling NaN, the invalid exception +| is raised. +*----------------------------------------------------------------------------*/ + +INLINE floatx80 propagateFloatx80NaNOneArg(floatx80 a) +{ + if (floatx80_is_signaling_nan(a)) + float_raise(float_flag_invalid); + + a.low |= U64(0xC000000000000000); + + return a; +} + +/*---------------------------------------------------------------------------- +| Normalizes the subnormal extended double-precision floating-point value +| represented by the denormalized significand `aSig'. The normalized exponent +| and significand are stored at the locations pointed to by `zExpPtr' and +| `zSigPtr', respectively. +*----------------------------------------------------------------------------*/ + +INLINE void normalizeFloatx80Subnormal(UINT64 aSig, INT32 *zExpPtr, UINT64 *zSigPtr) +{ + int shiftCount = countLeadingZeros64(aSig); + *zSigPtr = aSig< C * u q(u) = > C * u + // -- 2k -- 2k+1 + // k=0 k=0 + // + // 1+u 2 + // 1/2 ln --- ~ u * [ p(u) + u * q(u) ] + // 1-u + // +*/ + return OddPoly(x1, ln_arr, L2_ARR_SIZE); +} + +/* required sqrt(2)/2 < x < sqrt(2) */ +static float128 poly_l2(float128 x) +{ + /* using float128 for approximation */ + float128 x_p1 = float128_add(x, float128_one); + float128 x_m1 = float128_sub(x, float128_one); + x = float128_div(x_m1, x_p1); + x = poly_ln(x); + x = float128_mul(x, float128_ln2inv2); + return x; +} + +static float128 poly_l2p1(float128 x) +{ + /* using float128 for approximation */ + float128 x_p2 = float128_add(x, float128_two); + x = float128_div(x, x_p2); + x = poly_ln(x); + x = float128_mul(x, float128_ln2inv2); + return x; +} + +// ================================================= +// FYL2X Compute y * log (x) +// 2 +// ================================================= + +// +// Uses the following identities: +// +// 1. ---------------------------------------------------------- +// ln(x) +// log (x) = -------, ln (x*y) = ln(x) + ln(y) +// 2 ln(2) +// +// 2. ---------------------------------------------------------- +// 1+u x-1 +// ln (x) = ln -----, when u = ----- +// 1-u x+1 +// +// 3. ---------------------------------------------------------- +// 3 5 7 2n+1 +// 1+u u u u u +// ln ----- = 2 [ u + --- + --- + --- + ... + ------ + ... ] +// 1-u 3 5 7 2n+1 +// + +static floatx80 fyl2x(floatx80 a, floatx80 b) +{ + UINT64 aSig = extractFloatx80Frac(a); + INT32 aExp = extractFloatx80Exp(a); + int aSign = extractFloatx80Sign(a); + UINT64 bSig = extractFloatx80Frac(b); + INT32 bExp = extractFloatx80Exp(b); + int bSign = extractFloatx80Sign(b); + + int zSign = bSign ^ 1; + + if (aExp == 0x7FFF) { + if ((UINT64) (aSig<<1) + || ((bExp == 0x7FFF) && (UINT64) (bSig<<1))) + { + return propagateFloatx80NaN(a, b); + } + if (aSign) + { +invalid: + float_raise(float_flag_invalid); + return floatx80_default_nan; + } + else { + if (bExp == 0) { + if (bSig == 0) goto invalid; + float_raise(float_flag_denormal); + } + return packFloatx80(bSign, 0x7FFF, U64(0x8000000000000000)); + } + } + if (bExp == 0x7FFF) + { + if ((UINT64) (bSig<<1)) return propagateFloatx80NaN(a, b); + if (aSign && (UINT64)(aExp | aSig)) goto invalid; + if (aSig && (aExp == 0)) + float_raise(float_flag_denormal); + if (aExp < 0x3FFF) { + return packFloatx80(zSign, 0x7FFF, U64(0x8000000000000000)); + } + if (aExp == 0x3FFF && ((UINT64) (aSig<<1) == 0)) goto invalid; + return packFloatx80(bSign, 0x7FFF, U64(0x8000000000000000)); + } + if (aExp == 0) { + if (aSig == 0) { + if ((bExp | bSig) == 0) goto invalid; + float_raise(float_flag_divbyzero); + return packFloatx80(zSign, 0x7FFF, U64(0x8000000000000000)); + } + if (aSign) goto invalid; + float_raise(float_flag_denormal); + normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + } + if (aSign) goto invalid; + if (bExp == 0) { + if (bSig == 0) { + if (aExp < 0x3FFF) return packFloatx80(zSign, 0, 0); + return packFloatx80(bSign, 0, 0); + } + float_raise(float_flag_denormal); + normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + } + if (aExp == 0x3FFF && ((UINT64) (aSig<<1) == 0)) + return packFloatx80(bSign, 0, 0); + + float_raise(float_flag_inexact); + + int ExpDiff = aExp - 0x3FFF; + aExp = 0; + if (aSig >= SQRT2_HALF_SIG) { + ExpDiff++; + aExp--; + } + + /* ******************************** */ + /* using float128 for approximation */ + /* ******************************** */ + + UINT64 zSig0, zSig1; + shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); + float128 x = packFloat128(0, aExp+0x3FFF, zSig0, zSig1); + x = poly_l2(x); + x = float128_add(x, int64_to_float128((INT64) ExpDiff)); + return floatx80_mul(b, float128_to_floatx80(x)); +} + +// ================================================= +// FYL2XP1 Compute y * log (x + 1) +// 2 +// ================================================= + +// +// Uses the following identities: +// +// 1. ---------------------------------------------------------- +// ln(x) +// log (x) = ------- +// 2 ln(2) +// +// 2. ---------------------------------------------------------- +// 1+u x +// ln (x+1) = ln -----, when u = ----- +// 1-u x+2 +// +// 3. ---------------------------------------------------------- +// 3 5 7 2n+1 +// 1+u u u u u +// ln ----- = 2 [ u + --- + --- + --- + ... + ------ + ... ] +// 1-u 3 5 7 2n+1 +// + +floatx80 fyl2xp1(floatx80 a, floatx80 b) +{ + INT32 aExp, bExp; + UINT64 aSig, bSig, zSig0, zSig1, zSig2; + int aSign, bSign; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + bSig = extractFloatx80Frac(b); + bExp = extractFloatx80Exp(b); + bSign = extractFloatx80Sign(b); + int zSign = aSign ^ bSign; + + if (aExp == 0x7FFF) { + if ((UINT64) (aSig<<1) + || ((bExp == 0x7FFF) && (UINT64) (bSig<<1))) + { + return propagateFloatx80NaN(a, b); + } + if (aSign) + { +invalid: + float_raise(float_flag_invalid); + return floatx80_default_nan; + } + else { + if (bExp == 0) { + if (bSig == 0) goto invalid; + float_raise(float_flag_denormal); + } + return packFloatx80(bSign, 0x7FFF, U64(0x8000000000000000)); + } + } + if (bExp == 0x7FFF) + { + if ((UINT64) (bSig<<1)) + return propagateFloatx80NaN(a, b); + + if (aExp == 0) { + if (aSig == 0) goto invalid; + float_raise(float_flag_denormal); + } + + return packFloatx80(zSign, 0x7FFF, U64(0x8000000000000000)); + } + if (aExp == 0) { + if (aSig == 0) { + if (bSig && (bExp == 0)) float_raise(float_flag_denormal); + return packFloatx80(zSign, 0, 0); + } + float_raise(float_flag_denormal); + normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + } + if (bExp == 0) { + if (bSig == 0) return packFloatx80(zSign, 0, 0); + float_raise(float_flag_denormal); + normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + } + + float_raise(float_flag_inexact); + + if (aSign && aExp >= 0x3FFF) + return a; + + if (aExp >= 0x3FFC) // big argument + { + return fyl2x(floatx80_add(a, floatx80_one), b); + } + + // handle tiny argument + if (aExp < EXP_BIAS-70) + { + // first order approximation, return (a*b)/ln(2) + INT32 zExp = aExp + FLOAT_LN2INV_EXP - 0x3FFE; + + mul128By64To192(FLOAT_LN2INV_HI, FLOAT_LN2INV_LO, aSig, &zSig0, &zSig1, &zSig2); + if (0 < (INT64) zSig0) { + shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); + --zExp; + } + + zExp = zExp + bExp - 0x3FFE; + mul128By64To192(zSig0, zSig1, bSig, &zSig0, &zSig1, &zSig2); + if (0 < (INT64) zSig0) { + shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); + --zExp; + } + + return + roundAndPackFloatx80(80, aSign ^ bSign, zExp, zSig0, zSig1); + } + + /* ******************************** */ + /* using float128 for approximation */ + /* ******************************** */ + + shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); + float128 x = packFloat128(aSign, aExp, zSig0, zSig1); + x = poly_l2p1(x); + return floatx80_mul(b, float128_to_floatx80(x)); +} + +floatx80 floatx80_flognp1(floatx80 a) +{ + return fyl2xp1(a, floatx80_ln_2); +} + +floatx80 floatx80_flogn(floatx80 a) +{ + return fyl2x(a, floatx80_ln_2); +} + +floatx80 floatx80_flog2(floatx80 a) +{ + return fyl2x(a, floatx80_one); +} + +floatx80 floatx80_flog10(floatx80 a) +{ + return fyl2x(a, floatx80_log10_2); +} diff --git a/src/lib/softfloat/softfloat.c b/src/lib/softfloat/softfloat.c index f607feb27db..fe0137787bc 100644 --- a/src/lib/softfloat/softfloat.c +++ b/src/lib/softfloat/softfloat.c @@ -524,7 +524,9 @@ static void | Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ -static floatx80 +// roundAndPackFloatx80 is now also used in fyl2x.c + +/* static */ floatx80 roundAndPackFloatx80( int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ) diff --git a/src/lib/softfloat/softfloat.h b/src/lib/softfloat/softfloat.h index 642daa901d6..9e664c85bc0 100644 --- a/src/lib/softfloat/softfloat.h +++ b/src/lib/softfloat/softfloat.h @@ -246,6 +246,14 @@ int floatx80_fsin(floatx80 &a); int floatx80_fcos(floatx80 &a); int floatx80_ftan(floatx80 &a); +floatx80 floatx80_flognp1(floatx80 a); +floatx80 floatx80_flogn(floatx80 a); +floatx80 floatx80_flog2(floatx80 a); +floatx80 floatx80_flog10(floatx80 a); + +// roundAndPackFloatx80 used to be in softfloat-round-pack, is now in softfloat.c +floatx80 roundAndPackFloatx80(int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1); + #endif #ifdef FLOAT128