From patchwork Fri Jun 4 19:14:42 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 54697 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 02D58B7D24 for ; Sat, 5 Jun 2010 06:04:36 +1000 (EST) Received: from localhost ([127.0.0.1]:33546 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OKd7m-0004mY-4M for incoming@patchwork.ozlabs.org; Fri, 04 Jun 2010 16:04:14 -0400 Received: from [140.186.70.92] (port=59247 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OKcOU-0006Ff-HE for qemu-devel@nongnu.org; Fri, 04 Jun 2010 15:17:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OKcOS-0002fn-3T for qemu-devel@nongnu.org; Fri, 04 Jun 2010 15:17:26 -0400 Received: from are.twiddle.net ([75.149.56.221]:54826) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OKcOR-0002fM-PB for qemu-devel@nongnu.org; Fri, 04 Jun 2010 15:17:24 -0400 Received: from anchor.twiddle.home (anchor.twiddle.home [172.31.0.4]) by are.twiddle.net (Postfix) with ESMTPS id 329F646D; Fri, 4 Jun 2010 12:17:23 -0700 (PDT) Received: from anchor.twiddle.home (anchor.twiddle.home [127.0.0.1]) by anchor.twiddle.home (8.14.4/8.14.4) with ESMTP id o54JHMbW007326; Fri, 4 Jun 2010 12:17:22 -0700 Received: (from rth@localhost) by anchor.twiddle.home (8.14.4/8.14.4/Submit) id o54JHLjh007325; Fri, 4 Jun 2010 12:17:21 -0700 From: Richard Henderson To: qemu-devel@nongnu.org Date: Fri, 4 Jun 2010 12:14:42 -0700 Message-Id: <1275678883-7082-35-git-send-email-rth@twiddle.net> X-Mailer: git-send-email 1.7.0.1 In-Reply-To: <1275678883-7082-1-git-send-email-rth@twiddle.net> References: <1275678883-7082-1-git-send-email-rth@twiddle.net> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) Cc: agraf@suse.de, aurelien@aurel32.net Subject: [Qemu-devel] [PATCH 34/35] tcg-s390: Use COMPARE AND BRANCH instructions. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org These instructions are available with the general-instructions-extension facility. Use them if available. Signed-off-by: Richard Henderson --- tcg/s390/tcg-target.c | 102 +++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 95 insertions(+), 7 deletions(-) diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c index 691a3f5..d5c26b8 100644 --- a/tcg/s390/tcg-target.c +++ b/tcg/s390/tcg-target.c @@ -119,6 +119,15 @@ typedef enum S390Opcode { RI_OILH = 0xa50a, RI_OILL = 0xa50b, + RIE_CGIJ = 0xec7c, + RIE_CGRJ = 0xec64, + RIE_CIJ = 0xec7e, + RIE_CLGRJ = 0xec65, + RIE_CLIJ = 0xec7f, + RIE_CLGIJ = 0xec7d, + RIE_CLRJ = 0xec77, + RIE_CRJ = 0xec76, + RRE_AGR = 0xb908, RRE_CGR = 0xb920, RRE_CLGR = 0xb921, @@ -1110,6 +1119,7 @@ static void tgen64_xori(TCGContext *s, TCGReg dest, tcg_target_ulong val) static int tgen_cmp(TCGContext *s, TCGType type, TCGCond c, TCGReg r1, TCGArg c2, int c2const) { + _Bool is_unsigned = (c > TCG_COND_GT); if (c2const) { if (c2 == 0) { if (type == TCG_TYPE_I32) { @@ -1119,15 +1129,13 @@ static int tgen_cmp(TCGContext *s, TCGType type, TCGCond c, TCGReg r1, } return tcg_cond_to_ltr_cond[c]; } else { - if (c > TCG_COND_GT) { - /* unsigned */ + if (is_unsigned) { if (type == TCG_TYPE_I32) { tcg_out_insn(s, RIL, CLFI, r1, c2); } else { tcg_out_insn(s, RIL, CLGFI, r1, c2); } } else { - /* signed */ if (type == TCG_TYPE_I32) { tcg_out_insn(s, RIL, CFI, r1, c2); } else { @@ -1136,15 +1144,13 @@ static int tgen_cmp(TCGContext *s, TCGType type, TCGCond c, TCGReg r1, } } } else { - if (c > TCG_COND_GT) { - /* unsigned */ + if (is_unsigned) { if (type == TCG_TYPE_I32) { tcg_out_insn(s, RR, CLR, r1, c2); } else { tcg_out_insn(s, RRE, CLGR, r1, c2); } } else { - /* signed */ if (type == TCG_TYPE_I32) { tcg_out_insn(s, RR, CR, r1, c2); } else { @@ -1195,10 +1201,92 @@ static void tgen_branch(TCGContext *s, int cc, int labelno) } } +static void tgen_compare_branch(TCGContext *s, S390Opcode opc, int cc, + TCGReg r1, TCGReg r2, int labelno) +{ + TCGLabel* l = &s->labels[labelno]; + tcg_target_long off; + + if (l->has_value) { + off = (l->u.value - (tcg_target_long)s->code_ptr) >> 1; + } else { + /* We need to keep the offset unchanged for retranslation. */ + off = ((int16_t *)s->code_ptr)[1]; + tcg_out_reloc(s, s->code_ptr + 2, R_390_PC16DBL, labelno, -2); + } + + tcg_out16(s, (opc & 0xff00) | (r1 << 4) | r2); + tcg_out16(s, off); + tcg_out16(s, cc << 12 | (opc & 0xff)); +} + +static void tgen_compare_imm_branch(TCGContext *s, S390Opcode opc, int cc, + TCGReg r1, int i2, int labelno) +{ + TCGLabel* l = &s->labels[labelno]; + tcg_target_long off; + + if (l->has_value) { + off = (l->u.value - (tcg_target_long)s->code_ptr) >> 1; + } else { + /* We need to keep the offset unchanged for retranslation. */ + off = ((int16_t *)s->code_ptr)[1]; + tcg_out_reloc(s, s->code_ptr + 2, R_390_PC16DBL, labelno, -2); + } + + tcg_out16(s, (opc & 0xff00) | (r1 << 4) | cc); + tcg_out16(s, off); + tcg_out16(s, (i2 << 8) | (opc & 0xff)); +} + static void tgen_brcond(TCGContext *s, TCGType type, TCGCond c, TCGReg r1, TCGArg c2, int c2const, int labelno) { - int cc = tgen_cmp(s, type, c, r1, c2, c2const); + int cc; + + if (facilities & FACILITY_GEN_INST_EXT) { + _Bool is_unsigned = (c > TCG_COND_GT); + _Bool in_range; + S390Opcode opc; + + cc = tcg_cond_to_s390_cond[c]; + + if (!c2const) { + opc = (type == TCG_TYPE_I32 + ? (is_unsigned ? RIE_CLRJ : RIE_CRJ) + : (is_unsigned ? RIE_CLGRJ : RIE_CGRJ)); + tgen_compare_branch(s, opc, cc, r1, c2, labelno); + return; + } + + /* COMPARE IMMEDIATE AND BRANCH RELATIVE has an 8-bit immediate field. + If the immediate we've been given does not fit that range, we'll + fall back to separate compare and branch instructions using the + larger comparison range afforded by COMPARE IMMEDIATE. */ + if (type == TCG_TYPE_I32) { + if (is_unsigned) { + opc = RIE_CLIJ; + in_range = (uint32_t)c2 == (uint8_t)c2; + } else { + opc = RIE_CIJ; + in_range = (int32_t)c2 == (int8_t)c2; + } + } else { + if (is_unsigned) { + opc = RIE_CLGIJ; + in_range = (uint64_t)c2 == (uint8_t)c2; + } else { + opc = RIE_CGIJ; + in_range = (int64_t)c2 == (int8_t)c2; + } + } + if (in_range) { + tgen_compare_imm_branch(s, opc, cc, r1, c2, labelno); + return; + } + } + + cc = tgen_cmp(s, type, c, r1, c2, c2const); tgen_branch(s, cc, labelno); }