summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--target/s390x/helper.h2
-rw-r--r--target/s390x/mem_helper.c135
-rw-r--r--target/s390x/translate.c8
3 files changed, 78 insertions, 67 deletions
diff --git a/target/s390x/helper.h b/target/s390x/helper.h
index ea35834fc6..38194095c0 100644
--- a/target/s390x/helper.h
+++ b/target/s390x/helper.h
@@ -14,7 +14,7 @@ DEF_HELPER_4(srst, i64, env, i64, i64, i64)
 DEF_HELPER_4(clst, i64, env, i64, i64, i64)
 DEF_HELPER_FLAGS_4(mvpg, TCG_CALL_NO_WG, i32, env, i64, i64, i64)
 DEF_HELPER_4(mvst, i64, env, i64, i64, i64)
-DEF_HELPER_5(ex, i32, env, i32, i64, i64, i64)
+DEF_HELPER_4(ex, void, env, i32, i64, i64)
 DEF_HELPER_FLAGS_4(stam, TCG_CALL_NO_WG, void, env, i32, i64, i32)
 DEF_HELPER_FLAGS_4(lam, TCG_CALL_NO_WG, void, env, i32, i64, i32)
 DEF_HELPER_4(mvcle, i32, env, i32, i64, i32)
diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index a73d486165..fa03129e70 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -1245,76 +1245,87 @@ uint64_t HELPER(lra)(CPUS390XState *env, uint64_t addr)
    in other words: tricky...
    currently implemented by interpreting the cases it is most commonly used.
 */
-uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1,
-                    uint64_t addr, uint64_t ret)
+void HELPER(ex)(CPUS390XState *env, uint32_t ilen, uint64_t r1, uint64_t addr)
 {
     S390CPU *cpu = s390_env_get_cpu(env);
-    uint16_t insn = cpu_lduw_code(env, addr);
-
-    HELPER_LOG("%s: v1 0x%lx addr 0x%lx insn 0x%x\n", __func__, v1, addr,
-               insn);
-    if ((insn & 0xf0ff) == 0xd000) {
-        uint32_t l, insn2, b1, b2, d1, d2;
-
-        l = v1 & 0xff;
-        insn2 = cpu_ldl_code(env, addr + 2);
-        b1 = (insn2 >> 28) & 0xf;
-        b2 = (insn2 >> 12) & 0xf;
-        d1 = (insn2 >> 16) & 0xfff;
-        d2 = insn2 & 0xfff;
-        switch (insn & 0xf00) {
-        case 0x200:
+    uint64_t insn = cpu_lduw_code(env, addr);
+    uint8_t opc = insn >> 8;
+
+    /* Or in the contents of R1[56:63].  */
+    insn |= r1 & 0xff;
+
+    /* Load the rest of the instruction.  */
+    insn <<= 48;
+    switch (get_ilen(opc)) {
+    case 2:
+        break;
+    case 4:
+        insn |= (uint64_t)cpu_lduw_code(env, addr + 2) << 32;
+        break;
+    case 6:
+        insn |= (uint64_t)(uint32_t)cpu_ldl_code(env, addr + 2) << 16;
+        break;
+    default:
+        g_assert_not_reached();
+    }
+
+    HELPER_LOG("%s: addr 0x%lx insn 0x%" PRIx64 "\n", __func__, addr, insn);
+
+    if ((opc & 0xf0) == 0xd0) {
+        uint32_t l, b1, b2, d1, d2;
+
+        l = extract64(insn, 48, 8);
+        b1 = extract64(insn, 44, 4);
+        b2 = extract64(insn, 28, 4);
+        d1 = extract64(insn, 32, 12);
+        d2 = extract64(insn, 16, 12);
+        switch (opc & 0xf) {
+        case 0x2:
             do_helper_mvc(env, l, get_address(env, 0, b1, d1),
                           get_address(env, 0, b2, d2), 0);
-            break;
-        case 0x400:
-            cc = do_helper_nc(env, l, get_address(env, 0, b1, d1),
-                              get_address(env, 0, b2, d2), 0);
-            break;
-        case 0x500:
-            cc = do_helper_clc(env, l, get_address(env, 0, b1, d1),
-                               get_address(env, 0, b2, d2), 0);
-            break;
-        case 0x600:
-            cc = do_helper_oc(env, l, get_address(env, 0, b1, d1),
-                              get_address(env, 0, b2, d2), 0);
-            break;
-        case 0x700:
-            cc = do_helper_xc(env, l, get_address(env, 0, b1, d1),
-                              get_address(env, 0, b2, d2), 0);
-            break;
-        case 0xc00:
+            return;
+        case 0x4:
+            env->cc_op = do_helper_nc(env, l, get_address(env, 0, b1, d1),
+                                      get_address(env, 0, b2, d2), 0);
+            return;
+        case 0x5:
+            env->cc_op = do_helper_clc(env, l, get_address(env, 0, b1, d1),
+                                       get_address(env, 0, b2, d2), 0);
+            return;
+        case 0x6:
+            env->cc_op = do_helper_oc(env, l, get_address(env, 0, b1, d1),
+                                      get_address(env, 0, b2, d2), 0);
+            return;
+        case 0x7:
+            env->cc_op = do_helper_xc(env, l, get_address(env, 0, b1, d1),
+                                      get_address(env, 0, b2, d2), 0);
+            return;
+        case 0xc:
             do_helper_tr(env, l, get_address(env, 0, b1, d1),
                          get_address(env, 0, b2, d2), 0);
-            return cc;
-        case 0xd00:
-            cc = do_helper_trt(env, l, get_address(env, 0, b1, d1),
-                               get_address(env, 0, b2, d2), 0);
-            break;
-        default:
-            goto abort;
+            return;
+        case 0xd:
+            env->cc_op = do_helper_trt(env, l, get_address(env, 0, b1, d1),
+                                       get_address(env, 0, b2, d2), 0);
+            return;
         }
-    } else if ((insn & 0xff00) == 0x0a00) {
+    } else if (opc == 0x0a) {
         /* supervisor call */
-        HELPER_LOG("%s: svc %ld via execute\n", __func__, (insn | v1) & 0xff);
-        env->psw.addr = ret - 4;
-        env->int_svc_code = (insn | v1) & 0xff;
-        env->int_svc_ilen = 4;
+        env->int_svc_code = extract64(insn, 48, 8);
+        env->int_svc_ilen = ilen;
         helper_exception(env, EXCP_SVC);
-    } else if ((insn & 0xff00) == 0xbf00) {
-        uint32_t insn2, r1, r3, b2, d2;
-
-        insn2 = cpu_ldl_code(env, addr + 2);
-        r1 = (insn2 >> 20) & 0xf;
-        r3 = (insn2 >> 16) & 0xf;
-        b2 = (insn2 >> 12) & 0xf;
-        d2 = insn2 & 0xfff;
-        cc = helper_icm(env, r1, get_address(env, 0, b2, d2), r3);
-    } else {
-    abort:
-        cpu_abort(CPU(cpu),
-                  "EXECUTE on instruction prefix 0x%x not implemented\n",
-                  insn);
+        return;
+    } else if (opc == 0xbf) {
+        uint32_t r1, r3, b2, d2;
+
+        r1 = extract64(insn, 52, 4);
+        r3 = extract64(insn, 48, 4);
+        b2 = extract64(insn, 44, 4);
+        d2 = extract64(insn, 32, 12);
+        env->cc_op = helper_icm(env, r1, get_address(env, 0, b2, d2), r3);
+        return;
     }
-    return cc;
+
+    cpu_abort(CPU(cpu), "EXECUTE on instruction prefix 0x%x not implemented\n",
+              opc);
 }
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index e99fbd9f4c..c1162a134d 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -2164,14 +2164,14 @@ static ExitStatus op_ex(DisasContext *s, DisasOps *o)
        MVC inside of memcpy, which needs a helper call anyway.  So
        perhaps this doesn't bear thinking about any further.  */
 
-    TCGv_i64 tmp;
+    TCGv_i32 ilen;
 
     update_psw_addr(s);
     gen_op_calc_cc(s);
 
-    tmp = tcg_const_i64(s->next_pc);
-    gen_helper_ex(cc_op, cpu_env, cc_op, o->in1, o->in2, tmp);
-    tcg_temp_free_i64(tmp);
+    ilen = tcg_const_i32(s->next_pc - s->pc);
+    gen_helper_ex(cpu_env, ilen, o->in1, o->in2);
+    tcg_temp_free_i32(ilen);
 
     return NO_EXIT;
 }