target-s390: Convert TEST UNDER MASK

Signed-off-by: Richard Henderson <rth@twiddle.net>
master
Richard Henderson 2012-08-20 16:20:58 -07:00
parent b4e2bd3563
commit 00d2dc192f
3 changed files with 27 additions and 80 deletions

View File

@ -20,6 +20,7 @@
#include "cpu.h" #include "cpu.h"
#include "helper.h" #include "helper.h"
#include "qemu/host-utils.h"
/* #define DEBUG_HELPER */ /* #define DEBUG_HELPER */
#ifdef 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, static uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val, uint32_t mask)
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) {
if (r == 0 || mask == 0) {
return 0; return 0;
} else if (r == mask) { } else if (r == mask) {
return 3; 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 uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val, uint64_t mask)
static inline uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val,
uint32_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) {
if (r == 0 || mask == 0) {
return 0; return 0;
} else if (r == mask) { } else if (r == mask) {
return 3; return 3;
} else { } else {
while (!(mask & 0x8000)) { int top = clz64(mask);
mask <<= 1; if ((int64_t)(val << top) < 0) {
val <<= 1;
}
if (val & 0x8000) {
return 2; return 2;
} else { } else {
return 1; return 1;

View File

@ -336,3 +336,11 @@
C(0xb989, SLBGR, RRE, Z, r1, r2, r1, 0, subb, subb64) 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(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) 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)

View File

@ -1514,16 +1514,6 @@ do_mh:
tcg_temp_free_i32(tmp32_1); tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2); tcg_temp_free_i32(tmp32_2);
break; 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] */ case 0x52: /* MVIY D1(B1),I2 [SIY] */
tmp = get_address(s, 0, b2, d2); /* SIY -> this is the destination */ tmp = get_address(s, 0, b2, d2); /* SIY -> this is the destination */
tmp2 = tcg_const_i64((r1 << 4) | r3); 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); 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, static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
uint32_t insn) 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(tmp3);
tcg_temp_free_i64(tmp4); tcg_temp_free_i64(tmp4);
break; 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] */ case 0x92: /* MVI D1(B1),I2 [SI] */
insn = ld_code4(env, s->pc); insn = ld_code4(env, s->pc);
tmp = decode_si(s, insn, &i2, &b1, &d1); 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_1);
tcg_temp_free_i32(tmp32_2); tcg_temp_free_i32(tmp32_2);
break; 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] */ case 0xa8: /* MVCLE R1,R3,D2(B2) [RS] */
insn = ld_code4(env, s->pc); insn = ld_code4(env, s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2); 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); 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 /* The "PREPeration" generators. These initialize the DisasOps.OUT fields
with the TCG register to which we will write. Used in combination with with the TCG register to which we will write. Used in combination with