From patchwork Wed Sep 28 12:28:07 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 116779 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id D493CB6F91 for ; Wed, 28 Sep 2011 22:28:32 +1000 (EST) Received: from localhost ([::1]:51568 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R8tFV-0006rt-Em for incoming@patchwork.ozlabs.org; Wed, 28 Sep 2011 08:28:29 -0400 Received: from eggs.gnu.org ([140.186.70.92]:36328) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R8tFP-0006qd-LE for qemu-devel@nongnu.org; Wed, 28 Sep 2011 08:28:24 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1R8tFN-00057H-UY for qemu-devel@nongnu.org; Wed, 28 Sep 2011 08:28:23 -0400 Received: from goliath.siemens.de ([192.35.17.28]:25627) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R8tFN-000576-Hj for qemu-devel@nongnu.org; Wed, 28 Sep 2011 08:28:21 -0400 Received: from mail1.siemens.de (localhost [127.0.0.1]) by goliath.siemens.de (8.13.6/8.13.6) with ESMTP id p8SCSAmw016384; Wed, 28 Sep 2011 14:28:10 +0200 Received: from mchn199C.mchp.siemens.de ([139.25.109.49]) by mail1.siemens.de (8.13.6/8.13.6) with ESMTP id p8SCS7hD009138; Wed, 28 Sep 2011 14:28:07 +0200 Message-ID: <4E8312D7.4080403@siemens.com> Date: Wed, 28 Sep 2011 14:28:07 +0200 From: Jan Kiszka User-Agent: Mozilla/5.0 (X11; U; Linux i686 (x86_64); de; rv:1.8.1.12) Gecko/20080226 SUSE/2.0.0.12-1.1 Thunderbird/2.0.0.12 Mnenhy/0.7.5.666 MIME-Version: 1.0 To: qemu-devel X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) X-Received-From: 192.35.17.28 Cc: Blue Swirl , Aurelien Jarno , Richard Henderson Subject: [Qemu-devel] [PATCH] tcg-i386: Introduce specific deposit 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 x86 cannot provide an optimized generic deposit implementation. But at least for a few special cases, namely for writing bits 0..7, 8..15, and 0..15, a version using only a single instruction is feasible. Introducing such helpers improves emulating 16-bit x86 code on x86, but also rarer cases where 32-bit or 64-bit code accesses bytes or words. Signed-off-by: Jan Kiszka --- tcg/i386/tcg-target.c | 25 +++++++++++++++++++++++++ tcg/i386/tcg-target.h | 6 ++++++ tcg/tcg-op.h | 12 ++++++++++++ tcg/tcg-opc.h | 6 ++++++ tcg/tcg.h | 3 +++ 5 files changed, 52 insertions(+), 0 deletions(-) diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 281f87d..3f9d0ad 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -1747,6 +1747,19 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; #endif + OP_32_64(deposit8l): + tcg_out_modrm(s, OPC_MOVB_EvGv | P_REXB_R | P_REXB_RM, + args[2], args[0]); + break; + + OP_32_64(deposit8h): + tcg_out_modrm(s, OPC_MOVB_EvGv, args[2], args[0] + 4); + break; + + OP_32_64(deposit16l): + tcg_out_modrm(s, OPC_MOVL_EvGv | P_DATA16, args[2], args[0]); + break; + default: tcg_abort(); } @@ -1802,6 +1815,14 @@ static const TCGTargetOpDef x86_op_defs[] = { { INDEX_op_setcond_i32, { "q", "r", "ri" } }, +#if TCG_TARGET_REG_BITS == 64 + { INDEX_op_deposit8l_i32, { "r", "0", "r" } }, +#else + { INDEX_op_deposit8l_i32, { "abcd", "0", "abcd" } }, +#endif + { INDEX_op_deposit8h_i32, { "abcd", "0", "abcd" } }, + { INDEX_op_deposit16l_i32, { "r", "0", "r" } }, + #if TCG_TARGET_REG_BITS == 32 { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } }, { INDEX_op_add2_i32, { "r", "r", "0", "1", "ri", "ri" } }, @@ -1853,6 +1874,10 @@ static const TCGTargetOpDef x86_op_defs[] = { { INDEX_op_ext8u_i64, { "r", "r" } }, { INDEX_op_ext16u_i64, { "r", "r" } }, { INDEX_op_ext32u_i64, { "r", "r" } }, + + { INDEX_op_deposit8l_i64, { "r", "0", "r" } }, + { INDEX_op_deposit8h_i64, { "abcd", "0", "abcd" } }, + { INDEX_op_deposit16l_i64, { "r", "0", "r" } }, #endif #if TCG_TARGET_REG_BITS == 64 diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index 5088e47..54b2f60 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -91,6 +91,9 @@ enum { #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 #define TCG_TARGET_HAS_deposit_i32 0 +#define TCG_TARGET_HAS_deposit8l_i32 1 +#define TCG_TARGET_HAS_deposit8h_i32 1 +#define TCG_TARGET_HAS_deposit16l_i32 1 #if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_HAS_div2_i64 1 @@ -112,6 +115,9 @@ enum { #define TCG_TARGET_HAS_nand_i64 0 #define TCG_TARGET_HAS_nor_i64 0 #define TCG_TARGET_HAS_deposit_i64 0 +#define TCG_TARGET_HAS_deposit8l_i64 1 +#define TCG_TARGET_HAS_deposit8h_i64 1 +#define TCG_TARGET_HAS_deposit16l_i64 1 #endif #define TCG_TARGET_HAS_GUEST_BASE diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 404b637..80ffccb 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -2047,6 +2047,12 @@ static inline void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, { if (TCG_TARGET_HAS_deposit_i32) { tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, arg1, arg2, ofs, len); + } else if (ofs == 0 && len == 8 && TCG_TARGET_HAS_deposit8l_i32) { + tcg_gen_op3_i32(INDEX_op_deposit8l_i32, ret, arg1, arg2); + } else if (ofs == 8 && len == 8 && TCG_TARGET_HAS_deposit8h_i32) { + tcg_gen_op3_i32(INDEX_op_deposit8h_i32, ret, arg1, arg2); + } else if (ofs == 0 && len == 16 && TCG_TARGET_HAS_deposit16l_i32) { + tcg_gen_op3_i32(INDEX_op_deposit16l_i32, ret, arg1, arg2); } else { uint32_t mask = (1u << len) - 1; TCGv_i32 t1 = tcg_temp_new_i32 (); @@ -2066,6 +2072,12 @@ static inline void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, { if (TCG_TARGET_HAS_deposit_i64) { tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, arg1, arg2, ofs, len); + } else if (ofs == 0 && len == 8 && TCG_TARGET_HAS_deposit8l_i64) { + tcg_gen_op3_i32(INDEX_op_deposit8l_i64, ret, arg1, arg2); + } else if (ofs == 8 && len == 8 && TCG_TARGET_HAS_deposit8h_i64) { + tcg_gen_op3_i32(INDEX_op_deposit8h_i64, ret, arg1, arg2); + } else if (ofs == 0 && len == 16 && TCG_TARGET_HAS_deposit16l_i64) { + tcg_gen_op3_i32(INDEX_op_deposit16l_i64, ret, arg1, arg2); } else { uint64_t mask = (1ull << len) - 1; TCGv_i64 t1 = tcg_temp_new_i64 (); diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h index 8e06d03..0871d15 100644 --- a/tcg/tcg-opc.h +++ b/tcg/tcg-opc.h @@ -80,6 +80,9 @@ DEF(sar_i32, 1, 2, 0, 0) DEF(rotl_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rot_i32)) DEF(rotr_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rot_i32)) DEF(deposit_i32, 1, 2, 2, IMPL(TCG_TARGET_HAS_deposit_i32)) +DEF(deposit8l_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_deposit8l_i32)) +DEF(deposit8h_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_deposit8h_i32)) +DEF(deposit16l_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_deposit16l_i32)) DEF(brcond_i32, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS) @@ -139,6 +142,9 @@ DEF(sar_i64, 1, 2, 0, IMPL64) DEF(rotl_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rot_i64)) DEF(rotr_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rot_i64)) DEF(deposit_i64, 1, 2, 2, IMPL64 | IMPL(TCG_TARGET_HAS_deposit_i64)) +DEF(deposit8l_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_deposit8l_i64)) +DEF(deposit8h_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_deposit8h_i64)) +DEF(deposit16l_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_deposit16l_i64)) DEF(brcond_i64, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS | IMPL64) DEF(ext8s_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext8s_i64)) diff --git a/tcg/tcg.h b/tcg/tcg.h index dc5e9c9..9a95d2b 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -69,6 +69,9 @@ typedef uint64_t TCGRegSet; #define TCG_TARGET_HAS_nand_i64 0 #define TCG_TARGET_HAS_nor_i64 0 #define TCG_TARGET_HAS_deposit_i64 0 +#define TCG_TARGET_HAS_deposit8l_i64 0 +#define TCG_TARGET_HAS_deposit8h_i64 0 +#define TCG_TARGET_HAS_deposit16l_i64 0 #endif /* Only one of DIV or DIV2 should be defined. */