summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/softfloat
diff options
context:
space:
mode:
author R. Belmont <rb6502@users.noreply.github.com>2013-09-28 01:57:53 +0000
committer R. Belmont <rb6502@users.noreply.github.com>2013-09-28 01:57:53 +0000
commit3c4e5a1e36b7c9264fc1599c6a916d9bd21a364d (patch)
treea1aa686d1aac33d4e84e8871fa382c40926a45c3 /src/lib/softfloat
parent18da24faf4df6cf24e5eabe69ab4117adf780508 (diff)
m68k: add FSCALE instruction used by e.g. SimCity 2000 [R. Belmont]
Diffstat (limited to 'src/lib/softfloat')
-rwxr-xr-xsrc/lib/softfloat/fsincos.c80
-rw-r--r--src/lib/softfloat/fyl2x.c3
-rw-r--r--src/lib/softfloat/softfloat-specialize2
-rw-r--r--src/lib/softfloat/softfloat.h9
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