5544c1b
From 3616400bc0065f7114172ad7801d9d88332ef981 Mon Sep 17 00:00:00 2001
5544c1b
From: Richard Henderson <rth@twiddle.net>
5544c1b
Date: Tue, 18 Sep 2012 19:59:47 -0700
5544c1b
Subject: [PATCH] tcg-hppa: Fix brcond2 and setcond2
5544c1b
5544c1b
Neither of these functions were performing double-word
5544c1b
compares properly.
5544c1b
5544c1b
Signed-off-by: Richard Henderson <rth@twiddle.net>
5544c1b
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
5544c1b
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
5544c1b
---
5544c1b
 tcg/hppa/tcg-target.c | 51 ++++++++++++++++++++++++++++++++++++++++++---------
5544c1b
 1 file changed, 42 insertions(+), 9 deletions(-)
5544c1b
5544c1b
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
5544c1b
index 8b81b70..a76569d 100644
5544c1b
--- a/tcg/hppa/tcg-target.c
5544c1b
+++ b/tcg/hppa/tcg-target.c
5544c1b
@@ -820,19 +820,34 @@ static void tcg_out_comclr(TCGContext *s, int cond, TCGArg ret,
5544c1b
     tcg_out32(s, op);
5544c1b
 }
5544c1b
 
5544c1b
+static TCGCond const tcg_high_cond[] = {
5544c1b
+    [TCG_COND_EQ] = TCG_COND_EQ,
5544c1b
+    [TCG_COND_NE] = TCG_COND_NE,
5544c1b
+    [TCG_COND_LT] = TCG_COND_LT,
5544c1b
+    [TCG_COND_LE] = TCG_COND_LT,
5544c1b
+    [TCG_COND_GT] = TCG_COND_GT,
5544c1b
+    [TCG_COND_GE] = TCG_COND_GT,
5544c1b
+    [TCG_COND_LTU] = TCG_COND_LTU,
5544c1b
+    [TCG_COND_LEU] = TCG_COND_LTU,
5544c1b
+    [TCG_COND_GTU] = TCG_COND_GTU,
5544c1b
+    [TCG_COND_GEU] = TCG_COND_GTU
5544c1b
+};
5544c1b
+
5544c1b
 static void tcg_out_brcond2(TCGContext *s, int cond, TCGArg al, TCGArg ah,
5544c1b
                             TCGArg bl, int blconst, TCGArg bh, int bhconst,
5544c1b
                             int label_index)
5544c1b
 {
5544c1b
     switch (cond) {
5544c1b
     case TCG_COND_EQ:
5544c1b
+        tcg_out_comclr(s, TCG_COND_NE, TCG_REG_R0, al, bl, blconst);
5544c1b
+        tcg_out_brcond(s, TCG_COND_EQ, ah, bh, bhconst, label_index);
5544c1b
+        break;
5544c1b
     case TCG_COND_NE:
5544c1b
-        tcg_out_comclr(s, tcg_invert_cond(cond), TCG_REG_R0, al, bl, blconst);
5544c1b
-        tcg_out_brcond(s, cond, ah, bh, bhconst, label_index);
5544c1b
+        tcg_out_brcond(s, TCG_COND_NE, al, bl, bhconst, label_index);
5544c1b
+        tcg_out_brcond(s, TCG_COND_NE, ah, bh, bhconst, label_index);
5544c1b
         break;
5544c1b
-
5544c1b
     default:
5544c1b
-        tcg_out_brcond(s, cond, ah, bh, bhconst, label_index);
5544c1b
+        tcg_out_brcond(s, tcg_high_cond[cond], ah, bh, bhconst, label_index);
5544c1b
         tcg_out_comclr(s, TCG_COND_NE, TCG_REG_R0, ah, bh, bhconst);
5544c1b
         tcg_out_brcond(s, tcg_unsigned_cond(cond),
5544c1b
                        al, bl, blconst, label_index);
5544c1b
@@ -853,9 +868,8 @@ static void tcg_out_setcond2(TCGContext *s, int cond, TCGArg ret,
5544c1b
 {
5544c1b
     int scratch = TCG_REG_R20;
5544c1b
 
5544c1b
-    if (ret != al && ret != ah
5544c1b
-        && (blconst || ret != bl)
5544c1b
-        && (bhconst || ret != bh)) {
5544c1b
+    /* Note that the low parts are fully consumed before scratch is set.  */
5544c1b
+    if (ret != ah && (bhconst || ret != bh)) {
5544c1b
         scratch = ret;
5544c1b
     }
5544c1b
 
5544c1b
@@ -867,13 +881,32 @@ static void tcg_out_setcond2(TCGContext *s, int cond, TCGArg ret,
5544c1b
         tcg_out_movi(s, TCG_TYPE_I32, scratch, cond == TCG_COND_NE);
5544c1b
         break;
5544c1b
 
5544c1b
-    default:
5544c1b
+    case TCG_COND_GE:
5544c1b
+    case TCG_COND_GEU:
5544c1b
+    case TCG_COND_LT:
5544c1b
+    case TCG_COND_LTU:
5544c1b
+        /* Optimize compares with low part zero.  */
5544c1b
+        if (bl == 0) {
5544c1b
+            tcg_out_setcond(s, cond, ret, ah, bh, bhconst);
5544c1b
+            return;
5544c1b
+        }
5544c1b
+        /* FALLTHRU */
5544c1b
+
5544c1b
+    case TCG_COND_LE:
5544c1b
+    case TCG_COND_LEU:
5544c1b
+    case TCG_COND_GT:
5544c1b
+    case TCG_COND_GTU:
5544c1b
+        /* <= : ah < bh | (ah == bh && al <= bl) */
5544c1b
         tcg_out_setcond(s, tcg_unsigned_cond(cond), scratch, al, bl, blconst);
5544c1b
         tcg_out_comclr(s, TCG_COND_EQ, TCG_REG_R0, ah, bh, bhconst);
5544c1b
         tcg_out_movi(s, TCG_TYPE_I32, scratch, 0);
5544c1b
-        tcg_out_comclr(s, cond, TCG_REG_R0, ah, bh, bhconst);
5544c1b
+        tcg_out_comclr(s, tcg_invert_cond(tcg_high_cond[cond]),
5544c1b
+                       TCG_REG_R0, ah, bh, bhconst);
5544c1b
         tcg_out_movi(s, TCG_TYPE_I32, scratch, 1);
5544c1b
         break;
5544c1b
+
5544c1b
+    default:
5544c1b
+        tcg_abort();
5544c1b
     }
5544c1b
 
5544c1b
     tcg_out_mov(s, TCG_TYPE_I32, ret, scratch);