From patchwork Fri Oct 2 12:24:17 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hogan X-Patchwork-Id: 525493 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 150361402B6 for ; Fri, 2 Oct 2015 23:19:07 +1000 (AEST) Received: from localhost ([::1]:59535 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zi0Er-0007Nb-6t for incoming@patchwork.ozlabs.org; Fri, 02 Oct 2015 09:19:05 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54588) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZhzO7-0003Ql-IJ for qemu-devel@nongnu.org; Fri, 02 Oct 2015 08:24:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZhzO3-0007C2-SJ for qemu-devel@nongnu.org; Fri, 02 Oct 2015 08:24:35 -0400 Received: from mailapp01.imgtec.com ([195.59.15.196]:34259) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZhzO3-0007Bp-KO for qemu-devel@nongnu.org; Fri, 02 Oct 2015 08:24:31 -0400 Received: from KLMAIL01.kl.imgtec.org (unknown [192.168.5.35]) by Websense Email Security Gateway with ESMTPS id A4D4826649D22; Fri, 2 Oct 2015 13:24:27 +0100 (IST) Received: from LEMAIL01.le.imgtec.org (192.168.152.62) by KLMAIL01.kl.imgtec.org (192.168.5.35) with Microsoft SMTP Server (TLS) id 14.3.195.1; Fri, 2 Oct 2015 13:24:30 +0100 Received: from jhogan-linux.le.imgtec.org (192.168.154.110) by LEMAIL01.le.imgtec.org (192.168.152.62) with Microsoft SMTP Server (TLS) id 14.3.210.2; Fri, 2 Oct 2015 13:24:29 +0100 From: James Hogan To: Date: Fri, 2 Oct 2015 13:24:17 +0100 Message-ID: <1443788657-14537-7-git-send-email-james.hogan@imgtec.com> X-Mailer: git-send-email 2.4.9 In-Reply-To: <1443788657-14537-1-git-send-email-james.hogan@imgtec.com> References: <1443788657-14537-1-git-send-email-james.hogan@imgtec.com> MIME-Version: 1.0 X-Originating-IP: [192.168.154.110] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 195.59.15.196 Cc: James Hogan , Leon Alrae , Aurelien Jarno , Richard Henderson Subject: [Qemu-devel] [PATCH v3 6/6] tcg/mips: Support r6 SEL{NE, EQ}Z instead of MOVN/MOVZ 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 Extend MIPS movcond implementation to support the SELNEZ/SELEQZ instructions introduced in MIPS r6 (where MOVN/MOVZ have been removed). Whereas the "MOVN/MOVZ rd, rs, rt" instructions have the following semantics: rd = [!]rt ? rs : rd The "SELNEZ/SELEQZ rd, rs, rt" instructions are slightly different: rd = [!]rt ? rs : 0 First we ensure that if one of the movcond input values is zero that it comes last (we can swap the input arguments if we invert the condition). This is so that it can exactly match one of the SELNEZ/SELEQZ instructions and avoid the need to emit the other one. Otherwise we emit the opposite instruction first into a temporary register, and OR that into the result: SELNEZ/SELEQZ TMP1, v2, c1 SELEQZ/SELNEZ ret, v1, c1 OR ret, ret, TMP1 Which does the following: ret = cond ? v1 : v2 Signed-off-by: James Hogan Cc: Richard Henderson Cc: Aurelien Jarno Reviewed-by: Richard Henderson Reviewed-by: Aurelien Jarno --- Changes in v3: - Switch to using bool eqz to indicate whether to use SELEQZ / MOVZ instead of SELNEZ / MOVN (Richard). - Add tcg_debug_assert(v2 == ret) for pre-r6 case with comment to remind reader that it should be guaranteed via constraints (Richard). Changes in v2: - Combine with patch 6 from v1, and drop functional changes to movcond implementation pre-r6. We now provide different constraints for movcond depending on presence of r6. (thanks Richard for feedback). --- tcg/mips/tcg-target.c | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index a937b1475d04..eff498991096 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -314,6 +314,8 @@ typedef enum { OPC_NOR = OPC_SPECIAL | 0x27, OPC_SLT = OPC_SPECIAL | 0x2A, OPC_SLTU = OPC_SPECIAL | 0x2B, + OPC_SELEQZ = OPC_SPECIAL | 0x35, + OPC_SELNEZ = OPC_SPECIAL | 0x37, OPC_REGIMM = 0x01 << 26, OPC_BLTZ = OPC_REGIMM | (0x00 << 16), @@ -858,13 +860,20 @@ static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGReg al, TCGReg ah, } static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret, - TCGReg c1, TCGReg c2, TCGReg v) + TCGReg c1, TCGReg c2, TCGReg v1, TCGReg v2) { - MIPSInsn m_opc = OPC_MOVN; + bool eqz = false; + + /* If one of the values is zero, put it last to match SEL*Z instructions */ + if (use_mips32r6_instructions && v1 == 0) { + v1 = v2; + v2 = 0; + cond = tcg_invert_cond(cond); + } switch (cond) { case TCG_COND_EQ: - m_opc = OPC_MOVZ; + eqz = true; /* FALLTHRU */ case TCG_COND_NE: if (c2 != 0) { @@ -877,14 +886,32 @@ static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret, /* Minimize code size by preferring a compare not requiring INV. */ if (mips_cmp_map[cond] & MIPS_CMP_INV) { cond = tcg_invert_cond(cond); - m_opc = OPC_MOVZ; + eqz = true; } tcg_out_setcond(s, cond, TCG_TMP0, c1, c2); c1 = TCG_TMP0; break; } - tcg_out_opc_reg(s, m_opc, ret, v, c1); + if (use_mips32r6_instructions) { + MIPSInsn m_opc_t = eqz ? OPC_SELEQZ : OPC_SELNEZ; + MIPSInsn m_opc_f = eqz ? OPC_SELNEZ : OPC_SELEQZ; + + if (v2 != 0) { + tcg_out_opc_reg(s, m_opc_f, TCG_TMP1, v2, c1); + } + tcg_out_opc_reg(s, m_opc_t, ret, v1, c1); + if (v2 != 0) { + tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP1); + } + } else { + MIPSInsn m_opc = eqz ? OPC_MOVZ : OPC_MOVN; + + tcg_out_opc_reg(s, m_opc, ret, v1, c1); + + /* This should be guaranteed via constraints */ + tcg_debug_assert(v2 == ret); + } } static void tcg_out_call_int(TCGContext *s, tcg_insn_unit *arg, bool tail) @@ -1577,7 +1604,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_movcond_i32: - tcg_out_movcond(s, args[5], a0, a1, a2, args[3]); + tcg_out_movcond(s, args[5], a0, a1, a2, args[3], args[4]); break; case INDEX_op_setcond_i32: @@ -1666,7 +1693,11 @@ static const TCGTargetOpDef mips_op_defs[] = { { INDEX_op_deposit_i32, { "r", "0", "rZ" } }, { INDEX_op_brcond_i32, { "rZ", "rZ" } }, +#if !use_mips32r6_instructions { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "0" } }, +#else + { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "rZ" } }, +#endif { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } }, { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },