aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target-s390x/cc_helper.c25
-rw-r--r--target-s390x/insn-data.def8
-rw-r--r--target-s390x/translate.c74
3 files changed, 27 insertions, 80 deletions
diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index 880e3b234d..d20342cda0 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -20,6 +20,7 @@
#include "cpu.h"
#include "helper.h"
+#include "qemu/host-utils.h"
/* #define DEBUG_HELPER */
#ifdef DEBUG_HELPER
@@ -86,13 +87,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(CPUS390XState *env, 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 +100,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(CPUS390XState *env, 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;
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 921c216b7d..f70ede9bcf 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -336,3 +336,11 @@
C(0xb989, SLBGR, RRE, Z, r1, r2, r1, 0, subb, subb64)
C(0xe399, SLB, RXY_a, Z, r1, m2_32u, new, r1_32, subb, subb32)
C(0xe389, SLBG, RXY_a, Z, r1, m2_64, r1, 0, subb, subb64)
+
+/* TEST UNDER MASK */
+ C(0x9100, TM, SI, Z, m1_8u, i2_8u, 0, 0, 0, tm32)
+ C(0xeb51, TMY, SIY, LD, m1_8u, i2_8u, 0, 0, 0, tm32)
+ D(0xa702, TMHH, RI_a, Z, r1_o, i2_16u_shl, 0, 0, 0, tm64, 48)
+ D(0xa703, TMHL, RI_a, Z, r1_o, i2_16u_shl, 0, 0, 0, tm64, 32)
+ D(0xa700, TMLH, RI_a, Z, r1_o, i2_16u_shl, 0, 0, 0, tm64, 16)
+ D(0xa701, TMLL, RI_a, Z, r1_o, i2_16u_shl, 0, 0, 0, tm64, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 5667155c4a..4e3451964f 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1514,16 +1514,6 @@ do_mh:
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0x51: /* TMY D1(B1),I2 [SIY] */
- tmp = get_address(s, 0, b2, d2); /* SIY -> this is the destination */
- tmp2 = tcg_const_i64((r1 << 4) | r3);
- tcg_gen_qemu_ld8u(tmp, tmp, get_mem_index(s));
- /* yes, this is a 32 bit operation with 64 bit tcg registers, because
- that incurs less conversions */
- cmp_64(s, tmp, tmp2, CC_OP_TM_32);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0x52: /* MVIY D1(B1),I2 [SIY] */
tmp = get_address(s, 0, b2, d2); /* SIY -> this is the destination */
tmp2 = tcg_const_i64((r1 << 4) | r3);
@@ -1672,44 +1662,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
tcg_temp_free_i64(addr);
}
-static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1,
- int i2)
-{
- TCGv_i64 tmp, tmp2;
-
- LOG_DISAS("disas_a7: op 0x%x r1 %d i2 0x%x\n", op, r1, i2);
- switch (op) {
- case 0x0: /* TMLH or TMH R1,I2 [RI] */
- case 0x1: /* TMLL or TML R1,I2 [RI] */
- case 0x2: /* TMHH R1,I2 [RI] */
- case 0x3: /* TMHL R1,I2 [RI] */
- tmp = load_reg(r1);
- tmp2 = tcg_const_i64((uint16_t)i2);
- switch (op) {
- case 0x0:
- tcg_gen_shri_i64(tmp, tmp, 16);
- break;
- case 0x1:
- break;
- case 0x2:
- tcg_gen_shri_i64(tmp, tmp, 48);
- break;
- case 0x3:
- tcg_gen_shri_i64(tmp, tmp, 32);
- break;
- }
- tcg_gen_andi_i64(tmp, tmp, 0xffff);
- cmp_64(s, tmp, tmp2, CC_OP_TM_64);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
- default:
- LOG_DISAS("illegal a7 operation 0x%x\n", op);
- gen_illegal_opcode(s);
- return;
- }
-}
-
static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
uint32_t insn)
{
@@ -2678,15 +2630,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i64(tmp3);
tcg_temp_free_i64(tmp4);
break;
- case 0x91: /* TM D1(B1),I2 [SI] */
- insn = ld_code4(env, s->pc);
- tmp = decode_si(s, insn, &i2, &b1, &d1);
- tmp2 = tcg_const_i64(i2);
- tcg_gen_qemu_ld8u(tmp, tmp, get_mem_index(s));
- cmp_64(s, tmp, tmp2, CC_OP_TM_32);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0x92: /* MVI D1(B1),I2 [SI] */
insn = ld_code4(env, s->pc);
tmp = decode_si(s, insn, &i2, &b1, &d1);
@@ -2744,13 +2687,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0xa7:
- insn = ld_code4(env, s->pc);
- r1 = (insn >> 20) & 0xf;
- op = (insn >> 16) & 0xf;
- i2 = (short)insn;
- disas_a7(env, s, op, r1, i2);
- break;
case 0xa8: /* MVCLE R1,R3,D2(B2) [RS] */
insn = ld_code4(env, s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -3945,6 +3881,16 @@ static void cout_subb64(DisasContext *s, DisasOps *o)
gen_op_update3_cc_i64(s, CC_OP_SUBB_64, o->in1, o->in2, o->out);
}
+static void cout_tm32(DisasContext *s, DisasOps *o)
+{
+ gen_op_update2_cc_i64(s, CC_OP_TM_32, o->in1, o->in2);
+}
+
+static void cout_tm64(DisasContext *s, DisasOps *o)
+{
+ gen_op_update2_cc_i64(s, CC_OP_TM_64, o->in1, o->in2);
+}
+
/* ====================================================================== */
/* The "PREPeration" generators. These initialize the DisasOps.OUT fields
with the TCG register to which we will write. Used in combination with