From patchwork Wed Oct 10 16:02:44 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 190709 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 E33762C008A for ; Thu, 11 Oct 2012 03:05:12 +1100 (EST) Received: from localhost ([::1]:35406 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TLymU-0001Dq-QI for incoming@patchwork.ozlabs.org; Wed, 10 Oct 2012 12:05:10 -0400 Received: from eggs.gnu.org ([208.118.235.92]:52866) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TLykc-0005rP-Ht for qemu-devel@nongnu.org; Wed, 10 Oct 2012 12:03:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TLykU-0007hc-Lz for qemu-devel@nongnu.org; Wed, 10 Oct 2012 12:03:14 -0400 Received: from mail-pa0-f45.google.com ([209.85.220.45]:38945) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TLykU-0007dw-Bn for qemu-devel@nongnu.org; Wed, 10 Oct 2012 12:03:06 -0400 Received: by mail-pa0-f45.google.com with SMTP id fb10so744870pad.4 for ; Wed, 10 Oct 2012 09:03:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=ykgAV1mmIIHqvVx6LJzIqLhPAPPzEYKWW7Zyw53vfus=; b=XQaPzEjNTm07v+d6/4y4AbQD93QCCn/E7YQB9pA7gA50Y1DXfORwg79Q6MXOz41fx8 Hng1UU94mZel0d46CW7QFDq9JnUI0lRXalsSGM+NKa0y9/gXnDZl2F3g4LwecFYb8nDG otDpgKgrIIs88OigB2z5Wjn01SdZCrbJUXNQqvbLBt/OLnEAk5buyckJGqBmqcvOCuOx 4CQHgDv1qzA/ZlVSGV29UXByJtnuAwITIntIuP+t/sGAmooH8RORobyhbm2L4Ion8bKT ryWlkQAdvHaiLuN0NtT/tigCMu8AwWhmkzqpPEHmEDUH/S8D/jyLgdap8mQoKaP0Kinh 428A== Received: by 10.68.197.194 with SMTP id iw2mr74889540pbc.121.1349884985931; Wed, 10 Oct 2012 09:03:05 -0700 (PDT) Received: from anchor.twiddle.home.com (50-194-63-110-static.hfc.comcastbusiness.net. [50.194.63.110]) by mx.google.com with ESMTPS id sj5sm1216694pbc.30.2012.10.10.09.03.05 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 10 Oct 2012 09:03:05 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Wed, 10 Oct 2012 09:02:44 -0700 Message-Id: <1349884967-4608-11-git-send-email-rth@twiddle.net> X-Mailer: git-send-email 1.7.11.4 In-Reply-To: <1349884967-4608-1-git-send-email-rth@twiddle.net> References: <1349884967-4608-1-git-send-email-rth@twiddle.net> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.220.45 Cc: Blue Swirl Subject: [Qemu-devel] [PATCH 10/13] tcg-sparc: Drop use of Bicc in favor of BPcc 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 Now that we're always sparcv9, we can not bother using Bicc for 32-bit branches and BPcc for 64-bit branches and instead always use BPcc. New interfaces allow less direct use of tcg_out32 and raw numbers inside the qemu_ld/st routines. Signed-off-by: Richard Henderson --- tcg/sparc/tcg-target.c | 305 +++++++++++++++++++++++-------------------------- 1 file changed, 145 insertions(+), 160 deletions(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 9c87cb6..ab47c98 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -115,101 +115,6 @@ static const int tcg_target_call_oarg_regs[] = { TCG_REG_O3, }; -static inline int check_fit_tl(tcg_target_long val, unsigned int bits) -{ - return (val << ((sizeof(tcg_target_long) * 8 - bits)) - >> (sizeof(tcg_target_long) * 8 - bits)) == val; -} - -static inline int check_fit_i32(uint32_t val, unsigned int bits) -{ - return ((val << (32 - bits)) >> (32 - bits)) == val; -} - -static void patch_reloc(uint8_t *code_ptr, int type, - tcg_target_long value, tcg_target_long addend) -{ - value += addend; - switch (type) { - case R_SPARC_32: - if (value != (uint32_t)value) - tcg_abort(); - *(uint32_t *)code_ptr = value; - break; - case R_SPARC_WDISP22: - value -= (long)code_ptr; - value >>= 2; - if (!check_fit_tl(value, 22)) - tcg_abort(); - *(uint32_t *)code_ptr = ((*(uint32_t *)code_ptr) & ~0x3fffff) | value; - break; - case R_SPARC_WDISP19: - value -= (long)code_ptr; - value >>= 2; - if (!check_fit_tl(value, 19)) - tcg_abort(); - *(uint32_t *)code_ptr = ((*(uint32_t *)code_ptr) & ~0x7ffff) | value; - break; - default: - tcg_abort(); - } -} - -/* parse target specific constraints */ -static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) -{ - const char *ct_str; - - ct_str = *pct_str; - switch (ct_str[0]) { - case 'r': - ct->ct |= TCG_CT_REG; - tcg_regset_set32(ct->u.regs, 0, 0xffffffff); - break; - case 'L': /* qemu_ld/st constraint */ - ct->ct |= TCG_CT_REG; - tcg_regset_set32(ct->u.regs, 0, 0xffffffff); - // Helper args - tcg_regset_reset_reg(ct->u.regs, TCG_REG_O0); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_O1); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_O2); - break; - case 'I': - ct->ct |= TCG_CT_CONST_S11; - break; - case 'J': - ct->ct |= TCG_CT_CONST_S13; - break; - case 'Z': - ct->ct |= TCG_CT_CONST_ZERO; - break; - default: - return -1; - } - ct_str++; - *pct_str = ct_str; - return 0; -} - -/* test if a constant matches the constraint */ -static inline int tcg_target_const_match(tcg_target_long val, - const TCGArgConstraint *arg_ct) -{ - int ct = arg_ct->ct; - - if (ct & TCG_CT_CONST) { - return 1; - } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) { - return 1; - } else if ((ct & TCG_CT_CONST_S11) && check_fit_tl(val, 11)) { - return 1; - } else if ((ct & TCG_CT_CONST_S13) && check_fit_tl(val, 13)) { - return 1; - } else { - return 0; - } -} - #define INSN_OP(x) ((x) << 30) #define INSN_OP2(x) ((x) << 22) #define INSN_OP3(x) ((x) << 19) @@ -222,9 +127,8 @@ static inline int tcg_target_const_match(tcg_target_long val, #define INSN_IMM11(x) ((1 << 13) | ((x) & 0x7ff)) #define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff)) #define INSN_OFF19(x) (((x) >> 2) & 0x07ffff) -#define INSN_OFF22(x) (((x) >> 2) & 0x3fffff) +#define INSN_COND(x) ((x) << 25) -#define INSN_COND(x, a) (((x) << 25) | ((a) << 29)) #define COND_N 0x0 #define COND_E 0x1 #define COND_LE 0x2 @@ -241,11 +145,17 @@ static inline int tcg_target_const_match(tcg_target_long val, #define COND_CC 0xd #define COND_POS 0xe #define COND_VC 0xf -#define BA (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2)) +#define BA (INSN_OP(0) | INSN_COND(COND_A) | INSN_OP2(0x2)) #define MOVCC_ICC (1 << 18) #define MOVCC_XCC (1 << 18 | 1 << 12) +#define BPCC_ICC 0 +#define BPCC_XCC (2 << 20) +#define BPCC_PT (1 << 19) +#define BPCC_PN 0 +#define BPCC_A (1 << 29) + #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)) @@ -318,6 +228,99 @@ static inline int tcg_target_const_match(tcg_target_long val, #define STW_LE (STWA | INSN_ASI(ASI_PRIMARY_LITTLE)) #define STX_LE (STXA | INSN_ASI(ASI_PRIMARY_LITTLE)) +static inline int check_fit_tl(tcg_target_long val, unsigned int bits) +{ + return (val << ((sizeof(tcg_target_long) * 8 - bits)) + >> (sizeof(tcg_target_long) * 8 - bits)) == val; +} + +static inline int check_fit_i32(uint32_t val, unsigned int bits) +{ + return ((val << (32 - bits)) >> (32 - bits)) == val; +} + +static void patch_reloc(uint8_t *code_ptr, int type, + tcg_target_long value, tcg_target_long addend) +{ + uint32_t insn; + value += addend; + switch (type) { + case R_SPARC_32: + if (value != (uint32_t)value) { + tcg_abort(); + } + *(uint32_t *)code_ptr = value; + break; + case R_SPARC_WDISP19: + value -= (long)code_ptr; + if (!check_fit_tl(value >> 2, 19)) { + tcg_abort(); + } + insn = *(uint32_t *)code_ptr; + insn &= ~INSN_OFF19(-1); + insn |= INSN_OFF19(value); + *(uint32_t *)code_ptr = insn; + break; + default: + tcg_abort(); + } +} + +/* parse target specific constraints */ +static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) +{ + const char *ct_str; + + ct_str = *pct_str; + switch (ct_str[0]) { + case 'r': + ct->ct |= TCG_CT_REG; + tcg_regset_set32(ct->u.regs, 0, 0xffffffff); + break; + case 'L': /* qemu_ld/st constraint */ + ct->ct |= TCG_CT_REG; + tcg_regset_set32(ct->u.regs, 0, 0xffffffff); + // Helper args + tcg_regset_reset_reg(ct->u.regs, TCG_REG_O0); + tcg_regset_reset_reg(ct->u.regs, TCG_REG_O1); + tcg_regset_reset_reg(ct->u.regs, TCG_REG_O2); + break; + case 'I': + ct->ct |= TCG_CT_CONST_S11; + break; + case 'J': + ct->ct |= TCG_CT_CONST_S13; + break; + case 'Z': + ct->ct |= TCG_CT_CONST_ZERO; + break; + default: + return -1; + } + ct_str++; + *pct_str = ct_str; + return 0; +} + +/* test if a constant matches the constraint */ +static inline int tcg_target_const_match(tcg_target_long val, + const TCGArgConstraint *arg_ct) +{ + int ct = arg_ct->ct; + + if (ct & TCG_CT_CONST) { + return 1; + } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) { + return 1; + } else if ((ct & TCG_CT_CONST_S11) && check_fit_tl(val, 11)) { + return 1; + } else if ((ct & TCG_CT_CONST_S13) && check_fit_tl(val, 13)) { + return 1; + } else { + return 0; + } +} + static inline void tcg_out_arith(TCGContext *s, int rd, int rs1, int rs2, int op) { @@ -486,39 +489,6 @@ static inline void tcg_out_nop(TCGContext *s) tcg_out_sethi(s, TCG_REG_G0, 0); } -static void tcg_out_branch_i32(TCGContext *s, int opc, int label_index) -{ - TCGLabel *l = &s->labels[label_index]; - uint32_t off22; - - if (l->has_value) { - off22 = INSN_OFF22(l->u.value - (unsigned long)s->code_ptr); - } else { - /* Make sure to preserve destinations during retranslation. */ - off22 = *(uint32_t *)s->code_ptr & INSN_OFF22(-1); - tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP22, label_index, 0); - } - tcg_out32(s, INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2) | off22); -} - -#if TCG_TARGET_REG_BITS == 64 -static void tcg_out_branch_i64(TCGContext *s, int opc, int label_index) -{ - TCGLabel *l = &s->labels[label_index]; - uint32_t off19; - - if (l->has_value) { - off19 = INSN_OFF19(l->u.value - (unsigned long)s->code_ptr); - } else { - /* Make sure to preserve destinations during retranslation. */ - off19 = *(uint32_t *)s->code_ptr & INSN_OFF19(-1); - tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP19, label_index, 0); - } - tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x1) | - (0x5 << 19) | off19)); -} -#endif - static const uint8_t tcg_cond_to_bcond[] = { [TCG_COND_EQ] = COND_E, [TCG_COND_NE] = COND_NE, @@ -532,17 +502,36 @@ static const uint8_t tcg_cond_to_bcond[] = { [TCG_COND_GTU] = COND_GU, }; +static void tcg_out_bpcc0(TCGContext *s, int scond, int flags, int off19) +{ + tcg_out32(s, INSN_OP(0) | INSN_OP2(1) | INSN_COND(scond) | flags | off19); +} + +static void tcg_out_bpcc(TCGContext *s, int scond, int flags, int label) +{ + TCGLabel *l = &s->labels[label]; + int off19; + + if (l->has_value) { + off19 = INSN_OFF19(l->u.value - (unsigned long)s->code_ptr); + } else { + /* Make sure to preserve destinations during retranslation. */ + off19 = *(uint32_t *)s->code_ptr & INSN_OFF19(-1); + tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP19, label, 0); + } + tcg_out_bpcc0(s, scond, flags, off19); +} + static void tcg_out_cmp(TCGContext *s, TCGArg c1, TCGArg c2, int c2const) { tcg_out_arithc(s, TCG_REG_G0, c1, c2, c2const, ARITH_SUBCC); } -static void tcg_out_brcond_i32(TCGContext *s, TCGCond cond, - TCGArg arg1, TCGArg arg2, int const_arg2, - int label_index) +static void tcg_out_brcond_i32(TCGContext *s, TCGCond cond, TCGArg arg1, + TCGArg arg2, int const_arg2, int label) { tcg_out_cmp(s, arg1, arg2, const_arg2); - tcg_out_branch_i32(s, tcg_cond_to_bcond[cond], label_index); + tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_ICC | BPCC_PT, label); tcg_out_nop(s); } @@ -563,12 +552,11 @@ static void tcg_out_movcond_i32(TCGContext *s, TCGCond cond, TCGArg ret, } #if TCG_TARGET_REG_BITS == 64 -static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, - TCGArg arg1, TCGArg arg2, int const_arg2, - int label_index) +static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, TCGArg arg1, + TCGArg arg2, int const_arg2, int label) { tcg_out_cmp(s, arg1, arg2, const_arg2); - tcg_out_branch_i64(s, tcg_cond_to_bcond[cond], label_index); + tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_XCC | BPCC_PT, label); tcg_out_nop(s); } @@ -585,32 +573,32 @@ static void tcg_out_brcond2_i32(TCGContext *s, TCGCond cond, TCGArg bl, int blconst, TCGArg bh, int bhconst, int label_dest) { - int cc, label_next = gen_new_label(); + int scond, label_next = gen_new_label(); tcg_out_cmp(s, ah, bh, bhconst); /* Note that we fill one of the delay slots with the second compare. */ switch (cond) { case TCG_COND_EQ: - tcg_out_branch_i32(s, COND_NE, label_next); + tcg_out_bpcc(s, COND_NE, BPCC_ICC | BPCC_PT, label_next); tcg_out_cmp(s, al, bl, blconst); - tcg_out_branch_i32(s, COND_E, label_dest); + tcg_out_bpcc(s, COND_E, BPCC_ICC | BPCC_PT, label_dest); break; case TCG_COND_NE: - tcg_out_branch_i32(s, COND_NE, label_dest); + tcg_out_bpcc(s, COND_NE, BPCC_ICC | BPCC_PT, label_dest); tcg_out_cmp(s, al, bl, blconst); - tcg_out_branch_i32(s, COND_NE, label_dest); + tcg_out_bpcc(s, COND_NE, BPCC_ICC | BPCC_PT, label_dest); break; default: - cc = tcg_cond_to_bcond[tcg_high_cond(cond)]; - tcg_out_branch_i32(s, cc, label_dest); + scond = tcg_cond_to_bcond[tcg_high_cond(cond)]; + tcg_out_bpcc(s, scond, BPCC_ICC | BPCC_PT, label_dest); tcg_out_nop(s); - tcg_out_branch_i32(s, COND_NE, label_next); + tcg_out_bpcc(s, COND_NE, BPCC_ICC | BPCC_PT, label_next); tcg_out_cmp(s, al, bl, blconst); - cc = tcg_cond_to_bcond[tcg_unsigned_cond(cond)]; - tcg_out_branch_i32(s, cc, label_dest); + scond = tcg_cond_to_bcond[tcg_unsigned_cond(cond)]; + tcg_out_bpcc(s, scond, BPCC_ICC | BPCC_PT, label_dest); break; } tcg_out_nop(s); @@ -903,8 +891,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop) /* bne,pn %[xi]cc, label0 */ label_ptr[0] = (uint32_t *)s->code_ptr; - tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_NE, 0) | INSN_OP2(0x1) - | ((TARGET_LONG_BITS == 64) << 21))); + tcg_out_bpcc0(s, COND_NE, BPCC_PN + | (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0); /* TLB Hit. */ /* Load all 64-bits into an O/G register. */ @@ -919,8 +907,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop) /* b,a,pt label1 */ label_ptr[1] = (uint32_t *)s->code_ptr; - tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x1) - | (1 << 29) | (1 << 19))); + tcg_out_bpcc0(s, COND_A, BPCC_A | BPCC_PT, 0); } else { /* The fast path is exactly one insn. Thus we can perform the entire TLB Hit in the (annulled) delay slot of the branch @@ -929,9 +916,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop) /* beq,a,pt %[xi]cc, label0 */ label_ptr[0] = NULL; label_ptr[1] = (uint32_t *)s->code_ptr; - tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x1) - | ((TARGET_LONG_BITS == 64) << 21) - | (1 << 29) | (1 << 19))); + tcg_out_bpcc0(s, COND_E, BPCC_A | BPCC_PT + | (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0); /* delay slot */ tcg_out_ldst_rr(s, datalo, addr_reg, TCG_REG_O1, qemu_ld_opc[sizeop]); } @@ -1050,9 +1036,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop) TLB Hit in the (annulled) delay slot of the branch over TLB Miss. */ /* beq,a,pt %[xi]cc, label0 */ label_ptr = (uint32_t *)s->code_ptr; - tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x1) - | ((TARGET_LONG_BITS == 64) << 21) - | (1 << 29) | (1 << 19))); + tcg_out_bpcc0(s, COND_E, BPCC_A | BPCC_PT + | (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0); /* delay slot */ tcg_out_ldst_rr(s, datafull, addr_reg, TCG_REG_O1, qemu_st_opc[sizeop]); @@ -1143,7 +1128,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, tcg_out_nop(s); break; case INDEX_op_br: - tcg_out_branch_i32(s, COND_A, args[0]); + tcg_out_bpcc(s, COND_A, BPCC_PT, args[0]); tcg_out_nop(s); break; case INDEX_op_movi_i32: