From patchwork Tue Feb 9 10:39:50 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 8259571 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 6C083BEEE5 for ; Tue, 9 Feb 2016 10:40:46 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DFD2020263 for ; Tue, 9 Feb 2016 10:40:44 +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 A883F2022D for ; Tue, 9 Feb 2016 10:40:42 +0000 (UTC) Received: from localhost ([::1]:54059 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aT5is-0006Ju-3C for patchwork-qemu-devel@patchwork.kernel.org; Tue, 09 Feb 2016 05:40:42 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46088) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aT5iW-0006FD-At for qemu-devel@nongnu.org; Tue, 09 Feb 2016 05:40:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aT5iT-0005Mg-Tc for qemu-devel@nongnu.org; Tue, 09 Feb 2016 05:40:20 -0500 Received: from mail-pf0-x243.google.com ([2607:f8b0:400e:c00::243]:35766) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aT5iT-0005Mb-FL for qemu-devel@nongnu.org; Tue, 09 Feb 2016 05:40:17 -0500 Received: by mail-pf0-x243.google.com with SMTP id 66so9830577pfe.2 for ; Tue, 09 Feb 2016 02:40:17 -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=ZUk8+TDSsJ+yOA9syqdl94DI4Q5TeqSOP7kJrcb7a2A=; b=h6FZpTlGAMdw4nD3LFIzCu1lTGNQX7O3h5D4p5jB/G/IGrwIygnaqUkDzeeM7tG+9S QEIhLKbic6QwCommLTzc9FY8phlMUIpaCWhFiiLycKTTNUKGFpAshBLS7fVwmWGAe4uh lUpdGwUIWllzfUefySEIgQwp1ctFUZkV1wupUr9yvu3+uUagPM/eE6JiICy6lz5jUtre UWLKZc4Jq6wuscu12a4w2MpIv5Y0XYEWKz8wTGnX1Z5zXv75lN7pacehqzL+Y3qm66YO 8/BlyKyNxbLYVW52mJbNv3aGv3/4laapWMVOsYFf+naN6qYg3BbWmzD1LSa9umMboglp PoHA== 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=ZUk8+TDSsJ+yOA9syqdl94DI4Q5TeqSOP7kJrcb7a2A=; b=h/VHcF3kAJT+VIr8e7dopOsDPqH8HksFBHn8v8o/01cq7Un1cfp7RDBms45Knc7ueE 1FITnrY6RNusZoSW0lWXHaIEKWdauKxle1L1gMu/k/ftwgObRVgQFwxwy8aqbxlJkicS bbqwMvcIQ91TxSutMFEU4v5dXQINGBqJwb0BGQgJtuk78fr9KFroTJziYU2+vOyVn4/S lDuvzZKbpTHepA5f8rFsGktxRH8ZBNySrl8yayHPofR0a/1kLfE1Ck7d2k86xwMfNJl0 3/F791ZHra8N6Q8BixJzeWt6EgPXKHroOuhSiFFdfH5x1/fubq2x3C077lbSsZWHEQug c14g== X-Gm-Message-State: AG10YOT4WMRIYk+C17aHqbf5uzB0uAmbS1WFH2bAzv0pXHbWtJWDH1N1q2AjvzlgB6fdEg== X-Received: by 10.98.16.86 with SMTP id y83mr49045973pfi.45.1455014416838; Tue, 09 Feb 2016 02:40:16 -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.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 09 Feb 2016 02:40:16 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Tue, 9 Feb 2016 21:39:50 +1100 Message-Id: <1455014403-10742-3-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:c00::243 Cc: james.hogan@imgtec.com, aurelien@aurel32.net Subject: [Qemu-devel] [PATCH 02/15] tcg-mips: Support 64-bit opcodes 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 Bulk patch adding 64-bit opcodes into tcg_out_op. Note that mips64 is as yet neither complete nor enabled. Signed-off-by: Richard Henderson --- tcg/mips/tcg-target.c | 372 ++++++++++++++++++++++++++++++++++++++++++++++++-- tcg/mips/tcg-target.h | 43 ++++++ 2 files changed, 403 insertions(+), 12 deletions(-) diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index 68cd896..e56dbc6 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -325,7 +325,7 @@ typedef enum { OPC_DMOD = OPC_SPECIAL | 036 | 0300, OPC_DDIVU = OPC_SPECIAL | 037, OPC_DDIVU_R6 = OPC_SPECIAL | 037 | 0200, - OPC_DMODU_R6 = OPC_SPECIAL | 037 | 0300, + OPC_DMODU = OPC_SPECIAL | 037 | 0300, OPC_ADDU = OPC_SPECIAL | 041, OPC_SUBU = OPC_SPECIAL | 043, OPC_AND = OPC_SPECIAL | 044, @@ -431,6 +431,21 @@ static inline void tcg_out_opc_bf(TCGContext *s, MIPSInsn opc, TCGReg rt, tcg_out32(s, inst); } +static inline void tcg_out_opc_bf64(TCGContext *s, MIPSInsn opc, MIPSInsn opm, + MIPSInsn oph, TCGReg rt, TCGReg rs, + int msb, int lsb) +{ + if (lsb >= 32) { + opc = oph; + msb -= 32; + lsb -= 32; + } else if (msb >= 32) { + opc = opm; + msb -= 32; + } + tcg_out_opc_bf(s, opc, rt, rs, msb, lsb); +} + /* * Type branch */ @@ -461,6 +476,18 @@ static inline void tcg_out_opc_sa(TCGContext *s, MIPSInsn opc, } +static void tcg_out_opc_sa64(TCGContext *s, MIPSInsn opc1, MIPSInsn opc2, + TCGReg rd, TCGReg rt, TCGArg sa) +{ + int32_t inst; + + inst = (sa & 32 ? opc2 : opc1); + inst |= (rt & 0x1F) << 16; + inst |= (rd & 0x1F) << 11; + inst |= (sa & 0x1F) << 6; + tcg_out32(s, inst); +} + /* * Type jump. * Returns true if the branch was in range and the insn was emitted. @@ -489,6 +516,21 @@ static inline void tcg_out_nop(TCGContext *s) tcg_out32(s, 0); } +static inline void tcg_out_dsll(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa) +{ + tcg_out_opc_sa64(s, OPC_DSLL, OPC_DSLL32, rd, rt, sa); +} + +static inline void tcg_out_dsrl(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa) +{ + tcg_out_opc_sa64(s, OPC_DSRL, OPC_DSRL32, rd, rt, sa); +} + +static inline void tcg_out_dsra(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa) +{ + tcg_out_opc_sa64(s, OPC_DSRA, OPC_DSRA32, rd, rt, sa); +} + static inline void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) { @@ -574,6 +616,80 @@ static inline void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg) } } +static inline void tcg_out_bswap32u(TCGContext *s, TCGReg ret, TCGReg arg) +{ + if (use_mips32r2_instructions) { + tcg_out_opc_reg(s, OPC_DSBH, ret, 0, arg); + tcg_out_opc_reg(s, OPC_DSHD, ret, 0, arg); + tcg_out_dsrl(s, ret, ret, 32); + } else { + /* ret and arg must be different and can't be register at */ + if (ret == arg || ret == TCG_TMP0 || arg == TCG_TMP0) { + tcg_abort(); + } + + tcg_out_dsll(s, ret, arg, 24); + + tcg_out_dsrl(s, TCG_TMP0, arg, 24); + tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0); + + tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, arg, 0xff00); + tcg_out_dsll(s, TCG_TMP0, TCG_TMP0, 8); + tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0); + + tcg_out_dsrl(s, TCG_TMP0, arg, 8); + tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, TCG_TMP0, 0xff00); + tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0); + } +} + +static void tcg_out_bswap64(TCGContext *s, TCGReg ret, TCGReg arg) +{ + if (use_mips32r2_instructions) { + tcg_out_opc_reg(s, OPC_DSBH, ret, 0, arg); + tcg_out_opc_reg(s, OPC_DSHD, ret, 0, arg); + } else { + /* ret and arg must be different and can't be either tmp reg. */ + if (ret == arg || ret == TCG_TMP0 || arg == TCG_TMP0 + || ret == TCG_TMP1 || arg == TCG_TMP1) { + tcg_abort(); + } + + /* ??? Consider just making this a subroutine. */ + + /* A... ...H -> H... ...A */ + tcg_out_dsll(s, ret, arg, 56); + tcg_out_dsrl(s, TCG_TMP0, arg, 56); + tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0); + + /* .B.. ..G. -> .G.. ..B. */ + tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, arg, 0xff00); + tcg_out_dsrl(s, TCG_TMP1, arg, 40); + tcg_out_dsll(s, TCG_TMP0, TCG_TMP0, 40); + tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00); + tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0); + tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP1); + + /* ..CD .... -> .... DC.. */ + tcg_out_dsrl(s, TCG_TMP0, arg, 32); + tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP0, 0xff00); + tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, TCG_TMP0, 0x00ff); + tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 8); + tcg_out_dsll(s, TCG_TMP0, TCG_TMP0, 24); + tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP1); + tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0); + + /* .... EF.. -> ..FE .... */ + tcg_out_dsrl(s, TCG_TMP0, arg, 16); + tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP0, 0xff00); + tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, TCG_TMP0, 0x00ff); + tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 24); + tcg_out_dsll(s, TCG_TMP0, TCG_TMP0, 40); + tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP1); + tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0); + } +} + static inline void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg) { if (use_mips32r2_instructions) { @@ -1461,28 +1577,45 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_ld8u_i32: + case INDEX_op_ld8u_i64: i1 = OPC_LBU; goto do_ldst; case INDEX_op_ld8s_i32: + case INDEX_op_ld8s_i64: i1 = OPC_LB; goto do_ldst; case INDEX_op_ld16u_i32: + case INDEX_op_ld16u_i64: i1 = OPC_LHU; goto do_ldst; case INDEX_op_ld16s_i32: + case INDEX_op_ld16s_i64: i1 = OPC_LH; goto do_ldst; case INDEX_op_ld_i32: + case INDEX_op_ld32s_i64: i1 = OPC_LW; goto do_ldst; + case INDEX_op_ld32u_i64: + i1 = OPC_LWU; + goto do_ldst; + case INDEX_op_ld_i64: + i1 = OPC_LD; + goto do_ldst; case INDEX_op_st8_i32: + case INDEX_op_st8_i64: i1 = OPC_SB; goto do_ldst; case INDEX_op_st16_i32: + case INDEX_op_st16_i64: i1 = OPC_SH; goto do_ldst; case INDEX_op_st_i32: + case INDEX_op_st32_i64: i1 = OPC_SW; + goto do_ldst; + case INDEX_op_st_i64: + i1 = OPC_SD; do_ldst: tcg_out_ldst(s, i1, a0, a1, a2); break; @@ -1490,10 +1623,15 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, case INDEX_op_add_i32: i1 = OPC_ADDU, i2 = OPC_ADDIU; goto do_binary; + case INDEX_op_add_i64: + i1 = OPC_DADDU, i2 = OPC_DADDIU; + goto do_binary; case INDEX_op_or_i32: + case INDEX_op_or_i64: i1 = OPC_OR, i2 = OPC_ORI; goto do_binary; case INDEX_op_xor_i32: + case INDEX_op_xor_i64: i1 = OPC_XOR, i2 = OPC_XORI; do_binary: if (c2) { @@ -1505,12 +1643,16 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_sub_i32: + i1 = OPC_SUBU, i2 = OPC_ADDIU; + goto do_subtract; + case INDEX_op_sub_i64: + i1 = OPC_DSUBU, i2 = OPC_DADDIU; + do_subtract: if (c2) { - tcg_out_opc_imm(s, OPC_ADDIU, a0, a1, -a2); + tcg_out_opc_imm(s, i2, a0, a1, -a2); break; } - i1 = OPC_SUBU; - goto do_binary; + goto do_binaryv; case INDEX_op_and_i32: if (c2 && a2 != (uint16_t)a2) { int msb = ctz32(~a2) - 1; @@ -1521,7 +1663,18 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, } i1 = OPC_AND, i2 = OPC_ANDI; goto do_binary; + case INDEX_op_and_i64: + if (c2 && a2 != (uint16_t)a2) { + int msb = ctz64(~a2) - 1; + assert(use_mips32r2_instructions); + assert(is_p2m1(a2)); + tcg_out_opc_bf64(s, OPC_DEXT, OPC_DEXTM, OPC_DEXTU, a0, a1, msb, 0); + break; + } + i1 = OPC_AND, i2 = OPC_ANDI; + goto do_binary; case INDEX_op_nor_i32: + case INDEX_op_nor_i64: i1 = OPC_NOR; goto do_binaryv; @@ -1573,6 +1726,55 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; } i1 = OPC_DIVU, i2 = OPC_MFHI; + goto do_hilo1; + case INDEX_op_mul_i64: + if (use_mips32r6_instructions) { + tcg_out_opc_reg(s, OPC_DMUL, a0, a1, a2); + break; + } + i1 = OPC_DMULT, i2 = OPC_MFLO; + goto do_hilo1; + case INDEX_op_mulsh_i64: + if (use_mips32r6_instructions) { + tcg_out_opc_reg(s, OPC_DMUH, a0, a1, a2); + break; + } + i1 = OPC_DMULT, i2 = OPC_MFHI; + goto do_hilo1; + case INDEX_op_muluh_i64: + if (use_mips32r6_instructions) { + tcg_out_opc_reg(s, OPC_DMUHU, a0, a1, a2); + break; + } + i1 = OPC_DMULTU, i2 = OPC_MFHI; + goto do_hilo1; + case INDEX_op_div_i64: + if (use_mips32r6_instructions) { + tcg_out_opc_reg(s, OPC_DDIV_R6, a0, a1, a2); + break; + } + i1 = OPC_DDIV, i2 = OPC_MFLO; + goto do_hilo1; + case INDEX_op_divu_i64: + if (use_mips32r6_instructions) { + tcg_out_opc_reg(s, OPC_DDIVU_R6, a0, a1, a2); + break; + } + i1 = OPC_DDIVU, i2 = OPC_MFLO; + goto do_hilo1; + case INDEX_op_rem_i64: + if (use_mips32r6_instructions) { + tcg_out_opc_reg(s, OPC_DMOD, a0, a1, a2); + break; + } + i1 = OPC_DDIV, i2 = OPC_MFHI; + goto do_hilo1; + case INDEX_op_remu_i64: + if (use_mips32r6_instructions) { + tcg_out_opc_reg(s, OPC_DMODU, a0, a1, a2); + break; + } + i1 = OPC_DDIVU, i2 = OPC_MFHI; do_hilo1: tcg_out_opc_reg(s, i1, 0, a1, a2); tcg_out_opc_reg(s, i2, a0, 0, 0); @@ -1583,6 +1785,12 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, goto do_hilo2; case INDEX_op_mulu2_i32: i1 = OPC_MULTU; + goto do_hilo2; + case INDEX_op_muls2_i64: + i1 = OPC_DMULT; + goto do_hilo2; + case INDEX_op_mulu2_i64: + i1 = OPC_DMULTU; do_hilo2: tcg_out_opc_reg(s, i1, 0, a2, args[3]); tcg_out_opc_reg(s, OPC_MFLO, a0, 0, 0); @@ -1590,20 +1798,51 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_not_i32: + case INDEX_op_not_i64: i1 = OPC_NOR; goto do_unary; case INDEX_op_bswap16_i32: + case INDEX_op_bswap16_i64: i1 = OPC_WSBH; goto do_unary; case INDEX_op_ext8s_i32: + case INDEX_op_ext8s_i64: i1 = OPC_SEB; goto do_unary; case INDEX_op_ext16s_i32: + case INDEX_op_ext16s_i64: i1 = OPC_SEH; do_unary: tcg_out_opc_reg(s, i1, a0, TCG_REG_ZERO, a1); break; + case INDEX_op_bswap32_i32: + tcg_out_bswap32(s, a0, a1); + break; + case INDEX_op_bswap32_i64: + tcg_out_bswap32u(s, a0, a1); + break; + case INDEX_op_bswap64_i64: + tcg_out_bswap64(s, a0, a1); + break; + case INDEX_op_extrh_i64_i32: + tcg_out_dsra(s, a0, a1, 32); + break; + case INDEX_op_ext32s_i64: + case INDEX_op_ext_i32_i64: + case INDEX_op_extrl_i64_i32: + tcg_out_opc_sa(s, OPC_SLL, a0, a1, 0); + break; + case INDEX_op_ext32u_i64: + case INDEX_op_extu_i32_i64: + if (use_mips32r2_instructions) { + tcg_out_opc_bf(s, OPC_DEXT, a0, a1, 31, 0); + } else { + tcg_out_dsll(s, a0, a1, 32); + tcg_out_dsrl(s, a0, a0, 32); + } + break; + case INDEX_op_sar_i32: i1 = OPC_SRAV, i2 = OPC_SRA; goto do_shift; @@ -1618,9 +1857,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, do_shift: if (c2) { tcg_out_opc_sa(s, i2, a0, a1, a2); - } else { - tcg_out_opc_reg(s, i1, a0, a2, a1); + break; } + do_shiftv: + tcg_out_opc_reg(s, i1, a0, a2, a1); break; case INDEX_op_rotl_i32: if (c2) { @@ -1630,17 +1870,53 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_opc_reg(s, OPC_ROTRV, a0, TCG_TMP0, a1); } break; - - case INDEX_op_bswap32_i32: - tcg_out_opc_reg(s, OPC_WSBH, a0, 0, a1); - tcg_out_opc_sa(s, OPC_ROTR, a0, a0, 16); + case INDEX_op_sar_i64: + if (c2) { + tcg_out_dsra(s, a0, a1, a2); + break; + } + i1 = OPC_DSRAV; + goto do_shiftv; + case INDEX_op_shl_i64: + if (c2) { + tcg_out_dsll(s, a0, a1, a2); + break; + } + i1 = OPC_DSLLV; + goto do_shiftv; + case INDEX_op_shr_i64: + if (c2) { + tcg_out_dsrl(s, a0, a1, a2); + break; + } + i1 = OPC_DSRLV; + goto do_shiftv; + case INDEX_op_rotr_i64: + if (c2) { + tcg_out_opc_sa64(s, OPC_DROTR, OPC_DROTR32, a0, a1, a2); + break; + } + i1 = OPC_DROTRV; + goto do_shiftv; + case INDEX_op_rotl_i64: + if (c2) { + tcg_out_opc_sa64(s, OPC_DROTR, OPC_DROTR32, a0, a1, 64 - a2); + } else { + tcg_out_opc_reg(s, OPC_DSUBU, TCG_TMP0, TCG_REG_ZERO, a2); + tcg_out_opc_reg(s, OPC_DROTRV, a0, TCG_TMP0, a1); + } break; case INDEX_op_deposit_i32: tcg_out_opc_bf(s, OPC_INS, a0, a2, args[3] + args[4] - 1, args[3]); break; + case INDEX_op_deposit_i64: + tcg_out_opc_bf64(s, OPC_DINS, OPC_DINSM, OPC_DINSU, a0, a2, + args[3] + args[4] - 1, args[3]); + break; case INDEX_op_brcond_i32: + case INDEX_op_brcond_i64: tcg_out_brcond(s, a2, a0, a1, arg_label(args[3])); break; case INDEX_op_brcond2_i32: @@ -1648,10 +1924,12 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_movcond_i32: + case INDEX_op_movcond_i64: tcg_out_movcond(s, args[5], a0, a1, a2, args[3], args[4]); break; case INDEX_op_setcond_i32: + case INDEX_op_setcond_i64: tcg_out_setcond(s, args[3], a0, a1, a2); break; case INDEX_op_setcond2_i32: @@ -1681,7 +1959,9 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ + case INDEX_op_mov_i64: case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */ + case INDEX_op_movi_i64: case INDEX_op_call: /* Always emitted via tcg_out_call. */ default: tcg_abort(); @@ -1743,13 +2023,81 @@ static const TCGTargetOpDef mips_op_defs[] = { { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "0" } }, #endif { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } }, - { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } }, +#if TCG_TARGET_REG_BITS == 32 { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rN", "rN" } }, { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rN", "rN" } }, + { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } }, { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } }, +#endif -#if TARGET_LONG_BITS == 32 +#if TCG_TARGET_REG_BITS == 64 + { INDEX_op_ld8u_i64, { "r", "r" } }, + { INDEX_op_ld8s_i64, { "r", "r" } }, + { INDEX_op_ld16u_i64, { "r", "r" } }, + { INDEX_op_ld16s_i64, { "r", "r" } }, + { INDEX_op_ld32s_i64, { "r", "r" } }, + { INDEX_op_ld32u_i64, { "r", "r" } }, + { INDEX_op_ld_i64, { "r", "r" } }, + { INDEX_op_st8_i64, { "rZ", "r" } }, + { INDEX_op_st16_i64, { "rZ", "r" } }, + { INDEX_op_st32_i64, { "rZ", "r" } }, + { INDEX_op_st_i64, { "rZ", "r" } }, + + { INDEX_op_add_i64, { "r", "rZ", "rJ" } }, + { INDEX_op_mul_i64, { "r", "rZ", "rZ" } }, +#if !use_mips32r6_instructions + { INDEX_op_muls2_i64, { "r", "r", "rZ", "rZ" } }, + { INDEX_op_mulu2_i64, { "r", "r", "rZ", "rZ" } }, +#endif + { INDEX_op_mulsh_i64, { "r", "rZ", "rZ" } }, + { INDEX_op_muluh_i64, { "r", "rZ", "rZ" } }, + { INDEX_op_div_i64, { "r", "rZ", "rZ" } }, + { INDEX_op_divu_i64, { "r", "rZ", "rZ" } }, + { INDEX_op_rem_i64, { "r", "rZ", "rZ" } }, + { INDEX_op_remu_i64, { "r", "rZ", "rZ" } }, + { INDEX_op_sub_i64, { "r", "rZ", "rN" } }, + + { INDEX_op_and_i64, { "r", "rZ", "rIK" } }, + { INDEX_op_nor_i64, { "r", "rZ", "rZ" } }, + { INDEX_op_not_i64, { "r", "rZ" } }, + { INDEX_op_or_i64, { "r", "rZ", "rI" } }, + { INDEX_op_xor_i64, { "r", "rZ", "rI" } }, + + { INDEX_op_shl_i64, { "r", "rZ", "ri" } }, + { INDEX_op_shr_i64, { "r", "rZ", "ri" } }, + { INDEX_op_sar_i64, { "r", "rZ", "ri" } }, + { INDEX_op_rotr_i64, { "r", "rZ", "ri" } }, + { INDEX_op_rotl_i64, { "r", "rZ", "ri" } }, + + { INDEX_op_bswap16_i64, { "r", "r" } }, + { INDEX_op_bswap32_i64, { "r", "r" } }, + { INDEX_op_bswap64_i64, { "r", "r" } }, + + { INDEX_op_ext8s_i64, { "r", "rZ" } }, + { INDEX_op_ext16s_i64, { "r", "rZ" } }, + { INDEX_op_ext32s_i64, { "r", "rZ" } }, + { INDEX_op_ext32u_i64, { "r", "rZ" } }, + { INDEX_op_ext_i32_i64, { "r", "rZ" } }, + { INDEX_op_extu_i32_i64, { "r", "rZ" } }, + { INDEX_op_extrl_i64_i32, { "r", "rZ" } }, + { INDEX_op_extrh_i64_i32, { "r", "rZ" } }, + + { INDEX_op_deposit_i64, { "r", "0", "rZ" } }, + + { INDEX_op_brcond_i64, { "rZ", "rZ" } }, +#if use_mips32r6_instructions + { INDEX_op_movcond_i64, { "r", "rZ", "rZ", "rZ", "rZ" } }, +#else + { INDEX_op_movcond_i64, { "r", "rZ", "rZ", "rZ", "0" } }, +#endif + { INDEX_op_setcond_i64, { "r", "rZ", "rZ" } }, + + { INDEX_op_qemu_ld_i32, { "L", "lZ" } }, + { INDEX_op_qemu_st_i32, { "SZ", "SZ" } }, + { INDEX_op_qemu_ld_i64, { "L", "lZ" } }, + { INDEX_op_qemu_st_i64, { "SZ", "SZ" } }, +#elif TARGET_LONG_BITS == 32 { INDEX_op_qemu_ld_i32, { "L", "lZ" } }, { INDEX_op_qemu_st_i32, { "SZ", "SZ" } }, { INDEX_op_qemu_ld_i64, { "L", "L", "lZ" } }, diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index b1cda37..3de58ae 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -26,6 +26,7 @@ #ifndef TCG_TARGET_MIPS #define TCG_TARGET_MIPS 1 +#define TCG_TARGET_REG_BITS 32 #define TCG_TARGET_INSN_UNIT_SIZE 4 #define TCG_TARGET_TLB_DISPLACEMENT_BITS 16 #define TCG_TARGET_NB_REGS 32 @@ -117,6 +118,29 @@ extern bool use_mips32r2_instructions; #define TCG_TARGET_HAS_muluh_i32 1 #define TCG_TARGET_HAS_mulsh_i32 1 +#if TCG_TARGET_REG_BITS == 64 +#define TCG_TARGET_HAS_add2_i32 0 +#define TCG_TARGET_HAS_sub2_i32 0 +#define TCG_TARGET_HAS_extrl_i64_i32 1 +#define TCG_TARGET_HAS_extrh_i64_i32 1 +#define TCG_TARGET_HAS_div_i64 1 +#define TCG_TARGET_HAS_rem_i64 1 +#define TCG_TARGET_HAS_not_i64 1 +#define TCG_TARGET_HAS_nor_i64 1 +#define TCG_TARGET_HAS_andc_i64 0 +#define TCG_TARGET_HAS_orc_i64 0 +#define TCG_TARGET_HAS_eqv_i64 0 +#define TCG_TARGET_HAS_nand_i64 0 +#define TCG_TARGET_HAS_add2_i64 0 +#define TCG_TARGET_HAS_sub2_i64 0 +#define TCG_TARGET_HAS_mulu2_i64 1 +#define TCG_TARGET_HAS_muls2_i64 1 +#define TCG_TARGET_HAS_muluh_i64 1 +#define TCG_TARGET_HAS_mulsh_i64 1 +#define TCG_TARGET_HAS_ext32s_i64 1 +#define TCG_TARGET_HAS_ext32u_i64 1 +#endif + /* optional instructions detected at runtime */ #define TCG_TARGET_HAS_movcond_i32 use_movnz_instructions #define TCG_TARGET_HAS_bswap16_i32 use_mips32r2_instructions @@ -126,11 +150,30 @@ extern bool use_mips32r2_instructions; #define TCG_TARGET_HAS_ext16s_i32 use_mips32r2_instructions #define TCG_TARGET_HAS_rot_i32 use_mips32r2_instructions +#if TCG_TARGET_REG_BITS == 64 +#define TCG_TARGET_HAS_movcond_i64 use_movnz_instructions +#define TCG_TARGET_HAS_bswap16_i64 use_mips32r2_instructions +#define TCG_TARGET_HAS_bswap32_i64 use_mips32r2_instructions +#define TCG_TARGET_HAS_bswap64_i64 use_mips32r2_instructions +#define TCG_TARGET_HAS_deposit_i64 use_mips32r2_instructions +#define TCG_TARGET_HAS_ext8s_i64 use_mips32r2_instructions +#define TCG_TARGET_HAS_ext16s_i64 use_mips32r2_instructions +#define TCG_TARGET_HAS_rot_i64 use_mips32r2_instructions +#endif + /* optional instructions automatically implemented */ #define TCG_TARGET_HAS_neg_i32 0 /* sub rd, zero, rt */ #define TCG_TARGET_HAS_ext8u_i32 0 /* andi rt, rs, 0xff */ #define TCG_TARGET_HAS_ext16u_i32 0 /* andi rt, rs, 0xffff */ +#if TCG_TARGET_REG_BITS == 64 +#define TCG_TARGET_HAS_neg_i64 0 /* sub rd, zero, rt */ +#define TCG_TARGET_HAS_ext8u_i64 0 /* andi rt, rs, 0xff */ +#define TCG_TARGET_HAS_ext16u_i64 0 /* andi rt, rs, 0xffff */ +#endif + +#define TCG_TARGET_HAS_new_ldst 1 + #ifdef __OpenBSD__ #include #else