Mark Wielaard dcdfab
commit d6a810760ec61ddedf15445457edbbe288536a2f
Mark Wielaard dcdfab
Author: Julian Seward <jseward@acm.org>
Mark Wielaard dcdfab
Date:   Tue Dec 12 22:31:54 2017 +0100
Mark Wielaard dcdfab
Mark Wielaard dcdfab
    Fix false positive with s390x cgijnl instruction testing against sign bit.
Mark Wielaard dcdfab
    
Mark Wielaard dcdfab
    https://bugs.kde.org/show_bug.cgi?id=387712
Mark Wielaard dcdfab
    
Mark Wielaard dcdfab
    When the cgij "compare immediate and branch relative" instruction
Mark Wielaard dcdfab
    compares 0 <=signed dep1, that means dep1 >=signed 0, so it is a test
Mark Wielaard dcdfab
    against the most significant bit of dep1. So only that bit needs
Mark Wielaard dcdfab
    to be defined.
Mark Wielaard dcdfab
Mark Wielaard dcdfab
diff --git a/VEX/priv/guest_s390_helpers.c b/VEX/priv/guest_s390_helpers.c
Mark Wielaard dcdfab
index 4cccdec..aacd833 100644
Mark Wielaard dcdfab
--- a/VEX/priv/guest_s390_helpers.c
Mark Wielaard dcdfab
+++ b/VEX/priv/guest_s390_helpers.c
Mark Wielaard dcdfab
@@ -1818,6 +1818,13 @@ isC64(const IRExpr *expr)
Mark Wielaard dcdfab
    return expr->tag == Iex_Const && expr->Iex.Const.con->tag == Ico_U64;
Mark Wielaard dcdfab
 }
Mark Wielaard dcdfab
 
Mark Wielaard dcdfab
+static inline Bool
Mark Wielaard dcdfab
+isC64_exactly(const IRExpr *expr, ULong n)
Mark Wielaard dcdfab
+{
Mark Wielaard dcdfab
+   return expr->tag == Iex_Const && expr->Iex.Const.con->tag == Ico_U64
Mark Wielaard dcdfab
+          && expr->Iex.Const.con->Ico.U64 == n;
Mark Wielaard dcdfab
+}
Mark Wielaard dcdfab
+
Mark Wielaard dcdfab
 
Mark Wielaard dcdfab
 /* The returned expression is NULL if no specialization was found. In that
Mark Wielaard dcdfab
    case the helper function will be called. Otherwise, the expression has
Mark Wielaard dcdfab
@@ -1895,9 +1902,25 @@ guest_s390x_spechelper(const HChar *function_name, IRExpr **args,
Mark Wielaard dcdfab
          }
Mark Wielaard dcdfab
          /* cc_dep1 > cc_dep2  ---->  cc_dep2 < cc_dep1 */
Mark Wielaard dcdfab
          if (cond == 2 || cond == 2 + 1) {
Mark Wielaard dcdfab
+            /* If we ever need the counterpart of the bug387712 fix just
Mark Wielaard dcdfab
+               below, then here is the place.  We'll need to give an
Mark Wielaard dcdfab
+               alternative expression for the case "cc_dep2 
Mark Wielaard dcdfab
+               bit of simple testing, I've yet to see any such cases,
Mark Wielaard dcdfab
+               however. */
Mark Wielaard dcdfab
             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep2, cc_dep1));
Mark Wielaard dcdfab
          }
Mark Wielaard dcdfab
          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
Mark Wielaard dcdfab
+            if (isC64_exactly(cc_dep2, 0)) {
Mark Wielaard dcdfab
+               /*     0    <=signed dep1
Mark Wielaard dcdfab
+                  --> dep1 >=signed 0
Mark Wielaard dcdfab
+                  --> m.s.bit of dep1 == 0 */
Mark Wielaard dcdfab
+               /* See bug 387712.  This is an old trick from gcc to extract
Mark Wielaard dcdfab
+                  the most significant bit of a word. */
Mark Wielaard dcdfab
+               return unop(Iop_64to32,
Mark Wielaard dcdfab
+                           binop(Iop_Xor64,
Mark Wielaard dcdfab
+                                 binop(Iop_Shr64, cc_dep1, mkU8(63)),
Mark Wielaard dcdfab
+                                 mkU64(1)));
Mark Wielaard dcdfab
+            }
Mark Wielaard dcdfab
             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep2, cc_dep1));
Mark Wielaard dcdfab
          }
Mark Wielaard dcdfab
          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {