* [Qemu-devel] [PATCH 1/5] tcg: Introduce movcond
2012-09-18 14:23 [Qemu-devel] [PATCH 0/5] tcg: movcond Richard Henderson
@ 2012-09-18 14:23 ` Richard Henderson
2012-09-18 21:11 ` Aurelien Jarno
2012-09-20 22:06 ` Aurelien Jarno
2012-09-18 14:23 ` [Qemu-devel] [PATCH 2/5] target-alpha: Use movcond Richard Henderson
` (4 subsequent siblings)
5 siblings, 2 replies; 20+ messages in thread
From: Richard Henderson @ 2012-09-18 14:23 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Implemented with setcond if the target does not provide
the optional opcode.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/README | 6 ++++++
tcg/arm/tcg-target.h | 1 +
tcg/hppa/tcg-target.h | 1 +
tcg/i386/tcg-target.h | 2 ++
tcg/ia64/tcg-target.h | 2 ++
tcg/mips/tcg-target.h | 1 +
tcg/ppc/tcg-target.h | 1 +
tcg/ppc64/tcg-target.h | 2 ++
tcg/s390/tcg-target.h | 2 ++
tcg/sparc/tcg-target.h | 2 ++
tcg/tcg-op.h | 41 +++++++++++++++++++++++++++++++++++++++++
tcg/tcg-opc.h | 2 ++
tcg/tcg.c | 11 +++++------
tcg/tcg.h | 1 +
tcg/tci/tcg-target.h | 2 ++
15 files changed, 71 insertions(+), 6 deletions(-)
diff --git a/tcg/README b/tcg/README
index cfdfd96..d03ae05 100644
--- a/tcg/README
+++ b/tcg/README
@@ -307,6 +307,12 @@ dest = (t1 cond t2)
Set DEST to 1 if (T1 cond T2) is true, otherwise set to 0.
+* movcond_i32/i64 cond, dest, c1, c2, v1, v2
+
+dest = (c1 cond c2 ? v1 : v2)
+
+Set DEST to V1 if (C1 cond C2) is true, otherwise set to V2.
+
********* Type conversions
* ext_i32_i64 t0, t1
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index c0b8f72..e2299ca 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -73,6 +73,7 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i32 0
#define TCG_TARGET_HAS_nor_i32 0
#define TCG_TARGET_HAS_deposit_i32 0
+#define TCG_TARGET_HAS_movcond_i32 0
#define TCG_TARGET_HAS_GUEST_BASE
diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h
index 01ef960..4defd28 100644
--- a/tcg/hppa/tcg-target.h
+++ b/tcg/hppa/tcg-target.h
@@ -96,6 +96,7 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i32 0
#define TCG_TARGET_HAS_nor_i32 0
#define TCG_TARGET_HAS_deposit_i32 1
+#define TCG_TARGET_HAS_movcond_i32 0
/* optional instructions automatically implemented */
#define TCG_TARGET_HAS_neg_i32 0 /* sub rd, 0, rs */
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
index 8be42f3..504f953 100644
--- a/tcg/i386/tcg-target.h
+++ b/tcg/i386/tcg-target.h
@@ -86,6 +86,7 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i32 0
#define TCG_TARGET_HAS_nor_i32 0
#define TCG_TARGET_HAS_deposit_i32 1
+#define TCG_TARGET_HAS_movcond_i32 0
#if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_div2_i64 1
@@ -107,6 +108,7 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i64 0
#define TCG_TARGET_HAS_nor_i64 0
#define TCG_TARGET_HAS_deposit_i64 1
+#define TCG_TARGET_HAS_movcond_i64 0
#endif
#define TCG_TARGET_deposit_i32_valid(ofs, len) \
diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h
index c22962a..368aee4 100644
--- a/tcg/ia64/tcg-target.h
+++ b/tcg/ia64/tcg-target.h
@@ -133,6 +133,8 @@ typedef enum {
#define TCG_TARGET_HAS_rot_i64 1
#define TCG_TARGET_HAS_deposit_i32 0
#define TCG_TARGET_HAS_deposit_i64 0
+#define TCG_TARGET_HAS_movcond_i32 0
+#define TCG_TARGET_HAS_movcond_i64 0
/* optional instructions automatically implemented */
#define TCG_TARGET_HAS_neg_i32 0 /* sub r1, r0, r3 */
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index 1c61931..9c68a32 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -90,6 +90,7 @@ typedef enum {
#define TCG_TARGET_HAS_eqv_i32 0
#define TCG_TARGET_HAS_nand_i32 0
#define TCG_TARGET_HAS_deposit_i32 0
+#define TCG_TARGET_HAS_movcond_i32 0
/* optional instructions automatically implemented */
#define TCG_TARGET_HAS_neg_i32 0 /* sub rd, zero, rt */
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index 2f37fd2..177eea1 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -92,6 +92,7 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i32 1
#define TCG_TARGET_HAS_nor_i32 1
#define TCG_TARGET_HAS_deposit_i32 1
+#define TCG_TARGET_HAS_movcond_i32 0
#define TCG_AREG0 TCG_REG_R27
diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h
index 97eec08..57569e8 100644
--- a/tcg/ppc64/tcg-target.h
+++ b/tcg/ppc64/tcg-target.h
@@ -83,6 +83,7 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i32 0
#define TCG_TARGET_HAS_nor_i32 0
#define TCG_TARGET_HAS_deposit_i32 0
+#define TCG_TARGET_HAS_movcond_i32 0
#define TCG_TARGET_HAS_div_i64 1
#define TCG_TARGET_HAS_rot_i64 0
@@ -103,6 +104,7 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i64 0
#define TCG_TARGET_HAS_nor_i64 0
#define TCG_TARGET_HAS_deposit_i64 0
+#define TCG_TARGET_HAS_movcond_i64 0
#define TCG_AREG0 TCG_REG_R27
diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h
index 4f7dfab..ed55c33 100644
--- a/tcg/s390/tcg-target.h
+++ b/tcg/s390/tcg-target.h
@@ -63,6 +63,7 @@ typedef enum TCGReg {
#define TCG_TARGET_HAS_nand_i32 0
#define TCG_TARGET_HAS_nor_i32 0
#define TCG_TARGET_HAS_deposit_i32 0
+#define TCG_TARGET_HAS_movcond_i32 0
#if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_div2_i64 1
@@ -84,6 +85,7 @@ typedef enum TCGReg {
#define TCG_TARGET_HAS_nand_i64 0
#define TCG_TARGET_HAS_nor_i64 0
#define TCG_TARGET_HAS_deposit_i64 0
+#define TCG_TARGET_HAS_movcond_i64 0
#endif
#define TCG_TARGET_HAS_GUEST_BASE
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
index 0ea87be..d762574 100644
--- a/tcg/sparc/tcg-target.h
+++ b/tcg/sparc/tcg-target.h
@@ -102,6 +102,7 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i32 0
#define TCG_TARGET_HAS_nor_i32 0
#define TCG_TARGET_HAS_deposit_i32 0
+#define TCG_TARGET_HAS_movcond_i32 0
#if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_div_i64 1
@@ -123,6 +124,7 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i64 0
#define TCG_TARGET_HAS_nor_i64 0
#define TCG_TARGET_HAS_deposit_i64 0
+#define TCG_TARGET_HAS_movcond_i64 0
#endif
#ifdef CONFIG_SOLARIS
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index 169d3b2..3b3a746 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -2118,6 +2118,45 @@ static inline void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1,
tcg_temp_free_i64(t1);
}
+static inline void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret,
+ TCGv_i32 c1, TCGv_i32 c2,
+ TCGv_i32 v1, TCGv_i32 v2)
+{
+ if (TCG_TARGET_HAS_movcond_i32) {
+ tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond);
+ } else {
+ TCGv_i32 t0 = tcg_temp_new_i32();
+ TCGv_i32 t1 = tcg_temp_new_i32();
+ tcg_gen_setcond_i32(cond, t0, c1, c2);
+ tcg_gen_neg_i32(t0, t0);
+ tcg_gen_and_i32(t1, v1, t0);
+ tcg_gen_andc_i32(ret, v2, t0);
+ tcg_gen_or_i32(ret, ret, t1);
+ tcg_temp_free_i32(t0);
+ tcg_temp_free_i32(t1);
+ }
+}
+
+static inline void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret,
+ TCGv_i64 c1, TCGv_i64 c2,
+ TCGv_i64 v1, TCGv_i64 v2)
+{
+ if (TCG_TARGET_HAS_movcond_i64) {
+ tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond);
+ return;
+ } else {
+ TCGv_i64 t0 = tcg_temp_new_i64();
+ TCGv_i64 t1 = tcg_temp_new_i64();
+ tcg_gen_setcond_i64(cond, t0, c1, c2);
+ tcg_gen_neg_i64(t0, t0);
+ tcg_gen_and_i64(t1, v1, t0);
+ tcg_gen_andc_i64(ret, v2, t0);
+ tcg_gen_or_i64(ret, ret, t1);
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
+ }
+}
+
/***************************************/
/* QEMU specific operations. Their type depend on the QEMU CPU
type. */
@@ -2434,6 +2473,7 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
#define tcg_gen_deposit_tl tcg_gen_deposit_i64
#define tcg_const_tl tcg_const_i64
#define tcg_const_local_tl tcg_const_local_i64
+#define tcg_gen_movcond_tl tcg_gen_movcond_i64
#else
#define tcg_gen_movi_tl tcg_gen_movi_i32
#define tcg_gen_mov_tl tcg_gen_mov_i32
@@ -2505,6 +2545,7 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
#define tcg_gen_deposit_tl tcg_gen_deposit_i32
#define tcg_const_tl tcg_const_i32
#define tcg_const_local_tl tcg_const_local_i32
+#define tcg_gen_movcond_tl tcg_gen_movcond_i32
#endif
#if TCG_TARGET_REG_BITS == 32
diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h
index 8e06d03..8c624f0 100644
--- a/tcg/tcg-opc.h
+++ b/tcg/tcg-opc.h
@@ -51,6 +51,7 @@ DEF(br, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
DEF(mov_i32, 1, 1, 0, 0)
DEF(movi_i32, 1, 0, 1, 0)
DEF(setcond_i32, 1, 2, 1, 0)
+DEF(movcond_i32, 1, 4, 1, IMPL(TCG_TARGET_HAS_movcond_i32))
/* load/store */
DEF(ld8u_i32, 1, 1, 1, 0)
DEF(ld8s_i32, 1, 1, 1, 0)
@@ -107,6 +108,7 @@ DEF(nor_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_nor_i32))
DEF(mov_i64, 1, 1, 0, IMPL64)
DEF(movi_i64, 1, 0, 1, IMPL64)
DEF(setcond_i64, 1, 2, 1, IMPL64)
+DEF(movcond_i64, 1, 4, 1, IMPL64 | IMPL(TCG_TARGET_HAS_movcond_i64))
/* load/store */
DEF(ld8u_i64, 1, 1, 1, IMPL64)
DEF(ld8s_i64, 1, 1, 1, IMPL64)
diff --git a/tcg/tcg.c b/tcg/tcg.c
index a4e7f42..92ffc91 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -991,16 +991,15 @@ void tcg_dump_ops(TCGContext *s)
}
switch (c) {
case INDEX_op_brcond_i32:
-#if TCG_TARGET_REG_BITS == 32
- case INDEX_op_brcond2_i32:
-#elif TCG_TARGET_REG_BITS == 64
- case INDEX_op_brcond_i64:
-#endif
case INDEX_op_setcond_i32:
+ case INDEX_op_movcond_i32:
#if TCG_TARGET_REG_BITS == 32
+ case INDEX_op_brcond2_i32:
case INDEX_op_setcond2_i32:
-#elif TCG_TARGET_REG_BITS == 64
+#else
+ case INDEX_op_brcond_i64:
case INDEX_op_setcond_i64:
+ case INDEX_op_movcond_i64:
#endif
if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]]) {
qemu_log(",%s", cond_name[args[k++]]);
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 7a72729..f9a27ed 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -79,6 +79,7 @@ typedef uint64_t TCGRegSet;
#define TCG_TARGET_HAS_nand_i64 0
#define TCG_TARGET_HAS_nor_i64 0
#define TCG_TARGET_HAS_deposit_i64 0
+#define TCG_TARGET_HAS_movcond_i64 0
#endif
#ifndef TCG_TARGET_deposit_i32_valid
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
index 30a0f21..6d89495 100644
--- a/tcg/tci/tcg-target.h
+++ b/tcg/tci/tcg-target.h
@@ -75,6 +75,7 @@
#define TCG_TARGET_HAS_not_i32 1
#define TCG_TARGET_HAS_orc_i32 0
#define TCG_TARGET_HAS_rot_i32 1
+#define TCG_TARGET_HAS_movcond_i32 0
#if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_bswap16_i64 1
@@ -98,6 +99,7 @@
#define TCG_TARGET_HAS_not_i64 1
#define TCG_TARGET_HAS_orc_i64 0
#define TCG_TARGET_HAS_rot_i64 1
+#define TCG_TARGET_HAS_movcond_i64 0
#endif /* TCG_TARGET_REG_BITS == 64 */
/* Offset to user memory in user mode. */
--
1.7.11.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 1/5] tcg: Introduce movcond
2012-09-18 14:23 ` [Qemu-devel] [PATCH 1/5] tcg: Introduce movcond Richard Henderson
@ 2012-09-18 21:11 ` Aurelien Jarno
2012-09-20 22:06 ` Aurelien Jarno
1 sibling, 0 replies; 20+ messages in thread
From: Aurelien Jarno @ 2012-09-18 21:11 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Tue, Sep 18, 2012 at 07:23:56AM -0700, Richard Henderson wrote:
> Implemented with setcond if the target does not provide
> the optional opcode.
>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> tcg/README | 6 ++++++
> tcg/arm/tcg-target.h | 1 +
> tcg/hppa/tcg-target.h | 1 +
> tcg/i386/tcg-target.h | 2 ++
> tcg/ia64/tcg-target.h | 2 ++
> tcg/mips/tcg-target.h | 1 +
> tcg/ppc/tcg-target.h | 1 +
> tcg/ppc64/tcg-target.h | 2 ++
> tcg/s390/tcg-target.h | 2 ++
> tcg/sparc/tcg-target.h | 2 ++
> tcg/tcg-op.h | 41 +++++++++++++++++++++++++++++++++++++++++
> tcg/tcg-opc.h | 2 ++
> tcg/tcg.c | 11 +++++------
> tcg/tcg.h | 1 +
> tcg/tci/tcg-target.h | 2 ++
> 15 files changed, 71 insertions(+), 6 deletions(-)
>
> diff --git a/tcg/README b/tcg/README
> index cfdfd96..d03ae05 100644
> --- a/tcg/README
> +++ b/tcg/README
> @@ -307,6 +307,12 @@ dest = (t1 cond t2)
>
> Set DEST to 1 if (T1 cond T2) is true, otherwise set to 0.
>
> +* movcond_i32/i64 cond, dest, c1, c2, v1, v2
> +
> +dest = (c1 cond c2 ? v1 : v2)
> +
> +Set DEST to V1 if (C1 cond C2) is true, otherwise set to V2.
> +
> ********* Type conversions
>
> * ext_i32_i64 t0, t1
> diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
> index c0b8f72..e2299ca 100644
> --- a/tcg/arm/tcg-target.h
> +++ b/tcg/arm/tcg-target.h
> @@ -73,6 +73,7 @@ typedef enum {
> #define TCG_TARGET_HAS_nand_i32 0
> #define TCG_TARGET_HAS_nor_i32 0
> #define TCG_TARGET_HAS_deposit_i32 0
> +#define TCG_TARGET_HAS_movcond_i32 0
>
> #define TCG_TARGET_HAS_GUEST_BASE
>
> diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h
> index 01ef960..4defd28 100644
> --- a/tcg/hppa/tcg-target.h
> +++ b/tcg/hppa/tcg-target.h
> @@ -96,6 +96,7 @@ typedef enum {
> #define TCG_TARGET_HAS_nand_i32 0
> #define TCG_TARGET_HAS_nor_i32 0
> #define TCG_TARGET_HAS_deposit_i32 1
> +#define TCG_TARGET_HAS_movcond_i32 0
>
> /* optional instructions automatically implemented */
> #define TCG_TARGET_HAS_neg_i32 0 /* sub rd, 0, rs */
> diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
> index 8be42f3..504f953 100644
> --- a/tcg/i386/tcg-target.h
> +++ b/tcg/i386/tcg-target.h
> @@ -86,6 +86,7 @@ typedef enum {
> #define TCG_TARGET_HAS_nand_i32 0
> #define TCG_TARGET_HAS_nor_i32 0
> #define TCG_TARGET_HAS_deposit_i32 1
> +#define TCG_TARGET_HAS_movcond_i32 0
>
> #if TCG_TARGET_REG_BITS == 64
> #define TCG_TARGET_HAS_div2_i64 1
> @@ -107,6 +108,7 @@ typedef enum {
> #define TCG_TARGET_HAS_nand_i64 0
> #define TCG_TARGET_HAS_nor_i64 0
> #define TCG_TARGET_HAS_deposit_i64 1
> +#define TCG_TARGET_HAS_movcond_i64 0
> #endif
>
> #define TCG_TARGET_deposit_i32_valid(ofs, len) \
> diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h
> index c22962a..368aee4 100644
> --- a/tcg/ia64/tcg-target.h
> +++ b/tcg/ia64/tcg-target.h
> @@ -133,6 +133,8 @@ typedef enum {
> #define TCG_TARGET_HAS_rot_i64 1
> #define TCG_TARGET_HAS_deposit_i32 0
> #define TCG_TARGET_HAS_deposit_i64 0
> +#define TCG_TARGET_HAS_movcond_i32 0
> +#define TCG_TARGET_HAS_movcond_i64 0
>
> /* optional instructions automatically implemented */
> #define TCG_TARGET_HAS_neg_i32 0 /* sub r1, r0, r3 */
> diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
> index 1c61931..9c68a32 100644
> --- a/tcg/mips/tcg-target.h
> +++ b/tcg/mips/tcg-target.h
> @@ -90,6 +90,7 @@ typedef enum {
> #define TCG_TARGET_HAS_eqv_i32 0
> #define TCG_TARGET_HAS_nand_i32 0
> #define TCG_TARGET_HAS_deposit_i32 0
> +#define TCG_TARGET_HAS_movcond_i32 0
>
> /* optional instructions automatically implemented */
> #define TCG_TARGET_HAS_neg_i32 0 /* sub rd, zero, rt */
> diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
> index 2f37fd2..177eea1 100644
> --- a/tcg/ppc/tcg-target.h
> +++ b/tcg/ppc/tcg-target.h
> @@ -92,6 +92,7 @@ typedef enum {
> #define TCG_TARGET_HAS_nand_i32 1
> #define TCG_TARGET_HAS_nor_i32 1
> #define TCG_TARGET_HAS_deposit_i32 1
> +#define TCG_TARGET_HAS_movcond_i32 0
>
> #define TCG_AREG0 TCG_REG_R27
>
> diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h
> index 97eec08..57569e8 100644
> --- a/tcg/ppc64/tcg-target.h
> +++ b/tcg/ppc64/tcg-target.h
> @@ -83,6 +83,7 @@ typedef enum {
> #define TCG_TARGET_HAS_nand_i32 0
> #define TCG_TARGET_HAS_nor_i32 0
> #define TCG_TARGET_HAS_deposit_i32 0
> +#define TCG_TARGET_HAS_movcond_i32 0
>
> #define TCG_TARGET_HAS_div_i64 1
> #define TCG_TARGET_HAS_rot_i64 0
> @@ -103,6 +104,7 @@ typedef enum {
> #define TCG_TARGET_HAS_nand_i64 0
> #define TCG_TARGET_HAS_nor_i64 0
> #define TCG_TARGET_HAS_deposit_i64 0
> +#define TCG_TARGET_HAS_movcond_i64 0
>
> #define TCG_AREG0 TCG_REG_R27
>
> diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h
> index 4f7dfab..ed55c33 100644
> --- a/tcg/s390/tcg-target.h
> +++ b/tcg/s390/tcg-target.h
> @@ -63,6 +63,7 @@ typedef enum TCGReg {
> #define TCG_TARGET_HAS_nand_i32 0
> #define TCG_TARGET_HAS_nor_i32 0
> #define TCG_TARGET_HAS_deposit_i32 0
> +#define TCG_TARGET_HAS_movcond_i32 0
>
> #if TCG_TARGET_REG_BITS == 64
> #define TCG_TARGET_HAS_div2_i64 1
> @@ -84,6 +85,7 @@ typedef enum TCGReg {
> #define TCG_TARGET_HAS_nand_i64 0
> #define TCG_TARGET_HAS_nor_i64 0
> #define TCG_TARGET_HAS_deposit_i64 0
> +#define TCG_TARGET_HAS_movcond_i64 0
> #endif
>
> #define TCG_TARGET_HAS_GUEST_BASE
> diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
> index 0ea87be..d762574 100644
> --- a/tcg/sparc/tcg-target.h
> +++ b/tcg/sparc/tcg-target.h
> @@ -102,6 +102,7 @@ typedef enum {
> #define TCG_TARGET_HAS_nand_i32 0
> #define TCG_TARGET_HAS_nor_i32 0
> #define TCG_TARGET_HAS_deposit_i32 0
> +#define TCG_TARGET_HAS_movcond_i32 0
>
> #if TCG_TARGET_REG_BITS == 64
> #define TCG_TARGET_HAS_div_i64 1
> @@ -123,6 +124,7 @@ typedef enum {
> #define TCG_TARGET_HAS_nand_i64 0
> #define TCG_TARGET_HAS_nor_i64 0
> #define TCG_TARGET_HAS_deposit_i64 0
> +#define TCG_TARGET_HAS_movcond_i64 0
> #endif
>
> #ifdef CONFIG_SOLARIS
> diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
> index 169d3b2..3b3a746 100644
> --- a/tcg/tcg-op.h
> +++ b/tcg/tcg-op.h
> @@ -2118,6 +2118,45 @@ static inline void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1,
> tcg_temp_free_i64(t1);
> }
>
> +static inline void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret,
> + TCGv_i32 c1, TCGv_i32 c2,
> + TCGv_i32 v1, TCGv_i32 v2)
> +{
> + if (TCG_TARGET_HAS_movcond_i32) {
> + tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond);
> + } else {
> + TCGv_i32 t0 = tcg_temp_new_i32();
> + TCGv_i32 t1 = tcg_temp_new_i32();
> + tcg_gen_setcond_i32(cond, t0, c1, c2);
> + tcg_gen_neg_i32(t0, t0);
> + tcg_gen_and_i32(t1, v1, t0);
> + tcg_gen_andc_i32(ret, v2, t0);
> + tcg_gen_or_i32(ret, ret, t1);
> + tcg_temp_free_i32(t0);
> + tcg_temp_free_i32(t1);
> + }
> +}
> +
> +static inline void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret,
> + TCGv_i64 c1, TCGv_i64 c2,
> + TCGv_i64 v1, TCGv_i64 v2)
> +{
> + if (TCG_TARGET_HAS_movcond_i64) {
> + tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond);
> + return;
> + } else {
> + TCGv_i64 t0 = tcg_temp_new_i64();
> + TCGv_i64 t1 = tcg_temp_new_i64();
> + tcg_gen_setcond_i64(cond, t0, c1, c2);
> + tcg_gen_neg_i64(t0, t0);
> + tcg_gen_and_i64(t1, v1, t0);
> + tcg_gen_andc_i64(ret, v2, t0);
> + tcg_gen_or_i64(ret, ret, t1);
> + tcg_temp_free_i64(t0);
> + tcg_temp_free_i64(t1);
> + }
> +}
> +
> /***************************************/
> /* QEMU specific operations. Their type depend on the QEMU CPU
> type. */
> @@ -2434,6 +2473,7 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
> #define tcg_gen_deposit_tl tcg_gen_deposit_i64
> #define tcg_const_tl tcg_const_i64
> #define tcg_const_local_tl tcg_const_local_i64
> +#define tcg_gen_movcond_tl tcg_gen_movcond_i64
> #else
> #define tcg_gen_movi_tl tcg_gen_movi_i32
> #define tcg_gen_mov_tl tcg_gen_mov_i32
> @@ -2505,6 +2545,7 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
> #define tcg_gen_deposit_tl tcg_gen_deposit_i32
> #define tcg_const_tl tcg_const_i32
> #define tcg_const_local_tl tcg_const_local_i32
> +#define tcg_gen_movcond_tl tcg_gen_movcond_i32
> #endif
>
> #if TCG_TARGET_REG_BITS == 32
> diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h
> index 8e06d03..8c624f0 100644
> --- a/tcg/tcg-opc.h
> +++ b/tcg/tcg-opc.h
> @@ -51,6 +51,7 @@ DEF(br, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
> DEF(mov_i32, 1, 1, 0, 0)
> DEF(movi_i32, 1, 0, 1, 0)
> DEF(setcond_i32, 1, 2, 1, 0)
> +DEF(movcond_i32, 1, 4, 1, IMPL(TCG_TARGET_HAS_movcond_i32))
> /* load/store */
> DEF(ld8u_i32, 1, 1, 1, 0)
> DEF(ld8s_i32, 1, 1, 1, 0)
> @@ -107,6 +108,7 @@ DEF(nor_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_nor_i32))
> DEF(mov_i64, 1, 1, 0, IMPL64)
> DEF(movi_i64, 1, 0, 1, IMPL64)
> DEF(setcond_i64, 1, 2, 1, IMPL64)
> +DEF(movcond_i64, 1, 4, 1, IMPL64 | IMPL(TCG_TARGET_HAS_movcond_i64))
> /* load/store */
> DEF(ld8u_i64, 1, 1, 1, IMPL64)
> DEF(ld8s_i64, 1, 1, 1, IMPL64)
> diff --git a/tcg/tcg.c b/tcg/tcg.c
> index a4e7f42..92ffc91 100644
> --- a/tcg/tcg.c
> +++ b/tcg/tcg.c
> @@ -991,16 +991,15 @@ void tcg_dump_ops(TCGContext *s)
> }
> switch (c) {
> case INDEX_op_brcond_i32:
> -#if TCG_TARGET_REG_BITS == 32
> - case INDEX_op_brcond2_i32:
> -#elif TCG_TARGET_REG_BITS == 64
> - case INDEX_op_brcond_i64:
> -#endif
> case INDEX_op_setcond_i32:
> + case INDEX_op_movcond_i32:
> #if TCG_TARGET_REG_BITS == 32
> + case INDEX_op_brcond2_i32:
> case INDEX_op_setcond2_i32:
> -#elif TCG_TARGET_REG_BITS == 64
> +#else
> + case INDEX_op_brcond_i64:
> case INDEX_op_setcond_i64:
> + case INDEX_op_movcond_i64:
> #endif
> if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]]) {
> qemu_log(",%s", cond_name[args[k++]]);
> diff --git a/tcg/tcg.h b/tcg/tcg.h
> index 7a72729..f9a27ed 100644
> --- a/tcg/tcg.h
> +++ b/tcg/tcg.h
> @@ -79,6 +79,7 @@ typedef uint64_t TCGRegSet;
> #define TCG_TARGET_HAS_nand_i64 0
> #define TCG_TARGET_HAS_nor_i64 0
> #define TCG_TARGET_HAS_deposit_i64 0
> +#define TCG_TARGET_HAS_movcond_i64 0
> #endif
>
> #ifndef TCG_TARGET_deposit_i32_valid
> diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
> index 30a0f21..6d89495 100644
> --- a/tcg/tci/tcg-target.h
> +++ b/tcg/tci/tcg-target.h
> @@ -75,6 +75,7 @@
> #define TCG_TARGET_HAS_not_i32 1
> #define TCG_TARGET_HAS_orc_i32 0
> #define TCG_TARGET_HAS_rot_i32 1
> +#define TCG_TARGET_HAS_movcond_i32 0
>
> #if TCG_TARGET_REG_BITS == 64
> #define TCG_TARGET_HAS_bswap16_i64 1
> @@ -98,6 +99,7 @@
> #define TCG_TARGET_HAS_not_i64 1
> #define TCG_TARGET_HAS_orc_i64 0
> #define TCG_TARGET_HAS_rot_i64 1
> +#define TCG_TARGET_HAS_movcond_i64 0
> #endif /* TCG_TARGET_REG_BITS == 64 */
>
> /* Offset to user memory in user mode. */
> --
> 1.7.11.4
>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 1/5] tcg: Introduce movcond
2012-09-18 14:23 ` [Qemu-devel] [PATCH 1/5] tcg: Introduce movcond Richard Henderson
2012-09-18 21:11 ` Aurelien Jarno
@ 2012-09-20 22:06 ` Aurelien Jarno
2012-09-20 22:47 ` Richard Henderson
1 sibling, 1 reply; 20+ messages in thread
From: Aurelien Jarno @ 2012-09-20 22:06 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Tue, Sep 18, 2012 at 07:23:56AM -0700, Richard Henderson wrote:
> Implemented with setcond if the target does not provide
> the optional opcode.
>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> tcg/README | 6 ++++++
> tcg/arm/tcg-target.h | 1 +
> tcg/hppa/tcg-target.h | 1 +
> tcg/i386/tcg-target.h | 2 ++
> tcg/ia64/tcg-target.h | 2 ++
> tcg/mips/tcg-target.h | 1 +
> tcg/ppc/tcg-target.h | 1 +
> tcg/ppc64/tcg-target.h | 2 ++
> tcg/s390/tcg-target.h | 2 ++
> tcg/sparc/tcg-target.h | 2 ++
> tcg/tcg-op.h | 41 +++++++++++++++++++++++++++++++++++++++++
> tcg/tcg-opc.h | 2 ++
> tcg/tcg.c | 11 +++++------
> tcg/tcg.h | 1 +
> tcg/tci/tcg-target.h | 2 ++
> 15 files changed, 71 insertions(+), 6 deletions(-)
>
> diff --git a/tcg/README b/tcg/README
> index cfdfd96..d03ae05 100644
> --- a/tcg/README
> +++ b/tcg/README
> @@ -307,6 +307,12 @@ dest = (t1 cond t2)
>
> Set DEST to 1 if (T1 cond T2) is true, otherwise set to 0.
>
> +* movcond_i32/i64 cond, dest, c1, c2, v1, v2
> +
> +dest = (c1 cond c2 ? v1 : v2)
> +
> +Set DEST to V1 if (C1 cond C2) is true, otherwise set to V2.
> +
> ********* Type conversions
>
> * ext_i32_i64 t0, t1
> diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
> index c0b8f72..e2299ca 100644
> --- a/tcg/arm/tcg-target.h
> +++ b/tcg/arm/tcg-target.h
> @@ -73,6 +73,7 @@ typedef enum {
> #define TCG_TARGET_HAS_nand_i32 0
> #define TCG_TARGET_HAS_nor_i32 0
> #define TCG_TARGET_HAS_deposit_i32 0
> +#define TCG_TARGET_HAS_movcond_i32 0
>
> #define TCG_TARGET_HAS_GUEST_BASE
>
> diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h
> index 01ef960..4defd28 100644
> --- a/tcg/hppa/tcg-target.h
> +++ b/tcg/hppa/tcg-target.h
> @@ -96,6 +96,7 @@ typedef enum {
> #define TCG_TARGET_HAS_nand_i32 0
> #define TCG_TARGET_HAS_nor_i32 0
> #define TCG_TARGET_HAS_deposit_i32 1
> +#define TCG_TARGET_HAS_movcond_i32 0
>
> /* optional instructions automatically implemented */
> #define TCG_TARGET_HAS_neg_i32 0 /* sub rd, 0, rs */
> diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
> index 8be42f3..504f953 100644
> --- a/tcg/i386/tcg-target.h
> +++ b/tcg/i386/tcg-target.h
> @@ -86,6 +86,7 @@ typedef enum {
> #define TCG_TARGET_HAS_nand_i32 0
> #define TCG_TARGET_HAS_nor_i32 0
> #define TCG_TARGET_HAS_deposit_i32 1
> +#define TCG_TARGET_HAS_movcond_i32 0
>
> #if TCG_TARGET_REG_BITS == 64
> #define TCG_TARGET_HAS_div2_i64 1
> @@ -107,6 +108,7 @@ typedef enum {
> #define TCG_TARGET_HAS_nand_i64 0
> #define TCG_TARGET_HAS_nor_i64 0
> #define TCG_TARGET_HAS_deposit_i64 1
> +#define TCG_TARGET_HAS_movcond_i64 0
> #endif
>
> #define TCG_TARGET_deposit_i32_valid(ofs, len) \
> diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h
> index c22962a..368aee4 100644
> --- a/tcg/ia64/tcg-target.h
> +++ b/tcg/ia64/tcg-target.h
> @@ -133,6 +133,8 @@ typedef enum {
> #define TCG_TARGET_HAS_rot_i64 1
> #define TCG_TARGET_HAS_deposit_i32 0
> #define TCG_TARGET_HAS_deposit_i64 0
> +#define TCG_TARGET_HAS_movcond_i32 0
> +#define TCG_TARGET_HAS_movcond_i64 0
>
> /* optional instructions automatically implemented */
> #define TCG_TARGET_HAS_neg_i32 0 /* sub r1, r0, r3 */
> diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
> index 1c61931..9c68a32 100644
> --- a/tcg/mips/tcg-target.h
> +++ b/tcg/mips/tcg-target.h
> @@ -90,6 +90,7 @@ typedef enum {
> #define TCG_TARGET_HAS_eqv_i32 0
> #define TCG_TARGET_HAS_nand_i32 0
> #define TCG_TARGET_HAS_deposit_i32 0
> +#define TCG_TARGET_HAS_movcond_i32 0
>
> /* optional instructions automatically implemented */
> #define TCG_TARGET_HAS_neg_i32 0 /* sub rd, zero, rt */
> diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
> index 2f37fd2..177eea1 100644
> --- a/tcg/ppc/tcg-target.h
> +++ b/tcg/ppc/tcg-target.h
> @@ -92,6 +92,7 @@ typedef enum {
> #define TCG_TARGET_HAS_nand_i32 1
> #define TCG_TARGET_HAS_nor_i32 1
> #define TCG_TARGET_HAS_deposit_i32 1
> +#define TCG_TARGET_HAS_movcond_i32 0
>
> #define TCG_AREG0 TCG_REG_R27
>
> diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h
> index 97eec08..57569e8 100644
> --- a/tcg/ppc64/tcg-target.h
> +++ b/tcg/ppc64/tcg-target.h
> @@ -83,6 +83,7 @@ typedef enum {
> #define TCG_TARGET_HAS_nand_i32 0
> #define TCG_TARGET_HAS_nor_i32 0
> #define TCG_TARGET_HAS_deposit_i32 0
> +#define TCG_TARGET_HAS_movcond_i32 0
>
> #define TCG_TARGET_HAS_div_i64 1
> #define TCG_TARGET_HAS_rot_i64 0
> @@ -103,6 +104,7 @@ typedef enum {
> #define TCG_TARGET_HAS_nand_i64 0
> #define TCG_TARGET_HAS_nor_i64 0
> #define TCG_TARGET_HAS_deposit_i64 0
> +#define TCG_TARGET_HAS_movcond_i64 0
>
> #define TCG_AREG0 TCG_REG_R27
>
> diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h
> index 4f7dfab..ed55c33 100644
> --- a/tcg/s390/tcg-target.h
> +++ b/tcg/s390/tcg-target.h
> @@ -63,6 +63,7 @@ typedef enum TCGReg {
> #define TCG_TARGET_HAS_nand_i32 0
> #define TCG_TARGET_HAS_nor_i32 0
> #define TCG_TARGET_HAS_deposit_i32 0
> +#define TCG_TARGET_HAS_movcond_i32 0
>
> #if TCG_TARGET_REG_BITS == 64
> #define TCG_TARGET_HAS_div2_i64 1
> @@ -84,6 +85,7 @@ typedef enum TCGReg {
> #define TCG_TARGET_HAS_nand_i64 0
> #define TCG_TARGET_HAS_nor_i64 0
> #define TCG_TARGET_HAS_deposit_i64 0
> +#define TCG_TARGET_HAS_movcond_i64 0
> #endif
>
> #define TCG_TARGET_HAS_GUEST_BASE
> diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
> index 0ea87be..d762574 100644
> --- a/tcg/sparc/tcg-target.h
> +++ b/tcg/sparc/tcg-target.h
> @@ -102,6 +102,7 @@ typedef enum {
> #define TCG_TARGET_HAS_nand_i32 0
> #define TCG_TARGET_HAS_nor_i32 0
> #define TCG_TARGET_HAS_deposit_i32 0
> +#define TCG_TARGET_HAS_movcond_i32 0
>
> #if TCG_TARGET_REG_BITS == 64
> #define TCG_TARGET_HAS_div_i64 1
> @@ -123,6 +124,7 @@ typedef enum {
> #define TCG_TARGET_HAS_nand_i64 0
> #define TCG_TARGET_HAS_nor_i64 0
> #define TCG_TARGET_HAS_deposit_i64 0
> +#define TCG_TARGET_HAS_movcond_i64 0
> #endif
>
> #ifdef CONFIG_SOLARIS
> diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
> index 169d3b2..3b3a746 100644
> --- a/tcg/tcg-op.h
> +++ b/tcg/tcg-op.h
> @@ -2118,6 +2118,45 @@ static inline void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1,
> tcg_temp_free_i64(t1);
> }
>
> +static inline void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret,
> + TCGv_i32 c1, TCGv_i32 c2,
> + TCGv_i32 v1, TCGv_i32 v2)
> +{
> + if (TCG_TARGET_HAS_movcond_i32) {
> + tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond);
> + } else {
> + TCGv_i32 t0 = tcg_temp_new_i32();
> + TCGv_i32 t1 = tcg_temp_new_i32();
> + tcg_gen_setcond_i32(cond, t0, c1, c2);
> + tcg_gen_neg_i32(t0, t0);
> + tcg_gen_and_i32(t1, v1, t0);
> + tcg_gen_andc_i32(ret, v2, t0);
> + tcg_gen_or_i32(ret, ret, t1);
> + tcg_temp_free_i32(t0);
> + tcg_temp_free_i32(t1);
> + }
> +}
> +
> +static inline void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret,
> + TCGv_i64 c1, TCGv_i64 c2,
> + TCGv_i64 v1, TCGv_i64 v2)
> +{
> + if (TCG_TARGET_HAS_movcond_i64) {
> + tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond);
> + return;
Minor nitpick: there is useless return here, and it's not present for
movcond_i32.
> + } else {
> + TCGv_i64 t0 = tcg_temp_new_i64();
> + TCGv_i64 t1 = tcg_temp_new_i64();
> + tcg_gen_setcond_i64(cond, t0, c1, c2);
> + tcg_gen_neg_i64(t0, t0);
> + tcg_gen_and_i64(t1, v1, t0);
> + tcg_gen_andc_i64(ret, v2, t0);
> + tcg_gen_or_i64(ret, ret, t1);
> + tcg_temp_free_i64(t0);
> + tcg_temp_free_i64(t1);
> + }
> +}
> +
> /***************************************/
> /* QEMU specific operations. Their type depend on the QEMU CPU
> type. */
> @@ -2434,6 +2473,7 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
> #define tcg_gen_deposit_tl tcg_gen_deposit_i64
> #define tcg_const_tl tcg_const_i64
> #define tcg_const_local_tl tcg_const_local_i64
> +#define tcg_gen_movcond_tl tcg_gen_movcond_i64
> #else
> #define tcg_gen_movi_tl tcg_gen_movi_i32
> #define tcg_gen_mov_tl tcg_gen_mov_i32
> @@ -2505,6 +2545,7 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
> #define tcg_gen_deposit_tl tcg_gen_deposit_i32
> #define tcg_const_tl tcg_const_i32
> #define tcg_const_local_tl tcg_const_local_i32
> +#define tcg_gen_movcond_tl tcg_gen_movcond_i32
> #endif
>
> #if TCG_TARGET_REG_BITS == 32
> diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h
> index 8e06d03..8c624f0 100644
> --- a/tcg/tcg-opc.h
> +++ b/tcg/tcg-opc.h
> @@ -51,6 +51,7 @@ DEF(br, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
> DEF(mov_i32, 1, 1, 0, 0)
> DEF(movi_i32, 1, 0, 1, 0)
> DEF(setcond_i32, 1, 2, 1, 0)
> +DEF(movcond_i32, 1, 4, 1, IMPL(TCG_TARGET_HAS_movcond_i32))
> /* load/store */
> DEF(ld8u_i32, 1, 1, 1, 0)
> DEF(ld8s_i32, 1, 1, 1, 0)
> @@ -107,6 +108,7 @@ DEF(nor_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_nor_i32))
> DEF(mov_i64, 1, 1, 0, IMPL64)
> DEF(movi_i64, 1, 0, 1, IMPL64)
> DEF(setcond_i64, 1, 2, 1, IMPL64)
> +DEF(movcond_i64, 1, 4, 1, IMPL64 | IMPL(TCG_TARGET_HAS_movcond_i64))
> /* load/store */
> DEF(ld8u_i64, 1, 1, 1, IMPL64)
> DEF(ld8s_i64, 1, 1, 1, IMPL64)
> diff --git a/tcg/tcg.c b/tcg/tcg.c
> index a4e7f42..92ffc91 100644
> --- a/tcg/tcg.c
> +++ b/tcg/tcg.c
> @@ -991,16 +991,15 @@ void tcg_dump_ops(TCGContext *s)
> }
> switch (c) {
> case INDEX_op_brcond_i32:
> -#if TCG_TARGET_REG_BITS == 32
> - case INDEX_op_brcond2_i32:
> -#elif TCG_TARGET_REG_BITS == 64
> - case INDEX_op_brcond_i64:
> -#endif
> case INDEX_op_setcond_i32:
> + case INDEX_op_movcond_i32:
> #if TCG_TARGET_REG_BITS == 32
> + case INDEX_op_brcond2_i32:
> case INDEX_op_setcond2_i32:
> -#elif TCG_TARGET_REG_BITS == 64
> +#else
> + case INDEX_op_brcond_i64:
> case INDEX_op_setcond_i64:
> + case INDEX_op_movcond_i64:
> #endif
> if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]]) {
> qemu_log(",%s", cond_name[args[k++]]);
> diff --git a/tcg/tcg.h b/tcg/tcg.h
> index 7a72729..f9a27ed 100644
> --- a/tcg/tcg.h
> +++ b/tcg/tcg.h
> @@ -79,6 +79,7 @@ typedef uint64_t TCGRegSet;
> #define TCG_TARGET_HAS_nand_i64 0
> #define TCG_TARGET_HAS_nor_i64 0
> #define TCG_TARGET_HAS_deposit_i64 0
> +#define TCG_TARGET_HAS_movcond_i64 0
> #endif
>
> #ifndef TCG_TARGET_deposit_i32_valid
> diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
> index 30a0f21..6d89495 100644
> --- a/tcg/tci/tcg-target.h
> +++ b/tcg/tci/tcg-target.h
> @@ -75,6 +75,7 @@
> #define TCG_TARGET_HAS_not_i32 1
> #define TCG_TARGET_HAS_orc_i32 0
> #define TCG_TARGET_HAS_rot_i32 1
> +#define TCG_TARGET_HAS_movcond_i32 0
>
> #if TCG_TARGET_REG_BITS == 64
> #define TCG_TARGET_HAS_bswap16_i64 1
> @@ -98,6 +99,7 @@
> #define TCG_TARGET_HAS_not_i64 1
> #define TCG_TARGET_HAS_orc_i64 0
> #define TCG_TARGET_HAS_rot_i64 1
> +#define TCG_TARGET_HAS_movcond_i64 0
> #endif /* TCG_TARGET_REG_BITS == 64 */
>
> /* Offset to user memory in user mode. */
> --
> 1.7.11.4
>
>
>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 1/5] tcg: Introduce movcond
2012-09-20 22:06 ` Aurelien Jarno
@ 2012-09-20 22:47 ` Richard Henderson
0 siblings, 0 replies; 20+ messages in thread
From: Richard Henderson @ 2012-09-20 22:47 UTC (permalink / raw)
To: Aurelien Jarno; +Cc: qemu-devel
On 09/20/2012 03:06 PM, Aurelien Jarno wrote:
>> > + if (TCG_TARGET_HAS_movcond_i64) {
>> > + tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond);
>> > + return;
> Minor nitpick: there is useless return here, and it's not present for
> movcond_i32.
>
Ah, right. I started to add a case for implementing movcond_i64
with movcond_i32, but didn't finish.
r~
^ permalink raw reply [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 2/5] target-alpha: Use movcond
2012-09-18 14:23 [Qemu-devel] [PATCH 0/5] tcg: movcond Richard Henderson
2012-09-18 14:23 ` [Qemu-devel] [PATCH 1/5] tcg: Introduce movcond Richard Henderson
@ 2012-09-18 14:23 ` Richard Henderson
2012-09-18 14:23 ` [Qemu-devel] [PATCH 3/5] tcg-i386: Implement movcond Richard Henderson
` (3 subsequent siblings)
5 siblings, 0 replies; 20+ messages in thread
From: Richard Henderson @ 2012-09-18 14:23 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
For proper cmov insns, as well as the non-goto-tb case
of conditional branch.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/translate.c | 102 ++++++++++++++++++++++-------------------------
1 file changed, 48 insertions(+), 54 deletions(-)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 12de6a3..4a9011a 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -426,27 +426,15 @@ static ExitStatus gen_bcond_internal(DisasContext *ctx, TCGCond cond,
return EXIT_GOTO_TB;
} else {
- int lab_over = gen_new_label();
-
- /* ??? Consider using either
- movi pc, next
- addi tmp, pc, disp
- movcond pc, cond, 0, tmp, pc
- or
- setcond tmp, cond, 0
- movi pc, next
- neg tmp, tmp
- andi tmp, tmp, disp
- add pc, pc, tmp
- The current diamond subgraph surely isn't efficient. */
+ TCGv_i64 z = tcg_const_i64(0);
+ TCGv_i64 d = tcg_const_i64(dest);
+ TCGv_i64 p = tcg_const_i64(ctx->pc);
- tcg_gen_brcondi_i64(cond, cmp, 0, lab_true);
- tcg_gen_movi_i64(cpu_pc, ctx->pc);
- tcg_gen_br(lab_over);
- gen_set_label(lab_true);
- tcg_gen_movi_i64(cpu_pc, dest);
- gen_set_label(lab_over);
+ tcg_gen_movcond_i64(cond, cpu_pc, cmp, z, d, p);
+ tcg_temp_free_i64(z);
+ tcg_temp_free_i64(d);
+ tcg_temp_free_i64(p);
return EXIT_PC_UPDATED;
}
}
@@ -521,61 +509,67 @@ static ExitStatus gen_fbcond(DisasContext *ctx, TCGCond cond, int ra,
static void gen_cmov(TCGCond cond, int ra, int rb, int rc,
int islit, uint8_t lit, int mask)
{
- TCGCond inv_cond = tcg_invert_cond(cond);
- int l1;
+ TCGv_i64 c1, z, v1;
- if (unlikely(rc == 31))
+ if (unlikely(rc == 31)) {
return;
+ }
- l1 = gen_new_label();
-
- if (ra != 31) {
- if (mask) {
- TCGv tmp = tcg_temp_new();
- tcg_gen_andi_i64(tmp, cpu_ir[ra], 1);
- tcg_gen_brcondi_i64(inv_cond, tmp, 0, l1);
- tcg_temp_free(tmp);
- } else
- tcg_gen_brcondi_i64(inv_cond, cpu_ir[ra], 0, l1);
- } else {
+ if (ra == 31) {
/* Very uncommon case - Do not bother to optimize. */
- TCGv tmp = tcg_const_i64(0);
- tcg_gen_brcondi_i64(inv_cond, tmp, 0, l1);
- tcg_temp_free(tmp);
+ c1 = tcg_const_i64(0);
+ } else if (mask) {
+ c1 = tcg_const_i64(1);
+ tcg_gen_and_i64(c1, c1, cpu_ir[ra]);
+ } else {
+ c1 = cpu_ir[ra];
}
+ if (islit) {
+ v1 = tcg_const_i64(lit);
+ } else {
+ v1 = cpu_ir[rb];
+ }
+ z = tcg_const_i64(0);
- if (islit)
- tcg_gen_movi_i64(cpu_ir[rc], lit);
- else
- tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
- gen_set_label(l1);
+ tcg_gen_movcond_i64(cond, cpu_ir[rc], c1, z, v1, cpu_ir[rc]);
+
+ tcg_temp_free_i64(z);
+ if (ra == 31 || mask) {
+ tcg_temp_free_i64(c1);
+ }
+ if (islit) {
+ tcg_temp_free_i64(v1);
+ }
}
static void gen_fcmov(TCGCond cond, int ra, int rb, int rc)
{
- TCGv cmp_tmp;
- int l1;
+ TCGv_i64 c1, z, v1;
if (unlikely(rc == 31)) {
return;
}
- cmp_tmp = tcg_temp_new();
+ c1 = tcg_temp_new_i64();
if (unlikely(ra == 31)) {
- tcg_gen_movi_i64(cmp_tmp, 0);
+ tcg_gen_movi_i64(c1, 0);
+ } else {
+ gen_fold_mzero(cond, c1, cpu_fir[ra]);
+ }
+ if (rb == 31) {
+ v1 = tcg_const_i64(0);
} else {
- gen_fold_mzero(cond, cmp_tmp, cpu_fir[ra]);
+ v1 = cpu_fir[rb];
}
+ z = tcg_const_i64(0);
- l1 = gen_new_label();
- tcg_gen_brcondi_i64(tcg_invert_cond(cond), cmp_tmp, 0, l1);
- tcg_temp_free(cmp_tmp);
+ tcg_gen_movcond_i64(cond, cpu_fir[rc], c1, z, v1, cpu_fir[rc]);
- if (rb != 31)
- tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[rb]);
- else
- tcg_gen_movi_i64(cpu_fir[rc], 0);
- gen_set_label(l1);
+ tcg_temp_free_i64(z);
+ tcg_temp_free_i64(c1);
+ if (rb == 31) {
+ tcg_temp_free_i64(v1);
+ }
}
#define QUAL_RM_N 0x080 /* Round mode nearest even */
--
1.7.11.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 3/5] tcg-i386: Implement movcond
2012-09-18 14:23 [Qemu-devel] [PATCH 0/5] tcg: movcond Richard Henderson
2012-09-18 14:23 ` [Qemu-devel] [PATCH 1/5] tcg: Introduce movcond Richard Henderson
2012-09-18 14:23 ` [Qemu-devel] [PATCH 2/5] target-alpha: Use movcond Richard Henderson
@ 2012-09-18 14:23 ` Richard Henderson
2012-09-18 21:11 ` Aurelien Jarno
2012-09-18 14:23 ` [Qemu-devel] [PATCH 4/5] tcg: Optimize movcond for constant comparisons Richard Henderson
` (2 subsequent siblings)
5 siblings, 1 reply; 20+ messages in thread
From: Richard Henderson @ 2012-09-18 14:23 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/i386/tcg-target.c | 29 +++++++++++++++++++++++++++++
tcg/i386/tcg-target.h | 7 ++++++-
2 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 34c2df8..cf28f56 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -249,6 +249,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define OPC_ADD_GvEv (OPC_ARITH_GvEv | (ARITH_ADD << 3))
#define OPC_BSWAP (0xc8 | P_EXT)
#define OPC_CALL_Jz (0xe8)
+#define OPC_CMOVCC (0x40 | P_EXT) /* ... plus condition code */
#define OPC_CMP_GvEv (OPC_ARITH_GvEv | (ARITH_CMP << 3))
#define OPC_DEC_r32 (0x48)
#define OPC_IMUL_GvEv (0xaf | P_EXT)
@@ -935,6 +936,24 @@ static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
}
#endif
+static void tcg_out_movcond32(TCGContext *s, TCGCond cond, TCGArg dest,
+ TCGArg c1, TCGArg c2, int const_c2,
+ TCGArg v1)
+{
+ tcg_out_cmp(s, c1, c2, const_c2, 0);
+ tcg_out_modrm(s, OPC_CMOVCC | tcg_cond_to_jcc[cond], dest, v1);
+}
+
+#if TCG_TARGET_REG_BITS == 64
+static void tcg_out_movcond64(TCGContext *s, TCGCond cond, TCGArg dest,
+ TCGArg c1, TCGArg c2, int const_c2,
+ TCGArg v1)
+{
+ tcg_out_cmp(s, c1, c2, const_c2, P_REXW);
+ tcg_out_modrm(s, OPC_CMOVCC | tcg_cond_to_jcc[cond] | P_REXW, dest, v1);
+}
+#endif
+
static void tcg_out_branch(TCGContext *s, int call, tcg_target_long dest)
{
tcg_target_long disp = dest - (tcg_target_long)s->code_ptr - 5;
@@ -1650,6 +1669,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_setcond32(s, args[3], args[0], args[1],
args[2], const_args[2]);
break;
+ case INDEX_op_movcond_i32:
+ tcg_out_movcond32(s, args[5], args[0], args[1],
+ args[2], const_args[2], args[3]);
+ break;
OP_32_64(bswap16):
tcg_out_rolw_8(s, args[0]);
@@ -1772,6 +1795,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_setcond64(s, args[3], args[0], args[1],
args[2], const_args[2]);
break;
+ case INDEX_op_movcond_i64:
+ tcg_out_movcond64(s, args[5], args[0], args[1],
+ args[2], const_args[2], args[3]);
+ break;
case INDEX_op_bswap64_i64:
tcg_out_bswap64(s, args[0]);
@@ -1856,6 +1883,7 @@ static const TCGTargetOpDef x86_op_defs[] = {
{ INDEX_op_setcond_i32, { "q", "r", "ri" } },
{ INDEX_op_deposit_i32, { "Q", "0", "Q" } },
+ { INDEX_op_movcond_i32, { "r", "r", "ri", "r", "0" } },
#if TCG_TARGET_REG_BITS == 32
{ INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
@@ -1910,6 +1938,7 @@ static const TCGTargetOpDef x86_op_defs[] = {
{ INDEX_op_ext32u_i64, { "r", "r" } },
{ INDEX_op_deposit_i64, { "Q", "0", "Q" } },
+ { INDEX_op_movcond_i64, { "r", "r", "re", "r", "0" } },
#endif
#if TCG_TARGET_REG_BITS == 64
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
index 504f953..b356d76 100644
--- a/tcg/i386/tcg-target.h
+++ b/tcg/i386/tcg-target.h
@@ -86,7 +86,12 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i32 0
#define TCG_TARGET_HAS_nor_i32 0
#define TCG_TARGET_HAS_deposit_i32 1
+#if defined(__x86_64__) || defined(__i686__)
+/* Use cmov only if the compiler is already doing so. */
+#define TCG_TARGET_HAS_movcond_i32 1
+#else
#define TCG_TARGET_HAS_movcond_i32 0
+#endif
#if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_div2_i64 1
@@ -108,7 +113,7 @@ typedef enum {
#define TCG_TARGET_HAS_nand_i64 0
#define TCG_TARGET_HAS_nor_i64 0
#define TCG_TARGET_HAS_deposit_i64 1
-#define TCG_TARGET_HAS_movcond_i64 0
+#define TCG_TARGET_HAS_movcond_i64 1
#endif
#define TCG_TARGET_deposit_i32_valid(ofs, len) \
--
1.7.11.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 3/5] tcg-i386: Implement movcond
2012-09-18 14:23 ` [Qemu-devel] [PATCH 3/5] tcg-i386: Implement movcond Richard Henderson
@ 2012-09-18 21:11 ` Aurelien Jarno
0 siblings, 0 replies; 20+ messages in thread
From: Aurelien Jarno @ 2012-09-18 21:11 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Tue, Sep 18, 2012 at 07:23:58AM -0700, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> tcg/i386/tcg-target.c | 29 +++++++++++++++++++++++++++++
> tcg/i386/tcg-target.h | 7 ++++++-
> 2 files changed, 35 insertions(+), 1 deletion(-)
>
> diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
> index 34c2df8..cf28f56 100644
> --- a/tcg/i386/tcg-target.c
> +++ b/tcg/i386/tcg-target.c
> @@ -249,6 +249,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
> #define OPC_ADD_GvEv (OPC_ARITH_GvEv | (ARITH_ADD << 3))
> #define OPC_BSWAP (0xc8 | P_EXT)
> #define OPC_CALL_Jz (0xe8)
> +#define OPC_CMOVCC (0x40 | P_EXT) /* ... plus condition code */
> #define OPC_CMP_GvEv (OPC_ARITH_GvEv | (ARITH_CMP << 3))
> #define OPC_DEC_r32 (0x48)
> #define OPC_IMUL_GvEv (0xaf | P_EXT)
> @@ -935,6 +936,24 @@ static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
> }
> #endif
>
> +static void tcg_out_movcond32(TCGContext *s, TCGCond cond, TCGArg dest,
> + TCGArg c1, TCGArg c2, int const_c2,
> + TCGArg v1)
> +{
> + tcg_out_cmp(s, c1, c2, const_c2, 0);
> + tcg_out_modrm(s, OPC_CMOVCC | tcg_cond_to_jcc[cond], dest, v1);
> +}
> +
> +#if TCG_TARGET_REG_BITS == 64
> +static void tcg_out_movcond64(TCGContext *s, TCGCond cond, TCGArg dest,
> + TCGArg c1, TCGArg c2, int const_c2,
> + TCGArg v1)
> +{
> + tcg_out_cmp(s, c1, c2, const_c2, P_REXW);
> + tcg_out_modrm(s, OPC_CMOVCC | tcg_cond_to_jcc[cond] | P_REXW, dest, v1);
> +}
> +#endif
> +
> static void tcg_out_branch(TCGContext *s, int call, tcg_target_long dest)
> {
> tcg_target_long disp = dest - (tcg_target_long)s->code_ptr - 5;
> @@ -1650,6 +1669,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
> tcg_out_setcond32(s, args[3], args[0], args[1],
> args[2], const_args[2]);
> break;
> + case INDEX_op_movcond_i32:
> + tcg_out_movcond32(s, args[5], args[0], args[1],
> + args[2], const_args[2], args[3]);
> + break;
>
> OP_32_64(bswap16):
> tcg_out_rolw_8(s, args[0]);
> @@ -1772,6 +1795,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
> tcg_out_setcond64(s, args[3], args[0], args[1],
> args[2], const_args[2]);
> break;
> + case INDEX_op_movcond_i64:
> + tcg_out_movcond64(s, args[5], args[0], args[1],
> + args[2], const_args[2], args[3]);
> + break;
>
> case INDEX_op_bswap64_i64:
> tcg_out_bswap64(s, args[0]);
> @@ -1856,6 +1883,7 @@ static const TCGTargetOpDef x86_op_defs[] = {
> { INDEX_op_setcond_i32, { "q", "r", "ri" } },
>
> { INDEX_op_deposit_i32, { "Q", "0", "Q" } },
> + { INDEX_op_movcond_i32, { "r", "r", "ri", "r", "0" } },
>
> #if TCG_TARGET_REG_BITS == 32
> { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
> @@ -1910,6 +1938,7 @@ static const TCGTargetOpDef x86_op_defs[] = {
> { INDEX_op_ext32u_i64, { "r", "r" } },
>
> { INDEX_op_deposit_i64, { "Q", "0", "Q" } },
> + { INDEX_op_movcond_i64, { "r", "r", "re", "r", "0" } },
> #endif
>
> #if TCG_TARGET_REG_BITS == 64
> diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
> index 504f953..b356d76 100644
> --- a/tcg/i386/tcg-target.h
> +++ b/tcg/i386/tcg-target.h
> @@ -86,7 +86,12 @@ typedef enum {
> #define TCG_TARGET_HAS_nand_i32 0
> #define TCG_TARGET_HAS_nor_i32 0
> #define TCG_TARGET_HAS_deposit_i32 1
> +#if defined(__x86_64__) || defined(__i686__)
> +/* Use cmov only if the compiler is already doing so. */
> +#define TCG_TARGET_HAS_movcond_i32 1
> +#else
> #define TCG_TARGET_HAS_movcond_i32 0
> +#endif
>
> #if TCG_TARGET_REG_BITS == 64
> #define TCG_TARGET_HAS_div2_i64 1
> @@ -108,7 +113,7 @@ typedef enum {
> #define TCG_TARGET_HAS_nand_i64 0
> #define TCG_TARGET_HAS_nor_i64 0
> #define TCG_TARGET_HAS_deposit_i64 1
> -#define TCG_TARGET_HAS_movcond_i64 0
> +#define TCG_TARGET_HAS_movcond_i64 1
> #endif
>
> #define TCG_TARGET_deposit_i32_valid(ofs, len) \
> --
> 1.7.11.4
>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 4/5] tcg: Optimize movcond for constant comparisons
2012-09-18 14:23 [Qemu-devel] [PATCH 0/5] tcg: movcond Richard Henderson
` (2 preceding siblings ...)
2012-09-18 14:23 ` [Qemu-devel] [PATCH 3/5] tcg-i386: Implement movcond Richard Henderson
@ 2012-09-18 14:23 ` Richard Henderson
2012-09-18 21:11 ` Aurelien Jarno
2012-09-18 14:24 ` [Qemu-devel] [PATCH 5/5] tcg: Optimize two-address commutative operations Richard Henderson
2012-09-18 21:11 ` [Qemu-devel] [PATCH 0/5] tcg: movcond Aurelien Jarno
5 siblings, 1 reply; 20+ messages in thread
From: Richard Henderson @ 2012-09-18 14:23 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/optimize.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index fba0ed9..5b0a8ce 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -397,6 +397,14 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
args[3] = tcg_swap_cond(args[3]);
}
break;
+ CASE_OP_32_64(movcond):
+ if (temps[args[1]].state == TCG_TEMP_CONST
+ && temps[args[2]].state != TCG_TEMP_CONST) {
+ tmp = args[1];
+ args[1] = args[2];
+ args[2] = tmp;
+ args[5] = tcg_swap_cond(args[5]);
+ }
default:
break;
}
@@ -617,6 +625,27 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
}
args += 4;
break;
+ CASE_OP_32_64(movcond):
+ if (temps[args[1]].state == TCG_TEMP_CONST
+ && temps[args[2]].state == TCG_TEMP_CONST) {
+ gen_opc_buf[op_index] = op_to_mov(op);
+ tmp = do_constant_folding_cond(op, temps[args[1]].val,
+ temps[args[2]].val, args[5]);
+ tcg_opt_gen_mov(s, gen_args, args[0], args[4-tmp],
+ nb_temps, nb_globals);
+ gen_args += 2;
+ } else {
+ reset_temp(args[0], nb_temps, nb_globals);
+ gen_args[0] = args[0];
+ gen_args[1] = args[1];
+ gen_args[2] = args[2];
+ gen_args[3] = args[3];
+ gen_args[4] = args[4];
+ gen_args[5] = args[5];
+ gen_args += 6;
+ }
+ args += 6;
+ break;
case INDEX_op_call:
nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) {
--
1.7.11.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 4/5] tcg: Optimize movcond for constant comparisons
2012-09-18 14:23 ` [Qemu-devel] [PATCH 4/5] tcg: Optimize movcond for constant comparisons Richard Henderson
@ 2012-09-18 21:11 ` Aurelien Jarno
2012-09-20 22:04 ` Aurelien Jarno
0 siblings, 1 reply; 20+ messages in thread
From: Aurelien Jarno @ 2012-09-18 21:11 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Tue, Sep 18, 2012 at 07:23:59AM -0700, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> tcg/optimize.c | 29 +++++++++++++++++++++++++++++
> 1 file changed, 29 insertions(+)
>
> diff --git a/tcg/optimize.c b/tcg/optimize.c
> index fba0ed9..5b0a8ce 100644
> --- a/tcg/optimize.c
> +++ b/tcg/optimize.c
> @@ -397,6 +397,14 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
> args[3] = tcg_swap_cond(args[3]);
> }
> break;
> + CASE_OP_32_64(movcond):
> + if (temps[args[1]].state == TCG_TEMP_CONST
> + && temps[args[2]].state != TCG_TEMP_CONST) {
> + tmp = args[1];
> + args[1] = args[2];
> + args[2] = tmp;
> + args[5] = tcg_swap_cond(args[5]);
> + }
> default:
> break;
> }
> @@ -617,6 +625,27 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
> }
> args += 4;
> break;
> + CASE_OP_33_64(movcond):
> + if (temps[args[1]].state == TCG_TEMP_CONST
> + && temps[args[2]].state == TCG_TEMP_CONST) {
> + gen_opc_buf[op_index] = op_to_mov(op);
> + tmp = do_constant_folding_cond(op, temps[args[1]].val,
> + temps[args[2]].val, args[5]);
> + tcg_opt_gen_mov(s, gen_args, args[0], args[4-tmp],
> + nb_temps, nb_globals);
> + gen_args += 2;
> + } else {
> + reset_temp(args[0], nb_temps, nb_globals);
> + gen_args[0] = args[0];
> + gen_args[1] = args[1];
> + gen_args[2] = args[2];
> + gen_args[3] = args[3];
> + gen_args[4] = args[4];
> + gen_args[5] = args[5];
> + gen_args += 6;
> + }
> + args += 6;
> + break;
> case INDEX_op_call:
> nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
> if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) {
> --
> 1.7.11.4
>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 4/5] tcg: Optimize movcond for constant comparisons
2012-09-18 21:11 ` Aurelien Jarno
@ 2012-09-20 22:04 ` Aurelien Jarno
2012-09-21 14:33 ` Richard Henderson
0 siblings, 1 reply; 20+ messages in thread
From: Aurelien Jarno @ 2012-09-20 22:04 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Tue, Sep 18, 2012 at 11:11:48PM +0200, Aurelien Jarno wrote:
> On Tue, Sep 18, 2012 at 07:23:59AM -0700, Richard Henderson wrote:
> > Signed-off-by: Richard Henderson <rth@twiddle.net>
> > ---
> > tcg/optimize.c | 29 +++++++++++++++++++++++++++++
> > 1 file changed, 29 insertions(+)
> >
> > diff --git a/tcg/optimize.c b/tcg/optimize.c
> > index fba0ed9..5b0a8ce 100644
> > --- a/tcg/optimize.c
> > +++ b/tcg/optimize.c
> > @@ -397,6 +397,14 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
> > args[3] = tcg_swap_cond(args[3]);
> > }
> > break;
> > + CASE_OP_32_64(movcond):
> > + if (temps[args[1]].state == TCG_TEMP_CONST
> > + && temps[args[2]].state != TCG_TEMP_CONST) {
> > + tmp = args[1];
> > + args[1] = args[2];
> > + args[2] = tmp;
> > + args[5] = tcg_swap_cond(args[5]);
> > + }
> > default:
> > break;
> > }
> > @@ -617,6 +625,27 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
> > }
> > args += 4;
> > break;
> > + CASE_OP_33_64(movcond):
> > + if (temps[args[1]].state == TCG_TEMP_CONST
> > + && temps[args[2]].state == TCG_TEMP_CONST) {
> > + gen_opc_buf[op_index] = op_to_mov(op);
> > + tmp = do_constant_folding_cond(op, temps[args[1]].val,
> > + temps[args[2]].val, args[5]);
> > + tcg_opt_gen_mov(s, gen_args, args[0], args[4-tmp],
> > + nb_temps, nb_globals);
> > + gen_args += 2;
> > + } else {
> > + reset_temp(args[0], nb_temps, nb_globals);
> > + gen_args[0] = args[0];
> > + gen_args[1] = args[1];
> > + gen_args[2] = args[2];
> > + gen_args[3] = args[3];
> > + gen_args[4] = args[4];
> > + gen_args[5] = args[5];
> > + gen_args += 6;
> > + }
> > + args += 6;
> > + break;
> > case INDEX_op_call:
> > nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
> > if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) {
> > --
> > 1.7.11.4
> >
>
> Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Playing a bit more with this patch, I have found it fails when v1 or v2
or constants or copies. The additional patch below fixes the problem.
diff --git a/tcg/optimize.c b/tcg/optimize.c
index f95c511..b7e235e 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -641,12 +641,23 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
CASE_OP_32_64(movcond):
if (temps[args[1]].state == TCG_TEMP_CONST
&& temps[args[2]].state == TCG_TEMP_CONST) {
- gen_opc_buf[op_index] = op_to_mov(op);
tmp = do_constant_folding_cond(op, temps[args[1]].val,
temps[args[2]].val, args[5]);
- tcg_opt_gen_mov(gen_args, args[0], args[4-tmp],
- nb_temps, nb_globals);
- gen_args += 2;
+ if ((temps[args[4-tmp]].state == TCG_TEMP_COPY
+ && temps[args[4-tmp]].val == args[0])
+ || args[0] == args[4-tmp]) {
+ gen_opc_buf[op_index] = INDEX_op_nop;
+ } else if (tmp && temps[args[4-tmp]].state == TCG_TEMP_CONST) {
+ gen_opc_buf[op_index] = op_to_movi(op);
+ tcg_opt_gen_movi(gen_args, args[0], temps[args[4-tmp]].val,
+ nb_temps, nb_globals);
+ gen_args += 2;
+ } else {
+ gen_opc_buf[op_index] = op_to_mov(op);
+ tcg_opt_gen_mov(gen_args, args[0], args[4-tmp],
+ nb_temps, nb_globals);
+ gen_args += 2;
+ }
} else {
reset_temp(args[0], nb_temps, nb_globals);
gen_args[0] = args[0];
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 5/5] tcg: Optimize two-address commutative operations
2012-09-18 14:23 [Qemu-devel] [PATCH 0/5] tcg: movcond Richard Henderson
` (3 preceding siblings ...)
2012-09-18 14:23 ` [Qemu-devel] [PATCH 4/5] tcg: Optimize movcond for constant comparisons Richard Henderson
@ 2012-09-18 14:24 ` Richard Henderson
2012-09-18 21:11 ` Aurelien Jarno
2012-09-18 21:11 ` [Qemu-devel] [PATCH 0/5] tcg: movcond Aurelien Jarno
5 siblings, 1 reply; 20+ messages in thread
From: Richard Henderson @ 2012-09-18 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
While swapping constants to the second operand, swap
sources matching destinations to the first operand.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
tcg/optimize.c | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 5b0a8ce..becc408 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -337,6 +337,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
const TCGOpDef *def;
TCGArg *gen_args;
TCGArg tmp;
+ TCGCond cond;
+
/* Array VALS has an element for each temp.
If this temp holds a constant then its value is kept in VALS' element.
If this temp is a copy of other ones then this equivalence class'
@@ -363,7 +365,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
}
}
- /* For commutative operations make constant second argument */
+ /* For commutative operations make constant second argument, or
+ if the destination is an input, make it the first argument. */
switch (op) {
CASE_OP_32_64(add):
CASE_OP_32_64(mul):
@@ -373,7 +376,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
CASE_OP_32_64(eqv):
CASE_OP_32_64(nand):
CASE_OP_32_64(nor):
- if (temps[args[1]].state == TCG_TEMP_CONST) {
+ if (temps[args[1]].state == TCG_TEMP_CONST
+ || (args[0] == args[2]
+ && temps[args[1]].state != TCG_TEMP_CONST)) {
tmp = args[1];
args[1] = args[2];
args[2] = tmp;
@@ -398,13 +403,24 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
}
break;
CASE_OP_32_64(movcond):
+ cond = args[5];
if (temps[args[1]].state == TCG_TEMP_CONST
&& temps[args[2]].state != TCG_TEMP_CONST) {
tmp = args[1];
args[1] = args[2];
args[2] = tmp;
- args[5] = tcg_swap_cond(args[5]);
+ cond = tcg_swap_cond(cond);
+ }
+ /* For movcond, we canonicalize the "false" input reg to match
+ the destination reg so that the tcg backend can implement
+ a "move if true" operation. */
+ if (args[0] == args[3]) {
+ tmp = args[3];
+ args[3] = args[4];
+ args[4] = tmp;
+ cond = tcg_invert_cond(cond);
}
+ args[5] = cond;
default:
break;
}
--
1.7.11.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 5/5] tcg: Optimize two-address commutative operations
2012-09-18 14:24 ` [Qemu-devel] [PATCH 5/5] tcg: Optimize two-address commutative operations Richard Henderson
@ 2012-09-18 21:11 ` Aurelien Jarno
0 siblings, 0 replies; 20+ messages in thread
From: Aurelien Jarno @ 2012-09-18 21:11 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Tue, Sep 18, 2012 at 07:24:00AM -0700, Richard Henderson wrote:
> While swapping constants to the second operand, swap
> sources matching destinations to the first operand.
>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> tcg/optimize.c | 22 +++++++++++++++++++---
> 1 file changed, 19 insertions(+), 3 deletions(-)
>
> diff --git a/tcg/optimize.c b/tcg/optimize.c
> index 5b0a8ce..becc408 100644
> --- a/tcg/optimize.c
> +++ b/tcg/optimize.c
> @@ -337,6 +337,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
> const TCGOpDef *def;
> TCGArg *gen_args;
> TCGArg tmp;
> + TCGCond cond;
> +
> /* Array VALS has an element for each temp.
> If this temp holds a constant then its value is kept in VALS' element.
> If this temp is a copy of other ones then this equivalence class'
> @@ -363,7 +365,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
> }
> }
>
> - /* For commutative operations make constant second argument */
> + /* For commutative operations make constant second argument, or
> + if the destination is an input, make it the first argument. */
> switch (op) {
> CASE_OP_32_64(add):
> CASE_OP_32_64(mul):
> @@ -373,7 +376,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
> CASE_OP_32_64(eqv):
> CASE_OP_32_64(nand):
> CASE_OP_32_64(nor):
> - if (temps[args[1]].state == TCG_TEMP_CONST) {
> + if (temps[args[1]].state == TCG_TEMP_CONST
> + || (args[0] == args[2]
> + && temps[args[1]].state != TCG_TEMP_CONST)) {
> tmp = args[1];
Not directly related to movcond, and I also got that in my tree, but I
guess it's fine.
> args[1] = args[2];
> args[2] = tmp;
> @@ -398,13 +403,24 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
> }
> break;
> CASE_OP_32_64(movcond):
> + cond = args[5];
> if (temps[args[1]].state == TCG_TEMP_CONST
> && temps[args[2]].state != TCG_TEMP_CONST) {
> tmp = args[1];
> args[1] = args[2];
> args[2] = tmp;
> - args[5] = tcg_swap_cond(args[5]);
> + cond = tcg_swap_cond(cond);
> + }
> + /* For movcond, we canonicalize the "false" input reg to match
> + the destination reg so that the tcg backend can implement
> + a "move if true" operation. */
> + if (args[0] == args[3]) {
> + tmp = args[3];
> + args[3] = args[4];
> + args[4] = tmp;
> + cond = tcg_invert_cond(cond);
> }
> + args[5] = cond;
> default:
> break;
> }
> --
> 1.7.11.4
>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 0/5] tcg: movcond
2012-09-18 14:23 [Qemu-devel] [PATCH 0/5] tcg: movcond Richard Henderson
` (4 preceding siblings ...)
2012-09-18 14:24 ` [Qemu-devel] [PATCH 5/5] tcg: Optimize two-address commutative operations Richard Henderson
@ 2012-09-18 21:11 ` Aurelien Jarno
2012-09-19 13:03 ` malc
2012-09-19 19:07 ` Blue Swirl
5 siblings, 2 replies; 20+ messages in thread
From: Aurelien Jarno @ 2012-09-18 21:11 UTC (permalink / raw)
To: Richard Henderson; +Cc: Blue Swirl, qemu-devel
On Tue, Sep 18, 2012 at 07:23:55AM -0700, Richard Henderson wrote:
> As recently discussed, with the optional fallback to setcond.
>
> I include a patch to target-alpha to test correctness both
> before and after implementing the opcode in the i386 backend,
> as well as in the optimizations.
>
Thanks for this new implementation, it's a lot cleaner than the previous
one, especially the fallback to setcond if not implemented, and the
argument alias for the x86 backend, deferring the issue to the register
allocator instead of trying to do that in the backend.
>From my side, I am ok with it. That said I'd also like to have at least
the opinion of Malc and Blue (Cc:ed). Comments from others are also
welcome.
>
> Richard Henderson (5):
> tcg: Introduce movcond
> target-alpha: Use movcond
> tcg-i386: Implement movcond
> tcg: Optimize movcond for constant comparisons
> tcg: Optimize two-address commutative operations
>
> target-alpha/translate.c | 102 ++++++++++++++++++++++-------------------------
> tcg/README | 6 +++
> tcg/arm/tcg-target.h | 1 +
> tcg/hppa/tcg-target.h | 1 +
> tcg/i386/tcg-target.c | 29 ++++++++++++++
> tcg/i386/tcg-target.h | 7 ++++
> tcg/ia64/tcg-target.h | 2 +
> tcg/mips/tcg-target.h | 1 +
> tcg/optimize.c | 49 ++++++++++++++++++++++-
> tcg/ppc/tcg-target.h | 1 +
> tcg/ppc64/tcg-target.h | 2 +
> tcg/s390/tcg-target.h | 2 +
> tcg/sparc/tcg-target.h | 2 +
> tcg/tcg-op.h | 41 +++++++++++++++++++
> tcg/tcg-opc.h | 2 +
> tcg/tcg.c | 11 +++--
> tcg/tcg.h | 1 +
> tcg/tci/tcg-target.h | 2 +
> 18 files changed, 200 insertions(+), 62 deletions(-)
>
> --
> 1.7.11.4
>
>
>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 0/5] tcg: movcond
2012-09-18 21:11 ` [Qemu-devel] [PATCH 0/5] tcg: movcond Aurelien Jarno
@ 2012-09-19 13:03 ` malc
2012-09-19 14:26 ` Richard Henderson
2012-09-19 19:07 ` Blue Swirl
1 sibling, 1 reply; 20+ messages in thread
From: malc @ 2012-09-19 13:03 UTC (permalink / raw)
To: Aurelien Jarno; +Cc: Blue Swirl, qemu-devel, Richard Henderson
On Tue, 18 Sep 2012, Aurelien Jarno wrote:
> On Tue, Sep 18, 2012 at 07:23:55AM -0700, Richard Henderson wrote:
> > As recently discussed, with the optional fallback to setcond.
> >
> > I include a patch to target-alpha to test correctness both
> > before and after implementing the opcode in the i386 backend,
> > as well as in the optimizations.
> >
>
> Thanks for this new implementation, it's a lot cleaner than the previous
> one, especially the fallback to setcond if not implemented, and the
> argument alias for the x86 backend, deferring the issue to the register
> allocator instead of trying to do that in the backend.
>
> >From my side, I am ok with it. That said I'd also like to have at least
> the opinion of Malc and Blue (Cc:ed). Comments from others are also
> welcome.
I don't have objections (philosphical or otherwise) to this, the only
request is for a detailed directions on how to exercise non emulated
version (i.e. where to get the alpha image from how to run it exactly)
[..snip..]
P.S. The only thing i've noticed is somewhat unusual naming convention
in the README, nothing else uses cN and vN naming of arguments,
perhaps sticking to t0, t1, t2, t3 is better to avoid confusion?
--
mailto:av1474@comtv.ru
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 0/5] tcg: movcond
2012-09-19 13:03 ` malc
@ 2012-09-19 14:26 ` Richard Henderson
0 siblings, 0 replies; 20+ messages in thread
From: Richard Henderson @ 2012-09-19 14:26 UTC (permalink / raw)
To: malc; +Cc: Blue Swirl, qemu-devel, Aurelien Jarno
On 09/19/2012 06:03 AM, malc wrote:
> (i.e. where to get the alpha image from how to run it exactly)
The easiest alpha test is to just run the rom shipped with qemu,
i.e. no arguments. That will certainly be good enough to test
conditional move and conditional branch insns.
> P.S. The only thing i've noticed is somewhat unusual naming convention
> in the README, nothing else uses cN and vN naming of arguments,
> perhaps sticking to t0, t1, t2, t3 is better to avoid confusion?
I wanted better to highlight that the first two inputs are the
comparison inputs, and the second two inputs are the "values"
to be moved.
r~
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Qemu-devel] [PATCH 0/5] tcg: movcond
2012-09-18 21:11 ` [Qemu-devel] [PATCH 0/5] tcg: movcond Aurelien Jarno
2012-09-19 13:03 ` malc
@ 2012-09-19 19:07 ` Blue Swirl
2012-09-19 19:14 ` Richard Henderson
1 sibling, 1 reply; 20+ messages in thread
From: Blue Swirl @ 2012-09-19 19:07 UTC (permalink / raw)
To: Aurelien Jarno; +Cc: qemu-devel, Richard Henderson
On Tue, Sep 18, 2012 at 9:11 PM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> On Tue, Sep 18, 2012 at 07:23:55AM -0700, Richard Henderson wrote:
>> As recently discussed, with the optional fallback to setcond.
>>
>> I include a patch to target-alpha to test correctness both
>> before and after implementing the opcode in the i386 backend,
>> as well as in the optimizations.
>>
>
> Thanks for this new implementation, it's a lot cleaner than the previous
> one, especially the fallback to setcond if not implemented, and the
> argument alias for the x86 backend, deferring the issue to the register
> allocator instead of trying to do that in the backend.
>
> From my side, I am ok with it. That said I'd also like to have at least
> the opinion of Malc and Blue (Cc:ed). Comments from others are also
> welcome.
OK.
It looks like Sparc64 version should be similar to i386 one, cmp + movcc.
>
>>
>> Richard Henderson (5):
>> tcg: Introduce movcond
>> target-alpha: Use movcond
>> tcg-i386: Implement movcond
>> tcg: Optimize movcond for constant comparisons
>> tcg: Optimize two-address commutative operations
>>
>> target-alpha/translate.c | 102 ++++++++++++++++++++++-------------------------
>> tcg/README | 6 +++
>> tcg/arm/tcg-target.h | 1 +
>> tcg/hppa/tcg-target.h | 1 +
>> tcg/i386/tcg-target.c | 29 ++++++++++++++
>> tcg/i386/tcg-target.h | 7 ++++
>> tcg/ia64/tcg-target.h | 2 +
>> tcg/mips/tcg-target.h | 1 +
>> tcg/optimize.c | 49 ++++++++++++++++++++++-
>> tcg/ppc/tcg-target.h | 1 +
>> tcg/ppc64/tcg-target.h | 2 +
>> tcg/s390/tcg-target.h | 2 +
>> tcg/sparc/tcg-target.h | 2 +
>> tcg/tcg-op.h | 41 +++++++++++++++++++
>> tcg/tcg-opc.h | 2 +
>> tcg/tcg.c | 11 +++--
>> tcg/tcg.h | 1 +
>> tcg/tci/tcg-target.h | 2 +
>> 18 files changed, 200 insertions(+), 62 deletions(-)
>>
>> --
>> 1.7.11.4
>>
>>
>>
>
> --
> Aurelien Jarno GPG: 1024D/F1BCDB73
> aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 20+ messages in thread