aboutsummaryrefslogtreecommitdiff
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;
}