]> git.proxmox.com Git - qemu.git/blobdiff - target-s390x/cc_helper.c
audio: update documentation after removing --audio-card-list option
[qemu.git] / target-s390x / cc_helper.c
index 880e3b234d55685fc2fbb6cfab3740b76997274e..a6d60bf8851c22ab9a693f64930f4d36e630467c 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "cpu.h"
 #include "helper.h"
+#include "qemu/host-utils.h"
 
 /* #define DEBUG_HELPER */
 #ifdef DEBUG_HELPER
@@ -28,8 +29,7 @@
 #define HELPER_LOG(x...)
 #endif
 
-static inline uint32_t cc_calc_ltgt_32(CPUS390XState *env, int32_t src,
-                                       int32_t dst)
+static uint32_t cc_calc_ltgt_32(int32_t src, int32_t dst)
 {
     if (src == dst) {
         return 0;
@@ -40,13 +40,12 @@ static inline uint32_t cc_calc_ltgt_32(CPUS390XState *env, int32_t src,
     }
 }
 
-static inline uint32_t cc_calc_ltgt0_32(CPUS390XState *env, int32_t dst)
+static uint32_t cc_calc_ltgt0_32(int32_t dst)
 {
-    return cc_calc_ltgt_32(env, dst, 0);
+    return cc_calc_ltgt_32(dst, 0);
 }
 
-static inline uint32_t cc_calc_ltgt_64(CPUS390XState *env, int64_t src,
-                                       int64_t dst)
+static uint32_t cc_calc_ltgt_64(int64_t src, int64_t dst)
 {
     if (src == dst) {
         return 0;
@@ -57,13 +56,12 @@ static inline uint32_t cc_calc_ltgt_64(CPUS390XState *env, int64_t src,
     }
 }
 
-static inline uint32_t cc_calc_ltgt0_64(CPUS390XState *env, int64_t dst)
+static uint32_t cc_calc_ltgt0_64(int64_t dst)
 {
-    return cc_calc_ltgt_64(env, dst, 0);
+    return cc_calc_ltgt_64(dst, 0);
 }
 
-static inline uint32_t cc_calc_ltugtu_32(CPUS390XState *env, uint32_t src,
-                                         uint32_t dst)
+static uint32_t cc_calc_ltugtu_32(uint32_t src, uint32_t dst)
 {
     if (src == dst) {
         return 0;
@@ -74,8 +72,7 @@ static inline uint32_t cc_calc_ltugtu_32(CPUS390XState *env, uint32_t src,
     }
 }
 
-static inline uint32_t cc_calc_ltugtu_64(CPUS390XState *env, uint64_t src,
-                                         uint64_t dst)
+static uint32_t cc_calc_ltugtu_64(uint64_t src, uint64_t dst)
 {
     if (src == dst) {
         return 0;
@@ -86,13 +83,11 @@ static inline uint32_t cc_calc_ltugtu_64(CPUS390XState *env, uint64_t src,
     }
 }
 
-static inline uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val,
-                                     uint32_t mask)
+static uint32_t cc_calc_tm_32(uint32_t val, uint32_t mask)
 {
-    uint16_t r = val & mask;
+    uint32_t r = val & mask;
 
-    HELPER_LOG("%s: val 0x%x mask 0x%x\n", __func__, val, mask);
-    if (r == 0 || mask == 0) {
+    if (r == 0) {
         return 0;
     } else if (r == mask) {
         return 3;
@@ -101,23 +96,17 @@ static inline uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val,
     }
 }
 
-/* set condition code for test under mask */
-static inline uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val,
-                                     uint32_t mask)
+static uint32_t cc_calc_tm_64(uint64_t val, uint64_t mask)
 {
-    uint16_t r = val & mask;
+    uint64_t r = val & mask;
 
-    HELPER_LOG("%s: val 0x%lx mask 0x%x r 0x%x\n", __func__, val, mask, r);
-    if (r == 0 || mask == 0) {
+    if (r == 0) {
         return 0;
     } else if (r == mask) {
         return 3;
     } else {
-        while (!(mask & 0x8000)) {
-            mask <<= 1;
-            val <<= 1;
-        }
-        if (val & 0x8000) {
+        int top = clz64(mask);
+        if ((int64_t)(val << top) < 0) {
             return 2;
         } else {
             return 1;
@@ -125,13 +114,12 @@ static inline uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val,
     }
 }
 
-static inline uint32_t cc_calc_nz(CPUS390XState *env, uint64_t dst)
+static uint32_t cc_calc_nz(uint64_t dst)
 {
     return !!dst;
 }
 
-static inline uint32_t cc_calc_add_64(CPUS390XState *env, int64_t a1,
-                                      int64_t a2, int64_t ar)
+static uint32_t cc_calc_add_64(int64_t a1, int64_t a2, int64_t ar)
 {
     if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
         return 3; /* overflow */
@@ -146,14 +134,12 @@ static inline uint32_t cc_calc_add_64(CPUS390XState *env, int64_t a1,
     }
 }
 
-static uint32_t cc_calc_addu_64(CPUS390XState *env, uint64_t a1,
-                                uint64_t a2, uint64_t ar)
+static uint32_t cc_calc_addu_64(uint64_t a1, uint64_t a2, uint64_t ar)
 {
     return (ar != 0) + 2 * (ar < a1);
 }
 
-static uint32_t cc_calc_addc_64(CPUS390XState *env, uint64_t a1,
-                                uint64_t a2, uint64_t ar)
+static uint32_t cc_calc_addc_64(uint64_t a1, uint64_t a2, uint64_t ar)
 {
     /* Recover a2 + carry_in.  */
     uint64_t a2c = ar - a1;
@@ -163,8 +149,7 @@ static uint32_t cc_calc_addc_64(CPUS390XState *env, uint64_t a1,
     return (ar != 0) + 2 * carry_out;
 }
 
-static inline uint32_t cc_calc_sub_64(CPUS390XState *env, int64_t a1,
-                                      int64_t a2, int64_t ar)
+static uint32_t cc_calc_sub_64(int64_t a1, int64_t a2, int64_t ar)
 {
     if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
         return 3; /* overflow */
@@ -179,8 +164,7 @@ static inline uint32_t cc_calc_sub_64(CPUS390XState *env, int64_t a1,
     }
 }
 
-static inline uint32_t cc_calc_subu_64(CPUS390XState *env, uint64_t a1,
-                                       uint64_t a2, uint64_t ar)
+static uint32_t cc_calc_subu_64(uint64_t a1, uint64_t a2, uint64_t ar)
 {
     if (ar == 0) {
         return 2;
@@ -193,8 +177,7 @@ static inline uint32_t cc_calc_subu_64(CPUS390XState *env, uint64_t a1,
     }
 }
 
-static uint32_t cc_calc_subb_64(CPUS390XState *env, uint64_t a1,
-                                uint64_t a2, uint64_t ar)
+static uint32_t cc_calc_subb_64(uint64_t a1, uint64_t a2, uint64_t ar)
 {
     /* We had borrow-in if normal subtraction isn't equal.  */
     int borrow_in = ar - (a1 - a2);
@@ -212,7 +195,7 @@ static uint32_t cc_calc_subb_64(CPUS390XState *env, uint64_t a1,
     return (ar != 0) + 2 * !borrow_out;
 }
 
-static inline uint32_t cc_calc_abs_64(CPUS390XState *env, int64_t dst)
+static uint32_t cc_calc_abs_64(int64_t dst)
 {
     if ((uint64_t)dst == 0x8000000000000000ULL) {
         return 3;
@@ -223,12 +206,12 @@ static inline uint32_t cc_calc_abs_64(CPUS390XState *env, int64_t dst)
     }
 }
 
-static inline uint32_t cc_calc_nabs_64(CPUS390XState *env, int64_t dst)
+static uint32_t cc_calc_nabs_64(int64_t dst)
 {
     return !!dst;
 }
 
-static inline uint32_t cc_calc_comp_64(CPUS390XState *env, int64_t dst)
+static uint32_t cc_calc_comp_64(int64_t dst)
 {
     if ((uint64_t)dst == 0x8000000000000000ULL) {
         return 3;
@@ -242,8 +225,7 @@ static inline uint32_t cc_calc_comp_64(CPUS390XState *env, int64_t dst)
 }
 
 
-static inline uint32_t cc_calc_add_32(CPUS390XState *env, int32_t a1,
-                                      int32_t a2, int32_t ar)
+static uint32_t cc_calc_add_32(int32_t a1, int32_t a2, int32_t ar)
 {
     if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
         return 3; /* overflow */
@@ -258,14 +240,12 @@ static inline uint32_t cc_calc_add_32(CPUS390XState *env, int32_t a1,
     }
 }
 
-static uint32_t cc_calc_addu_32(CPUS390XState *env, uint32_t a1,
-                                uint32_t a2, uint32_t ar)
+static uint32_t cc_calc_addu_32(uint32_t a1, uint32_t a2, uint32_t ar)
 {
     return (ar != 0) + 2 * (ar < a1);
 }
 
-static uint32_t cc_calc_addc_32(CPUS390XState *env, uint32_t a1,
-                                uint32_t a2, uint32_t ar)
+static uint32_t cc_calc_addc_32(uint32_t a1, uint32_t a2, uint32_t ar)
 {
     /* Recover a2 + carry_in.  */
     uint32_t a2c = ar - a1;
@@ -275,8 +255,7 @@ static uint32_t cc_calc_addc_32(CPUS390XState *env, uint32_t a1,
     return (ar != 0) + 2 * carry_out;
 }
 
-static inline uint32_t cc_calc_sub_32(CPUS390XState *env, int32_t a1,
-                                      int32_t a2, int32_t ar)
+static uint32_t cc_calc_sub_32(int32_t a1, int32_t a2, int32_t ar)
 {
     if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
         return 3; /* overflow */
@@ -291,8 +270,7 @@ static inline uint32_t cc_calc_sub_32(CPUS390XState *env, int32_t a1,
     }
 }
 
-static inline uint32_t cc_calc_subu_32(CPUS390XState *env, uint32_t a1,
-                                       uint32_t a2, uint32_t ar)
+static uint32_t cc_calc_subu_32(uint32_t a1, uint32_t a2, uint32_t ar)
 {
     if (ar == 0) {
         return 2;
@@ -305,8 +283,7 @@ static inline uint32_t cc_calc_subu_32(CPUS390XState *env, uint32_t a1,
     }
 }
 
-static uint32_t cc_calc_subb_32(CPUS390XState *env, uint32_t a1,
-                                uint32_t a2, uint32_t ar)
+static uint32_t cc_calc_subb_32(uint32_t a1, uint32_t a2, uint32_t ar)
 {
     /* We had borrow-in if normal subtraction isn't equal.  */
     int borrow_in = ar - (a1 - a2);
@@ -324,7 +301,7 @@ static uint32_t cc_calc_subb_32(CPUS390XState *env, uint32_t a1,
     return (ar != 0) + 2 * !borrow_out;
 }
 
-static inline uint32_t cc_calc_abs_32(CPUS390XState *env, int32_t dst)
+static uint32_t cc_calc_abs_32(int32_t dst)
 {
     if ((uint32_t)dst == 0x80000000UL) {
         return 3;
@@ -335,12 +312,12 @@ static inline uint32_t cc_calc_abs_32(CPUS390XState *env, int32_t dst)
     }
 }
 
-static inline uint32_t cc_calc_nabs_32(CPUS390XState *env, int32_t dst)
+static uint32_t cc_calc_nabs_32(int32_t dst)
 {
     return !!dst;
 }
 
-static inline uint32_t cc_calc_comp_32(CPUS390XState *env, int32_t dst)
+static uint32_t cc_calc_comp_32(int32_t dst)
 {
     if ((uint32_t)dst == 0x80000000UL) {
         return 3;
@@ -354,69 +331,80 @@ static inline uint32_t cc_calc_comp_32(CPUS390XState *env, int32_t dst)
 }
 
 /* calculate condition code for insert character under mask insn */
-static inline uint32_t cc_calc_icm_32(CPUS390XState *env, uint32_t mask,
-                                      uint32_t val)
+static uint32_t cc_calc_icm(uint64_t mask, uint64_t val)
 {
-    uint32_t cc;
-
-    HELPER_LOG("%s: mask 0x%x val %d\n", __func__, mask, val);
-    if (mask == 0xf) {
-        if (!val) {
-            return 0;
-        } else if (val & 0x80000000) {
+    if ((val & mask) == 0) {
+        return 0;
+    } else {
+        int top = clz64(mask);
+        if ((int64_t)(val << top) < 0) {
             return 1;
         } else {
             return 2;
         }
     }
+}
+
+static uint32_t cc_calc_sla_32(uint32_t src, int shift)
+{
+    uint32_t mask = ((1U << shift) - 1U) << (32 - shift);
+    uint32_t sign = 1U << 31;
+    uint32_t match;
+    int32_t r;
 
-    if (!val || !mask) {
-        cc = 0;
+    /* Check if the sign bit stays the same.  */
+    if (src & sign) {
+        match = mask;
     } else {
-        while (mask != 1) {
-            mask >>= 1;
-            val >>= 8;
-        }
-        if (val & 0x80) {
-            cc = 1;
-        } else {
-            cc = 2;
-        }
+        match = 0;
     }
-    return cc;
+    if ((src & mask) != match) {
+        /* Overflow.  */
+        return 3;
+    }
+
+    r = ((src << shift) & ~sign) | (src & sign);
+    if (r == 0) {
+        return 0;
+    } else if (r < 0) {
+        return 1;
+    }
+    return 2;
 }
 
-static inline uint32_t cc_calc_slag(CPUS390XState *env, uint64_t src,
-                                    uint64_t shift)
+static uint32_t cc_calc_sla_64(uint64_t src, int shift)
 {
     uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift);
-    uint64_t match, r;
+    uint64_t sign = 1ULL << 63;
+    uint64_t match;
+    int64_t r;
 
-    /* check if the sign bit stays the same */
-    if (src & (1ULL << 63)) {
+    /* Check if the sign bit stays the same.  */
+    if (src & sign) {
         match = mask;
     } else {
         match = 0;
     }
-
     if ((src & mask) != match) {
-        /* overflow */
+        /* Overflow.  */
         return 3;
     }
 
-    r = ((src << shift) & ((1ULL << 63) - 1)) | (src & (1ULL << 63));
-
-    if ((int64_t)r == 0) {
+    r = ((src << shift) & ~sign) | (src & sign);
+    if (r == 0) {
         return 0;
-    } else if ((int64_t)r < 0) {
+    } else if (r < 0) {
         return 1;
     }
-
     return 2;
 }
 
+static uint32_t cc_calc_flogr(uint64_t dst)
+{
+    return dst ? 2 : 0;
+}
 
-static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
+static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
                                   uint64_t src, uint64_t dst, uint64_t vr)
 {
     uint32_t r = 0;
@@ -430,107 +418,110 @@ static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
         r = cc_op;
         break;
     case CC_OP_LTGT0_32:
-        r = cc_calc_ltgt0_32(env, dst);
+        r = cc_calc_ltgt0_32(dst);
         break;
     case CC_OP_LTGT0_64:
-        r =  cc_calc_ltgt0_64(env, dst);
+        r =  cc_calc_ltgt0_64(dst);
         break;
     case CC_OP_LTGT_32:
-        r =  cc_calc_ltgt_32(env, src, dst);
+        r =  cc_calc_ltgt_32(src, dst);
         break;
     case CC_OP_LTGT_64:
-        r =  cc_calc_ltgt_64(env, src, dst);
+        r =  cc_calc_ltgt_64(src, dst);
         break;
     case CC_OP_LTUGTU_32:
-        r =  cc_calc_ltugtu_32(env, src, dst);
+        r =  cc_calc_ltugtu_32(src, dst);
         break;
     case CC_OP_LTUGTU_64:
-        r =  cc_calc_ltugtu_64(env, src, dst);
+        r =  cc_calc_ltugtu_64(src, dst);
         break;
     case CC_OP_TM_32:
-        r =  cc_calc_tm_32(env, src, dst);
+        r =  cc_calc_tm_32(src, dst);
         break;
     case CC_OP_TM_64:
-        r =  cc_calc_tm_64(env, src, dst);
+        r =  cc_calc_tm_64(src, dst);
         break;
     case CC_OP_NZ:
-        r =  cc_calc_nz(env, dst);
+        r =  cc_calc_nz(dst);
         break;
     case CC_OP_ADD_64:
-        r =  cc_calc_add_64(env, src, dst, vr);
+        r =  cc_calc_add_64(src, dst, vr);
         break;
     case CC_OP_ADDU_64:
-        r =  cc_calc_addu_64(env, src, dst, vr);
+        r =  cc_calc_addu_64(src, dst, vr);
         break;
     case CC_OP_ADDC_64:
-        r =  cc_calc_addc_64(env, src, dst, vr);
+        r =  cc_calc_addc_64(src, dst, vr);
         break;
     case CC_OP_SUB_64:
-        r =  cc_calc_sub_64(env, src, dst, vr);
+        r =  cc_calc_sub_64(src, dst, vr);
         break;
     case CC_OP_SUBU_64:
-        r =  cc_calc_subu_64(env, src, dst, vr);
+        r =  cc_calc_subu_64(src, dst, vr);
         break;
     case CC_OP_SUBB_64:
-        r =  cc_calc_subb_64(env, src, dst, vr);
+        r =  cc_calc_subb_64(src, dst, vr);
         break;
     case CC_OP_ABS_64:
-        r =  cc_calc_abs_64(env, dst);
+        r =  cc_calc_abs_64(dst);
         break;
     case CC_OP_NABS_64:
-        r =  cc_calc_nabs_64(env, dst);
+        r =  cc_calc_nabs_64(dst);
         break;
     case CC_OP_COMP_64:
-        r =  cc_calc_comp_64(env, dst);
+        r =  cc_calc_comp_64(dst);
         break;
 
     case CC_OP_ADD_32:
-        r =  cc_calc_add_32(env, src, dst, vr);
+        r =  cc_calc_add_32(src, dst, vr);
         break;
     case CC_OP_ADDU_32:
-        r =  cc_calc_addu_32(env, src, dst, vr);
+        r =  cc_calc_addu_32(src, dst, vr);
         break;
     case CC_OP_ADDC_32:
-        r =  cc_calc_addc_32(env, src, dst, vr);
+        r =  cc_calc_addc_32(src, dst, vr);
         break;
     case CC_OP_SUB_32:
-        r =  cc_calc_sub_32(env, src, dst, vr);
+        r =  cc_calc_sub_32(src, dst, vr);
         break;
     case CC_OP_SUBU_32:
-        r =  cc_calc_subu_32(env, src, dst, vr);
+        r =  cc_calc_subu_32(src, dst, vr);
         break;
     case CC_OP_SUBB_32:
-        r =  cc_calc_subb_32(env, src, dst, vr);
+        r =  cc_calc_subb_32(src, dst, vr);
         break;
     case CC_OP_ABS_32:
-        r =  cc_calc_abs_64(env, dst);
+        r =  cc_calc_abs_32(dst);
         break;
     case CC_OP_NABS_32:
-        r =  cc_calc_nabs_64(env, dst);
+        r =  cc_calc_nabs_32(dst);
         break;
     case CC_OP_COMP_32:
-        r =  cc_calc_comp_32(env, dst);
+        r =  cc_calc_comp_32(dst);
         break;
 
     case CC_OP_ICM:
-        r =  cc_calc_icm_32(env, src, dst);
+        r =  cc_calc_icm(src, dst);
         break;
-    case CC_OP_SLAG:
-        r =  cc_calc_slag(env, src, dst);
+    case CC_OP_SLA_32:
+        r =  cc_calc_sla_32(src, dst);
         break;
-
-    case CC_OP_LTGT_F32:
-        r = set_cc_f32(env, src, dst);
+    case CC_OP_SLA_64:
+        r =  cc_calc_sla_64(src, dst);
         break;
-    case CC_OP_LTGT_F64:
-        r = set_cc_f64(env, src, dst);
+    case CC_OP_FLOGR:
+        r = cc_calc_flogr(dst);
         break;
+
     case CC_OP_NZ_F32:
         r = set_cc_nz_f32(dst);
         break;
     case CC_OP_NZ_F64:
         r = set_cc_nz_f64(dst);
         break;
+    case CC_OP_NZ_F128:
+        r = set_cc_nz_f128(make_float128(src, dst));
+        break;
 
     default:
         cpu_abort(env, "Unknown CC operation: %s\n", cc_name(cc_op));
@@ -553,18 +544,6 @@ uint32_t HELPER(calc_cc)(CPUS390XState *env, uint32_t cc_op, uint64_t src,
     return do_calc_cc(env, cc_op, src, dst, vr);
 }
 
-/* insert psw mask and condition code into r1 */
-void HELPER(ipm)(CPUS390XState *env, uint32_t cc, uint32_t r1)
-{
-    uint64_t r = env->regs[r1];
-
-    r &= 0xffffffff00ffffffULL;
-    r |= (cc << 28) | ((env->psw.mask >> 40) & 0xf);
-    env->regs[r1] = r;
-    HELPER_LOG("%s: cc %d psw.mask 0x%lx r1 0x%lx\n", __func__,
-               cc, env->psw.mask, r);
-}
-
 #ifndef CONFIG_USER_ONLY
 void HELPER(load_psw)(CPUS390XState *env, uint64_t mask, uint64_t addr)
 {