From patchwork Tue Feb 9 21:37:30 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 44962 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 7B6E5B7CF9 for ; Wed, 10 Feb 2010 08:53:15 +1100 (EST) Received: from localhost ([127.0.0.1]:47526 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Nextt-0003p4-AG for incoming@patchwork.ozlabs.org; Tue, 09 Feb 2010 16:45:41 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Nexqe-0002aJ-OH for qemu-devel@nongnu.org; Tue, 09 Feb 2010 16:42:20 -0500 Received: from [199.232.76.173] (port=49442 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Nexqd-0002YT-Fn for qemu-devel@nongnu.org; Tue, 09 Feb 2010 16:42:19 -0500 Received: from Debian-exim by monty-python.gnu.org with spam-scanned (Exim 4.60) (envelope-from ) id 1Nexqa-0003oo-DQ for qemu-devel@nongnu.org; Tue, 09 Feb 2010 16:42:19 -0500 Received: from are.twiddle.net ([75.149.56.221]:60030) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NexqZ-0003oE-NT for qemu-devel@nongnu.org; Tue, 09 Feb 2010 16:42:16 -0500 Received: by are.twiddle.net (Postfix, from userid 5000) id 87AD4C2A; Tue, 9 Feb 2010 13:42:14 -0800 (PST) Message-Id: <083a0c3b5513cdecbed907b80a64aa4647de9138.1265751626.git.rth@twiddle.net> In-Reply-To: References: From: Richard Henderson Date: Tue, 9 Feb 2010 13:37:30 -0800 To: qemu-devel@nongnu.org X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6 (newer, 2) Cc: blauwirbel@gmail.com Subject: [Qemu-devel] [PATCH 2/2] tcg-sparc: Implement setcond, setcond2. 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 --- tcg/sparc/tcg-target.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 126 insertions(+), 0 deletions(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index dd7a598..8c36e3b 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -217,6 +217,9 @@ static inline int tcg_target_const_match(tcg_target_long val, #define COND_VC 0xf #define BA (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2)) +#define MOVCC_ICC (1 << 18) +#define MOVCC_XCC (1 << 18 | 1 << 12) + #define ARITH_ADD (INSN_OP(2) | INSN_OP3(0x00)) #define ARITH_ADDCC (INSN_OP(2) | INSN_OP3(0x10)) #define ARITH_AND (INSN_OP(2) | INSN_OP3(0x01)) @@ -233,6 +236,7 @@ static inline int tcg_target_const_match(tcg_target_long val, #define ARITH_MULX (INSN_OP(2) | INSN_OP3(0x09)) #define ARITH_UDIVX (INSN_OP(2) | INSN_OP3(0x0d)) #define ARITH_SDIVX (INSN_OP(2) | INSN_OP3(0x2d)) +#define ARITH_MOVCC (INSN_OP(2) | INSN_OP3(0x2c)) #define SHIFT_SLL (INSN_OP(2) | INSN_OP3(0x25)) #define SHIFT_SRL (INSN_OP(2) | INSN_OP3(0x26)) @@ -580,6 +584,109 @@ static void tcg_out_brcond2_i32(TCGContext *s, int cond, } #endif +static void tcg_out_setcond_i32(TCGContext *s, int cond, TCGArg ret, + TCGArg c1, TCGArg c2, int c2const) +{ + TCGArg t; + + /* For 32-bit comparisons, we can play games with ADDX/SUBX. */ + switch (cond) { + case TCG_COND_EQ: + case TCG_COND_NE: + if (c2 != 0) { + tcg_out_arithc(s, ret, c1, c2, c2const, ARITH_XOR); + } + c1 = TCG_REG_G0, c2 = ret, c2const = 0; + cond = (cond == TCG_COND_EQ ? TCG_COND_LEU : TCG_COND_LTU); + break; + + case TCG_COND_GTU: + case TCG_COND_GEU: + if (c2const && c2 != 0) { + tcg_out_movi_imm13(s, TCG_REG_I5, c2); + c2 = TCG_REG_I5; + } + t = c1, c1 = c2, c2 = t, c2const = 0; + cond = tcg_swap_cond(cond); + break; + + case TCG_COND_LTU: + case TCG_COND_LEU: + break; + + default: + tcg_out_cmp(s, c1, c2, c2const); +#if defined(__sparc_v9__) || defined(__sparc_v8plus__) + tcg_out_movi_imm13(s, ret, 0); + tcg_out32 (s, ARITH_MOVCC | INSN_RD(ret) + | INSN_RS1(tcg_cond_to_bcond[cond]) + | MOVCC_ICC | INSN_IMM11(1)); +#else + t = gen_new_label(); + tcg_out_branch_i32(s, INSN_COND(tcg_cond_to_bcond[cond], 1), t); + tcg_out_movi_imm13(s, ret, 1); + tcg_out_movi_imm13(s, ret, 0); + tcg_out_label(s, t, (tcg_target_long)s->code_ptr); +#endif + return; + } + + tcg_out_cmp(s, c1, c2, c2const); + if (cond == TCG_COND_LTU) { + tcg_out_arithi(s, ret, TCG_REG_G0, 0, ARITH_ADDX); + } else { + tcg_out_arithi(s, ret, TCG_REG_G0, -1, ARITH_SUBX); + } +} + +#if TCG_TARGET_REG_BITS == 64 +static void tcg_out_setcond_i64(TCGContext *s, int cond, TCGArg ret, + TCGArg c1, TCGArg c2, int c2const) +{ + tcg_out_cmp(s, c1, c2, c2const); + tcg_out_movi_imm13(s, ret, 0); + tcg_out32 (s, ARITH_MOVCC | INSN_RD(ret) + | INSN_RS1(tcg_cond_to_bcond[cond]) + | MOVCC_XCC | INSN_IMM11(1)); +} +#else +static void tcg_out_setcond2_i32(TCGContext *s, int cond, TCGArg ret, + TCGArg al, TCGArg ah, + TCGArg bl, int blconst, + TCGArg bh, int bhconst) +{ + int lab; + + switch (cond) { + case TCG_COND_EQ: + tcg_out_setcond_i32(s, TCG_COND_EQ, TCG_REG_I5, al, bl, blconst); + tcg_out_setcond_i32(s, TCG_COND_EQ, ret, ah, bh, bhconst); + tcg_out_arith(s, ret, ret, TCG_REG_I5, ARITH_AND); + break; + + case TCG_COND_NE: + tcg_out_setcond_i32(s, TCG_COND_NE, TCG_REG_I5, al, al, blconst); + tcg_out_setcond_i32(s, TCG_COND_NE, ret, ah, bh, bhconst); + tcg_out_arith(s, ret, ret, TCG_REG_I5, ARITH_OR); + break; + + default: + lab = gen_new_label(); + + tcg_out_cmp(s, ah, bh, bhconst); + tcg_out_branch_i32(s, INSN_COND(tcg_cond_to_bcond[cond], 1), lab); + tcg_out_movi_imm13(s, ret, 1); + tcg_out_branch_i32(s, INSN_COND(COND_NE, 1), lab); + tcg_out_movi_imm13(s, ret, 0); + + tcg_out_setcond_i32(s, tcg_unsigned_cond(cond), ret, al, bl, blconst); + + tcg_out_label(s, lab, (tcg_target_long)s->code_ptr); + break; + } +} +#endif + /* Generate global QEMU prologue and epilogue code */ void tcg_target_qemu_prologue(TCGContext *s) { @@ -1146,12 +1253,22 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, tcg_out_brcond_i32(s, args[2], args[0], args[1], const_args[1], args[3]); break; + case INDEX_op_setcond_i32: + tcg_out_setcond_i32(s, args[3], args[0], args[1], + args[2], const_args[2]); + break; + #if TCG_TARGET_REG_BITS == 32 case INDEX_op_brcond2_i32: tcg_out_brcond2_i32(s, args[4], args[0], args[1], args[2], const_args[2], args[3], const_args[3], args[5]); break; + case INDEX_op_setcond2_i32: + tcg_out_setcond2_i32(s, args[5], args[0], args[1], args[2], + args[3], const_args[3], + args[4], const_args[4]); + break; case INDEX_op_add2_i32: tcg_out_arithc(s, args[0], args[2], args[4], const_args[4], ARITH_ADDCC); @@ -1257,6 +1374,11 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, tcg_out_brcond_i64(s, args[2], args[0], args[1], const_args[1], args[3]); break; + case INDEX_op_setcond_i64: + tcg_out_setcond_i64(s, args[3], args[0], args[1], + args[2], const_args[2]); + break; + case INDEX_op_qemu_ld64: tcg_out_qemu_ld(s, args, 3); break; @@ -1309,8 +1431,11 @@ static const TCGTargetOpDef sparc_op_defs[] = { { INDEX_op_sar_i32, { "r", "r", "rJ" } }, { INDEX_op_brcond_i32, { "r", "rJ" } }, + { INDEX_op_setcond_i32 { "r", "r", "rJ" } }, + #if TCG_TARGET_REG_BITS == 32 { INDEX_op_brcond2_i32, { "r", "r", "rJ", "rJ" } }, + { INDEX_op_setcond2_i32, { "r", "r", "r", "rJ", "rJ" } }, { INDEX_op_add2_i32, { "r", "r", "r", "r", "rJ", "rJ" } }, { INDEX_op_sub2_i32, { "r", "r", "r", "r", "rJ", "rJ" } }, { INDEX_op_mulu2_i32, { "r", "r", "r", "rJ" } }, @@ -1362,6 +1487,7 @@ static const TCGTargetOpDef sparc_op_defs[] = { { INDEX_op_ext32u_i64, { "r", "ri" } }, { INDEX_op_brcond_i64, { "r", "rJ" } }, + { INDEX_op_setcond_i64 { "r", "r", "rJ" } }, #endif { -1 }, };