aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2012-09-24 14:21:40 -0700
committerAurelien Jarno <aurelien@aurel32.net>2012-10-06 18:48:40 +0200
commit0aed257f08444feb6269d0c302b35a8fb10fcb3f (patch)
tree17afe2f486f714ed5b6c3460f4dbec15e6563c3e
parentbcc66562ad185e9c2a667b00426f625e2489bda9 (diff)
downloadqemu-0aed257f08444feb6269d0c302b35a8fb10fcb3f.zip
qemu-0aed257f08444feb6269d0c302b35a8fb10fcb3f.tar.gz
qemu-0aed257f08444feb6269d0c302b35a8fb10fcb3f.tar.bz2
tcg: Add TCG_COND_NEVER, TCG_COND_ALWAYS
There are several cases that can be handled easier inside both translators and code generators if we have out-of-band values for conditions. It's easy enough to handle ALWAYS and NEVER in the natural way inside the tcg middle-end. Signed-off-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
-rw-r--r--tcg/arm/tcg-target.c2
-rw-r--r--tcg/hppa/tcg-target.c2
-rw-r--r--tcg/i386/tcg-target.c2
-rw-r--r--tcg/optimize.c6
-rw-r--r--tcg/ppc/tcg-target.c2
-rw-r--r--tcg/ppc64/tcg-target.c2
-rw-r--r--tcg/s390/tcg-target.c4
-rw-r--r--tcg/sparc/tcg-target.c2
-rw-r--r--tcg/tcg-op.h82
-rw-r--r--tcg/tcg.c2
-rw-r--r--tcg/tcg.h37
11 files changed, 102 insertions, 41 deletions
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 1e61864..fbbbefe 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -335,7 +335,7 @@ enum arm_cond_code_e {
COND_AL = 0xe,
};
-static const uint8_t tcg_cond_to_arm_cond[10] = {
+static const uint8_t tcg_cond_to_arm_cond[] = {
[TCG_COND_EQ] = COND_EQ,
[TCG_COND_NE] = COND_NE,
[TCG_COND_LT] = COND_LT,
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index 44974c4..b933430 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -732,7 +732,7 @@ static void tcg_out_branch(TCGContext *s, int label_index, int nul)
}
}
-static const uint8_t tcg_cond_to_cmp_cond[10] =
+static const uint8_t tcg_cond_to_cmp_cond[] =
{
[TCG_COND_EQ] = COND_EQ,
[TCG_COND_NE] = COND_EQ | COND_FALSE,
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index bb2306d..4952c05 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -338,7 +338,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define JCC_JLE 0xe
#define JCC_JG 0xf
-static const uint8_t tcg_cond_to_jcc[10] = {
+static const uint8_t tcg_cond_to_jcc[] = {
[TCG_COND_EQ] = JCC_JE,
[TCG_COND_NE] = JCC_JNE,
[TCG_COND_LT] = JCC_JL,
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 35532a1..edb2b0e 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -321,6 +321,8 @@ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
return (uint32_t)temps[x].val <= (uint32_t)temps[y].val;
case TCG_COND_GTU:
return (uint32_t)temps[x].val > (uint32_t)temps[y].val;
+ default:
+ break;
}
break;
case 64:
@@ -345,6 +347,8 @@ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
return (uint64_t)temps[x].val <= (uint64_t)temps[y].val;
case TCG_COND_GTU:
return (uint64_t)temps[x].val > (uint64_t)temps[y].val;
+ default:
+ break;
}
break;
}
@@ -362,6 +366,8 @@ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
case TCG_COND_LEU:
case TCG_COND_EQ:
return 1;
+ default:
+ break;
}
} else if (temps[y].state == TCG_TEMP_CONST && temps[y].val == 0) {
switch (c) {
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index 56baedd..60b7b92 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -437,7 +437,7 @@ enum {
CR_SO
};
-static const uint32_t tcg_to_bc[10] = {
+static const uint32_t tcg_to_bc[] = {
[TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE,
[TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE,
[TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE,
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 6e9b363..5403fc1 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -418,7 +418,7 @@ enum {
CR_SO
};
-static const uint32_t tcg_to_bc[10] = {
+static const uint32_t tcg_to_bc[] = {
[TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE,
[TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE,
[TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE,
diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
index c0ef6ba..fd9286f 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -268,7 +268,7 @@ static const int tcg_target_call_oarg_regs[] = {
#define S390_CC_ALWAYS 15
/* Condition codes that result from a COMPARE and COMPARE LOGICAL. */
-static const uint8_t tcg_cond_to_s390_cond[10] = {
+static const uint8_t tcg_cond_to_s390_cond[] = {
[TCG_COND_EQ] = S390_CC_EQ,
[TCG_COND_NE] = S390_CC_NE,
[TCG_COND_LT] = S390_CC_LT,
@@ -284,7 +284,7 @@ static const uint8_t tcg_cond_to_s390_cond[10] = {
/* Condition codes that result from a LOAD AND TEST. Here, we have no
unsigned instruction variation, however since the test is vs zero we
can re-map the outcomes appropriately. */
-static const uint8_t tcg_cond_to_ltr_cond[10] = {
+static const uint8_t tcg_cond_to_ltr_cond[] = {
[TCG_COND_EQ] = S390_CC_EQ,
[TCG_COND_NE] = S390_CC_NE,
[TCG_COND_LT] = S390_CC_LT,
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index e82fab2..0c32baa 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -512,7 +512,7 @@ static void tcg_out_branch_i64(TCGContext *s, int opc, int label_index)
}
#endif
-static const uint8_t tcg_cond_to_bcond[10] = {
+static const uint8_t tcg_cond_to_bcond[] = {
[TCG_COND_EQ] = COND_E,
[TCG_COND_NE] = COND_NE,
[TCG_COND_LT] = COND_L,
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index bd93fe4..5518458 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -646,29 +646,49 @@ static inline void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
static inline void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1,
TCGv_i32 arg2, int label_index)
{
- tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_index);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_br(label_index);
+ } else if (cond != TCG_COND_NEVER) {
+ tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_index);
+ }
}
static inline void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1,
int32_t arg2, int label_index)
{
- TCGv_i32 t0 = tcg_const_i32(arg2);
- tcg_gen_brcond_i32(cond, arg1, t0, label_index);
- tcg_temp_free_i32(t0);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_br(label_index);
+ } else if (cond != TCG_COND_NEVER) {
+ TCGv_i32 t0 = tcg_const_i32(arg2);
+ tcg_gen_brcond_i32(cond, arg1, t0, label_index);
+ tcg_temp_free_i32(t0);
+ }
}
static inline void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret,
TCGv_i32 arg1, TCGv_i32 arg2)
{
- tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_movi_i32(ret, 1);
+ } else if (cond == TCG_COND_NEVER) {
+ tcg_gen_movi_i32(ret, 0);
+ } else {
+ tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond);
+ }
}
static inline void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret,
TCGv_i32 arg1, int32_t arg2)
{
- TCGv_i32 t0 = tcg_const_i32(arg2);
- tcg_gen_setcond_i32(cond, ret, arg1, t0);
- tcg_temp_free_i32(t0);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_movi_i32(ret, 1);
+ } else if (cond == TCG_COND_NEVER) {
+ tcg_gen_movi_i32(ret, 0);
+ } else {
+ TCGv_i32 t0 = tcg_const_i32(arg2);
+ tcg_gen_setcond_i32(cond, ret, arg1, t0);
+ tcg_temp_free_i32(t0);
+ }
}
static inline void tcg_gen_mul_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
@@ -964,17 +984,27 @@ static inline void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
static inline void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1,
TCGv_i64 arg2, int label_index)
{
- tcg_gen_op6ii_i32(INDEX_op_brcond2_i32,
- TCGV_LOW(arg1), TCGV_HIGH(arg1), TCGV_LOW(arg2),
- TCGV_HIGH(arg2), cond, label_index);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_br(label_index);
+ } else if (cond != TCG_COND_NEVER) {
+ tcg_gen_op6ii_i32(INDEX_op_brcond2_i32,
+ TCGV_LOW(arg1), TCGV_HIGH(arg1), TCGV_LOW(arg2),
+ TCGV_HIGH(arg2), cond, label_index);
+ }
}
static inline void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
- TCGV_LOW(arg1), TCGV_HIGH(arg1),
- TCGV_LOW(arg2), TCGV_HIGH(arg2), cond);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_movi_i32(TCGV_LOW(ret), 1);
+ } else if (cond == TCG_COND_NEVER) {
+ tcg_gen_movi_i32(TCGV_LOW(ret), 0);
+ } else {
+ tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
+ TCGV_LOW(arg1), TCGV_HIGH(arg1),
+ TCGV_LOW(arg2), TCGV_HIGH(arg2), cond);
+ }
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
}
@@ -1273,13 +1303,23 @@ static inline void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
static inline void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1,
TCGv_i64 arg2, int label_index)
{
- tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond, label_index);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_br(label_index);
+ } else if (cond != TCG_COND_NEVER) {
+ tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond, label_index);
+ }
}
static inline void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_movi_i64(ret, 1);
+ } else if (cond == TCG_COND_NEVER) {
+ tcg_gen_movi_i64(ret, 0);
+ } else {
+ tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond);
+ }
}
static inline void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
@@ -1397,9 +1437,13 @@ static inline void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
static inline void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1,
int64_t arg2, int label_index)
{
- TCGv_i64 t0 = tcg_const_i64(arg2);
- tcg_gen_brcond_i64(cond, arg1, t0, label_index);
- tcg_temp_free_i64(t0);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_br(label_index);
+ } else if (cond != TCG_COND_NEVER) {
+ TCGv_i64 t0 = tcg_const_i64(arg2);
+ tcg_gen_brcond_i64(cond, arg1, t0, label_index);
+ tcg_temp_free_i64(t0);
+ }
}
static inline void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret,
diff --git a/tcg/tcg.c b/tcg/tcg.c
index c069e44..78ef50b 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -864,6 +864,8 @@ static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
static const char * const cond_name[] =
{
+ [TCG_COND_NEVER] = "never",
+ [TCG_COND_ALWAYS] = "always",
[TCG_COND_EQ] = "eq",
[TCG_COND_NE] = "ne",
[TCG_COND_LT] = "lt",
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 6ff2ab5..75f0239 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -266,18 +266,28 @@ typedef int TCGv_i64;
#define TCG_CALL_DUMMY_TCGV MAKE_TCGV_I32(-1)
#define TCG_CALL_DUMMY_ARG ((TCGArg)(-1))
+/* Conditions. Note that these are layed out for easy manipulation by
+ the the functions below:
+ bit 0 is used for inverting;
+ bit 1 is signed,
+ bit 2 is unsigned,
+ bit 3 is used with bit 0 for swapping signed/unsigned. */
typedef enum {
- TCG_COND_EQ,
- TCG_COND_NE,
- TCG_COND_LT,
- TCG_COND_GE,
- TCG_COND_LE,
- TCG_COND_GT,
+ /* non-signed */
+ TCG_COND_NEVER = 0 | 0 | 0 | 0,
+ TCG_COND_ALWAYS = 0 | 0 | 0 | 1,
+ TCG_COND_EQ = 8 | 0 | 0 | 0,
+ TCG_COND_NE = 8 | 0 | 0 | 1,
+ /* signed */
+ TCG_COND_LT = 0 | 0 | 2 | 0,
+ TCG_COND_GE = 0 | 0 | 2 | 1,
+ TCG_COND_LE = 8 | 0 | 2 | 0,
+ TCG_COND_GT = 8 | 0 | 2 | 1,
/* unsigned */
- TCG_COND_LTU,
- TCG_COND_GEU,
- TCG_COND_LEU,
- TCG_COND_GTU,
+ TCG_COND_LTU = 0 | 4 | 0 | 0,
+ TCG_COND_GEU = 0 | 4 | 0 | 1,
+ TCG_COND_LEU = 8 | 4 | 0 | 0,
+ TCG_COND_GTU = 8 | 4 | 0 | 1,
} TCGCond;
/* Invert the sense of the comparison. */
@@ -289,18 +299,17 @@ static inline TCGCond tcg_invert_cond(TCGCond c)
/* Swap the operands in a comparison. */
static inline TCGCond tcg_swap_cond(TCGCond c)
{
- int mask = (c < TCG_COND_LT ? 0 : c < TCG_COND_LTU ? 7 : 15);
- return (TCGCond)(c ^ mask);
+ return c & 6 ? (TCGCond)(c ^ 9) : c;
}
static inline TCGCond tcg_unsigned_cond(TCGCond c)
{
- return (c >= TCG_COND_LT && c <= TCG_COND_GT ? c + 4 : c);
+ return c & 2 ? (TCGCond)(c ^ 6) : c;
}
static inline bool is_unsigned_cond(TCGCond c)
{
- return c >= TCG_COND_LTU;
+ return (c & 4) != 0;
}
#define TEMP_VAL_DEAD 0