]> git.proxmox.com Git - qemu.git/commitdiff
target-alpha: Split up FPCR value into separate fields.
authorRichard Henderson <rth@twiddle.net>
Thu, 31 Dec 2009 20:41:07 +0000 (12:41 -0800)
committerAurelien Jarno <aurelien@aurel32.net>
Tue, 23 Feb 2010 22:36:22 +0000 (23:36 +0100)
The fpcr_exc_status, fpcr_exc_mask, and fpcr_dyn_round fields
are stored in <softfloat.h> format for convenience during
regular execution.

Revert the addition of float_exception_mask to float_status,
added in ba0e276db4b51bd2255a5d5ff8902c70d32ade40.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
fpu/softfloat.h
target-alpha/cpu.h
target-alpha/helper.c

index 9d82694119e259f0de6bbe6bddd1f636e68f7676..636591b04cdb9043f94975c5f1f801aa66dcb558 100644 (file)
@@ -187,7 +187,6 @@ typedef struct float_status {
     signed char float_detect_tininess;
     signed char float_rounding_mode;
     signed char float_exception_flags;
-    signed char float_exception_mask;
 #ifdef FLOATX80
     signed char floatx80_rounding_precision;
 #endif
index c0dff4bb8763700f0a931d419162cd2f121a042c..47224153ff378a2c015d5553ecf86835edd18f68 100644 (file)
@@ -145,6 +145,10 @@ enum {
 #define FPCR_UNFD              (1ULL << 61)
 #define FPCR_UNDZ              (1ULL << 60)
 #define FPCR_DYN_SHIFT         58
+#define FPCR_DYN_CHOPPED       (0ULL << FPCR_DYN_SHIFT)
+#define FPCR_DYN_MINUS         (1ULL << FPCR_DYN_SHIFT)
+#define FPCR_DYN_NORMAL                (2ULL << FPCR_DYN_SHIFT)
+#define FPCR_DYN_PLUS          (3ULL << FPCR_DYN_SHIFT)
 #define FPCR_DYN_MASK          (3ULL << FPCR_DYN_SHIFT)
 #define FPCR_IOV               (1ULL << 57)
 #define FPCR_INE               (1ULL << 56)
@@ -341,17 +345,27 @@ struct pal_handler_t {
 
 struct CPUAlphaState {
     uint64_t ir[31];
-    float64  fir[31];
-    float_status fp_status;
-    uint64_t fpcr;
+    float64 fir[31];
     uint64_t pc;
     uint64_t lock;
     uint32_t pcc[2];
     uint64_t ipr[IPR_LAST];
     uint64_t ps;
     uint64_t unique;
-    int saved_mode; /* Used for HW_LD / HW_ST */
-    int intr_flag; /* For RC and RS */
+    float_status fp_status;
+    /* The following fields make up the FPCR, but in FP_STATUS format.  */
+    uint8_t fpcr_exc_status;
+    uint8_t fpcr_exc_mask;
+    uint8_t fpcr_dyn_round;
+    uint8_t fpcr_flush_to_zero;
+    uint8_t fpcr_dnz;
+    uint8_t fpcr_dnod;
+    uint8_t fpcr_undz;
+
+    /* Used for HW_LD / HW_ST */
+    uint8_t saved_mode;
+    /* For RC and RS */
+    uint8_t intr_flag;
 
 #if TARGET_LONG_BITS > HOST_LONG_BITS
     /* temporary fixed-point registers
index 1e0bc4a15545899422994ab1e118e571778ea8ad..f35ca9ac54692fd5578c0ccdc0f912cb820b2e9f 100644 (file)
 
 uint64_t cpu_alpha_load_fpcr (CPUState *env)
 {
-    uint64_t ret = 0;
-    int flags, mask;
-
-    flags = env->fp_status.float_exception_flags;
-    ret |= (uint64_t) flags << 52;
-    if (flags)
-        ret |= FPCR_SUM;
-    env->ipr[IPR_EXC_SUM] &= ~0x3E;
-    env->ipr[IPR_EXC_SUM] |= flags << 1;
-
-    mask = env->fp_status.float_exception_mask;
-    if (mask & float_flag_invalid)
-        ret |= FPCR_INVD;
-    if (mask & float_flag_divbyzero)
-        ret |= FPCR_DZED;
-    if (mask & float_flag_overflow)
-        ret |= FPCR_OVFD;
-    if (mask & float_flag_underflow)
-        ret |= FPCR_UNFD;
-    if (mask & float_flag_inexact)
-        ret |= FPCR_INED;
-
-    switch (env->fp_status.float_rounding_mode) {
+    uint64_t r = 0;
+    uint8_t t;
+
+    t = env->fpcr_exc_status;
+    if (t) {
+        r = FPCR_SUM;
+        if (t & float_flag_invalid) {
+            r |= FPCR_INV;
+        }
+        if (t & float_flag_divbyzero) {
+            r |= FPCR_DZE;
+        }
+        if (t & float_flag_overflow) {
+            r |= FPCR_OVF;
+        }
+        if (t & float_flag_underflow) {
+            r |= FPCR_UNF;
+        }
+        if (t & float_flag_inexact) {
+            r |= FPCR_INE;
+        }
+    }
+
+    t = env->fpcr_exc_mask;
+    if (t & float_flag_invalid) {
+        r |= FPCR_INVD;
+    }
+    if (t & float_flag_divbyzero) {
+        r |= FPCR_DZED;
+    }
+    if (t & float_flag_overflow) {
+        r |= FPCR_OVFD;
+    }
+    if (t & float_flag_underflow) {
+        r |= FPCR_UNFD;
+    }
+    if (t & float_flag_inexact) {
+        r |= FPCR_INED;
+    }
+
+    switch (env->fpcr_dyn_round) {
     case float_round_nearest_even:
-        ret |= 2ULL << FPCR_DYN_SHIFT;
+        r |= FPCR_DYN_NORMAL;
         break;
     case float_round_down:
-        ret |= 1ULL << FPCR_DYN_SHIFT;
+        r |= FPCR_DYN_MINUS;
         break;
     case float_round_up:
-        ret |= 3ULL << FPCR_DYN_SHIFT;
+        r |= FPCR_DYN_PLUS;
         break;
     case float_round_to_zero:
+        r |= FPCR_DYN_CHOPPED;
         break;
     }
-    return ret;
+
+    if (env->fpcr_dnz) {
+        r |= FPCR_DNZ;
+    }
+    if (env->fpcr_dnod) {
+        r |= FPCR_DNOD;
+    }
+    if (env->fpcr_undz) {
+        r |= FPCR_UNDZ;
+    }
+
+    return r;
 }
 
 void cpu_alpha_store_fpcr (CPUState *env, uint64_t val)
 {
-    int round_mode, mask;
+    uint8_t t;
 
-    set_float_exception_flags((val >> 52) & 0x3F, &env->fp_status);
+    t = 0;
+    if (val & FPCR_INV) {
+        t |= float_flag_invalid;
+    }
+    if (val & FPCR_DZE) {
+        t |= float_flag_divbyzero;
+    }
+    if (val & FPCR_OVF) {
+        t |= float_flag_overflow;
+    }
+    if (val & FPCR_UNF) {
+        t |= float_flag_underflow;
+    }
+    if (val & FPCR_INE) {
+        t |= float_flag_inexact;
+    }
+    env->fpcr_exc_status = t;
 
-    mask = 0;
-    if (val & FPCR_INVD)
-        mask |= float_flag_invalid;
-    if (val & FPCR_DZED)
-        mask |= float_flag_divbyzero;
-    if (val & FPCR_OVFD)
-        mask |= float_flag_overflow;
-    if (val & FPCR_UNFD)
-        mask |= float_flag_underflow;
-    if (val & FPCR_INED)
-        mask |= float_flag_inexact;
-    env->fp_status.float_exception_mask = mask;
+    t = 0;
+    if (val & FPCR_INVD) {
+        t |= float_flag_invalid;
+    }
+    if (val & FPCR_DZED) {
+        t |= float_flag_divbyzero;
+    }
+    if (val & FPCR_OVFD) {
+        t |= float_flag_overflow;
+    }
+    if (val & FPCR_UNFD) {
+        t |= float_flag_underflow;
+    }
+    if (val & FPCR_INED) {
+        t |= float_flag_inexact;
+    }
+    env->fpcr_exc_mask = t;
 
-    switch ((val >> FPCR_DYN_SHIFT) & 3) {
-    case 0:
-        round_mode = float_round_to_zero;
+    switch (val & FPCR_DYN_MASK) {
+    case FPCR_DYN_CHOPPED:
+        t = float_round_to_zero;
         break;
-    case 1:
-        round_mode = float_round_down;
+    case FPCR_DYN_MINUS:
+        t = float_round_down;
         break;
-    case 2:
-        round_mode = float_round_nearest_even;
+    case FPCR_DYN_NORMAL:
+        t = float_round_nearest_even;
         break;
-    case 3:
-    default: /* this avoids a gcc (< 4.4) warning */
-        round_mode = float_round_up;
+    case FPCR_DYN_PLUS:
+        t = float_round_up;
         break;
     }
-    set_float_rounding_mode(round_mode, &env->fp_status);
+    env->fpcr_dyn_round = t;
+
+    env->fpcr_flush_to_zero
+      = (val & (FPCR_UNDZ|FPCR_UNFD)) == (FPCR_UNDZ|FPCR_UNFD);
+
+    env->fpcr_dnz = (val & FPCR_DNZ) != 0;
+    env->fpcr_dnod = (val & FPCR_DNOD) != 0;
+    env->fpcr_undz = (val & FPCR_UNDZ) != 0;
 }
 
 #if defined(CONFIG_USER_ONLY)