From patchwork Tue Feb 9 10:40:02 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 8259791 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id CF09B9F8AA for ; Tue, 9 Feb 2016 10:44:50 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C9DA120263 for ; Tue, 9 Feb 2016 10:44:49 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id BFD4B2022D for ; Tue, 9 Feb 2016 10:44:48 +0000 (UTC) Received: from localhost ([::1]:54105 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aT5mq-0005N8-6E for patchwork-qemu-devel@patchwork.kernel.org; Tue, 09 Feb 2016 05:44:48 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46408) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aT5j4-00072h-SL for qemu-devel@nongnu.org; Tue, 09 Feb 2016 05:40:59 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aT5j0-0005TW-Bb for qemu-devel@nongnu.org; Tue, 09 Feb 2016 05:40:54 -0500 Received: from mail-pa0-x243.google.com ([2607:f8b0:400e:c03::243]:36386) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aT5iz-0005TQ-Va for qemu-devel@nongnu.org; Tue, 09 Feb 2016 05:40:50 -0500 Received: by mail-pa0-x243.google.com with SMTP id sv5so3718487pab.3 for ; Tue, 09 Feb 2016 02:40:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=LlPKBzjToPiDY1QWGd5Vws6XUsUB6m3ZBIaU8fsFvTg=; b=o0xcWcsXbc8AXvLW1mgodNkr0nJ/nsyulmvwZV5Lh0aJou50FXMQyYrOfHlNGbdLOs Tss7ismckL+aA4nvlAYdG9IlZRnN3PzQcYsE0Qx/PjnIc/cX5n5B+GU7jh8nLNho2jnL 6yqw+9OKijN2Szd5mOf/J7QHrsDH+sVnb3TJ/nWCAWzNYeUzQxLxhfw2yC2JrE7j9DGq B+ilXpXHqRM0qGlaQTXgbBP3o/jOR8LlP4oMgr2I+u2OC6ghJXGXejziSDl+wEX6WpNU KAryA5Kr8D9KMQLQmV8887vJds6oZvo/ql01Ouk10pU8DHnKP5DsjnpPrPiBlOSkbE/a p3nA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=LlPKBzjToPiDY1QWGd5Vws6XUsUB6m3ZBIaU8fsFvTg=; b=OTfOOZjDWLiAMKT1R+qMYlHHpI/DEzHWVsKDv5vwRIeeUMSK7QalQM9A/nnklB4/Pj RGQm7c9xbdVPHvImhQPxJy4iTXUw8ZLZ9VU5oCbl6jlI6yZeCjwj5hUG6e9f0a4wtQq/ CQOPKGakyMUiRJEm2zk32SsYOu7phBuM4mfIVKUoohlCC6w7wjcZ9zrx8iM9dpVzE1V0 biVsd4tY/UP4bZ8TLlPJldcBxSss4C0x3wj1sdyE9x2pR85wdZRzf8ogUq8V33j/9eUs odBU2ZPAg36FqOBa16eGuxx8oVyyw4YZM4OQ6JpNHxb3etiwIqHMc35ZOaa5l44YbpaH z5/g== X-Gm-Message-State: AG10YORbO4nEm327J+OYZUSuUWPFjHsTPtAjmGYpEaVfj8/1dT10j5bWSUbwoYykZrZZjQ== X-Received: by 10.66.142.73 with SMTP id ru9mr49311253pab.121.1455014449283; Tue, 09 Feb 2016 02:40:49 -0800 (PST) Received: from bigtime.gateway (alanje.lnk.telstra.net. [120.151.179.201]) by smtp.gmail.com with ESMTPSA id 1sm49669183pfm.10.2016.02.09.02.40.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 09 Feb 2016 02:40:48 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Tue, 9 Feb 2016 21:40:02 +1100 Message-Id: <1455014403-10742-15-git-send-email-rth@twiddle.net> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1455014403-10742-1-git-send-email-rth@twiddle.net> References: <1455014403-10742-1-git-send-email-rth@twiddle.net> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:400e:c03::243 Cc: james.hogan@imgtec.com, aurelien@aurel32.net Subject: [Qemu-devel] [PATCH 14/15] tcg-mips: Use mipsr6 instructions in branches 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+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Using compact branches, when possible, avoids a delay slot nop. Signed-off-by: Richard Henderson --- include/elf.h | 4 + tcg/mips/tcg-target.c | 216 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 172 insertions(+), 48 deletions(-) diff --git a/include/elf.h b/include/elf.h index 1098d21..6e52ba0 100644 --- a/include/elf.h +++ b/include/elf.h @@ -352,6 +352,10 @@ typedef struct { #define R_MIPS_CALLHI16 30 #define R_MIPS_CALLLO16 31 /* + * Incomplete list of MIPS R6 relocation types. + */ +#define R_MIPS_PC26_S2 61 +/* * This range is reserved for vendor specific relocations. */ #define R_MIPS_LOVENDOR 100 diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index e0972ba..06e15d4 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -152,6 +152,19 @@ static inline void reloc_pc16(tcg_insn_unit *pc, tcg_insn_unit *target) *pc = deposit32(*pc, 0, 16, reloc_pc16_val(pc, target)); } +static inline uint32_t reloc_pc26_val(tcg_insn_unit *pc, tcg_insn_unit *target) +{ + /* Let the compiler perform the right-shift as part of the arithmetic. */ + ptrdiff_t disp = target - (pc + 1); + assert(disp == sextract32(disp, 0, 26)); + return disp & 0x1ffffff; +} + +static inline void reloc_pc26(tcg_insn_unit *pc, tcg_insn_unit *target) +{ + *pc = deposit32(*pc, 0, 26, reloc_pc16_val(pc, target)); +} + static inline uint32_t reloc_26_val(tcg_insn_unit *pc, tcg_insn_unit *target) { assert((((uintptr_t)pc ^ (uintptr_t)target) & 0xf0000000) == 0); @@ -166,9 +179,17 @@ static inline void reloc_26(tcg_insn_unit *pc, tcg_insn_unit *target) static void patch_reloc(tcg_insn_unit *code_ptr, int type, intptr_t value, intptr_t addend) { - assert(type == R_MIPS_PC16); assert(addend == 0); - reloc_pc16(code_ptr, (tcg_insn_unit *)value); + switch (type) { + case R_MIPS_PC16: + reloc_pc16(code_ptr, (tcg_insn_unit *)value); + break; + case R_MIPS_PC26_S2: + reloc_pc26(code_ptr, (tcg_insn_unit *)value); + break; + default: + tcg_abort(); + } } #define TCG_CT_CONST_ZERO 0x100 @@ -309,7 +330,10 @@ typedef enum { OPC_BEQ = 004 << 26, OPC_BNE = 005 << 26, OPC_BLEZ = 006 << 26, + OPC_BGEUC = OPC_BLEZ, /* R6: rs != 0, rt != 0, rs != rt */ OPC_BGTZ = 007 << 26, + OPC_BLTUC = OPC_BGTZ, /* R6: rs != 0, rt != 0, rs != rt */ + OPC_BEQC = 010 << 26, /* R6: rs > rt */ OPC_ADDIU = 011 << 26, OPC_SLTI = 012 << 26, OPC_SLTIU = 013 << 26, @@ -318,6 +342,9 @@ typedef enum { OPC_XORI = 016 << 26, OPC_LUI = 017 << 26, OPC_AUI = OPC_LUI, + OPC_BGEC = 026 << 26, + OPC_BLTC = 027 << 26, + OPC_BNEC = 030 << 26, /* R6: rs > rt */ OPC_DADDIU = 031 << 26, OPC_DAUI = 035 << 26, OPC_LB = 040 << 26, @@ -329,6 +356,7 @@ typedef enum { OPC_SB = 050 << 26, OPC_SH = 051 << 26, OPC_SW = 053 << 26, + OPC_BC = 062 << 26, OPC_LD = 067 << 26, OPC_SD = 077 << 26, @@ -527,6 +555,17 @@ static inline void tcg_out_opc_br(TCGContext *s, MIPSInsn opc, tcg_out_opc_imm(s, opc, rt, rs, offset); } +static void tcg_out_opc_br_pc16(TCGContext *s, MIPSInsn opc, + TCGReg arg1, TCGReg arg2, TCGLabel *l) +{ + tcg_out_opc_br(s, opc, arg1, arg2); + if (l->has_value) { + reloc_pc16(s->code_ptr - 1, l->u.value_ptr); + } else { + tcg_out_reloc(s, s->code_ptr - 1, R_MIPS_PC16, l, 0); + } +} + /* * Type sa */ @@ -1002,59 +1041,129 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1, [TCG_COND_GE] = OPC_BGEZ, }; - MIPSInsn s_opc = OPC_SLTU; - MIPSInsn b_opc; - int cmp_map; + MIPSInsn b_opc = 0; + bool compact = false; + int cmp_map, t; + + /* We shouldn't expect to have arg1 == arg2, as the TCG optimizer + should have eliminated all such. However, the R6 encodings do + not allow this situation, so e.g. if the optimizer is disabled + we must fall back to normal compares. */ + if (use_mips32r6_instructions && arg1 != arg2) { + switch (cond) { + case TCG_COND_EQ: + case TCG_COND_NE: + if (arg1 < arg2) { + t = arg1, arg1 = arg2, arg2 = t; + } + b_opc = cond == TCG_COND_EQ ? OPC_BEQC : OPC_BNEC; + compact = true; + break; - switch (cond) { - case TCG_COND_EQ: - b_opc = OPC_BEQ; - break; - case TCG_COND_NE: - b_opc = OPC_BNE; - break; + case TCG_COND_LE: + case TCG_COND_GT: + if (arg1 == TCG_REG_ZERO) { + break; + } + /* Swap arguments to turn LE to GE or GT to LT. + This also produces BLEZC/BGTZC when arg2 = 0. */ + t = arg1, arg1 = arg2, arg2 = t; + b_opc = cond == TCG_COND_LE ? OPC_BGEC : OPC_BLTC; + compact = true; + break; - case TCG_COND_LT: - case TCG_COND_GT: - case TCG_COND_LE: - case TCG_COND_GE: - if (arg2 == 0) { - b_opc = b_zero[cond]; - arg2 = arg1; - arg1 = 0; + case TCG_COND_GE: + case TCG_COND_LT: + if (arg1 == TCG_REG_ZERO) { + break; + } + /* The encoding of BGEZC/BLTZC requires rs = rt. */ + if (arg2 == TCG_REG_ZERO) { + arg2 = arg1; + } + b_opc = cond == TCG_COND_GE ? OPC_BGEC : OPC_BLTC; + compact = true; break; - } - s_opc = OPC_SLT; - /* FALLTHRU */ - case TCG_COND_LTU: - case TCG_COND_GTU: - case TCG_COND_LEU: - case TCG_COND_GEU: - cmp_map = mips_cmp_map[cond]; - if (cmp_map & MIPS_CMP_SWAP) { - TCGReg t = arg1; - arg1 = arg2; - arg2 = t; + case TCG_COND_LEU: + /* Swap arguments to turn LE to GE. */ + t = arg1, arg1 = arg2, arg2 = t; + /* FALLTHRU */ + case TCG_COND_GEU: + b_opc = OPC_BGEUC; + compact = true; + break; + + case TCG_COND_GTU: + /* Swap arguments to turn GT to LT. */ + t = arg1, arg1 = arg2, arg2 = t; + /* FALLTHRU */ + case TCG_COND_LTU: + b_opc = OPC_BLTUC; + compact = true; + break; + + default: + tcg_abort(); + break; } - tcg_out_opc_reg(s, s_opc, TCG_TMP0, arg1, arg2); - b_opc = (cmp_map & MIPS_CMP_INV ? OPC_BEQ : OPC_BNE); - arg1 = TCG_TMP0; - arg2 = TCG_REG_ZERO; - break; + } - default: - tcg_abort(); - break; + if (b_opc == 0) { + MIPSInsn s_opc = OPC_SLTU; + + switch (cond) { + case TCG_COND_EQ: + b_opc = OPC_BEQ; + break; + case TCG_COND_NE: + b_opc = OPC_BNE; + break; + + case TCG_COND_LT: + case TCG_COND_GT: + case TCG_COND_LE: + case TCG_COND_GE: + if (arg2 == 0) { + b_opc = b_zero[cond]; + arg2 = arg1; + arg1 = 0; + break; + } + s_opc = OPC_SLT; + /* FALLTHRU */ + + case TCG_COND_LTU: + case TCG_COND_GTU: + case TCG_COND_LEU: + case TCG_COND_GEU: + cmp_map = mips_cmp_map[cond]; + if (cmp_map & MIPS_CMP_SWAP) { + TCGReg t = arg1; + arg1 = arg2; + arg2 = t; + } + tcg_out_opc_reg(s, s_opc, TCG_TMP0, arg1, arg2); + if (use_mips32r6_instructions) { + b_opc = (cmp_map & MIPS_CMP_INV ? OPC_BEQC : OPC_BNEC); + compact = true; + } else { + b_opc = (cmp_map & MIPS_CMP_INV ? OPC_BEQ : OPC_BNE); + } + arg1 = TCG_TMP0; + arg2 = TCG_REG_ZERO; + break; + + default: + tcg_abort(); + break; + } } - tcg_out_opc_br(s, b_opc, arg1, arg2); - if (l->has_value) { - reloc_pc16(s->code_ptr - 1, l->u.value_ptr); - } else { - tcg_out_reloc(s, s->code_ptr - 1, R_MIPS_PC16, l, 0); + tcg_out_opc_br_pc16(s, b_opc, arg1, arg2, l); + if (!compact) { + tcg_out_nop(s); } - tcg_out_nop(s); } static TCGReg tcg_out_reduce_eq2(TCGContext *s, TCGReg tmp0, TCGReg tmp1, @@ -1826,8 +1935,19 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, s->tb_next_offset[a0] = tcg_current_code_size(s); break; case INDEX_op_br: - tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, - arg_label(a0)); + { + TCGLabel *l = arg_label(a0); + if (use_mips32r6_instructions) { + tcg_out32(s, OPC_BC); + if (l->has_value) { + reloc_pc26(s->code_ptr - 1, l->u.value_ptr); + } else { + tcg_out_reloc(s, s->code_ptr - 1, R_MIPS_PC26_S2, l, 0); + } + } else { + tcg_out_opc_br_pc16(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO, l); + } + } break; case INDEX_op_ld8u_i32: