]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
amd64 and x86 front ends: add a few more spec rules.
authorJulian Seward <jseward@acm.org>
Wed, 4 Jan 2023 16:04:03 +0000 (17:04 +0100)
committerJulian Seward <jseward@acm.org>
Wed, 4 Jan 2023 16:06:01 +0000 (17:06 +0100)
amd64:
  S and NS  after LOGICQ (per comments from Eyal Soha on the dev list)
  S         after SHLQ
  NZ        after SHLL

x86:
  NZ        after SHRL
  Z         after SHLL

I would have liked to have added the inverse conditions in all cases (eg, both
S and NS, or both Z and NZ), but finding use cases for some of these is almost
impossible, hence they are sometimes omitted.  All of the added cases have
been tested.

VEX/priv/guest_amd64_helpers.c
VEX/priv/guest_x86_helpers.c

index abd2a1e370cf89bd48c6cd29cc907c3b1c2636df..42ec80e0369a82e1487b77377eaf090414c0aa4e 100644 (file)
@@ -1684,6 +1684,19 @@ IRExpr* guest_amd64_spechelper ( const HChar* function_name,
                            mkU64(0)));
       }
 
+      // Verified
+      if (isU64(cc_op, AMD64G_CC_OP_LOGICQ) && isU64(cond, AMD64CondS)) {
+         /* long long and/or/xor, then S --> (ULong)result[63] */
+         return binop(Iop_Shr64, cc_dep1, mkU8(63));
+      }
+      // Verified
+      if (isU64(cc_op, AMD64G_CC_OP_LOGICQ) && isU64(cond, AMD64CondNS)) {
+         /* long long and/or/xor, then S --> (ULong) ~ result[63] */
+         return binop(Iop_Xor64,
+                      binop(Iop_Shr64, cc_dep1, mkU8(63)),
+                      mkU64(1));
+      }
+
       /*---------------- LOGICL ----------------*/
 
       if (isU64(cc_op, AMD64G_CC_OP_LOGICL) && isU64(cond, AMD64CondZ)) {
@@ -1932,10 +1945,12 @@ IRExpr* guest_amd64_spechelper ( const HChar* function_name,
                      binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
       }
 
-      //if (isU64(cc_op, AMD64G_CC_OP_SHLQ) && isU64(cond, AMD64CondS)) {
-      //   /* SHLQ, then S --> (ULong)result[63] */
-      //   vassert(0);
-      //}
+      // Verified
+      if (isU64(cc_op, AMD64G_CC_OP_SHLQ) && isU64(cond, AMD64CondS)) {
+         /* SHLQ, then S --> (ULong)result[63] */
+         return binop(Iop_Shr64, cc_dep1, mkU8(63));
+      }
+      // No known test case
       //if (isU64(cc_op, AMD64G_CC_OP_SHLQ) && isU64(cond, AMD64CondNS)) {
       //   /* SHLQ, then NS --> (ULong) ~ result[63] */
       //   vassert(0);
@@ -1949,10 +1964,13 @@ IRExpr* guest_amd64_spechelper ( const HChar* function_name,
                      binop(Iop_CmpEQ32, unop(Iop_64to32, cc_dep1),
                            mkU32(0)));
       }
-      //if (isU64(cc_op, AMD64G_CC_OP_SHLL) && isU64(cond, AMD64CondNZ)) {
-      //   /* SHLL, then NZ --> test dep1 != 0 */
-      //   vassert(0);
-      //}
+      // Verified
+      if (isU64(cc_op, AMD64G_CC_OP_SHLL) && isU64(cond, AMD64CondNZ)) {
+         /* SHLL, then NZ --> test dep1 != 0 */
+         return unop(Iop_1Uto64,
+                     binop(Iop_CmpNE32, unop(Iop_64to32, cc_dep1),
+                           mkU32(0)));
+      }
 
       if (isU64(cc_op, AMD64G_CC_OP_SHLL) && isU64(cond, AMD64CondS)) {
          /* SHLL, then S --> (ULong)result[31] */
@@ -1960,6 +1978,7 @@ IRExpr* guest_amd64_spechelper ( const HChar* function_name,
                       binop(Iop_Shr64, cc_dep1, mkU8(31)),
                       mkU64(1));
       }
+      // No known test case
       //if (isU64(cc_op, AMD64G_CC_OP_SHLL) && isU64(cond, AMD64CondNS)) {
       //   /* SHLL, then NS --> (ULong) ~ result[31] */
       //   vassert(0);
index 7b229cb79593d530a9a1cb96242262cdf94e4920..a1d086369d17ac7b367291efdcb0973a04e8dbea 100644 (file)
@@ -1203,9 +1203,24 @@ IRExpr* guest_x86_spechelper ( const HChar* function_name,
       /*---------------- SHRL ----------------*/
 
       if (isU32(cc_op, X86G_CC_OP_SHRL) && isU32(cond, X86CondZ)) {
-         /* SHRL, then Z --> test dep1 == 0 */
+         /* SHRL, then Z --> test dep1(result) == 0 */
          return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
       }
+      if (isU32(cc_op, X86G_CC_OP_SHRL) && isU32(cond, X86CondNZ)) {
+         /* SHRL, then NZ --> test dep1(result) != 0 */
+         return unop(Iop_1Uto32,binop(Iop_CmpNE32, cc_dep1, mkU32(0)));
+      }
+
+      /*---------------- SHLL ----------------*/
+
+      if (isU32(cc_op, X86G_CC_OP_SHLL) && isU32(cond, X86CondZ)) {
+         /* SHLL, then Z --> test dep1(result) == 0 */
+         return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
+      }
+      //if (isU32(cc_op, X86G_CC_OP_SHLL) && isU32(cond, X86CondNZ)) {
+      //   /* SHLL, then NZ --> test dep1(result) != 0 */
+      //   vassert(0); // No test case yet observed
+      //}
 
       /*---------------- COPY ----------------*/
       /* This can happen, as a result of x87 FP compares: "fcom ... ;