From patchwork Tue Mar 12 13:15:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Palmer Dabbelt X-Patchwork-Id: 1055404 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=sifive.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=sifive.com header.i=@sifive.com header.b="nLltYaSB"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44JbYq5bhjz9s6w for ; Wed, 13 Mar 2019 00:34:55 +1100 (AEDT) Received: from localhost ([127.0.0.1]:52579 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h3hYT-0006Hy-Nf for incoming@patchwork.ozlabs.org; Tue, 12 Mar 2019 09:34:53 -0400 Received: from eggs.gnu.org ([209.51.188.92]:54982) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h3hU4-00035N-Pg for qemu-devel@nongnu.org; Tue, 12 Mar 2019 09:30:24 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1h3hHC-0000PJ-Jf for qemu-devel@nongnu.org; Tue, 12 Mar 2019 09:17:06 -0400 Received: from mail-pg1-x52c.google.com ([2607:f8b0:4864:20::52c]:38521) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1h3hHC-0000Nz-BL for qemu-devel@nongnu.org; Tue, 12 Mar 2019 09:17:02 -0400 Received: by mail-pg1-x52c.google.com with SMTP id m2so1820039pgl.5 for ; Tue, 12 Mar 2019 06:17:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; h=subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding:cc:from:to; bh=OPUNxKf4mTX+Vnf601r72Ss5k2kVOhk1wPtz3HBIudU=; b=nLltYaSBECwavrrh52909PFn2C11gb1tSzkbliy5MSv5Rlie3JVDygtybhNmGI4NzF SUDQhY+ecq5STHRtqXQYfmRo20GNptU+l7EaLJNboeJu2PjdBSMAjEWq3BqFNnGG+5xQ 2knb83GptljsANt0BGFa4r1KwHIdhkXnthof+zfQ8zi4oCmmVf/repkfFTf/7TXGAOEg T/Yay299FWx//cBSwAc2BcTww5mYE1PBbsEuc7kl2B0ssvSEQn44tDzLAmzhmSPnwLoL g2J+zh5WAsiuF2c8Ev2j/hii7cWPXj4hIcCv9FGVKG7gGP1s1ikMXqTdFDdUBd64yh8w goPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:cc:from:to; bh=OPUNxKf4mTX+Vnf601r72Ss5k2kVOhk1wPtz3HBIudU=; b=DdTEsAAQ9qotRorYQ3a4JFj9D7vzfyQFafzbm2ZplcWF1D3WWQbkUFgW7tLOTewVpQ Hz9jxc0j06BrrF3JYPs3oOZEd/8UBw8AZDAbPJwnsl9jXuNT0x0SspuT5l9ydko/L6TH MZrhbpJ7WVp4V2JrGr9HoWhsksMlGR495HxH554j/LinjvhKp6xXSUHZxA4QZH4e8E2R qZjM8I8X/pmz4A29M0Pxi3OEkJYzfGUnGPMYzCfpFCkCCp6HSDEIPf6twieL5yPXKcBL 76JCEStWiGeo29aCc7OHIbpRFqH/iOm0S2WkfUEJOobMC602ZxEZn9g0SEf+Soz6D94T kLqg== X-Gm-Message-State: APjAAAUw2/IhQIS/zPPzENKFJmGw7UBppQTKGXJh0DNDT/MkFkc7GYF+ YHhRdW3OCvflpO3w/WPy/c+exrn9g5/D6veX X-Google-Smtp-Source: APXvYqx4cHbGoiXudBG9mEBlHNV+CZhxSAyMbFTXpk+E+Utsl0cacKWraYIvObSDp7sQwCir0ft6Bg== X-Received: by 2002:a62:1f5d:: with SMTP id f90mr38312961pff.104.1552396620021; Tue, 12 Mar 2019 06:17:00 -0700 (PDT) Received: from localhost (2001-b011-7001-120c-5816-f057-fc2f-b780.dynamic-ip6.hinet.net. [2001:b011:7001:120c:5816:f057:fc2f:b780]) by smtp.gmail.com with ESMTPSA id n75sm17343899pfb.39.2019.03.12.06.16.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 12 Mar 2019 06:16:59 -0700 (PDT) Date: Tue, 12 Mar 2019 06:15:23 -0700 Message-Id: <20190312131526.14710-27-palmer@sifive.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20190312131526.14710-1-palmer@sifive.com> References: <20190312131526.14710-1-palmer@sifive.com> MIME-Version: 1.0 From: Palmer Dabbelt To: Peter Maydell X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::52c Subject: [Qemu-devel] [PULL 26/29] target/riscv: Remove manual decoding of RV32/64M insn X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Bastian Koppelmann , Peer Adelt , qemu-riscv@nongnu.org, qemu-devel@nongnu.org, Palmer Dabbelt Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Bastian Koppelmann Reviewed-by: Richard Henderson Signed-off-by: Bastian Koppelmann Signed-off-by: Peer Adelt Signed-off-by: Palmer Dabbelt --- target/riscv/insn_trans/trans_rvm.inc.c | 55 ++-- target/riscv/translate.c | 320 ++++++++++-------------- 2 files changed, 164 insertions(+), 211 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvm.inc.c b/target/riscv/insn_trans/trans_rvm.inc.c index 69631c9e3783..d2bf2f171904 100644 --- a/target/riscv/insn_trans/trans_rvm.inc.c +++ b/target/riscv/insn_trans/trans_rvm.inc.c @@ -22,92 +22,99 @@ static bool trans_mul(DisasContext *ctx, arg_mul *a) { REQUIRE_EXT(ctx, RVM); - gen_arith(ctx, OPC_RISC_MUL, a->rd, a->rs1, a->rs2); - return true; + return trans_arith(ctx, a, &tcg_gen_mul_tl); } static bool trans_mulh(DisasContext *ctx, arg_mulh *a) { REQUIRE_EXT(ctx, RVM); - gen_arith(ctx, OPC_RISC_MULH, a->rd, a->rs1, a->rs2); + TCGv source1 = tcg_temp_new(); + TCGv source2 = tcg_temp_new(); + gen_get_gpr(source1, a->rs1); + gen_get_gpr(source2, a->rs2); + + tcg_gen_muls2_tl(source2, source1, source1, source2); + + gen_set_gpr(a->rd, source1); + tcg_temp_free(source1); + tcg_temp_free(source2); return true; } static bool trans_mulhsu(DisasContext *ctx, arg_mulhsu *a) { REQUIRE_EXT(ctx, RVM); - gen_arith(ctx, OPC_RISC_MULHSU, a->rd, a->rs1, a->rs2); - return true; + return trans_arith(ctx, a, &gen_mulhsu); } static bool trans_mulhu(DisasContext *ctx, arg_mulhu *a) { REQUIRE_EXT(ctx, RVM); - gen_arith(ctx, OPC_RISC_MULHU, a->rd, a->rs1, a->rs2); + TCGv source1 = tcg_temp_new(); + TCGv source2 = tcg_temp_new(); + gen_get_gpr(source1, a->rs1); + gen_get_gpr(source2, a->rs2); + + tcg_gen_mulu2_tl(source2, source1, source1, source2); + + gen_set_gpr(a->rd, source1); + tcg_temp_free(source1); + tcg_temp_free(source2); return true; } static bool trans_div(DisasContext *ctx, arg_div *a) { REQUIRE_EXT(ctx, RVM); - gen_arith(ctx, OPC_RISC_DIV, a->rd, a->rs1, a->rs2); - return true; + return trans_arith(ctx, a, &gen_div); } static bool trans_divu(DisasContext *ctx, arg_divu *a) { REQUIRE_EXT(ctx, RVM); - gen_arith(ctx, OPC_RISC_DIVU, a->rd, a->rs1, a->rs2); - return true; + return trans_arith(ctx, a, &gen_divu); } static bool trans_rem(DisasContext *ctx, arg_rem *a) { REQUIRE_EXT(ctx, RVM); - gen_arith(ctx, OPC_RISC_REM, a->rd, a->rs1, a->rs2); - return true; + return trans_arith(ctx, a, &gen_rem); } static bool trans_remu(DisasContext *ctx, arg_remu *a) { REQUIRE_EXT(ctx, RVM); - gen_arith(ctx, OPC_RISC_REMU, a->rd, a->rs1, a->rs2); - return true; + return trans_arith(ctx, a, &gen_remu); } #ifdef TARGET_RISCV64 static bool trans_mulw(DisasContext *ctx, arg_mulw *a) { REQUIRE_EXT(ctx, RVM); - gen_arith(ctx, OPC_RISC_MULW, a->rd, a->rs1, a->rs2); - return true; + return trans_arith(ctx, a, &gen_mulw); } static bool trans_divw(DisasContext *ctx, arg_divw *a) { REQUIRE_EXT(ctx, RVM); - gen_arith(ctx, OPC_RISC_DIVW, a->rd, a->rs1, a->rs2); - return true; + return gen_arith_div_w(ctx, a, &gen_div); } static bool trans_divuw(DisasContext *ctx, arg_divuw *a) { REQUIRE_EXT(ctx, RVM); - gen_arith(ctx, OPC_RISC_DIVUW, a->rd, a->rs1, a->rs2); - return true; + return gen_arith_div_w(ctx, a, &gen_divu); } static bool trans_remw(DisasContext *ctx, arg_remw *a) { REQUIRE_EXT(ctx, RVM); - gen_arith(ctx, OPC_RISC_REMW, a->rd, a->rs1, a->rs2); - return true; + return gen_arith_div_w(ctx, a, &gen_rem); } static bool trans_remuw(DisasContext *ctx, arg_remuw *a) { REQUIRE_EXT(ctx, RVM); - gen_arith(ctx, OPC_RISC_REMUW, a->rd, a->rs1, a->rs2); - return true; + return gen_arith_div_w(ctx, a, &gen_remu); } #endif diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 9ae40f65096f..3cd7e16c63cf 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -188,193 +188,112 @@ static void gen_mulhsu(TCGv ret, TCGv arg1, TCGv arg2) tcg_temp_free(rh); } -static void gen_arith(DisasContext *ctx, uint32_t opc, int rd, int rs1, - int rs2) -{ - TCGv source1, source2, cond1, cond2, zeroreg, resultopt1; - source1 = tcg_temp_new(); - source2 = tcg_temp_new(); - gen_get_gpr(source1, rs1); - gen_get_gpr(source2, rs2); - - switch (opc) { - CASE_OP_32_64(OPC_RISC_MUL): - if (!has_ext(ctx, RVM)) { - goto do_illegal; - } - tcg_gen_mul_tl(source1, source1, source2); - break; - case OPC_RISC_MULH: - if (!has_ext(ctx, RVM)) { - goto do_illegal; - } - tcg_gen_muls2_tl(source2, source1, source1, source2); - break; - case OPC_RISC_MULHSU: - if (!has_ext(ctx, RVM)) { - goto do_illegal; - } - gen_mulhsu(source1, source1, source2); - break; - case OPC_RISC_MULHU: - if (!has_ext(ctx, RVM)) { - goto do_illegal; - } - tcg_gen_mulu2_tl(source2, source1, source1, source2); - break; -#if defined(TARGET_RISCV64) - case OPC_RISC_DIVW: - if (!has_ext(ctx, RVM)) { - goto do_illegal; - } - tcg_gen_ext32s_tl(source1, source1); - tcg_gen_ext32s_tl(source2, source2); - /* fall through to DIV */ -#endif - case OPC_RISC_DIV: - if (!has_ext(ctx, RVM)) { - goto do_illegal; - } - /* Handle by altering args to tcg_gen_div to produce req'd results: - * For overflow: want source1 in source1 and 1 in source2 - * For div by zero: want -1 in source1 and 1 in source2 -> -1 result */ - cond1 = tcg_temp_new(); - cond2 = tcg_temp_new(); - zeroreg = tcg_const_tl(0); - resultopt1 = tcg_temp_new(); - - tcg_gen_movi_tl(resultopt1, (target_ulong)-1); - tcg_gen_setcondi_tl(TCG_COND_EQ, cond2, source2, (target_ulong)(~0L)); - tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source1, - ((target_ulong)1) << (TARGET_LONG_BITS - 1)); - tcg_gen_and_tl(cond1, cond1, cond2); /* cond1 = overflow */ - tcg_gen_setcondi_tl(TCG_COND_EQ, cond2, source2, 0); /* cond2 = div 0 */ - /* if div by zero, set source1 to -1, otherwise don't change */ - tcg_gen_movcond_tl(TCG_COND_EQ, source1, cond2, zeroreg, source1, - resultopt1); - /* if overflow or div by zero, set source2 to 1, else don't change */ - tcg_gen_or_tl(cond1, cond1, cond2); - tcg_gen_movi_tl(resultopt1, (target_ulong)1); - tcg_gen_movcond_tl(TCG_COND_EQ, source2, cond1, zeroreg, source2, - resultopt1); - tcg_gen_div_tl(source1, source1, source2); - - tcg_temp_free(cond1); - tcg_temp_free(cond2); - tcg_temp_free(zeroreg); - tcg_temp_free(resultopt1); - break; -#if defined(TARGET_RISCV64) - case OPC_RISC_DIVUW: - if (!has_ext(ctx, RVM)) { - goto do_illegal; - } - tcg_gen_ext32u_tl(source1, source1); - tcg_gen_ext32u_tl(source2, source2); - /* fall through to DIVU */ -#endif - case OPC_RISC_DIVU: - if (!has_ext(ctx, RVM)) { - goto do_illegal; - } - cond1 = tcg_temp_new(); - zeroreg = tcg_const_tl(0); - resultopt1 = tcg_temp_new(); - - tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source2, 0); - tcg_gen_movi_tl(resultopt1, (target_ulong)-1); - tcg_gen_movcond_tl(TCG_COND_EQ, source1, cond1, zeroreg, source1, - resultopt1); - tcg_gen_movi_tl(resultopt1, (target_ulong)1); - tcg_gen_movcond_tl(TCG_COND_EQ, source2, cond1, zeroreg, source2, - resultopt1); - tcg_gen_divu_tl(source1, source1, source2); - - tcg_temp_free(cond1); - tcg_temp_free(zeroreg); - tcg_temp_free(resultopt1); - break; -#if defined(TARGET_RISCV64) - case OPC_RISC_REMW: - if (!has_ext(ctx, RVM)) { - goto do_illegal; - } - tcg_gen_ext32s_tl(source1, source1); - tcg_gen_ext32s_tl(source2, source2); - /* fall through to REM */ -#endif - case OPC_RISC_REM: - if (!has_ext(ctx, RVM)) { - goto do_illegal; - } - cond1 = tcg_temp_new(); - cond2 = tcg_temp_new(); - zeroreg = tcg_const_tl(0); - resultopt1 = tcg_temp_new(); - - tcg_gen_movi_tl(resultopt1, 1L); - tcg_gen_setcondi_tl(TCG_COND_EQ, cond2, source2, (target_ulong)-1); - tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source1, - (target_ulong)1 << (TARGET_LONG_BITS - 1)); - tcg_gen_and_tl(cond2, cond1, cond2); /* cond1 = overflow */ - tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source2, 0); /* cond2 = div 0 */ - /* if overflow or div by zero, set source2 to 1, else don't change */ - tcg_gen_or_tl(cond2, cond1, cond2); - tcg_gen_movcond_tl(TCG_COND_EQ, source2, cond2, zeroreg, source2, - resultopt1); - tcg_gen_rem_tl(resultopt1, source1, source2); - /* if div by zero, just return the original dividend */ - tcg_gen_movcond_tl(TCG_COND_EQ, source1, cond1, zeroreg, resultopt1, - source1); - - tcg_temp_free(cond1); - tcg_temp_free(cond2); - tcg_temp_free(zeroreg); - tcg_temp_free(resultopt1); - break; -#if defined(TARGET_RISCV64) - case OPC_RISC_REMUW: - if (!has_ext(ctx, RVM)) { - goto do_illegal; - } - tcg_gen_ext32u_tl(source1, source1); - tcg_gen_ext32u_tl(source2, source2); - /* fall through to REMU */ -#endif - case OPC_RISC_REMU: - if (!has_ext(ctx, RVM)) { - goto do_illegal; - } - cond1 = tcg_temp_new(); - zeroreg = tcg_const_tl(0); - resultopt1 = tcg_temp_new(); - - tcg_gen_movi_tl(resultopt1, (target_ulong)1); - tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source2, 0); - tcg_gen_movcond_tl(TCG_COND_EQ, source2, cond1, zeroreg, source2, - resultopt1); - tcg_gen_remu_tl(resultopt1, source1, source2); - /* if div by zero, just return the original dividend */ - tcg_gen_movcond_tl(TCG_COND_EQ, source1, cond1, zeroreg, resultopt1, - source1); - - tcg_temp_free(cond1); - tcg_temp_free(zeroreg); - tcg_temp_free(resultopt1); - break; - do_illegal: - default: - gen_exception_illegal(ctx); - return; - } - - if (opc & 0x8) { /* sign extend for W instructions */ - tcg_gen_ext32s_tl(source1, source1); - } - - gen_set_gpr(rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); +static void gen_div(TCGv ret, TCGv source1, TCGv source2) +{ + TCGv cond1, cond2, zeroreg, resultopt1; + /* + * Handle by altering args to tcg_gen_div to produce req'd results: + * For overflow: want source1 in source1 and 1 in source2 + * For div by zero: want -1 in source1 and 1 in source2 -> -1 result + */ + cond1 = tcg_temp_new(); + cond2 = tcg_temp_new(); + zeroreg = tcg_const_tl(0); + resultopt1 = tcg_temp_new(); + + tcg_gen_movi_tl(resultopt1, (target_ulong)-1); + tcg_gen_setcondi_tl(TCG_COND_EQ, cond2, source2, (target_ulong)(~0L)); + tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source1, + ((target_ulong)1) << (TARGET_LONG_BITS - 1)); + tcg_gen_and_tl(cond1, cond1, cond2); /* cond1 = overflow */ + tcg_gen_setcondi_tl(TCG_COND_EQ, cond2, source2, 0); /* cond2 = div 0 */ + /* if div by zero, set source1 to -1, otherwise don't change */ + tcg_gen_movcond_tl(TCG_COND_EQ, source1, cond2, zeroreg, source1, + resultopt1); + /* if overflow or div by zero, set source2 to 1, else don't change */ + tcg_gen_or_tl(cond1, cond1, cond2); + tcg_gen_movi_tl(resultopt1, (target_ulong)1); + tcg_gen_movcond_tl(TCG_COND_EQ, source2, cond1, zeroreg, source2, + resultopt1); + tcg_gen_div_tl(ret, source1, source2); + + tcg_temp_free(cond1); + tcg_temp_free(cond2); + tcg_temp_free(zeroreg); + tcg_temp_free(resultopt1); +} + +static void gen_divu(TCGv ret, TCGv source1, TCGv source2) +{ + TCGv cond1, zeroreg, resultopt1; + cond1 = tcg_temp_new(); + + zeroreg = tcg_const_tl(0); + resultopt1 = tcg_temp_new(); + + tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source2, 0); + tcg_gen_movi_tl(resultopt1, (target_ulong)-1); + tcg_gen_movcond_tl(TCG_COND_EQ, source1, cond1, zeroreg, source1, + resultopt1); + tcg_gen_movi_tl(resultopt1, (target_ulong)1); + tcg_gen_movcond_tl(TCG_COND_EQ, source2, cond1, zeroreg, source2, + resultopt1); + tcg_gen_divu_tl(ret, source1, source2); + + tcg_temp_free(cond1); + tcg_temp_free(zeroreg); + tcg_temp_free(resultopt1); +} + +static void gen_rem(TCGv ret, TCGv source1, TCGv source2) +{ + TCGv cond1, cond2, zeroreg, resultopt1; + + cond1 = tcg_temp_new(); + cond2 = tcg_temp_new(); + zeroreg = tcg_const_tl(0); + resultopt1 = tcg_temp_new(); + + tcg_gen_movi_tl(resultopt1, 1L); + tcg_gen_setcondi_tl(TCG_COND_EQ, cond2, source2, (target_ulong)-1); + tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source1, + (target_ulong)1 << (TARGET_LONG_BITS - 1)); + tcg_gen_and_tl(cond2, cond1, cond2); /* cond1 = overflow */ + tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source2, 0); /* cond2 = div 0 */ + /* if overflow or div by zero, set source2 to 1, else don't change */ + tcg_gen_or_tl(cond2, cond1, cond2); + tcg_gen_movcond_tl(TCG_COND_EQ, source2, cond2, zeroreg, source2, + resultopt1); + tcg_gen_rem_tl(resultopt1, source1, source2); + /* if div by zero, just return the original dividend */ + tcg_gen_movcond_tl(TCG_COND_EQ, ret, cond1, zeroreg, resultopt1, + source1); + + tcg_temp_free(cond1); + tcg_temp_free(cond2); + tcg_temp_free(zeroreg); + tcg_temp_free(resultopt1); +} + +static void gen_remu(TCGv ret, TCGv source1, TCGv source2) +{ + TCGv cond1, zeroreg, resultopt1; + cond1 = tcg_temp_new(); + zeroreg = tcg_const_tl(0); + resultopt1 = tcg_temp_new(); + + tcg_gen_movi_tl(resultopt1, (target_ulong)1); + tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source2, 0); + tcg_gen_movcond_tl(TCG_COND_EQ, source2, cond1, zeroreg, source2, + resultopt1); + tcg_gen_remu_tl(resultopt1, source1, source2); + /* if div by zero, just return the original dividend */ + tcg_gen_movcond_tl(TCG_COND_EQ, ret, cond1, zeroreg, resultopt1, + source1); + + tcg_temp_free(cond1); + tcg_temp_free(zeroreg); + tcg_temp_free(resultopt1); } static void gen_jal(DisasContext *ctx, int rd, target_ulong imm) @@ -681,6 +600,33 @@ static void gen_subw(TCGv ret, TCGv arg1, TCGv arg2) tcg_gen_ext32s_tl(ret, ret); } +static void gen_mulw(TCGv ret, TCGv arg1, TCGv arg2) +{ + tcg_gen_mul_tl(ret, arg1, arg2); + tcg_gen_ext32s_tl(ret, ret); +} + +static bool gen_arith_div_w(DisasContext *ctx, arg_r *a, + void(*func)(TCGv, TCGv, TCGv)) +{ + TCGv source1, source2; + source1 = tcg_temp_new(); + source2 = tcg_temp_new(); + + gen_get_gpr(source1, a->rs1); + gen_get_gpr(source2, a->rs2); + tcg_gen_ext32s_tl(source1, source1); + tcg_gen_ext32s_tl(source2, source2); + + (*func)(source1, source1, source2); + + tcg_gen_ext32s_tl(source1, source1); + gen_set_gpr(a->rd, source1); + tcg_temp_free(source1); + tcg_temp_free(source2); + return true; +} + #endif static bool trans_arith(DisasContext *ctx, arg_r *a,