* [Qemu-devel] [PATCH 1/2] tcg: Add tcg_swap_cond. @ 2010-02-09 20:33 Richard Henderson 2010-02-09 21:37 ` [Qemu-devel] [PATCH 2/2] tcg-sparc: Implement setcond, setcond2 Richard Henderson 0 siblings, 1 reply; 5+ messages in thread From: Richard Henderson @ 2010-02-09 20:33 UTC (permalink / raw) To: qemu-devel; +Cc: blauwirbel Returns the condition as if with swapped comparison operands. --- tcg/tcg.h | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/tcg/tcg.h b/tcg/tcg.h index b218abe..563eccd 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -205,11 +205,19 @@ typedef enum { TCG_COND_GTU, } TCGCond; +/* Invert the sense of the comparison. */ static inline TCGCond tcg_invert_cond(TCGCond c) { return (TCGCond)(c ^ 1); } +/* Swap the operands in a comparison. */ +static inline TCGCond tcg_swap_cond(TCGCond c) +{ + int mask = (c < TCG_COND_LT ? 0 : c < TCG_COND_LTU ? 7 : 15); + return (TCGCond)(c ^ mask); +} + static inline TCGCond tcg_unsigned_cond(TCGCond c) { return (c >= TCG_COND_LT && c <= TCG_COND_GT ? c + 4 : c); -- 1.6.6 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH 2/2] tcg-sparc: Implement setcond, setcond2. 2010-02-09 20:33 [Qemu-devel] [PATCH 1/2] tcg: Add tcg_swap_cond Richard Henderson @ 2010-02-09 21:37 ` Richard Henderson 2010-02-13 22:01 ` [Qemu-devel] " Blue Swirl 0 siblings, 1 reply; 5+ messages in thread From: Richard Henderson @ 2010-02-09 21:37 UTC (permalink / raw) To: qemu-devel; +Cc: blauwirbel --- 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 }, }; -- 1.6.6 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Qemu-devel] Re: [PATCH 2/2] tcg-sparc: Implement setcond, setcond2. 2010-02-09 21:37 ` [Qemu-devel] [PATCH 2/2] tcg-sparc: Implement setcond, setcond2 Richard Henderson @ 2010-02-13 22:01 ` Blue Swirl 2010-02-15 21:22 ` Richard Henderson 0 siblings, 1 reply; 5+ messages in thread From: Blue Swirl @ 2010-02-13 22:01 UTC (permalink / raw) To: Richard Henderson; +Cc: qemu-devel On Tue, Feb 9, 2010 at 11:37 PM, Richard Henderson <rth@twiddle.net> wrote: > --- > tcg/sparc/tcg-target.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 126 insertions(+), 0 deletions(-) Something's wrong with the patch: CC sparc-bsd-user/tcg/tcg.o In file included from /src/qemu/tcg/tcg.c:158: /src/qemu/tcg/sparc/tcg-target.c: In function `tcg_out_setcond_i32': /src/qemu/tcg/sparc/tcg-target.c:623: warning: implicit declaration of function `INSN_IMM11' /src/qemu/tcg/sparc/tcg-target.c: At top level: /src/qemu/tcg/sparc/tcg-target.c:1434: error: syntax error before '{' token /src/qemu/tcg/sparc/tcg-target.c:1434: warning: initialization makes integer from pointer without a cast /src/qemu/tcg/sparc/tcg-target.c:1434: error: initializer element is not computable at load time /src/qemu/tcg/sparc/tcg-target.c:1434: error: (near initialization for `sparc_op_defs[29].op') /src/qemu/tcg/sparc/tcg-target.c:1434: warning: missing braces around initializer /src/qemu/tcg/sparc/tcg-target.c:1434: warning: (near initialization for `sparc_op_defs[29].args_ct_str') /src/qemu/tcg/sparc/tcg-target.c:1434: error: initializer element is not constant /src/qemu/tcg/sparc/tcg-target.c:1434: error: (near initialization for `sparc_op_defs[29].args_ct_str') /src/qemu/tcg/sparc/tcg-target.c:1434: error: initializer element is not constant /src/qemu/tcg/sparc/tcg-target.c:1434: error: (near initialization for `sparc_op_defs[29]') /src/qemu/tcg/sparc/tcg-target.c:1444: error: syntax error before '{' token /src/qemu/tcg/tcg.c:68: warning: `tcg_op_defs' defined but not used /src/qemu/tcg/tcg.c:76: warning: `tcg_target_available_regs' defined but not used /src/qemu/tcg/tcg.c:77: warning: `tcg_target_call_clobber_regs' defined but not used /src/qemu/tcg/tcg.c:127: warning: `tcg_out_label' defined but not used /src/qemu/tcg/sparc/tcg-target.c:140: warning: `target_parse_constraint' defined but not used gmake[1]: *** [tcg/tcg.o] Error 1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] Re: [PATCH 2/2] tcg-sparc: Implement setcond, setcond2. 2010-02-13 22:01 ` [Qemu-devel] " Blue Swirl @ 2010-02-15 21:22 ` Richard Henderson 2010-02-17 18:06 ` Blue Swirl 0 siblings, 1 reply; 5+ messages in thread From: Richard Henderson @ 2010-02-15 21:22 UTC (permalink / raw) To: Blue Swirl; +Cc: qemu-devel On 02/13/2010 02:01 PM, Blue Swirl wrote: > On Tue, Feb 9, 2010 at 11:37 PM, Richard Henderson <rth@twiddle.net> wrote: >> --- >> tcg/sparc/tcg-target.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++ >> 1 files changed, 126 insertions(+), 0 deletions(-) > > Something's wrong with the patch... Oops. The tree wasn't properly committed when I extracted the patch. Here's that last again. r~ --- commit 8f76ac8882ff2b0d9db402352b9cf632cc92f84f Author: Richard Henderson <rth@twiddle.net> Date: Mon Feb 15 13:19:49 2010 -0800 tcg-sparc: Implement setcond, setcond2. diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index dd7a598..5b4347a 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -194,6 +194,7 @@ static inline int tcg_target_const_match(tcg_target_long val, #define INSN_RS2(x) (x) #define INSN_ASI(x) ((x) << 5) +#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) @@ -217,6 +218,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 +237,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 +585,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 +1254,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 +1375,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 +1432,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 +1488,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 }, }; ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] Re: [PATCH 2/2] tcg-sparc: Implement setcond, setcond2. 2010-02-15 21:22 ` Richard Henderson @ 2010-02-17 18:06 ` Blue Swirl 0 siblings, 0 replies; 5+ messages in thread From: Blue Swirl @ 2010-02-17 18:06 UTC (permalink / raw) To: Richard Henderson; +Cc: qemu-devel Thanks, applied. Please remember the Signed-off-by: line. On Mon, Feb 15, 2010 at 11:22 PM, Richard Henderson <rth@twiddle.net> wrote: > On 02/13/2010 02:01 PM, Blue Swirl wrote: >> On Tue, Feb 9, 2010 at 11:37 PM, Richard Henderson <rth@twiddle.net> wrote: >>> --- >>> tcg/sparc/tcg-target.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++ >>> 1 files changed, 126 insertions(+), 0 deletions(-) >> >> Something's wrong with the patch... > > Oops. The tree wasn't properly committed when I > extracted the patch. Here's that last again. > > > r~ > --- > commit 8f76ac8882ff2b0d9db402352b9cf632cc92f84f > Author: Richard Henderson <rth@twiddle.net> > Date: Mon Feb 15 13:19:49 2010 -0800 > > tcg-sparc: Implement setcond, setcond2. > > diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c > index dd7a598..5b4347a 100644 > --- a/tcg/sparc/tcg-target.c > +++ b/tcg/sparc/tcg-target.c > @@ -194,6 +194,7 @@ static inline int tcg_target_const_match(tcg_target_long val, > #define INSN_RS2(x) (x) > #define INSN_ASI(x) ((x) << 5) > > +#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) > @@ -217,6 +218,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 +237,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 +585,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 +1254,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 +1375,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 +1432,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 +1488,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 }, > }; > ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2010-02-17 18:07 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-02-09 20:33 [Qemu-devel] [PATCH 1/2] tcg: Add tcg_swap_cond Richard Henderson 2010-02-09 21:37 ` [Qemu-devel] [PATCH 2/2] tcg-sparc: Implement setcond, setcond2 Richard Henderson 2010-02-13 22:01 ` [Qemu-devel] " Blue Swirl 2010-02-15 21:22 ` Richard Henderson 2010-02-17 18:06 ` Blue Swirl
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).