diff options
| author | 2013-09-28 01:57:53 +0000 | |
|---|---|---|
| committer | 2013-09-28 01:57:53 +0000 | |
| commit | 3c4e5a1e36b7c9264fc1599c6a916d9bd21a364d (patch) | |
| tree | a1aa686d1aac33d4e84e8871fa382c40926a45c3 /src/lib/softfloat | |
| parent | 18da24faf4df6cf24e5eabe69ab4117adf780508 (diff) | |
m68k: add FSCALE instruction used by e.g. SimCity 2000 [R. Belmont]
Diffstat (limited to 'src/lib/softfloat')
| -rwxr-xr-x | src/lib/softfloat/fsincos.c | 80 | ||||
| -rw-r--r-- | src/lib/softfloat/fyl2x.c | 3 | ||||
| -rw-r--r-- | src/lib/softfloat/softfloat-specialize | 2 | ||||
| -rw-r--r-- | src/lib/softfloat/softfloat.h | 9 |
4 files changed, 84 insertions, 10 deletions
diff --git a/src/lib/softfloat/fsincos.c b/src/lib/softfloat/fsincos.c index 084c753c231..889bb566793 100755 --- a/src/lib/softfloat/fsincos.c +++ b/src/lib/softfloat/fsincos.c @@ -563,3 +563,83 @@ float128 OddPoly(float128 x, float128 *arr, unsigned n) { return float128_mul(x, EvenPoly(x, arr, n)); } + +/*---------------------------------------------------------------------------- +| Scales extended double-precision floating-point value in operand `a' by +| value `b'. The function truncates the value in the second operand 'b' to +| an integral value and adds that value to the exponent of the operand 'a'. +| The operation performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +extern floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ); + +floatx80 floatx80_scale(floatx80 a, floatx80 b) +{ + sbits32 aExp, bExp; + bits64 aSig, bSig; + + // handle unsupported extended double-precision floating encodings +/* if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) + { + float_raise(float_flag_invalid); + return floatx80_default_nan; + }*/ + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + int aSign = extractFloatx80Sign(a); + bSig = extractFloatx80Frac(b); + bExp = extractFloatx80Exp(b); + int bSign = extractFloatx80Sign(b); + + if (aExp == 0x7FFF) { + if ((bits64) (aSig<<1) || ((bExp == 0x7FFF) && (bits64) (bSig<<1))) + { + return propagateFloatx80NaN(a, b); + } + if ((bExp == 0x7FFF) && bSign) { + float_raise(float_flag_invalid); + return floatx80_default_nan; + } + if (bSig && (bExp == 0)) float_raise(float_flag_denormal); + return a; + } + if (bExp == 0x7FFF) { + if ((bits64) (bSig<<1)) return propagateFloatx80NaN(a, b); + if ((aExp | aSig) == 0) { + if (! bSign) { + float_raise(float_flag_invalid); + return floatx80_default_nan; + } + return a; + } + if (aSig && (aExp == 0)) float_raise(float_flag_denormal); + if (bSign) return packFloatx80(aSign, 0, 0); + return packFloatx80(aSign, 0x7FFF, U64(0x8000000000000000)); + } + if (aExp == 0) { + if (aSig == 0) return a; + float_raise(float_flag_denormal); + normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + } + if (bExp == 0) { + if (bSig == 0) return a; + float_raise(float_flag_denormal); + normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + } + + if (bExp > 0x400E) { + /* generate appropriate overflow/underflow */ + return roundAndPackFloatx80(80, aSign, + bSign ? -0x3FFF : 0x7FFF, aSig, 0); + } + if (bExp < 0x3FFF) return a; + + int shiftCount = 0x403E - bExp; + bSig >>= shiftCount; + sbits32 scale = bSig; + if (bSign) scale = -scale; /* -32768..32767 */ + return + roundAndPackFloatx80(80, aSign, aExp+scale, aSig, 0); +} diff --git a/src/lib/softfloat/fyl2x.c b/src/lib/softfloat/fyl2x.c index 9cda55fa39a..3a04cc79117 100644 --- a/src/lib/softfloat/fyl2x.c +++ b/src/lib/softfloat/fyl2x.c @@ -32,9 +32,6 @@ these four paragraphs for those parts of this code that are retained. //#include "softfloat-specialize" #include "fpu_constant.h" -// FIXME: -#define float_flag_denormal float_flag_invalid - static const floatx80 floatx80_log10_2 = packFloatx80(0, 0x3ffd, U64(0x9a209a84fbcff798)); static const floatx80 floatx80_ln_2 = packFloatx80(0, 0x3ffe, U64(0xb17217f7d1cf79ac)); static const floatx80 floatx80_one = packFloatx80(0, 0x3fff, U64(0x8000000000000000)); diff --git a/src/lib/softfloat/softfloat-specialize b/src/lib/softfloat/softfloat-specialize index 9993f3fd2b3..9865c9dda82 100644 --- a/src/lib/softfloat/softfloat-specialize +++ b/src/lib/softfloat/softfloat-specialize @@ -311,7 +311,7 @@ static floatx80 commonNaNToFloatx80( commonNaNT a ) | `b' is a signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) +floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) { flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; diff --git a/src/lib/softfloat/softfloat.h b/src/lib/softfloat/softfloat.h index 260c4810332..77abbdb2984 100644 --- a/src/lib/softfloat/softfloat.h +++ b/src/lib/softfloat/softfloat.h @@ -89,11 +89,8 @@ enum { *----------------------------------------------------------------------------*/ extern int8 float_exception_flags; enum { - float_flag_inexact = 1, - float_flag_underflow = 2, - float_flag_overflow = 4, - float_flag_divbyzero = 8, - float_flag_invalid = 16 + float_flag_invalid = 0x01, float_flag_denormal = 0x02, float_flag_divbyzero = 0x04, float_flag_overflow = 0x08, + float_flag_underflow = 0x10, float_flag_inexact = 0x20 }; /*---------------------------------------------------------------------------- @@ -202,6 +199,7 @@ float64 floatx80_to_float64( floatx80 ); #ifdef FLOAT128 float128 floatx80_to_float128( floatx80 ); #endif +floatx80 floatx80_scale(floatx80 a, floatx80 b); /*---------------------------------------------------------------------------- | Packs the sign `zSign', exponent `zExp', and significand `zSig' into an @@ -459,5 +457,4 @@ INLINE float128 return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); } - #endif |
