From patchwork Wed Feb 20 07:51:55 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 222072 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 42FB92C007C for ; Wed, 20 Feb 2013 23:00:53 +1100 (EST) Received: from localhost ([::1]:48255 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U84Ua-0001me-2u for incoming@patchwork.ozlabs.org; Wed, 20 Feb 2013 02:53:28 -0500 Received: from eggs.gnu.org ([208.118.235.92]:43671) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U84Tx-0000MC-Jg for qemu-devel@nongnu.org; Wed, 20 Feb 2013 02:52:53 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1U84Tt-00029P-TF for qemu-devel@nongnu.org; Wed, 20 Feb 2013 02:52:49 -0500 Received: from mail-pa0-f44.google.com ([209.85.220.44]:36402) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U84Tt-00029A-Kg for qemu-devel@nongnu.org; Wed, 20 Feb 2013 02:52:45 -0500 Received: by mail-pa0-f44.google.com with SMTP id kp1so3886285pab.3 for ; Tue, 19 Feb 2013 23:52:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:sender:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references; bh=ckDTyQ6R9G4F1X1HFzgGz8cOeYndNXRmRQ3Lqwllcj8=; b=FU43qCPtohTPe9jJVnL3eTUynW49BhtGzEPOOCSPWWkZLrwaKzrZEILi5hKQseG2hy OEdYLfp6lPQvabgsl/0o02KndpX5IfQQejk0yl3Q7R0haUR7W0So/h58bsNEIBPcSqa0 MmIrklTy80u12RKNDpdhK0+tjm09Sq4btErC8YosZEoEAMGHKmZ1x2qkdsdPKWnoqWMX lbjtD/VejOsEkRrnX0C/aTWlnCMIRJCYgJkeegfDNE7vbu1xWwAlNM9R6s1Xiykp0sOR Ks36A8OpyB9Xgv8AfaaIymDzdRTHmBd0H8IMB2zkLvTflSgGKePQAFXH/WU86dMqdSD6 vYJw== X-Received: by 10.68.220.230 with SMTP id pz6mr7228009pbc.46.1361346764698; Tue, 19 Feb 2013 23:52:44 -0800 (PST) Received: from anchor.twiddle.net (50-194-63-110-static.hfc.comcastbusiness.net. [50.194.63.110]) by mx.google.com with ESMTPS id c8sm20826347pbq.10.2013.02.19.23.52.42 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Tue, 19 Feb 2013 23:52:43 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Tue, 19 Feb 2013 23:51:55 -0800 Message-Id: <1361346746-8511-8-git-send-email-rth@twiddle.net> X-Mailer: git-send-email 1.8.1.2 In-Reply-To: <1361346746-8511-1-git-send-email-rth@twiddle.net> References: <1361346746-8511-1-git-send-email-rth@twiddle.net> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 209.85.220.44 Cc: blauwirbel@gmail.com, aurelien@aurel32.net Subject: [Qemu-devel] [PATCH 07/38] tcg: Implement multiword multiply helpers 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 Signed-off-by: Richard Henderson --- tcg-runtime.c | 16 ++++++++++- tcg/tcg-op.h | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ tcg/tcg-runtime.h | 2 ++ 3 files changed, 101 insertions(+), 1 deletion(-) diff --git a/tcg-runtime.c b/tcg-runtime.c index abfc364..4b66e51 100644 --- a/tcg-runtime.c +++ b/tcg-runtime.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include - +#include "qemu/host-utils.h" #include "tcg/tcg-runtime.h" /* 32-bit helpers */ @@ -83,3 +83,17 @@ uint64_t tcg_helper_remu_i64(uint64_t arg1, uint64_t arg2) { return arg1 % arg2; } + +uint64_t tcg_helper_muluh_i64(uint64_t arg1, uint64_t arg2) +{ + uint64_t l, h; + mulu64(&l, &h, arg1, arg2); + return h; +} + +int64_t tcg_helper_mulsh_i64(int64_t arg1, int64_t arg2) +{ + uint64_t l, h; + muls64(&l, &h, arg1, arg2); + return h; +} diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 4ded249..97e0795 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -2332,6 +2332,86 @@ static inline void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, #endif } +static inline void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, + TCGv_i32 arg1, TCGv_i32 arg2) +{ + if (TCG_TARGET_HAS_mulu2_i32) { + tcg_gen_op4_i32(INDEX_op_mulu2_i32, rl, rh, arg1, arg2); + /* Allow the optimizer room to replace mulu2 with two moves. */ + tcg_gen_op0(INDEX_op_nop); + } else { + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + tcg_gen_extu_i32_i64(t0, arg1); + tcg_gen_extu_i32_i64(t1, arg2); + tcg_gen_mul_i64(t0, t0, t1); + tcg_gen_extr_i64_i32(rl, rh, t0); + tcg_temp_free_i64(t0); + tcg_temp_free_i64(t1); + } +} + +static inline void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, + TCGv_i32 arg1, TCGv_i32 arg2) +{ + if (TCG_TARGET_HAS_muls2_i32) { + tcg_gen_op4_i32(INDEX_op_muls2_i32, rl, rh, arg1, arg2); + /* Allow the optimizer room to replace muls2 with two moves. */ + tcg_gen_op0(INDEX_op_nop); + } else { + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + tcg_gen_ext_i32_i64(t0, arg1); + tcg_gen_ext_i32_i64(t1, arg2); + tcg_gen_mul_i64(t0, t0, t1); + tcg_gen_extr_i64_i32(rl, rh, t0); + tcg_temp_free_i64(t0); + tcg_temp_free_i64(t1); + } +} + +static inline void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, + TCGv_i64 arg1, TCGv_i64 arg2) +{ + if (TCG_TARGET_HAS_mulu2_i64) { + tcg_gen_op4_i64(INDEX_op_mulu2_i64, rl, rh, arg1, arg2); + /* Allow the optimizer room to replace mulu2 with two moves. */ + tcg_gen_op0(INDEX_op_nop); + } else { + TCGv_i64 t0 = tcg_temp_new_i64(); + int sizemask = 0; + /* Return value and both arguments are 64-bit and unsigned. */ + sizemask |= tcg_gen_sizemask(0, 1, 0); + sizemask |= tcg_gen_sizemask(1, 1, 0); + sizemask |= tcg_gen_sizemask(2, 1, 0); + tcg_gen_mul_i64(t0, arg1, arg2); + tcg_gen_helper64(tcg_helper_muluh_i64, sizemask, rh, arg1, arg2); + tcg_gen_mov_i64(rl, t0); + tcg_temp_free_i64(t0); + } +} + +static inline void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, + TCGv_i64 arg1, TCGv_i64 arg2) +{ + if (TCG_TARGET_HAS_muls2_i64) { + tcg_gen_op4_i64(INDEX_op_muls2_i64, rl, rh, arg1, arg2); + /* Allow the optimizer room to replace muls2 with two moves. */ + tcg_gen_op0(INDEX_op_nop); + } else { + TCGv_i64 t0 = tcg_temp_new_i64(); + int sizemask = 0; + /* Return value and both arguments are 64-bit and signed. */ + sizemask |= tcg_gen_sizemask(0, 1, 1); + sizemask |= tcg_gen_sizemask(1, 1, 1); + sizemask |= tcg_gen_sizemask(2, 1, 1); + tcg_gen_mul_i64(t0, arg1, arg2); + tcg_gen_helper64(tcg_helper_mulsh_i64, sizemask, rh, arg1, arg2); + tcg_gen_mov_i64(rl, t0); + tcg_temp_free_i64(t0); + } +} + /***************************************/ /* QEMU specific operations. Their type depend on the QEMU CPU type. */ @@ -2659,6 +2739,8 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index) #define tcg_const_tl tcg_const_i64 #define tcg_const_local_tl tcg_const_local_i64 #define tcg_gen_movcond_tl tcg_gen_movcond_i64 +#define tcg_gen_mulu2_tl tcg_gen_mulu2_i64 +#define tcg_gen_muls2_tl tcg_gen_muls2_i64 #else #define tcg_gen_movi_tl tcg_gen_movi_i32 #define tcg_gen_mov_tl tcg_gen_mov_i32 @@ -2732,6 +2814,8 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index) #define tcg_const_tl tcg_const_i32 #define tcg_const_local_tl tcg_const_local_i32 #define tcg_gen_movcond_tl tcg_gen_movcond_i32 +#define tcg_gen_mulu2_tl tcg_gen_mulu2_i32 +#define tcg_gen_muls2_tl tcg_gen_muls2_i32 #endif #if TCG_TARGET_REG_BITS == 32 diff --git a/tcg/tcg-runtime.h b/tcg/tcg-runtime.h index 5615b13..a1ebef9 100644 --- a/tcg/tcg-runtime.h +++ b/tcg/tcg-runtime.h @@ -12,7 +12,9 @@ int64_t tcg_helper_shr_i64(int64_t arg1, int64_t arg2); int64_t tcg_helper_sar_i64(int64_t arg1, int64_t arg2); int64_t tcg_helper_div_i64(int64_t arg1, int64_t arg2); int64_t tcg_helper_rem_i64(int64_t arg1, int64_t arg2); +int64_t tcg_helper_mulsh_i64(int64_t arg1, int64_t arg2); uint64_t tcg_helper_divu_i64(uint64_t arg1, uint64_t arg2); uint64_t tcg_helper_remu_i64(uint64_t arg1, uint64_t arg2); +uint64_t tcg_helper_muluh_i64(uint64_t arg1, uint64_t arg2); #endif