]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
FPU update.
authorToni Wilen <twilen@winuae.net>
Tue, 31 Jan 2017 19:46:39 +0000 (21:46 +0200)
committerToni Wilen <twilen@winuae.net>
Tue, 31 Jan 2017 19:46:39 +0000 (21:46 +0200)
fpp.cpp
fpp_native.cpp
fpp_softfloat.cpp
include/fpp.h
include/newcpu.h
softfloat/softfloat.cpp
softfloat/softfloat.h

diff --git a/fpp.cpp b/fpp.cpp
index e7bd149e70ea81f51a8094bb66152bae95ef6cbc..af152c1e4189348cb9fca760df1cf792343fbdba 100644 (file)
--- a/fpp.cpp
+++ b/fpp.cpp
@@ -105,6 +105,7 @@ FPP_AB fpp_scale;
 FPP_AB fpp_sub;
 FPP_AB fpp_sgldiv;
 FPP_AB fpp_sglmul;
+FPP_AB fpp_cmp;
 
 #define DEBUG_FPP 0
 #define EXCEPTION_FPP 1
@@ -308,15 +309,6 @@ static void from_exten(fpdata *fpd, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wr
 #define FPSR_QUOT_SIGN  0x00800000
 #define FPSR_QUOT_LSB   0x007F0000
 
-#define FPSR_BSUN       0x00008000
-#define FPSR_SNAN       0x00004000
-#define FPSR_OPERR      0x00002000
-#define FPSR_OVFL       0x00001000
-#define FPSR_UNFL       0x00000800
-#define FPSR_DZ         0x00000400
-#define FPSR_INEX2      0x00000200
-#define FPSR_INEX1      0x00000100
-
 #define FPSR_AE_IOP     0x00000080
 #define FPSR_AE_OVFL    0x00000040
 #define FPSR_AE_UNFL    0x00000020
@@ -324,7 +316,7 @@ static void from_exten(fpdata *fpd, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wr
 #define FPSR_AE_INEX    0x00000008
 
 
-static void fpsr_set_exception(uae_u32 exception)
+void fpsr_set_exception(uae_u32 exception)
 {
     regs.fpsr |= exception;
 }
@@ -347,26 +339,28 @@ static void fpsr_check_exception(void)
         write_log (_T("FPU exception: FPSR: %08x, FPCR: %04x (vector: %d)!\n"), regs.fpsr, regs.fpcr, vector);
     }
 }
