* [Qemu-devel] [PATCH 1/6] tcg-sparc: Fix imm13 check in movi.
2009-12-19 21:08 [Qemu-devel] [PATCH 0/6] tcg sparc improvements Richard Henderson
@ 2009-12-17 23:20 ` Richard Henderson
2009-12-17 23:47 ` [Qemu-devel] [PATCH 3/6] tcg-sparc: Use TCG_TARGET_REG_BITS in conditional compilation Richard Henderson
` (5 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2009-12-17 23:20 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
We were unnecessarily restricting imm13 constants to 12 bits.
---
tcg/sparc/tcg-target.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 23cd9cd..b480ed6 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -302,7 +302,7 @@ static inline void tcg_out_movi_imm13(TCGContext *s, int ret, uint32_t arg)
static inline void tcg_out_movi_imm32(TCGContext *s, int ret, uint32_t arg)
{
- if (check_fit_tl(arg, 12))
+ if (check_fit_tl(arg, 13))
tcg_out_movi_imm13(s, ret, arg);
else {
tcg_out_sethi(s, ret, arg);
--
1.6.5.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH 3/6] tcg-sparc: Use TCG_TARGET_REG_BITS in conditional compilation.
2009-12-19 21:08 [Qemu-devel] [PATCH 0/6] tcg sparc improvements Richard Henderson
2009-12-17 23:20 ` [Qemu-devel] [PATCH 1/6] tcg-sparc: Fix imm13 check in movi Richard Henderson
@ 2009-12-17 23:47 ` Richard Henderson
2009-12-19 19:45 ` [Qemu-devel] [PATCH 2/6] tcg-sparc: Improve tcg_out_movi for sparc64 Richard Henderson
` (4 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2009-12-17 23:47 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
The test TCG_TARGET_REG_BITS==64 is exactly the feature that we
are checking for, whereas something involving __sparc_v9__ or
__sparc_v8plus__ should be reserved for something ISA related,
as with SMULX.
---
tcg/sparc/tcg-target.c | 32 ++++++++++++++++----------------
1 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 78b26c9..78f851d 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -348,13 +348,13 @@ static inline void tcg_out_ld_ptr(TCGContext *s, int ret,
{
if (!check_fit_tl(arg, 10))
tcg_out_movi(s, TCG_TYPE_PTR, ret, arg & ~0x3ffULL);
-#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
- tcg_out32(s, LDX | INSN_RD(ret) | INSN_RS1(ret) |
- INSN_IMM13(arg & 0x3ff));
-#else
- tcg_out32(s, LDUW | INSN_RD(ret) | INSN_RS1(ret) |
- INSN_IMM13(arg & 0x3ff));
-#endif
+ if (TCG_TARGET_REG_BITS == 64) {
+ tcg_out32(s, LDX | INSN_RD(ret) | INSN_RS1(ret) |
+ INSN_IMM13(arg & 0x3ff));
+ } else {
+ tcg_out32(s, LDUW | INSN_RD(ret) | INSN_RS1(ret) |
+ INSN_IMM13(arg & 0x3ff));
+ }
}
static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, int offset, int op)
@@ -447,7 +447,7 @@ static void tcg_out_branch_i32(TCGContext *s, int opc, int label_index)
}
}
-#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
+#if TCG_TARGET_REG_BITS == 64
static void tcg_out_branch_i64(TCGContext *s, int opc, int label_index)
{
int32_t val;
@@ -493,7 +493,7 @@ static void tcg_out_brcond_i32(TCGContext *s, int cond,
tcg_out_nop(s);
}
-#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
+#if TCG_TARGET_REG_BITS == 64
static void tcg_out_brcond_i64(TCGContext *s, int cond,
TCGArg arg1, TCGArg arg2, int const_arg2,
int label_index)
@@ -989,7 +989,7 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
tcg_out_movi(s, TCG_TYPE_I32, args[0], (uint32_t)args[1]);
break;
-#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
+#if TCG_TARGET_REG_BITS == 64
#define OP_32_64(x) \
glue(glue(case INDEX_op_, x), _i32:) \
glue(glue(case INDEX_op_, x), _i64:)
@@ -1010,7 +1010,7 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
tcg_out_ldst(s, args[0], args[1], args[2], LDSH);
break;
case INDEX_op_ld_i32:
-#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
+#if TCG_TARGET_REG_BITS == 64
case INDEX_op_ld32u_i64:
#endif
tcg_out_ldst(s, args[0], args[1], args[2], LDUW);
@@ -1022,7 +1022,7 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
tcg_out_ldst(s, args[0], args[1], args[2], STH);
break;
case INDEX_op_st_i32:
-#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
+#if TCG_TARGET_REG_BITS == 64
case INDEX_op_st32_i64:
#endif
tcg_out_ldst(s, args[0], args[1], args[2], STW);
@@ -1106,7 +1106,7 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
tcg_out_qemu_st(s, args, 2);
break;
-#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
+#if TCG_TARGET_REG_BITS == 64
case INDEX_op_movi_i64:
tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
break;
@@ -1208,7 +1208,7 @@ static const TCGTargetOpDef sparc_op_defs[] = {
{ INDEX_op_qemu_st16, { "L", "L" } },
{ INDEX_op_qemu_st32, { "L", "L" } },
-#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
+#if TCG_TARGET_REG_BITS == 64
{ INDEX_op_mov_i64, { "r", "r" } },
{ INDEX_op_movi_i64, { "r" } },
{ INDEX_op_ld8u_i64, { "r", "r" } },
@@ -1246,7 +1246,7 @@ static const TCGTargetOpDef sparc_op_defs[] = {
void tcg_target_init(TCGContext *s)
{
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
-#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
+#if TCG_TARGET_REG_BITS == 64
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
#endif
tcg_regset_set32(tcg_target_call_clobber_regs, 0,
@@ -1267,7 +1267,7 @@ void tcg_target_init(TCGContext *s)
tcg_regset_clear(s->reserved_regs);
tcg_regset_set_reg(s->reserved_regs, TCG_REG_G0);
-#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
+#if TCG_TARGET_REG_BITS == 64
tcg_regset_set_reg(s->reserved_regs, TCG_REG_I4); // for internal use
#endif
tcg_regset_set_reg(s->reserved_regs, TCG_REG_I5); // for internal use
--
1.6.5.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH 2/6] tcg-sparc: Improve tcg_out_movi for sparc64.
2009-12-19 21:08 [Qemu-devel] [PATCH 0/6] tcg sparc improvements Richard Henderson
2009-12-17 23:20 ` [Qemu-devel] [PATCH 1/6] tcg-sparc: Fix imm13 check in movi Richard Henderson
2009-12-17 23:47 ` [Qemu-devel] [PATCH 3/6] tcg-sparc: Use TCG_TARGET_REG_BITS in conditional compilation Richard Henderson
@ 2009-12-19 19:45 ` Richard Henderson
2009-12-19 20:23 ` [Qemu-devel] [PATCH 4/6] tcg-sparc: Implement brcond2 Richard Henderson
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2009-12-19 19:45 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
Generate sign-extended 32-bit constants with SETHI+XOR.
Otherwise tidy the routine to avoid the need for
conditional compilation and code duplication with movi_imm32.
---
tcg/sparc/tcg-target.c | 27 +++++++++++++++------------
1 files changed, 15 insertions(+), 12 deletions(-)
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index b480ed6..78b26c9 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -314,22 +314,25 @@ static inline void tcg_out_movi_imm32(TCGContext *s, int ret, uint32_t arg)
static inline void tcg_out_movi(TCGContext *s, TCGType type,
int ret, tcg_target_long arg)
{
-#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
- if (!check_fit_tl(arg, 32) && (arg & ~0xffffffffULL) != 0) {
- tcg_out_movi_imm32(s, TCG_REG_I4, arg >> 32);
+ /* All 32-bit constants, as well as 64-bit constants with
+ no high bits set go through movi_imm32. */
+ if (TCG_TARGET_REG_BITS == 32
+ || type == TCG_TYPE_I32
+ || (arg & ~(tcg_target_long)0xffffffff) == 0) {
+ tcg_out_movi_imm32(s, ret, arg);
+ } else if (check_fit_tl(arg, 13)) {
+ /* A 13-bit constant sign-extended to 64-bits. */
+ tcg_out_movi_imm13(s, ret, arg);
+ } else if (check_fit_tl(arg, 32)) {
+ /* A 32-bit constant sign-extended to 64-bits. */
+ tcg_out_sethi(s, ret, ~arg);
+ tcg_out_arithi(s, ret, ret, (arg & 0x3ff) | -0x400, ARITH_XOR);
+ } else {
+ tcg_out_movi_imm32(s, TCG_REG_I4, arg >> (TCG_TARGET_REG_BITS / 2));
tcg_out_arithi(s, TCG_REG_I4, TCG_REG_I4, 32, SHIFT_SLLX);
tcg_out_movi_imm32(s, ret, arg);
tcg_out_arith(s, ret, ret, TCG_REG_I4, ARITH_OR);
- } else if (check_fit_tl(arg, 12))
- tcg_out_movi_imm13(s, ret, arg);
- else {
- tcg_out_sethi(s, ret, arg);
- if (arg & 0x3ff)
- tcg_out_arithi(s, ret, ret, arg & 0x3ff, ARITH_OR);
}
-#else
- tcg_out_movi_imm32(s, ret, arg);
-#endif
}
static inline void tcg_out_ld_raw(TCGContext *s, int ret,
--
1.6.5.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH 4/6] tcg-sparc: Implement brcond2.
2009-12-19 21:08 [Qemu-devel] [PATCH 0/6] tcg sparc improvements Richard Henderson
` (2 preceding siblings ...)
2009-12-19 19:45 ` [Qemu-devel] [PATCH 2/6] tcg-sparc: Improve tcg_out_movi for sparc64 Richard Henderson
@ 2009-12-19 20:23 ` Richard Henderson
2009-12-19 20:24 ` [Qemu-devel] [PATCH 5/6] tcg: Add tcg_unsigned_cond Richard Henderson
` (2 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2009-12-19 20:23 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
Split out tcg_out_cmp and properly handle immediate arguments.
Fix constraints on brcond to match what SUBCC accepts.
Add tcg_out_brcond2_i32 for 32-bit host.
---
tcg/sparc/tcg-target.c | 83 +++++++++++++++++++++++++++++++++++++++--------
1 files changed, 69 insertions(+), 14 deletions(-)
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 78f851d..8f094e5 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -479,16 +479,19 @@ static const uint8_t tcg_cond_to_bcond[10] = {
[TCG_COND_GTU] = COND_GU,
};
+static void tcg_out_cmp(TCGContext *s, TCGArg c1, TCGArg c2, int c2const)
+{
+ if (c2const)
+ tcg_out_arithi(s, TCG_REG_G0, c1, c2, ARITH_SUBCC);
+ else
+ tcg_out_arith(s, TCG_REG_G0, c1, c2, ARITH_SUBCC);
+}
+
static void tcg_out_brcond_i32(TCGContext *s, int cond,
TCGArg arg1, TCGArg arg2, int const_arg2,
int label_index)
{
- if (const_arg2 && arg2 == 0)
- /* orcc %g0, r, %g0 */
- tcg_out_arith(s, TCG_REG_G0, TCG_REG_G0, arg1, ARITH_ORCC);
- else
- /* subcc r1, r2, %g0 */
- tcg_out_arith(s, TCG_REG_G0, arg1, arg2, ARITH_SUBCC);
+ tcg_out_cmp(s, arg1, arg2, const_arg2);
tcg_out_branch_i32(s, tcg_cond_to_bcond[cond], label_index);
tcg_out_nop(s);
}
@@ -498,15 +501,57 @@ static void tcg_out_brcond_i64(TCGContext *s, int cond,
TCGArg arg1, TCGArg arg2, int const_arg2,
int label_index)
{
- if (const_arg2 && arg2 == 0)
- /* orcc %g0, r, %g0 */
- tcg_out_arith(s, TCG_REG_G0, TCG_REG_G0, arg1, ARITH_ORCC);
- else
- /* subcc r1, r2, %g0 */
- tcg_out_arith(s, TCG_REG_G0, arg1, arg2, ARITH_SUBCC);
+ tcg_out_cmp(s, arg1, arg2, const_arg2);
tcg_out_branch_i64(s, tcg_cond_to_bcond[cond], label_index);
tcg_out_nop(s);
}
+#else
+static void tcg_out_brcond2_i32(TCGContext *s, int cond,
+ TCGArg al, TCGArg ah,
+ TCGArg bl, int blconst,
+ TCGArg bh, int bhconst, int label_dest)
+{
+ int cc, 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:
+ cc = INSN_COND(tcg_cond_to_bcond[TCG_COND_NE], 0);
+ tcg_out_branch_i32(s, cc, label_next);
+ tcg_out_cmp(s, al, bl, blconst);
+ cc = INSN_COND(tcg_cond_to_bcond[TCG_COND_EQ], 0);
+ tcg_out_branch_i32(s, cc, label_dest);
+ break;
+
+ case TCG_COND_NE:
+ cc = INSN_COND(tcg_cond_to_bcond[TCG_COND_NE], 0);
+ tcg_out_branch_i32(s, cc, label_dest);
+ tcg_out_cmp(s, al, bl, blconst);
+ tcg_out_branch_i32(s, cc, label_dest);
+ break;
+
+ default:
+ /* ??? One could fairly easily special-case 64-bit unsigned
+ compares against 32-bit zero-extended constants. For instance,
+ we know that (unsigned)AH < 0 is false and need not emit it.
+ Similarly, (unsigned)AH > 0 being true implies AH != 0, so the
+ second branch will never be taken. */
+ cc = INSN_COND(tcg_cond_to_bcond[cond], 0);
+ tcg_out_branch_i32(s, cc, label_dest);
+ tcg_out_nop(s);
+ cc = INSN_COND(tcg_cond_to_bcond[TCG_COND_NE], 0);
+ tcg_out_branch_i32(s, cc, label_next);
+ tcg_out_cmp(s, al, bl, blconst);
+ cc = INSN_COND(tcg_cond_to_bcond[tcg_unsigned_cond(cond)], 0);
+ tcg_out_branch_i32(s, cc, label_dest);
+ break;
+ }
+ tcg_out_nop(s);
+
+ tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
+}
#endif
/* Generate global QEMU prologue and epilogue code */
@@ -1077,6 +1122,13 @@ 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;
+#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;
+#endif
case INDEX_op_qemu_ld8u:
tcg_out_qemu_ld(s, args, 0);
@@ -1195,7 +1247,10 @@ static const TCGTargetOpDef sparc_op_defs[] = {
{ INDEX_op_shr_i32, { "r", "r", "rJ" } },
{ INDEX_op_sar_i32, { "r", "r", "rJ" } },
- { INDEX_op_brcond_i32, { "r", "ri" } },
+ { INDEX_op_brcond_i32, { "r", "rJ" } },
+#if TCG_TARGET_REG_BITS == 32
+ { INDEX_op_brcond2_i32, { "r", "r", "rJ", "rJ" } },
+#endif
{ INDEX_op_qemu_ld8u, { "r", "L" } },
{ INDEX_op_qemu_ld8s, { "r", "L" } },
@@ -1238,7 +1293,7 @@ static const TCGTargetOpDef sparc_op_defs[] = {
{ INDEX_op_shr_i64, { "r", "r", "rJ" } },
{ INDEX_op_sar_i64, { "r", "r", "rJ" } },
- { INDEX_op_brcond_i64, { "r", "ri" } },
+ { INDEX_op_brcond_i64, { "r", "rJ" } },
#endif
{ -1 },
};
--
1.6.5.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH 5/6] tcg: Add tcg_unsigned_cond.
2009-12-19 21:08 [Qemu-devel] [PATCH 0/6] tcg sparc improvements Richard Henderson
` (3 preceding siblings ...)
2009-12-19 20:23 ` [Qemu-devel] [PATCH 4/6] tcg-sparc: Implement brcond2 Richard Henderson
@ 2009-12-19 20:24 ` Richard Henderson
2009-12-19 21:07 ` [Qemu-devel] [PATCH 6/6] tcg-sparc: Implement setcond, movcond, setcond2 Richard Henderson
2009-12-20 11:24 ` [Qemu-devel] Re: [PATCH 0/6] tcg sparc improvements Blue Swirl
6 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2009-12-19 20:24 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
Returns an unsigned version of a signed condition;
returns the original condition otherwise.
---
tcg/tcg.h | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 376d6af..b218abe 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -210,6 +210,11 @@ static inline TCGCond tcg_invert_cond(TCGCond c)
return (TCGCond)(c ^ 1);
}
+static inline TCGCond tcg_unsigned_cond(TCGCond c)
+{
+ return (c >= TCG_COND_LT && c <= TCG_COND_GT ? c + 4 : c);
+}
+
#define TEMP_VAL_DEAD 0
#define TEMP_VAL_REG 1
#define TEMP_VAL_MEM 2
--
1.6.5.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH 6/6] tcg-sparc: Implement setcond, movcond, setcond2.
2009-12-19 21:08 [Qemu-devel] [PATCH 0/6] tcg sparc improvements Richard Henderson
` (4 preceding siblings ...)
2009-12-19 20:24 ` [Qemu-devel] [PATCH 5/6] tcg: Add tcg_unsigned_cond Richard Henderson
@ 2009-12-19 21:07 ` Richard Henderson
2009-12-20 11:24 ` [Qemu-devel] Re: [PATCH 0/6] tcg sparc improvements Blue Swirl
6 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2009-12-19 21:07 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
For the time being, the movcond opcodes are protected by
MOVCOND_PATCH_APPLIED. But since setcond largely depends
on movcond, it didn't seem worthwhile to spend too much
effort splitting this into two patches. Hopefully we can
simply resolve the issue of what to do with movcond before
having to implement setcond without it.
---
tcg/sparc/tcg-target.c | 253 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 253 insertions(+), 0 deletions(-)
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 8f094e5..6686ce2 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -191,6 +191,8 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define INSN_RS2(x) (x)
#define INSN_ASI(x) ((x) << 5)
+#define INSN_IMM10(x) ((1 << 13) | ((x) & 0x3ff))
+#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)
@@ -214,6 +216,17 @@ 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 MRCOND_E 0x1
+#define MRCOND_LE 0x2
+#define MRCOND_L 0x3
+#define MRCOND_NE 0x5
+#define MRCOND_G 0x6
+#define MRCOND_GE 0x7
+#define INSN_MRCOND(c) ((c) << 10)
+
#define ARITH_ADD (INSN_OP(2) | INSN_OP3(0x00))
#define ARITH_AND (INSN_OP(2) | INSN_OP3(0x01))
#define ARITH_OR (INSN_OP(2) | INSN_OP3(0x02))
@@ -228,7 +241,9 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define ARITH_SDIV (INSN_OP(2) | INSN_OP3(0x0f))
#define ARITH_MULX (INSN_OP(2) | INSN_OP3(0x09))
#define ARITH_UDIVX (INSN_OP(2) | INSN_OP3(0x0d))
+#define ARITH_MOVCC (INSN_OP(2) | INSN_OP3(0x2c))
#define ARITH_SDIVX (INSN_OP(2) | INSN_OP3(0x2d))
+#define ARITH_MOVR (INSN_OP(2) | INSN_OP3(0x2f))
#define SHIFT_SLL (INSN_OP(2) | INSN_OP3(0x25))
#define SHIFT_SRL (INSN_OP(2) | INSN_OP3(0x26))
@@ -554,6 +569,205 @@ static void tcg_out_brcond2_i32(TCGContext *s, int cond,
}
#endif
+#if defined(__sparc_v9__) || defined(__sparc_v8plus__)
+static const uint8_t tcg_cond_to_mrcond[10] = {
+ [TCG_COND_EQ] = MRCOND_E,
+ [TCG_COND_NE] = MRCOND_NE,
+ [TCG_COND_LT] = MRCOND_L,
+ [TCG_COND_GE] = MRCOND_GE,
+ [TCG_COND_LE] = MRCOND_LE,
+ [TCG_COND_GT] = MRCOND_G
+};
+#endif
+
+static void tcg_out_movcond(TCGContext *s, int cond, TCGArg d,
+ TCGArg c1, TCGArg c2, int c2const,
+ TCGArg vt, int vtconst, TCGArg vf, int vfconst,
+ int i64 __attribute__((unused)))
+{
+ TCGArg t;
+
+ if (vtconst == vfconst && vt == vf) {
+ if (vtconst) {
+ tcg_out_movi_imm13(s, d, vt);
+ } else if (d != vt) {
+ tcg_out_mov(s, d, vt);
+ }
+ return;
+ }
+
+#if defined(__sparc_v9__) || defined(__sparc_v8plus__)
+ /* Use MOVR when possible. We have constrained the constants to IMM11
+ for the sake of MOVCC, but MOVR only takes IMM10. Also, we cannot
+ overwrite the condition with our initial store to D. Any attempt to
+ work around these extra conditions is just as much work as falling
+ back to MOVCC. */
+ if (c2 == 0 && tcg_cond_to_mrcond[cond] && d != c1) {
+ int use_movr = 1, do_swap = 0;
+
+ if (vtconst) {
+ if (!check_fit_tl(vt, 10)) {
+ do_swap = 1;
+ if (vfconst) {
+ use_movr = check_fit_tl(vt, 10);
+ } else {
+ use_movr = (d != vf);
+ }
+ }
+ } else if (d == vt) {
+ do_swap = 1;
+ if (vfconst) {
+ use_movr = check_fit_tl(vt, 10);
+ }
+ }
+ if (use_movr) {
+ if (do_swap) {
+ cond = tcg_invert_cond(cond);
+ t = vt, vt = vf, vf = t;
+ t = vtconst, vtconst = vfconst, vfconst = t;
+ }
+ if (vfconst) {
+ tcg_out_movi_imm13(s, d, vf);
+ } else if (d != vf) {
+ tcg_out_mov(s, d, vf);
+ }
+ tcg_out32(s, ARITH_MOVR | INSN_RD(d) | INSN_RS1(c1)
+ | INSN_MRCOND(tcg_cond_to_mrcond[cond])
+ | (vtconst ? INSN_IMM10(vt) : INSN_RS2(vt)));
+ return;
+ }
+ }
+
+ tcg_out_cmp(s, c1, c2, c2const);
+
+ if (!vtconst && vt == d) {
+ cond = tcg_invert_cond(cond);
+ vt = vf, vf = d;
+ vtconst = vfconst, vfconst = 0;
+ }
+ if (vfconst) {
+ tcg_out_movi_imm13(s, d, vf);
+ } else if (d != vf) {
+ tcg_out_mov(s, d, vf);
+ }
+ tcg_out32(s, ARITH_MOVCC | INSN_RD(d)
+ | INSN_RS1(tcg_cond_to_bcond[cond])
+ | (i64 ? MOVCC_XCC : MOVCC_ICC)
+ | (vtconst ? INSN_IMM11(vt) : INSN_RS2(vt)));
+#else
+ t = gen_new_label ();
+
+ tcg_out_cmp(s, c1, c2, c2const);
+
+ /* Note we set the annul bit do avoid clobbering D on the false path. */
+ tcg_out_branch_i32(s, INSN_COND(tcg_cond_to_bcond[cond], 1), t);
+
+ if (vtconst) {
+ tcg_out_movi_imm13(s, d, vt);
+ } else if (d != vt) {
+ tcg_out_mov(s, d, vt);
+ } else {
+ tcg_out_nop(s);
+ }
+
+ if (vfconst) {
+ tcg_out_movi_imm13(s, d, vf);
+ } else if (d != vf) {
+ tcg_out_mov(s, d, vf);
+ }
+
+ tcg_out_label(s, t, (tcg_target_long)s->code_ptr);
+#endif
+}
+
+static void tcg_out_setcond_i32(TCGContext *s, int cond, TCGArg d,
+ TCGArg c1, TCGArg c2, int c2const)
+{
+ TCGArg t;
+
+ /* For 32-bit comparisons, we can play games with ADDX/SUBX in order
+ to get the correct value into the register. Don't go beyond this
+ because the movcond fallback is only 4 insns. */
+ switch (cond) {
+ case TCG_COND_EQ:
+ case TCG_COND_NE:
+ if (c2 != 0) {
+ if (c2const) {
+ tcg_out_arithi(s, d, c1, c2, ARITH_XOR);
+ } else {
+ tcg_out_arith(s, d, c1, c2, ARITH_XOR);
+ }
+ }
+ c1 = TCG_REG_G0, c2 = d, 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 = (cond == TCG_COND_GTU ? TCG_COND_LTU : TCG_COND_LEU);
+ break;
+
+ case TCG_COND_LTU:
+ case TCG_COND_LEU:
+ break;
+
+ default:
+ tcg_out_movcond(s, cond, d, c1, c2, c2const, 1, 1, 0, 1, 0);
+ return;
+ }
+
+ tcg_out_arith(s, TCG_REG_G0, c1, c2, ARITH_SUBCC);
+ if (cond == TCG_COND_LTU) {
+ tcg_out_arithi(s, d, TCG_REG_G0, 0, ARITH_ADDX);
+ } else {
+ tcg_out_arithi(s, d, TCG_REG_G0, -1, ARITH_SUBX);
+ }
+}
+
+#if TCG_TARGET_REG_BITS == 32
+static void tcg_out_setcond2_i32(TCGContext *s, int cond, TCGArg d,
+ TCGArg al, TCGArg ah, TCGArg bl, int blconst,
+ TCGArg bh, int bhconst)
+{
+ TCGArg scratch = TCG_REG_I5;
+ int label;
+
+ if (d != al && d != ah && (blconst || d != bl) && (bhconst || d != bh)) {
+ scratch = d;
+ }
+
+ switch (cond) {
+ case TCG_COND_EQ:
+ tcg_out_setcond_i32(s, TCG_COND_EQ, scratch, al, bl, blconst);
+ tcg_out_movcond(s, TCG_COND_NE, scratch, ah, bh, bhconst,
+ 0, 1, scratch, 0, 0);
+ break;
+ case TCG_COND_NE:
+ tcg_out_setcond_i32(s, TCG_COND_NE, scratch, al, bl, blconst);
+ tcg_out_movcond(s, TCG_COND_NE, scratch, ah, bh, bhconst,
+ 1, 1, scratch, 0, 0);
+ break;
+
+ default:
+ label = gen_new_label();
+ tcg_out_movi_imm13(s, scratch, 1);
+ tcg_out_brcond2_i32(s, cond, al, ah, bl, blconst, bh, bhconst, label);
+ tcg_out_movi_imm13(s, scratch, 0);
+ tcg_out_label(s, label, (tcg_target_long)s->code_ptr);
+ break;
+ }
+
+ if (d != scratch) {
+ tcg_out_mov(s, d, scratch);
+ }
+}
+#endif
+
/* Generate global QEMU prologue and epilogue code */
void tcg_target_qemu_prologue(TCGContext *s)
{
@@ -1122,12 +1336,27 @@ 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;
+#ifdef MOVCOND_PATCH_APPLIED
+ case INDEX_op_movcond_i32:
+ tcg_out_movcond(s, args[5], args[0], args[1], args[2],
+ const_args[2], args[3], const_args[3],
+ args[4], const_args[4], 0);
+ break;
+#endif
#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;
#endif
case INDEX_op_qemu_ld8u:
@@ -1194,6 +1423,17 @@ 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_movcond(s, args[3], args[0], args[1], args[2],
+ const_args[2], 1, 1, 0, 1, 1);
+ break;
+#ifdef MOVCOND_PATCH_APPLIED
+ case INDEX_op_movcond_i64:
+ tcg_out_movcond(s, args[5], args[0], args[1], args[2],
+ const_args[2], args[3], const_args[3],
+ args[4], const_args[4], 1);
+ break;
+#endif
case INDEX_op_qemu_ld64:
tcg_out_qemu_ld(s, args, 3);
break;
@@ -1248,8 +1488,17 @@ 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" } },
+#ifdef MOVCOND_PATCH_APPLIED
+#if defined(__sparc_v9__) || defined(__sparc_v8plus__)
+ { INDEX_op_movcond_i32, { "r", "r", "rJ", "rI", "rI" } },
+#else
+ { INDEX_op_movcond_i32, { "r", "r", "rJ", "rJ", "rJ" } },
+#endif
+#endif
#if TCG_TARGET_REG_BITS == 32
{ INDEX_op_brcond2_i32, { "r", "r", "rJ", "rJ" } },
+ { INDEX_op_setcond2_i32, { "r", "r", "r", "rJ", "rJ" } },
#endif
{ INDEX_op_qemu_ld8u, { "r", "L" } },
@@ -1294,6 +1543,10 @@ static const TCGTargetOpDef sparc_op_defs[] = {
{ INDEX_op_sar_i64, { "r", "r", "rJ" } },
{ INDEX_op_brcond_i64, { "r", "rJ" } },
+ { INDEX_op_setcond_i64, { "r", "r", "rJ" } },
+#ifdef MOVCOND_PATCH_APPLIED
+ { INDEX_op_movcond_i64, { "r", "r", "rJ", "rI", "rI" } },
+#endif
#endif
{ -1 },
};
--
1.6.5.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH 0/6] tcg sparc improvements
@ 2009-12-19 21:08 Richard Henderson
2009-12-17 23:20 ` [Qemu-devel] [PATCH 1/6] tcg-sparc: Fix imm13 check in movi Richard Henderson
` (6 more replies)
0 siblings, 7 replies; 9+ messages in thread
From: Richard Henderson @ 2009-12-19 21:08 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
Here's a split up version of the patch you looked at yesterday.
r~
Richard Henderson (6):
tcg-sparc: Fix imm13 check in movi.
tcg-sparc: Improve tcg_out_movi for sparc64.
tcg-sparc: Use TCG_TARGET_REG_BITS in conditional compilation.
tcg: Add tcg_unsigned_cond.
tcg-sparc: Implement brcond2.
tcg-sparc: Implement setcond, movcond, setcond2.
tcg/sparc/tcg-target.c | 397 ++++++++++++++++++++++++++++++++++++++++++-----
tcg/tcg.h | 5 +
2 files changed, 359 insertions(+), 43 deletions(-)
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Qemu-devel] Re: [PATCH 0/6] tcg sparc improvements
2009-12-19 21:08 [Qemu-devel] [PATCH 0/6] tcg sparc improvements Richard Henderson
` (5 preceding siblings ...)
2009-12-19 21:07 ` [Qemu-devel] [PATCH 6/6] tcg-sparc: Implement setcond, movcond, setcond2 Richard Henderson
@ 2009-12-20 11:24 ` Blue Swirl
6 siblings, 0 replies; 9+ messages in thread
From: Blue Swirl @ 2009-12-20 11:24 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Sat, Dec 19, 2009 at 9:08 PM, Richard Henderson <rth@twiddle.net> wrote:
>
> Here's a split up version of the patch you looked at yesterday.
I was going to apply the patches, but the Signed-off-By line is missing.
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH 0/6] tcg sparc improvements
@ 2014-08-06 19:49 Richard Henderson
0 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2014-08-06 19:49 UTC (permalink / raw)
To: qemu-devel
Three of these patches are related to the new instructions added
in 2011 with the VIS3 instruction set, as present in the T4 cpus.
r~
Richard Henderson (6):
tcg-sparc: Support addsub2_i64
tcg-sparc: Use ADDXC in addsub2_i64
tcg-sparc: Fix setcond_i32 uninitialized value
tcg-sparc: Use ADDXC in setcond_i64
tcg-sparc: Rename ADDX/SUBX insns
tcg-sparc: Use UMULXHI instruction
disas/sparc.c | 34 ++++++-------
include/elf.h | 37 +++++++++++---
tcg/sparc/tcg-target.c | 129 +++++++++++++++++++++++++++++++++++++++++++------
tcg/sparc/tcg-target.h | 12 +++--
4 files changed, 167 insertions(+), 45 deletions(-)
--
1.9.3
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2014-08-06 19:50 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-12-19 21:08 [Qemu-devel] [PATCH 0/6] tcg sparc improvements Richard Henderson
2009-12-17 23:20 ` [Qemu-devel] [PATCH 1/6] tcg-sparc: Fix imm13 check in movi Richard Henderson
2009-12-17 23:47 ` [Qemu-devel] [PATCH 3/6] tcg-sparc: Use TCG_TARGET_REG_BITS in conditional compilation Richard Henderson
2009-12-19 19:45 ` [Qemu-devel] [PATCH 2/6] tcg-sparc: Improve tcg_out_movi for sparc64 Richard Henderson
2009-12-19 20:23 ` [Qemu-devel] [PATCH 4/6] tcg-sparc: Implement brcond2 Richard Henderson
2009-12-19 20:24 ` [Qemu-devel] [PATCH 5/6] tcg: Add tcg_unsigned_cond Richard Henderson
2009-12-19 21:07 ` [Qemu-devel] [PATCH 6/6] tcg-sparc: Implement setcond, movcond, setcond2 Richard Henderson
2009-12-20 11:24 ` [Qemu-devel] Re: [PATCH 0/6] tcg sparc improvements Blue Swirl
-- strict thread matches above, loose matches on Subject: below --
2014-08-06 19:49 [Qemu-devel] " Richard Henderson
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).