soft floats for SPARC (Blue Swirl)
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Wed, 21 Jun 2006 18:37:05 +0000 (18:37 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Wed, 21 Jun 2006 18:37:05 +0000 (18:37 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2000 c046a42c-6fe2-441c-8c8c-71466251a162

configure
target-sparc/cpu.h
target-sparc/op.c
target-sparc/op_helper.c

index 57b59aa..59dcee4 100755 (executable)
--- a/configure
+++ b/configure
@@ -850,7 +850,7 @@ if test "$target_user_only" = "yes" ; then
   echo "#define CONFIG_USER_ONLY 1" >> $config_h
 fi
 
-if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" ; then
+if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64"; then
   echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
   echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
 fi
index 28efab7..c6d5621 100644 (file)
@@ -12,7 +12,7 @@
 #define TARGET_FPREGS 64
 #define TARGET_PAGE_BITS 12 /* XXX */
 #endif
-#define TARGET_FPREG_T float
+#define TARGET_FPREG_T float32
 
 #include "cpu-defs.h"
 
 typedef struct CPUSPARCState {
     target_ulong gregs[8]; /* general registers */
     target_ulong *regwptr; /* pointer to current register window */
-    TARGET_FPREG_T    fpr[TARGET_FPREGS];  /* floating point registers */
+    float32 fpr[TARGET_FPREGS];  /* floating point registers */
     target_ulong pc;       /* program counter */
     target_ulong npc;      /* next program counter */
     target_ulong y;        /* multiply/divide register */
@@ -187,8 +187,8 @@ typedef struct CPUSPARCState {
     uint32_t mmuregs[16];
 #endif
     /* temporary float registers */
-    float ft0, ft1;
-    double dt0, dt1;
+    float32 ft0, ft1;
+    float64 dt0, dt1;
     float_status fp_status;
 #if defined(TARGET_SPARC64)
 #define MAXTL 4
@@ -236,8 +236,6 @@ typedef struct CPUSPARCState {
 CPUSPARCState *cpu_sparc_init(void);
 int cpu_sparc_exec(CPUSPARCState *s);
 int cpu_sparc_close(CPUSPARCState *s);
-void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f);
-double cpu_put_fp64(uint64_t mant, uint16_t exp);
 
 /* Fake impl 0, version 4 */
 #define GET_PSR(env) ((0 << 28) | (4 << 24) | (env->psr & PSR_ICC) |   \
index 4609cdf..d5df859 100644 (file)
@@ -1339,94 +1339,66 @@ void OPPROTO op_flush_T0(void)
     helper_flush(T0);
 }
 
-void OPPROTO op_fnegs(void)
-{
-    FT0 = -FT1;
-}
-
-void OPPROTO op_fabss(void)
-{
-    do_fabss();
-}
-
-#ifdef TARGET_SPARC64
-void OPPROTO op_fnegd(void)
-{
-    DT0 = -DT1;
-}
-
-void OPPROTO op_fabsd(void)
-{
-    do_fabsd();
-}
-#endif
-
-void OPPROTO op_fsqrts(void)
-{
-    do_fsqrts();
-}
-
-void OPPROTO op_fsqrtd(void)
-{
-    do_fsqrtd();
-}
-
-void OPPROTO op_fmuls(void)
-{
-    FT0 *= FT1;
-}
+#define F_OP(name, p) void OPPROTO op_f##name##p(void)
+
+#define F_BINOP(name)                                           \
+    F_OP(name, s)                                               \
+    {                                                           \
+        FT0 = float32_ ## name (FT0, FT1, &env->fp_status);     \
+    }                                                           \
+    F_OP(name, d)                                               \
+    {                                                           \
+        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
+    }
 
-void OPPROTO op_fmuld(void)
-{
-    DT0 *= DT1;
-}
+F_BINOP(add);
+F_BINOP(sub);
+F_BINOP(mul);
+F_BINOP(div);
+#undef F_BINOP
 
 void OPPROTO op_fsmuld(void)
 {
-    DT0 = FT0 * FT1;
-}
-
-void OPPROTO op_fadds(void)
-{
-    FT0 += FT1;
+    DT0 = float64_mul(float32_to_float64(FT0, &env->fp_status),
+                      float32_to_float64(FT1, &env->fp_status),
+                      &env->fp_status);
 }
 
-void OPPROTO op_faddd(void)
-{
-    DT0 += DT1;
-}
+#define F_HELPER(name)    \
+    F_OP(name, s)         \
+    {                     \
+        do_f##name##s();  \
+    }                     \
+    F_OP(name, d)         \
+    {                     \
+        do_f##name##d();  \
+    }
 
-void OPPROTO op_fsubs(void)
-{
-    FT0 -= FT1;
-}
+F_HELPER(sqrt);
 
-void OPPROTO op_fsubd(void)
+F_OP(neg, s)
 {
-    DT0 -= DT1;
+    FT0 = float32_chs(FT1);
 }
 
-void OPPROTO op_fdivs(void)
+F_OP(abs, s)
 {
-    FT0 /= FT1;
+    do_fabss();
 }
 
-void OPPROTO op_fdivd(void)
-{
-    DT0 /= DT1;
-}
+F_HELPER(cmp);
 
-void OPPROTO op_fcmps(void)
+#ifdef TARGET_SPARC64
+F_OP(neg, d)
 {
-    do_fcmps();
+    DT0 = float64_chs(DT1);
 }
 
-void OPPROTO op_fcmpd(void)
+F_OP(abs, d)
 {
-    do_fcmpd();
+    do_fabsd();
 }
 
-#ifdef TARGET_SPARC64
 void OPPROTO op_fcmps_fcc1(void)
 {
     do_fcmps_fcc1();
@@ -1458,69 +1430,65 @@ void OPPROTO op_fcmpd_fcc3(void)
 }
 #endif
 
+/* Integer to float conversion.  */
 #ifdef USE_INT_TO_FLOAT_HELPERS
-void OPPROTO op_fitos(void)
-{
-    do_fitos();
-}
-
-void OPPROTO op_fitod(void)
-{
-    do_fitod();
-}
+F_HELPER(ito);
 #else
-void OPPROTO op_fitos(void)
+F_OP(ito, s)
 {
-    FT0 = (float) *((int32_t *)&FT1);
+    FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
 }
 
-void OPPROTO op_fitod(void)
+F_OP(ito, d)
 {
-    DT0 = (double) *((int32_t *)&FT1);
+    DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
 }
 
 #ifdef TARGET_SPARC64
-void OPPROTO op_fxtos(void)
+F_OP(xto, s)
 {
-    FT0 = (float) *((int64_t *)&DT1);
+    FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
 }
 
-void OPPROTO op_fxtod(void)
+F_OP(xto, d)
 {
-    DT0 = (double) *((int64_t *)&DT1);
+    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
 }
 #endif
 #endif
+#undef F_HELPER
 
+/* floating point conversion */
 void OPPROTO op_fdtos(void)
 {
-    FT0 = (float) DT1;
+    FT0 = float64_to_float32(DT1, &env->fp_status);
 }
 
 void OPPROTO op_fstod(void)
 {
-    DT0 = (double) FT1;
+    DT0 = float32_to_float64(FT1, &env->fp_status);
 }
 
+/* Float to integer conversion.  */
 void OPPROTO op_fstoi(void)
 {
-    *((int32_t *)&FT0) = (int32_t) FT1;
+    *((int32_t *)&FT0) = float32_to_int32(FT1, &env->fp_status);
 }
 
 void OPPROTO op_fdtoi(void)
 {
-    *((int32_t *)&FT0) = (int32_t) DT1;
+    *((int32_t *)&FT0) = float64_to_int32(DT1, &env->fp_status);
 }
 
 #ifdef TARGET_SPARC64
 void OPPROTO op_fstox(void)
 {
-    *((int64_t *)&DT0) = (int64_t) FT1;
+    *((int64_t *)&DT0) = float32_to_int64(FT1, &env->fp_status);
 }
 
 void OPPROTO op_fdtox(void)
 {
-    *((int64_t *)&DT0) = (int64_t) DT1;
+    *((int64_t *)&DT0) = float64_to_int64(DT1, &env->fp_status);
 }
 
 void OPPROTO op_fmovs_cc(void)
index 030b2f7..5f88459 100644 (file)
@@ -12,12 +12,12 @@ void raise_exception(int tt)
 #ifdef USE_INT_TO_FLOAT_HELPERS
 void do_fitos(void)
 {
-    FT0 = (float) *((int32_t *)&FT1);
+    FT0 = int32_to_float32(*((int32_t *)&FT1));
 }
 
 void do_fitod(void)
 {
-    DT0 = (double) *((int32_t *)&FT1);
+    DT0 = int32_to_float64(*((int32_t *)&FT1));
 }
 #endif
 
@@ -43,182 +43,45 @@ void do_fsqrtd(void)
     DT0 = float64_sqrt(DT1, &env->fp_status);
 }
 
-#define FS 0
-void do_fcmps (void)
-{
-    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
-    if (isnan(FT0) || isnan(FT1)) {
-        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
-       if (env->fsr & FSR_NVM) {
-           env->fsr |= T0;
-           raise_exception(TT_FP_EXCP);
-       } else {
-           env->fsr |= FSR_NVA;
-       }
-    } else if (FT0 < FT1) {
-        T0 = FSR_FCC0 << FS;
-    } else if (FT0 > FT1) {
-        T0 = FSR_FCC1 << FS;
-    } else {
-        T0 = 0;
+#define GEN_FCMP(name, size, reg1, reg2, FS)                            \
+    void glue(do_, name) (void)                                         \
+    {                                                                   \
+        env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
+        switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
+        case float_relation_unordered:                                  \
+            T0 = (FSR_FCC1 | FSR_FCC0) << FS;                           \
+            if (env->fsr & FSR_NVM) {                                   \
+                env->fsr |= T0;                                         \
+                raise_exception(TT_FP_EXCP);                            \
+            } else {                                                    \
+                env->fsr |= FSR_NVA;                                    \
+            }                                                           \
+            break;                                                      \
+        case float_relation_less:                                       \
+            T0 = FSR_FCC0 << FS;                                        \
+            break;                                                      \
+        case float_relation_greater:                                    \
+            T0 = FSR_FCC1 << FS;                                        \
+            break;                                                      \
+        default:                                                        \
+            T0 = 0;                                                     \
+            break;                                                      \
+        }                                                               \
+        env->fsr |= T0;                                                 \
     }
-    env->fsr |= T0;
-}
 
-void do_fcmpd (void)
-{
-    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
-    if (isnan(DT0) || isnan(DT1)) {
-        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
-       if (env->fsr & FSR_NVM) {
-           env->fsr |= T0;
-           raise_exception(TT_FP_EXCP);
-       } else {
-           env->fsr |= FSR_NVA;
-       }
-    } else if (DT0 < DT1) {
-        T0 = FSR_FCC0 << FS;
-    } else if (DT0 > DT1) {
-        T0 = FSR_FCC1 << FS;
-    } else {
-        T0 = 0;
-    }
-    env->fsr |= T0;
-}
+GEN_FCMP(fcmps, float32, FT0, FT1, 0);
+GEN_FCMP(fcmpd, float64, DT0, DT1, 0);
 
 #ifdef TARGET_SPARC64
-#undef FS
-#define FS 22
-void do_fcmps_fcc1 (void)
-{
-    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
-    if (isnan(FT0) || isnan(FT1)) {
-        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
-       if (env->fsr & FSR_NVM) {
-           env->fsr |= T0;
-           raise_exception(TT_FP_EXCP);
-       } else {
-           env->fsr |= FSR_NVA;
-       }
-    } else if (FT0 < FT1) {
-        T0 = FSR_FCC0 << FS;
-    } else if (FT0 > FT1) {
-        T0 = FSR_FCC1 << FS;
-    } else {
-        T0 = 0;
-    }
-    env->fsr |= T0;
-}
-
-void do_fcmpd_fcc1 (void)
-{
-    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
-    if (isnan(DT0) || isnan(DT1)) {
-        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
-       if (env->fsr & FSR_NVM) {
-           env->fsr |= T0;
-           raise_exception(TT_FP_EXCP);
-       } else {
-           env->fsr |= FSR_NVA;
-       }
-    } else if (DT0 < DT1) {
-        T0 = FSR_FCC0 << FS;
-    } else if (DT0 > DT1) {
-        T0 = FSR_FCC1 << FS;
-    } else {
-        T0 = 0;
-    }
-    env->fsr |= T0;
-}
+GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22);
+GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22);
 
-#undef FS
-#define FS 24
-void do_fcmps_fcc2 (void)
-{
-    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
-    if (isnan(FT0) || isnan(FT1)) {
-        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
-       if (env->fsr & FSR_NVM) {
-           env->fsr |= T0;
-           raise_exception(TT_FP_EXCP);
-       } else {
-           env->fsr |= FSR_NVA;
-       }
-    } else if (FT0 < FT1) {
-        T0 = FSR_FCC0 << FS;
-    } else if (FT0 > FT1) {
-        T0 = FSR_FCC1 << FS;
-    } else {
-        T0 = 0;
-    }
-    env->fsr |= T0;
-}
+GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24);
+GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24);
 
-void do_fcmpd_fcc2 (void)
-{
-    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
-    if (isnan(DT0) || isnan(DT1)) {
-        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
-       if (env->fsr & FSR_NVM) {
-           env->fsr |= T0;
-           raise_exception(TT_FP_EXCP);
-       } else {
-           env->fsr |= FSR_NVA;
-       }
-    } else if (DT0 < DT1) {
-        T0 = FSR_FCC0 << FS;
-    } else if (DT0 > DT1) {
-        T0 = FSR_FCC1 << FS;
-    } else {
-        T0 = 0;
-    }
-    env->fsr |= T0;
-}
-
-#undef FS
-#define FS 26
-void do_fcmps_fcc3 (void)
-{
-    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
-    if (isnan(FT0) || isnan(FT1)) {
-        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
-       if (env->fsr & FSR_NVM) {
-           env->fsr |= T0;
-           raise_exception(TT_FP_EXCP);
-       } else {
-           env->fsr |= FSR_NVA;
-       }
-    } else if (FT0 < FT1) {
-        T0 = FSR_FCC0 << FS;
-    } else if (FT0 > FT1) {
-        T0 = FSR_FCC1 << FS;
-    } else {
-        T0 = 0;
-    }
-    env->fsr |= T0;
-}
-
-void do_fcmpd_fcc3 (void)
-{
-    env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
-    if (isnan(DT0) || isnan(DT1)) {
-        T0 = (FSR_FCC1 | FSR_FCC0) << FS;
-       if (env->fsr & FSR_NVM) {
-           env->fsr |= T0;
-           raise_exception(TT_FP_EXCP);
-       } else {
-           env->fsr |= FSR_NVA;
-       }
-    } else if (DT0 < DT1) {
-        T0 = FSR_FCC0 << FS;
-    } else if (DT0 > DT1) {
-        T0 = FSR_FCC1 << FS;
-    } else {
-        T0 = 0;
-    }
-    env->fsr |= T0;
-}
-#undef FS
+GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26);
+GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26);
 #endif
 
 #if defined(CONFIG_USER_ONLY) 
@@ -783,19 +646,6 @@ void helper_ldfsr(void)
     set_float_rounding_mode(rnd_mode, &env->fp_status);
 }
 
-void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f)
-{
-    int exptemp;
-
-    *pmant = ldexp(frexp(f, &exptemp), 53);
-    *pexp = exptemp;
-}
-
-double cpu_put_fp64(uint64_t mant, uint16_t exp)
-{
-    return ldexp((double) mant, exp - 53);
-}
-
 void helper_debug()
 {
     env->exception_index = EXCP_DEBUG;