From patchwork Sun Sep 9 21:05:38 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 182727 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 727E82C0087 for ; Mon, 10 Sep 2012 09:04:05 +1000 (EST) Received: from localhost ([::1]:54830 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TAqXr-0000jI-I6 for incoming@patchwork.ozlabs.org; Sun, 09 Sep 2012 19:04:03 -0400 Received: from eggs.gnu.org ([208.118.235.92]:57126) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TAojJ-00007f-8a for qemu-devel@nongnu.org; Sun, 09 Sep 2012 17:07:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TAojH-0006D9-32 for qemu-devel@nongnu.org; Sun, 09 Sep 2012 17:07:45 -0400 Received: from mail-pb0-f45.google.com ([209.85.160.45]:63857) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TAojG-0005xl-Tk for qemu-devel@nongnu.org; Sun, 09 Sep 2012 17:07:43 -0400 Received: by mail-pb0-f45.google.com with SMTP id rp12so292285pbb.4 for ; Sun, 09 Sep 2012 14:07:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=B3N0Rpd+6JuzwhUKjqO8k9gOpIarbL0dSVOJFmuPqzw=; b=aivvY6WXGpnQd18AsqZ1kCupi7iMxZcMDYXCAhzIj6whZI0B1NO9ETq9ONNAfmni3t h4g8qGGSVLKW2u+hxV5wwvhAPHSUl/Dt5nTlXvqM53OWVnU7fv5IrcWpO40S72xB2qua ytFiEsdhS7WTzRwBguWl4B35aWEkfXQxrP6MdTli+Xe7pakUPUDlCoWo98otVwOJChua ZNpuJ8desjcjef1pXUhJJCe+GKTDgYCGQz5yJKPJ1nz+Vj+NycianIq2RjYt2KS0nTtk 3Ah4R8ajRMADhSwhgLcXHGaqxojH21zbAki5MoCwTMLpAr2IXJgH7ZYnGQgGSR7Aki2c fcIw== Received: by 10.66.78.99 with SMTP id a3mr18096052pax.22.1347224862662; Sun, 09 Sep 2012 14:07:42 -0700 (PDT) Received: from anchor.twiddle.home ([173.160.232.49]) by mx.google.com with ESMTPS id tw5sm662053pbc.48.2012.09.09.14.07.41 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 09 Sep 2012 14:07:42 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sun, 9 Sep 2012 14:05:38 -0700 Message-Id: <1347224784-19472-81-git-send-email-rth@twiddle.net> X-Mailer: git-send-email 1.7.11.4 In-Reply-To: <1347224784-19472-1-git-send-email-rth@twiddle.net> References: <1347224784-19472-1-git-send-email-rth@twiddle.net> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.160.45 Cc: Alexander Graf Subject: [Qemu-devel] [PATCH 080/126] target-s390: Convert FLOGR X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Richard Henderson --- target-s390x/cc_helper.c | 8 ++++++ target-s390x/cpu.h | 2 ++ target-s390x/helper.h | 2 +- target-s390x/insn-data.def | 3 +++ target-s390x/int_helper.c | 22 +++------------- target-s390x/translate.c | 65 +++++++++++++++++++++++++--------------------- 6 files changed, 53 insertions(+), 49 deletions(-) diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c index 27aac03..46c6d84 100644 --- a/target-s390x/cc_helper.c +++ b/target-s390x/cc_helper.c @@ -399,6 +399,11 @@ static uint32_t cc_calc_sla_64(uint64_t src, int shift) return 2; } +static uint32_t cc_calc_flogr(uint64_t dst) +{ + return dst ? 2 : 0; +} + static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst, uint64_t vr) { @@ -504,6 +509,9 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, case CC_OP_SLA_64: r = cc_calc_sla_64(src, dst); break; + case CC_OP_FLOGR: + r = cc_calc_flogr(dst); + break; case CC_OP_NZ_F32: r = set_cc_nz_f32(dst); diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 37a91d3..e7d37f3 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -472,6 +472,7 @@ enum cc_op { CC_OP_ICM, /* insert characters under mask */ CC_OP_SLA_32, /* Calculate shift left signed (32bit) */ CC_OP_SLA_64, /* Calculate shift left signed (64bit) */ + CC_OP_FLOGR, /* find leftmost one */ CC_OP_MAX }; @@ -515,6 +516,7 @@ static const char *cc_names[] = { [CC_OP_ICM] = "CC_OP_ICM", [CC_OP_SLA_32] = "CC_OP_SLA_32", [CC_OP_SLA_64] = "CC_OP_SLA_64", + [CC_OP_FLOGR] = "CC_OP_FLOGR", }; static inline const char *cc_name(int cc_op) diff --git a/target-s390x/helper.h b/target-s390x/helper.h index 7d8efec..0ba0342 100644 --- a/target-s390x/helper.h +++ b/target-s390x/helper.h @@ -80,7 +80,7 @@ DEF_HELPER_4(msdb, i64, env, i64, i64, i64) DEF_HELPER_FLAGS_2(tceb, TCG_CALL_PURE | TCG_CALL_CONST, i32, i64, i64) DEF_HELPER_FLAGS_2(tcdb, TCG_CALL_PURE | TCG_CALL_CONST, i32, i64, i64) DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_PURE | TCG_CALL_CONST, i32, i64, i64, i64) -DEF_HELPER_3(flogr, i32, env, i32, i64) +DEF_HELPER_FLAGS_1(clz, TCG_CALL_PURE | TCG_CALL_CONST, i64, i64) DEF_HELPER_2(sqeb, i64, env, i64) DEF_HELPER_2(sqdb, i64, env, i64) DEF_HELPER_3(sqxb, i64, env, i64, i64) diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def index e3ca83c..f08a37e 100644 --- a/target-s390x/insn-data.def +++ b/target-s390x/insn-data.def @@ -220,6 +220,9 @@ /* EXTRACT FPC */ C(0xb38c, EFPC, RRE, Z, 0, 0, new, r1_32, efpc, 0) +/* FIND LEFTMOST ONE */ + C(0xb983, FLOGR, RRE, EI, 0, r2_o, r1_P, 0, flogr, 0) + /* INSERT CHARACTER */ C(0x4300, IC, RX_a, Z, 0, m2_8u, 0, r1_8, mov2, 0) C(0xe373, ICY, RXY_a, LD, 0, m2_8u, 0, r1_8, mov2, 0) diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c index f2f420c..00f764c 100644 --- a/target-s390x/int_helper.c +++ b/target-s390x/int_helper.c @@ -165,26 +165,10 @@ int64_t HELPER(nabs_i64)(int64_t val) } } -/* find leftmost one */ -uint32_t HELPER(flogr)(CPUS390XState *env, uint32_t r1, uint64_t v2) +/* count leading zeros, for find leftmost one */ +uint64_t HELPER(clz)(uint64_t v) { - uint64_t res = 0; - uint64_t ov2 = v2; - - while (!(v2 & 0x8000000000000000ULL) && v2) { - v2 <<= 1; - res++; - } - - if (!v2) { - env->regs[r1] = 64; - env->regs[r1 + 1] = 0; - return 0; - } else { - env->regs[r1] = res; - env->regs[r1 + 1] = ov2 & ~(0x8000000000000000ULL >> res); - return 2; - } + return clz64(v); } uint64_t HELPER(cvd)(int32_t bin) diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 2326387..f07bed1 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -618,6 +618,7 @@ static void gen_op_calc_cc(DisasContext *s) case CC_OP_COMP_64: case CC_OP_NZ_F32: case CC_OP_NZ_F64: + case CC_OP_FLOGR: /* 1 argument */ gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, dummy, cc_dst, dummy); break; @@ -850,6 +851,20 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask) account_inline_branch(s, old_cc_op); break; + case CC_OP_FLOGR: + switch (mask & 0xa) { + case 8: /* src == 0 -> no one bit found */ + cond = TCG_COND_EQ; + break; + case 2: /* src != 0 -> one bit found */ + cond = TCG_COND_NE; + break; + default: + goto do_dynamic; + } + account_inline_branch(s, old_cc_op); + break; + default: do_dynamic: /* Calculate cc value. */ @@ -886,6 +901,7 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask) case CC_OP_LTGT0_64: case CC_OP_NZ: + case CC_OP_FLOGR: c->u.s64.a = cc_dst; c->u.s64.b = tcg_const_i64(0); c->g1 = true; @@ -1410,28 +1426,6 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2) #undef FP_HELPER } -static void disas_b9(DisasContext *s, int op, int r1, int r2) -{ - TCGv_i64 tmp; - TCGv_i32 tmp32_1; - - LOG_DISAS("disas_b9: op 0x%x r1 %d r2 %d\n", op, r1, r2); - switch (op) { - case 0x83: /* FLOGR R1,R2 [RRE] */ - tmp = load_reg(r2); - tmp32_1 = tcg_const_i32(r1); - gen_helper_flogr(cc_op, cpu_env, tmp32_1, tmp); - set_cc_static(s); - tcg_temp_free_i64(tmp); - tcg_temp_free_i32(tmp32_1); - break; - default: - LOG_DISAS("illegal b9 operation 0x%x\n", op); - gen_illegal_opcode(s); - break; - } -} - static void disas_s390_insn(DisasContext *s) { unsigned char opc; @@ -1455,13 +1449,6 @@ static void disas_s390_insn(DisasContext *s) r2 = insn & 0xf; disas_b3(s, op, r3, r1, r2); break; - case 0xb9: - insn = ld_code4(s->pc); - r1 = (insn >> 4) & 0xf; - r2 = insn & 0xf; - op = (insn >> 16) & 0xff; - disas_b9(s, op, r1, r2); - break; default: qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc); gen_illegal_opcode(s); @@ -2281,6 +2268,26 @@ static ExitStatus op_ex(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_flogr(DisasContext *s, DisasOps *o) +{ + /* We'll use the original input for cc computation, since we get to + compare that against 0, which ought to be better than comparing + the real output against 64. It also lets cc_dst be a convenient + temporary during our computation. */ + gen_op_update1_cc_i64(s, CC_OP_FLOGR, o->in2); + + /* R1 = IN ? CLZ(IN) : 64. */ + gen_helper_clz(o->out, o->in2); + + /* R1+1 = IN & ~(found bit). Note that we may attempt to shift this + value by 64, which is undefined. But since the shift is 64 iff the + input is zero, we still get the correct result after and'ing. */ + tcg_gen_movi_i64(o->out2, 0x8000000000000000ull); + tcg_gen_shr_i64(o->out2, o->out2, o->out); + tcg_gen_andc_i64(o->out2, cc_dst, o->out2); + return NO_EXIT; +} + static ExitStatus op_icm(DisasContext *s, DisasOps *o) { int m3 = get_field(s->fields, m3);