+
+
 static void fpsr_set_result(fpdata *result)
 {
-    regs.fp_result = *result;
-    
-    // condition code byte
+#ifdef JIT
+       regs.fp_result = *result;
+#endif
+       // condition code byte
     regs.fpsr &= 0x00fffff8; // clear cc
-    if (fpp_is_nan (&regs.fp_result)) {
+    if (fpp_is_nan (result)) {
         regs.fpsr |= FPSR_CC_NAN;
+           // check if result is signaling nan
+               if (fpp_is_snan(result))
+                       regs.fpsr |= FPSR_SNAN;
     } else {
-        if (fpp_is_zero(&regs.fp_result))
+        if (fpp_is_zero(result))
             regs.fpsr |= FPSR_CC_Z;
-        if (fpp_is_infinity (&regs.fp_result))
+        if (fpp_is_infinity (result))
             regs.fpsr |= FPSR_CC_I;
     }
-    if (fpp_is_neg(&regs.fp_result))
+    if (fpp_is_neg(result))
         regs.fpsr |= FPSR_CC_N;
-    
-    // check if result is signaling nan
-    if (fpp_is_snan(&regs.fp_result))
-        regs.fpsr |= FPSR_SNAN;
 }
 static void fpsr_clear_status(void)
 {
@@ -929,8 +923,6 @@ static void fpu_null (void)
        regs.fpcr = 0;
        regs.fpsr = 0;
        regs.fpiar = 0;
-       fpset(&regs.fp_result, 1);
-       fpclear (&regs.fp_result);
        for (int i = 0; i < 8; i++)
                fpnan (&regs.fp[i]);
 }
@@ -1607,11 +1599,9 @@ STATIC_INLINE int get_fp_ad (uae_u32 opcode, uae_u32 * ad)
 
 int fpp_cond (int condition)
 {
-       int NotANumber, Z, N;
-
-       NotANumber = fpp_is_nan(&regs.fp_result);
-       N = fpp_is_neg(&regs.fp_result);
-       Z = fpp_is_zero(&regs.fp_result);
+       int NotANumber = (regs.fpsr & FPSR_CC_NAN) != 0;
+       int N = (regs.fpsr & FPSR_CC_N) != 0;
+       int Z = (regs.fpsr & FPSR_CC_Z) != 0;
 
     if ((condition & 0x10) && NotANumber) {
         if (fpsr_set_bsun())
@@ -2419,12 +2409,9 @@ static bool arithmetic(fpdata *src, int reg, int extra)
                        break;
                case 0x38: /* FCMP */
                {
-                       fpdata t = *dst;
-                       uae_u32 status = regs.fpsr;
-                       fpp_sub(&t, src);
-                       fpsr_clear_status();
-                       fpp_set_fpsr(status);
-                       fpsr_set_result(&t);
+                       fpdata v = *dst;
+                       fpp_cmp(&v, src);
+                       fpsr_set_result(&v);
                        return true;
                }
                case 0x3a: /* FTST */
@@ -2754,7 +2741,6 @@ void fpu_reset (void)
 
        regs.fpcr = regs.fpsr = regs.fpiar = 0;
        regs.fpu_exp_state = 0;
-       fpset (&regs.fp_result, 1);
        fpsr_make_status();
        fpux_restore (NULL);
 }
index 3611969e4d1fced361ad83fef22bf69395dbdd89..87455467ab98fd078531bb4e881aa0425e7890e4 100644 (file)
@@ -121,6 +121,8 @@ static const double twoto32 = 4294967296.0;
 #define        FPCR_PRECISION_DOUBLE   0x00000080
 #define FPCR_PRECISION_EXTENDED        0x00000000
 
+static struct float_status fs;
+
 #if defined(CPU_i386) || defined(CPU_x86_64)
 
 /* The main motivation for dynamically creating an x86(-64) function in
@@ -244,15 +246,15 @@ static void fp_get_status(uae_u32 *status)
     int exp_flags = fetestexcept(FE_ALL_EXCEPT);
     if (exp_flags) {
         if (exp_flags & FE_INEXACT)
-            *status |= 0x0200;
+            *status |= FPSR_INEX2;
         if (exp_flags & FE_DIVBYZERO)
-            *status |= 0x0400;
+            *status |= FPSR_DZ;
         if (exp_flags & FE_UNDERFLOW)
-            *status |= 0x0800;
+            *status |= FPSR_UNFL;
         if (exp_flags & FE_OVERFLOW)
-            *status |= 0x1000;
+            *status |= FPSR_OVFL;
         if (exp_flags & FE_INVALID)
-            *status |= 0x2000;
+            *status |= FPSR_OPERR;
     }
 }
 
@@ -300,11 +302,13 @@ static bool fp_is_neg(fpdata *fpd)
 }
 static bool fp_is_denormal(fpdata *fpd)
 {
-    return (isnormal(fpd->fp) == 0); /* FIXME: how to differ denormal/unnormal? */
+    return false;
+       //return (isnormal(fpd->fp) == 0); /* FIXME: how to differ denormal/unnormal? */
 }
 static bool fp_is_unnormal(fpdata *fpd)
 {
-    return (isnormal(fpd->fp) == 0); /* FIXME: how to differ denormal/unnormal? */
+       return false;
+    //return (isnormal(fpd->fp) == 0); /* FIXME: how to differ denormal/unnormal? */
 }
 
 /* Functions for converting between float formats */
@@ -438,6 +442,13 @@ static void fp_from_exten_x(fpdata *fpd, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *
 #else // if !USE_LONG_DOUBLE
 static void fp_to_exten_x(fpdata *fpd, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
 {
+#if 1
+       floatx80 fx80;
+       fx80.high = wrd1 >> 16;
+       fx80.low = (((uae_u64)wrd2) << 32) | wrd3;
+       float64 f = floatx80_to_float64(fx80, &fs);
+       fp_to_double_x(fpd, f >> 32, (uae_u32)f);
+#else
     double frac;
     if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) {
         fpd->fp = (wrd1 & 0x80000000) ? -0.0 : +0.0;
@@ -447,9 +458,18 @@ static void fp_to_exten_x(fpdata *fpd, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
     if (wrd1 & 0x80000000)
         frac = -frac;
     fpd->fp = ldexp (frac, ((wrd1 >> 16) & 0x7fff) - 16383);
+#endif
 }
 static void fp_from_exten_x(fpdata *fpd, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3)
 {
+#if 1
+       uae_u32 w1, w2;
+       fp_from_double_x(fpd, &w1, &w2);
+       floatx80 f = float64_to_floatx80(((uae_u64)w1 << 32) | w2, &fs);
+       *wrd1 = f.high << 16;
+       *wrd2 = f.low >> 32;
+       *wrd3 = (uae_u32)f.low;
+#else
     int expon;
     double frac;
     fptype v;
@@ -476,6 +496,7 @@ static void fp_from_exten_x(fpdata *fpd, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *
     *wrd1 |= (((expon + 16383 - 1) & 0x7fff) << 16);
     *wrd2 = (uae_u32) (frac * twoto32);
     *wrd3 = (uae_u32) ((frac * twoto32 - *wrd2) * twoto32);
+#endif
 }
 #endif // !USE_LONG_DOUBLE
 
@@ -489,10 +510,34 @@ static uae_s64 fp_to_int(fpdata *src, int size)
     };
 
        fptype fp = src->fp;
-       if (fp < fxsizes[size * 2 + 0])
+       if (fp_is_nan(src)) {
+               uae_u32 w1, w2, w3;
+               fp_from_exten_x(src, &w1, &w2, &w3);
+               uae_s64 v = 0;
+               fpsr_set_exception(FPSR_OPERR);
+               // return mantissa
+               switch (size)
+               {
+                       case 0:
+                       v = w2 >> 24;
+                       break;
+                       case 1:
+                       v = w2 >> 16;
+                       break;
+                       case 2:
+                       v = w2 >> 0;
+                       break;
+               }
+               return v;
+       }
+       if (fp < fxsizes[size * 2 + 0]) {
                fp = fxsizes[size * 2 + 0];
-       if (fp > fxsizes[size * 2 + 1])
+               fpsr_set_exception(FPSR_OPERR);
+       }
+       if (fp > fxsizes[size * 2 + 1]) {
                fp = fxsizes[size * 2 + 1];
+               fpsr_set_exception(FPSR_OPERR);
+       }
 #ifdef USE_HOST_ROUNDING
 #ifdef USE_LONG_DOUBLE
        return lrintl(fp);
@@ -830,8 +875,60 @@ static void fp_normalize(fpdata *a)
 {
 }
 
+static void fp_cmp(fpdata *a, fpdata *b)
+{
+       bool a_neg = fpp_is_neg(a);
+       bool b_neg = fpp_is_neg(b);
+       bool a_inf = fpp_is_infinity(a);
+       bool b_inf = fpp_is_infinity(b);
+       bool a_zero = fpp_is_zero(a);
+       bool b_zero = fpp_is_zero(b);
+       bool a_nan = fpp_is_nan(a);
+       bool b_nan = fpp_is_nan(b);
+       fptype v = 1.0;
+
+       if (a_nan || b_nan) {
+               // FCMP never returns N + NaN
+               v = *fp_nan;
+       } else if (a_zero && b_zero) {
+               if ((a_neg && b_neg) || (a_neg && !b_neg))
+                       v = -0.0;
+               else
+                       v = 0.0;
+       } else if (a_zero && b_inf) {
+               if (!b_neg)
+                       v = -1.0;
+               else
+                       v = 1.0;
+       } else if (a_inf && b_zero) {
+               if (!a_neg)
+                       v = -1.0;
+               else
+                       v = 1.0;
+       } else if (a_inf && b_inf) {
+               if (a_neg == b_neg)
+                       v = 0.0;
+               if ((a_neg && b_neg) || (a_neg && !b_neg))
+                       v = -v;
+       } else if (a_inf) {
+               if (a_neg)
+                       v = -1.0;
+       } else if (b_inf) {
+               if (!b_neg)
+                       v = -1.0;
+       } else {
+               fpp_sub(a, b);
+               v = a->fp;
+               fp_clear_status();
+       }
+       a->fp = v;
+}
+
 void fp_init_native(void)
 {
+       set_floatx80_rounding_precision(80, &fs);
+       set_float_rounding_mode(float_round_to_zero, &fs);
+
        fpp_print = fp_print;
        fpp_is_snan = fp_is_snan;
        fpp_unset_snan = fp_unset_snan;
@@ -904,4 +1001,5 @@ void fp_init_native(void)
        fpp_sub = fp_sub;
        fpp_sgldiv = fp_sgldiv;
        fpp_sglmul = fp_sglmul;
+       fpp_cmp = fp_cmp;
 }
index 83aa2d43e8c5a0f7211108100837700c8fb6c7b3..00d11fd0e908f7620947097e28997f177e978dd8 100644 (file)
@@ -39,8 +39,6 @@
 #define        FPCR_PRECISION_DOUBLE   0x00000080
 #define FPCR_PRECISION_EXTENDED        0x00000000
 
-static floatx80 fxsizes[6];
-static floatx80 fxzero;
 static struct float_status fs;
 
 /* Functions for setting host/library modes and getting status */
@@ -172,6 +170,15 @@ static bool fp_is_unnormal(fpdata *fpd)
     return floatx80_is_unnormal(fpd->fpx) != 0;
 }
 
+static inline int32_t extractFloatx80Exp( floatx80 a )
+{
+    return a.high & 0x7FFF;
+}
+static inline uint64_t extractFloatx80Frac( floatx80 a )
+{
+    return a.low;
+}
+
 /* Functions for converting between float formats */
 static const fptype twoto32 = 4294967296.0;
 
@@ -214,6 +221,18 @@ static void to_native(fptype *fp, fpdata *fpd)
 #endif
 }
 
+static bool to_native_checked(fptype *fp, fpdata *fpd, fpdata *dst)
+{
+    uint64_t aSig = extractFloatx80Frac(fpd->fpx);
+    int32_t aExp = extractFloatx80Exp(fpd->fpx);
+       if (aExp == 0x7FFF && (uint64_t)(aSig << 1)) {
+               dst->fpx = propagateFloatx80NaN(fpd->fpx, fpd->fpx, &fs);
+               return true;
+       }       
+       to_native(fp, fpd);
+       return false;
+}
+
 static void from_native(fptype fp, fpdata *fpd)
 {
     int expon;
@@ -313,13 +332,12 @@ static void from_exten_x(fpdata *fpd, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd
 
 static uae_s64 to_int(fpdata *src, int size)
 {
-    if (floatx80_lt(src->fpx, fxsizes[size * 2 + 0], &fs)) {
-        return floatx80_to_int32(fxsizes[size * 2 + 0], &fs);
-    }
-    if (floatx80_le(fxsizes[size * 2 + 1], src->fpx, &fs)) {
-        return floatx80_to_int32(fxsizes[size * 2 + 1], &fs);
-    }
-    return floatx80_to_int32(src->fpx, &fs);
+       switch (size) {
+               case 0: return floatx80_to_int8(src->fpx, &fs);
+               case 1: return floatx80_to_int16(src->fpx, &fs);
+               case 2: return floatx80_to_int32(src->fpx, &fs);
+               default: return 0;
+     }
 }
 static void from_int(fpdata *fpd, uae_s32 src)
 {
@@ -327,16 +345,6 @@ static void from_int(fpdata *fpd, uae_s32 src)
 }
 
 
-static inline int32_t extractFloatx80Exp( floatx80 a )
-{
-    return a.high & 0x7FFF;
-}
-static inline uint64_t extractFloatx80Frac( floatx80 a )
-{
-    return a.low;
-}
-
-
 /* Functions for rounding */
 
 static floatx80 fp_to_sgl(floatx80 a)
@@ -391,14 +399,16 @@ static void fp_sqrt(fpdata *a, fpdata *dst)
 static void fp_lognp1(fpdata *a, fpdata *dst)
 {
     fptype fpa;
-    to_native(&fpa, a);
+    if (to_native_checked(&fpa, a, dst))
+               return;
     fpa = log(a->fp + 1.0);
     from_native(fpa, dst);
 }
 static void fp_sin(fpdata *a, fpdata *dst)
 {
     fptype fpa;
-    to_native(&fpa, a);
+    if (to_native_checked(&fpa, a, dst))
+               return;
     fpa = sin(fpa);
     from_native(fpa, dst);
 }
@@ -502,7 +512,10 @@ static void fp_sub(fpdata *a, fpdata *b)
 {
     a->fpx = floatx80_sub(a->fpx, b->fpx, &fs);
 }
-
+static void fp_cmp(fpdata *a, fpdata *b)
+{
+    a->fpx = floatx80_cmp(a->fpx, b->fpx, &fs);
+}
 
 /* FIXME: create softfloat functions for following arithmetics */
 
@@ -594,12 +607,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);
-       fxsizes[0] = int32_to_floatx80(-128, &fsx);
-       fxsizes[1] = int32_to_floatx80(127, &fsx);
-       fxsizes[2] = int32_to_floatx80(-32768, &fsx);
-       fxsizes[3] = int32_to_floatx80(32767, &fsx);
-       fxsizes[4] = int32_to_floatx80(-2147483648, &fsx);
-       fxsizes[5] = int32_to_floatx80(2147483647, &fsx);
 
        fpp_print = fp_print;
        fpp_is_snan = fp_is_snan;
@@ -673,5 +680,6 @@ void fp_init_softfloat(void)
        fpp_sub = fp_sub;
        fpp_sgldiv = fp_sgldiv;
        fpp_sglmul = fp_sglmul;
+       fpp_cmp = fp_cmp;
 }
 
index 0eed12d648b13af84ed66c82db0914359af4c530..434059eff5f1488d6cc4eccad02590988e2904e0 100644 (file)
@@ -1,6 +1,16 @@
 
 extern void fp_init_native(void);
 extern void fp_init_softfloat(void);
+extern void fpsr_set_exception(uae_u32 exception);
+
+#define FPSR_BSUN       0x00008000
+#define FPSR_SNAN       0x00004000
+#define FPSR_OPERR      0x00002000
+#define FPSR_OVFL       0x00001000
+#define FPSR_UNFL       0x00000800
+#define FPSR_DZ         0x00000400
+#define FPSR_INEX2      0x00000200
+#define FPSR_INEX1      0x00000100
 
 #if defined(CPU_i386) || defined(CPU_x86_64)
 extern void init_fpucw_x87(void);
@@ -109,3 +119,4 @@ extern FPP_AB fpp_scale;
 extern FPP_AB fpp_sub;
 extern FPP_AB fpp_sgldiv;
 extern FPP_AB fpp_sglmul;
+extern FPP_AB fpp_cmp;
index 2898583969a9324cf4a1c78eb8fc416232fe8ce2..5d6020fd883c79d073c2a8c861688e398afff501 100644 (file)
@@ -180,7 +180,9 @@ struct regstruct
 
 #ifdef FPUEMU
        fpdata fp[8];
+#ifdef JIT
        fpdata fp_result;
+#endif
        uae_u32 fp_result_status;
        uae_u32 fpcr, fpsr, fpiar;
        uae_u32 fpu_state;
index 83af324ea1ab55bb77bf3df3d0b21d55000c3d3b..a24dc90f3e959fdd78714669d43b111614720229 100644 (file)
@@ -186,6 +186,87 @@ static int32_t roundAndPackInt32(flag zSign, uint64_t absZ, float_status *status
 
 }
 
+
+#ifdef SOFTFLOAT_68K // 30-01-2017: Added for Previous
+static int16_t roundAndPackInt16( flag zSign, uint64_t absZ, float_status *status )
+{
+    int8_t roundingMode;
+    flag roundNearestEven;
+    int8_t roundIncrement, roundBits;
+    int16_t z;
+    
+    roundingMode = status->float_rounding_mode;
+    roundNearestEven = ( roundingMode == float_round_nearest_even );
+    roundIncrement = 0x40;
+    if ( ! roundNearestEven ) {
+        if ( roundingMode == float_round_to_zero ) {
+            roundIncrement = 0;
+        }
+        else {
+            roundIncrement = 0x7F;
+            if ( zSign ) {
+                if ( roundingMode == float_round_up ) roundIncrement = 0;
+            }
+            else {
+                if ( roundingMode == float_round_down ) roundIncrement = 0;
+            }
+        }
+    }
+    roundBits = absZ & 0x7F;
+    absZ = ( absZ + roundIncrement )>>7;
+    absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
+    z = absZ;
+    if ( zSign ) z = - z;
+    z = (int16_t) z;
+    if ( ( absZ>>16 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) {
+        float_raise( float_flag_invalid, status );
+        return zSign ? (int16_t) 0x8000 : 0x7FFF;
+    }
+    if ( roundBits ) status->float_exception_flags |= float_flag_inexact;
+    return z;
+    
+}
+
+static int8_t roundAndPackInt8( flag zSign, uint64_t absZ, float_status *status )
+{
+    int8_t roundingMode;
+    flag roundNearestEven;
+    int8_t roundIncrement, roundBits;
+    int8_t z;
+    
+    roundingMode = status->float_rounding_mode;
+    roundNearestEven = ( roundingMode == float_round_nearest_even );
+    roundIncrement = 0x40;
+    if ( ! roundNearestEven ) {
+        if ( roundingMode == float_round_to_zero ) {
+            roundIncrement = 0;
+        }
+        else {
+            roundIncrement = 0x7F;
+            if ( zSign ) {
+                if ( roundingMode == float_round_up ) roundIncrement = 0;
+            }
+            else {
+                if ( roundingMode == float_round_down ) roundIncrement = 0;
+            }
+        }
+    }
+    roundBits = absZ & 0x7F;
+    absZ = ( absZ + roundIncrement )>>7;
+    absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
+    z = absZ;
+    if ( zSign ) z = - z;
+    z = (int8_t) z;
+    if ( ( absZ>>8 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) {
+        float_raise( float_flag_invalid, status );
+        return zSign ? (int8_t) 0x80 : 0x7F;
+    }
+    if ( roundBits ) status->float_exception_flags |= float_flag_inexact;
+    return z;
+    
+}
+#endif // End of addition for Previous
+
 /*----------------------------------------------------------------------------
 | Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
 | `absZ1', with binary point between bits 63 and 64 (between the input words),
@@ -4995,7 +5076,15 @@ int32_t floatx80_to_int32(floatx80 a, float_status *status)
     aSig = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
     aSign = extractFloatx80Sign( a );
-    if ( ( aExp == 0x7FFF ) && (uint64_t) ( aSig<<1 ) ) aSign = 0;
+#ifdef SOFTFLOAT_68K
+    if ( aExp == 0x7FFF ) {
+        float_raise( float_flag_invalid, status );
+        if ( (uint64_t) ( aSig<<1 ) ) return (int32_t)(aSig>>32);
+        return aSign ? (int32_t) 0x80000000 : 0x7FFFFFFF;
+    }
+#else
+       if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0;
+#endif
     shiftCount = 0x4037 - aExp;
     if ( shiftCount <= 0 ) shiftCount = 1;
     shift64RightJamming( aSig, shiftCount, &aSig );
@@ -5003,6 +5092,50 @@ int32_t floatx80_to_int32(floatx80 a, float_status *status)
 
 }
 
+#ifdef SOFTFLOAT_68K // 30-01-2017: Addition for Previous
+int16_t floatx80_to_int16( floatx80 a, float_status *status)
+{
+    flag aSign;
+    int32_t aExp, shiftCount;
+    uint64_t aSig;
+    
+    aSig = extractFloatx80Frac( a );
+    aExp = extractFloatx80Exp( a );
+    aSign = extractFloatx80Sign( a );
+    if ( aExp == 0x7FFF ) {
+        float_raise( float_flag_invalid, status );
+        if ( (uint64_t) ( aSig<<1 ) ) return (int16_t)(aSig>>48);
+        return aSign ? (int16_t) 0x8000 : 0x7FFF;
+    }
+    shiftCount = 0x4037 - aExp;
+    if ( shiftCount <= 0 ) shiftCount = 1;
+    shift64RightJamming( aSig, shiftCount, &aSig );
+    return roundAndPackInt16( aSign, aSig, status );
+    
+}
+int8_t floatx80_to_int8( floatx80 a, float_status *status)
+{
+    flag aSign;
+    int32_t aExp, shiftCount;
+    uint64_t aSig;
+    
+    aSig = extractFloatx80Frac( a );
+    aExp = extractFloatx80Exp( a );
+    aSign = extractFloatx80Sign( a );
+    if ( aExp == 0x7FFF ) {
+        float_raise( float_flag_invalid, status );
+        if ( (uint64_t) ( aSig<<1 ) ) return (int8_t)(aSig>>56);
+        return aSign ? (int8_t) 0x80 : 0x7F;
+    }
+    shiftCount = 0x4037 - aExp;
+    if ( shiftCount <= 0 ) shiftCount = 1;
+    shift64RightJamming( aSig, shiftCount, &aSig );
+    return roundAndPackInt8( aSign, aSig, status );
+    
+}
+#endif // End of addition for Previous
+
+
 /*----------------------------------------------------------------------------
 | Returns the result of converting the extended double-precision floating-
 | point value `a' to the 32-bit two's complement integer format.  The
@@ -6100,8 +6233,7 @@ floatx80 floatx80_rem( floatx80 a, floatx80 b, uint64_t *q, flag *s, float_statu
         mul64To128( bSig, qTemp, &term0, &term1 );
         sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
         shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 );
-        *q += qTemp;
-        *q <<= 62;
+        *q = ( expDiff > 63 ) ? 0 : ( qTemp<<expDiff );
         expDiff -= 62;
     }
     expDiff += 64;
@@ -6207,9 +6339,8 @@ floatx80 floatx80_mod( floatx80 a, floatx80 b, uint64_t *q, flag *s, float_statu
         mul64To128( bSig, qTemp, &term0, &term1 );
         sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
         shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 );
-        *q += qTemp;
-        *q <<= 62;
-        expDiff -= 62;
+        *q = ( expDiff > 63 ) ? 0 : ( qTemp<<expDiff );
+               expDiff -= 62;
     }
     expDiff += 64;
     if ( 0 < expDiff ) {
@@ -6425,8 +6556,50 @@ floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status)
                 status->floatx80_rounding_precision, aSign, aExp, aSig, 0, status);
     
 }
-#endif // End of addition for Previous
 
+/*----------------------------------------------------------------------------
+ | Returns the result of comparing the extended double-precision floating-
+ | point values `a' and `b'.  The result is abstracted for matching the
+ | corresponding condition codes.
+ *----------------------------------------------------------------------------*/
+    
+floatx80 floatx80_cmp( floatx80 a, floatx80 b, float_status *status )
+{
+    flag aSign, bSign;
+    int32_t aExp, bExp;
+    uint64_t aSig, bSig;
+    
+    aSig = extractFloatx80Frac( a );
+    aExp = extractFloatx80Exp( a );
+    aSign = extractFloatx80Sign( a );
+    bSig = extractFloatx80Frac( b );
+    bExp = extractFloatx80Exp( b );
+    bSign = extractFloatx80Sign( b );
+    
+    if ( ( aExp == 0x7FFF && (uint64_t) ( aSig<<1 ) ) ||
+         ( bExp == 0x7FFF && (uint64_t) ( bSig<<1 ) ) ) {
+               return packFloatx80(0, 0x7FFF, floatx80_default_nan_low);    }
+    
+    if ( bExp < aExp ) return packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) );
+    if ( aExp < bExp ) return packFloatx80( bSign ^ 1, 0x3FFF, LIT64( 0x8000000000000000 ) );
+    
+    if ( aExp == 0x7FFF ) {
+        if ( aSign == bSign ) return packFloatx80( aSign, 0, 0 );
+        return packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) );
+    }
+    
+    if ( bSig < aSig ) return packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) );
+    if ( aSig < bSig ) return packFloatx80( bSign ^ 1, 0x3FFF, LIT64( 0x8000000000000000 ) );
+    
+    if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 );
+    
+    if ( aSign == bSign ) return packFloatx80( 0, 0, 0 );
+    
+    return packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) );
+    
+}
+    
+#endif // End of addition for Previous
 
 /*----------------------------------------------------------------------------
 | Returns 1 if the extended double-precision floating-point value `a' is equal
index e9eeeaac4829643996d31c79e6e0f237c88f8ec6..f5f1c4707d9ff10fce2f79a6bea19d7acbdd2953 100644 (file)
@@ -596,6 +596,10 @@ float64 float64_default_nan(float_status *status);
 | Software IEC/IEEE extended double-precision conversion routines.
 *----------------------------------------------------------------------------*/
 int32_t floatx80_to_int32(floatx80, float_status *status);
+#ifdef SOFTFLOAT_68K
+int16_t floatx80_to_int16(floatx80, float_status *status);
+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);
@@ -624,6 +628,7 @@ floatx80 floatx80_mod( floatx80 a, floatx80 b, uint64_t *q, flag *s, float_statu
 floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status);
 floatx80 floatx80_sglmul( floatx80 a, floatx80 b, float_status *status);
 floatx80 floatx80_sgldiv( floatx80 a, floatx80 b, float_status *status);
+floatx80 floatx80_cmp( floatx80 a, floatx80 b, float_status *status);
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE extended double-precision operations.