From patchwork Thu Dec 17 17:55:02 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 41335 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 39F541007D1 for ; Fri, 18 Dec 2009 06:42:52 +1100 (EST) Received: from localhost ([127.0.0.1]:45889 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NLMFN-0007p1-70 for incoming@patchwork.ozlabs.org; Thu, 17 Dec 2009 14:42:49 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NLMCw-0006qU-Ie for qemu-devel@nongnu.org; Thu, 17 Dec 2009 14:40:18 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NLMCu-0006p5-NK for qemu-devel@nongnu.org; Thu, 17 Dec 2009 14:40:16 -0500 Received: from [199.232.76.173] (port=50132 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NLMCt-0006oc-Hi for qemu-devel@nongnu.org; Thu, 17 Dec 2009 14:40:15 -0500 Received: from are.twiddle.net ([75.149.56.221]:35333) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NLMCt-0004Ht-0u for qemu-devel@nongnu.org; Thu, 17 Dec 2009 14:40:15 -0500 Received: by are.twiddle.net (Postfix, from userid 5000) id 741A28E0; Thu, 17 Dec 2009 11:40:12 -0800 (PST) Message-Id: <89dbe5fc9e003225157911e8ad8b19b73cae7177.1261078375.git.rth@twiddle.net> In-Reply-To: References: <761ea48b0912170620l534dcb02m8ea6b59524d76dbe@mail.gmail.com> From: Richard Henderson Date: Thu, 17 Dec 2009 09:55:02 -0800 To: qemu-devel@nongnu.org X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6 (newer, 2) Cc: Laurent Desnogues Subject: [Qemu-devel] [PATCH 4/6] tcg-i386: Implement small forward branches. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org There are places, like brcond2, where we know that the destination of a forward branch will be within 127 bytes. Add the R_386_PC8 relocation type to support this, and add a flag to tcg_out_jxx to generate it. Set the flag in the small forward branches in brcond2. Signed-off-by: Richard Henderson --- elf.h | 2 ++ tcg/i386/tcg-target.c | 36 +++++++++++++++++++++++++----------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/elf.h b/elf.h index 11674d7..c84c8ab 100644 --- a/elf.h +++ b/elf.h @@ -243,6 +243,8 @@ typedef struct { #define R_386_GOTOFF 9 #define R_386_GOTPC 10 #define R_386_NUM 11 +/* Not a dynamic reloc, so not included in R_386_NUM. Used in TCG. */ +#define R_386_PC8 23 #define R_MIPS_NONE 0 #define R_MIPS_16 1 diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 972b102..cc3d28f 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -61,6 +61,9 @@ static void patch_reloc(uint8_t *code_ptr, int type, case R_386_PC32: *(uint32_t *)code_ptr = value - (long)code_ptr; break; + case R_386_PC8: + *(uint8_t *)code_ptr = value - (long)code_ptr; + break; default: tcg_abort(); } @@ -305,7 +308,8 @@ static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val) tgen_arithi(s, ARITH_ADD, reg, val, 0); } -static void tcg_out_jxx(TCGContext *s, int opc, int label_index) +/* Use SMALL != 0 to force a short forward branch. */ +static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small) { int32_t val, val1; TCGLabel *l = &s->labels[label_index]; @@ -320,6 +324,7 @@ static void tcg_out_jxx(TCGContext *s, int opc, int label_index) tcg_out8(s, 0x70 + opc); tcg_out8(s, val1); } else { + assert (!small); if (opc == -1) { tcg_out8(s, 0xe9); tcg_out32(s, val - 5); @@ -329,6 +334,15 @@ static void tcg_out_jxx(TCGContext *s, int opc, int label_index) tcg_out32(s, val - 6); } } + } else if (small) { + if (opc == -1) { + tcg_out8(s, 0xeb); + } else { + tcg_out8(s, 0x0f); + tcg_out8(s, 0x70 + opc); + } + tcg_out_reloc(s, s->code_ptr, R_386_PC8, label_index, -1); + s->code_ptr += 1; } else { if (opc == -1) { tcg_out8(s, 0xe9); @@ -355,7 +369,7 @@ static void tcg_out_brcond(TCGContext *s, int cond, } else { tcg_out_modrm(s, 0x01 | (ARITH_CMP << 3), arg2, arg1); } - tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index); + tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index, 0); } /* XXX: we implement it at the target level to avoid having to @@ -376,42 +390,42 @@ static void tcg_out_brcond2(TCGContext *s, break; case TCG_COND_LT: tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3], args[5]); - tcg_out_jxx(s, JCC_JNE, label_next); + tcg_out_jxx(s, JCC_JNE, label_next, 1); tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2], args[5]); break; case TCG_COND_LE: tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3], args[5]); - tcg_out_jxx(s, JCC_JNE, label_next); + tcg_out_jxx(s, JCC_JNE, label_next, 1); tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2], args[5]); break; case TCG_COND_GT: tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3], args[5]); - tcg_out_jxx(s, JCC_JNE, label_next); + tcg_out_jxx(s, JCC_JNE, label_next, 1); tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2], args[5]); break; case TCG_COND_GE: tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3], args[5]); - tcg_out_jxx(s, JCC_JNE, label_next); + tcg_out_jxx(s, JCC_JNE, label_next, 1); tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2], args[5]); break; case TCG_COND_LTU: tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3], args[5]); - tcg_out_jxx(s, JCC_JNE, label_next); + tcg_out_jxx(s, JCC_JNE, label_next, 1); tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2], args[5]); break; case TCG_COND_LEU: tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3], args[5]); - tcg_out_jxx(s, JCC_JNE, label_next); + tcg_out_jxx(s, JCC_JNE, label_next, 1); tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2], args[5]); break; case TCG_COND_GTU: tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3], args[5]); - tcg_out_jxx(s, JCC_JNE, label_next); + tcg_out_jxx(s, JCC_JNE, label_next, 1); tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2], args[5]); break; case TCG_COND_GEU: tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3], args[5]); - tcg_out_jxx(s, JCC_JNE, label_next); + tcg_out_jxx(s, JCC_JNE, label_next, 1); tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2], args[5]); break; default: @@ -913,7 +927,7 @@ static inline void tcg_out_op(TCGContext *s, int opc, } break; case INDEX_op_br: - tcg_out_jxx(s, JCC_JMP, args[0]); + tcg_out_jxx(s, JCC_JMP, args[0], 0); break; case INDEX_op_movi_i32: tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);