Blame SOURCES/valgrind-3.14.0-memcheck-new-IROps.patch

cb589a
commit e221eca26be6b2396e3fcbf4117e630fc22e79f6
cb589a
Author: Julian Seward <jseward@acm.org>
cb589a
Date:   Tue Nov 20 11:28:42 2018 +0100
cb589a
cb589a
    Add Memcheck support for IROps added in 42719898.
cb589a
    
cb589a
    memcheck/mc_translate.c:
cb589a
    
cb589a
    Add mkRight{32,64} as right-travelling analogues to mkLeft{32,64}.
cb589a
    
cb589a
    doCmpORD: for the cases of a signed comparison against zero, compute
cb589a
    definedness of the 3 result bits (lt,gt,eq) separately, and, for the lt and eq
cb589a
    bits, do it exactly accurately.
cb589a
    
cb589a
    expensiveCountTrailingZeroes: no functional change.  Re-analyse/verify and add
cb589a
    comments.
cb589a
    
cb589a
    expensiveCountLeadingZeroes: add.  Very similar to
cb589a
    expensiveCountTrailingZeroes.
cb589a
    
cb589a
    Add some comments to mark unary ops which are self-shadowing.
cb589a
    
cb589a
    Route Iop_Ctz{,Nat}{32,64} through expensiveCountTrailingZeroes.
cb589a
    Route Iop_Clz{,Nat}{32,64} through expensiveCountLeadingZeroes.
cb589a
    
cb589a
    Add instrumentation for Iop_PopCount{32,64} and Iop_Reverse8sIn32_x1.
cb589a
    
cb589a
    memcheck/tests/vbit-test/irops.c
cb589a
    
cb589a
    Add dummy new entries for all new IROps, just enough to make it compile and
cb589a
    run.
cb589a
cb589a
diff --git a/memcheck/mc_translate.c b/memcheck/mc_translate.c
cb589a
index 68a2ab3..c24db91 100644
cb589a
--- a/memcheck/mc_translate.c
cb589a
+++ b/memcheck/mc_translate.c
cb589a
@@ -737,6 +737,34 @@ static IRAtom* mkLeft64 ( MCEnv* mce, IRAtom* a1 ) {
cb589a
    return assignNew('V', mce, Ity_I64, unop(Iop_Left64, a1));
cb589a
 }
cb589a
 
cb589a
+/* --------- The Right-family of operations. --------- */
cb589a
+
cb589a
+/* Unfortunately these are a lot more expensive then their Left
cb589a
+   counterparts.  Fortunately they are only very rarely used -- only for
cb589a
+   count-leading-zeroes instrumentation. */
cb589a
+
cb589a
+static IRAtom* mkRight32 ( MCEnv* mce, IRAtom* a1 )
cb589a
+{
cb589a
+   for (Int i = 1; i <= 16; i *= 2) {
cb589a
+      // a1 |= (a1 >>u i)
cb589a
+      IRAtom* tmp
cb589a
+         = assignNew('V', mce, Ity_I32, binop(Iop_Shr32, a1, mkU8(i)));
cb589a
+      a1 = assignNew('V', mce, Ity_I32, binop(Iop_Or32, a1, tmp));
cb589a
+   }
cb589a
+   return a1;
cb589a
+}
cb589a
+
cb589a
+static IRAtom* mkRight64 ( MCEnv* mce, IRAtom* a1 )
cb589a
+{
cb589a
+   for (Int i = 1; i <= 32; i *= 2) {
cb589a
+      // a1 |= (a1 >>u i)
cb589a
+      IRAtom* tmp
cb589a
+         = assignNew('V', mce, Ity_I64, binop(Iop_Shr64, a1, mkU8(i)));
cb589a
+      a1 = assignNew('V', mce, Ity_I64, binop(Iop_Or64, a1, tmp));
cb589a
+   }
cb589a
+   return a1;
cb589a
+}
cb589a
+
cb589a
 /* --------- 'Improvement' functions for AND/OR. --------- */
cb589a
 
cb589a
 /* ImproveAND(data, vbits) = data OR vbits.  Defined (0) data 0s give
cb589a
@@ -1280,20 +1308,18 @@ static IRAtom* doCmpORD ( MCEnv*  mce,
cb589a
                           IRAtom* xxhash, IRAtom* yyhash, 
cb589a
                           IRAtom* xx,     IRAtom* yy )
cb589a
 {
cb589a
-   Bool   m64    = cmp_op == Iop_CmpORD64S || cmp_op == Iop_CmpORD64U;
cb589a
-   Bool   syned  = cmp_op == Iop_CmpORD64S || cmp_op == Iop_CmpORD32S;
cb589a
-   IROp   opOR   = m64 ? Iop_Or64  : Iop_Or32;
cb589a
-   IROp   opAND  = m64 ? Iop_And64 : Iop_And32;
cb589a
-   IROp   opSHL  = m64 ? Iop_Shl64 : Iop_Shl32;
cb589a
-   IROp   opSHR  = m64 ? Iop_Shr64 : Iop_Shr32;
cb589a
-   IRType ty     = m64 ? Ity_I64   : Ity_I32;
cb589a
-   Int    width  = m64 ? 64        : 32;
cb589a
+   Bool   m64      = cmp_op == Iop_CmpORD64S || cmp_op == Iop_CmpORD64U;
cb589a
+   Bool   syned    = cmp_op == Iop_CmpORD64S || cmp_op == Iop_CmpORD32S;
cb589a
+   IROp   opOR     = m64 ? Iop_Or64   : Iop_Or32;
cb589a
+   IROp   opAND    = m64 ? Iop_And64  : Iop_And32;
cb589a
+   IROp   opSHL    = m64 ? Iop_Shl64  : Iop_Shl32;
cb589a
+   IROp   opSHR    = m64 ? Iop_Shr64  : Iop_Shr32;
cb589a
+   IROp   op1UtoWS = m64 ? Iop_1Uto64 : Iop_1Uto32;
cb589a
+   IRType ty       = m64 ? Ity_I64    : Ity_I32;
cb589a
+   Int    width    = m64 ? 64         : 32;
cb589a
 
cb589a
    Bool (*isZero)(IRAtom*) = m64 ? isZeroU64 : isZeroU32;
cb589a
 
cb589a
-   IRAtom* threeLeft1 = NULL;
cb589a
-   IRAtom* sevenLeft1 = NULL;
cb589a
-
cb589a
    tl_assert(isShadowAtom(mce,xxhash));
cb589a
    tl_assert(isShadowAtom(mce,yyhash));
cb589a
    tl_assert(isOriginalAtom(mce,xx));
cb589a
@@ -1312,30 +1338,55 @@ static IRAtom* doCmpORD ( MCEnv*  mce,
cb589a
       /* fancy interpretation */
cb589a
       /* if yy is zero, then it must be fully defined (zero#). */
cb589a
       tl_assert(isZero(yyhash));
cb589a
-      threeLeft1 = m64 ? mkU64(3<<1) : mkU32(3<<1);
cb589a
+      // This is still inaccurate, but I don't think it matters, since
cb589a
+      // nobody writes code of the form
cb589a
+      // "is <partially-undefined-value> signedly greater than zero?".
cb589a
+      // We therefore simply declare "x >s 0" to be undefined if any bit in
cb589a
+      // x is undefined.  That's clearly suboptimal in some cases.  Eg, if
cb589a
+      // the highest order bit is a defined 1 then x is negative so it
cb589a
+      // doesn't matter whether the remaining bits are defined or not.
cb589a
+      IRAtom* t_0_gt_0_0
cb589a
+         = assignNew(
cb589a
+              'V', mce,ty,
cb589a
+              binop(
cb589a
+                 opAND,
cb589a
+                 mkPCastTo(mce,ty, xxhash),
cb589a
+                 m64 ? mkU64(1<<2) : mkU32(1<<2)
cb589a
+              ));
cb589a
+      // For "x 
cb589a
+      // and we have a precise result.
cb589a
+      IRAtom* t_lt_0_0_0
cb589a
+         = assignNew(
cb589a
+              'V', mce,ty,
cb589a
+              binop(
cb589a
+                 opSHL,
cb589a
+                 assignNew(
cb589a
+                    'V', mce,ty,
cb589a
+                    binop(opSHR, xxhash, mkU8(width-1))),
cb589a
+                 mkU8(3)
cb589a
+              ));
cb589a
+      // For "x == 0" we can hand the problem off to expensiveCmpEQorNE.
cb589a
+      IRAtom* t_0_0_eq_0
cb589a
+         = assignNew(
cb589a
+              'V', mce,ty,
cb589a
+              binop(
cb589a
+                 opSHL,
cb589a
+                 assignNew('V', mce,ty,
cb589a
+                    unop(
cb589a
+                    op1UtoWS,
cb589a
+                    expensiveCmpEQorNE(mce, ty, xxhash, yyhash, xx, yy))
cb589a
+                 ),
cb589a
+                 mkU8(1)
cb589a
+              ));
cb589a
       return
cb589a
          binop(
cb589a
             opOR,
cb589a
-            assignNew(
cb589a
-               'V', mce,ty,
cb589a
-               binop(
cb589a
-                  opAND,
cb589a
-                  mkPCastTo(mce,ty, xxhash), 
cb589a
-                  threeLeft1
cb589a
-               )),
cb589a
-            assignNew(
cb589a
-               'V', mce,ty,
cb589a
-               binop(
cb589a
-                  opSHL,
cb589a
-                  assignNew(
cb589a
-                     'V', mce,ty,
cb589a
-                     binop(opSHR, xxhash, mkU8(width-1))),
cb589a
-                  mkU8(3)
cb589a
-               ))
cb589a
-	 );
cb589a
+            assignNew('V', mce,ty, binop(opOR, t_lt_0_0_0, t_0_gt_0_0)),
cb589a
+            t_0_0_eq_0
cb589a
+         );
cb589a
    } else {
cb589a
       /* standard interpretation */
cb589a
-      sevenLeft1 = m64 ? mkU64(7<<1) : mkU32(7<<1);
cb589a
+      IRAtom* sevenLeft1 = m64 ? mkU64(7<<1) : mkU32(7<<1);
cb589a
       return 
cb589a
          binop( 
cb589a
             opAND, 
cb589a
@@ -2211,14 +2262,14 @@ IRAtom* expensiveCountTrailingZeroes ( MCEnv* mce, IROp czop,
cb589a
    tl_assert(sameKindedAtoms(atom,vatom));
cb589a
 
cb589a
    switch (czop) {
cb589a
-      case Iop_Ctz32:
cb589a
+      case Iop_Ctz32: case Iop_CtzNat32:
cb589a
          ty = Ity_I32;
cb589a
          xorOp = Iop_Xor32;
cb589a
          subOp = Iop_Sub32;
cb589a
          andOp = Iop_And32;
cb589a
          one = mkU32(1);
cb589a
          break;
cb589a
-      case Iop_Ctz64:
cb589a
+      case Iop_Ctz64: case Iop_CtzNat64:
cb589a
          ty = Ity_I64;
cb589a
          xorOp = Iop_Xor64;
cb589a
          subOp = Iop_Sub64;
cb589a
@@ -2232,8 +2283,30 @@ IRAtom* expensiveCountTrailingZeroes ( MCEnv* mce, IROp czop,
cb589a
 
cb589a
    // improver = atom ^ (atom - 1)
cb589a
    //
cb589a
-   // That is, improver has its low ctz(atom) bits equal to one;
cb589a
-   // higher bits (if any) equal to zero.
cb589a
+   // That is, improver has its low ctz(atom)+1 bits equal to one;
cb589a
+   // higher bits (if any) equal to zero.  So it's exactly the right
cb589a
+   // mask to use to remove the irrelevant undefined input bits.
cb589a
+   /* Here are some examples:
cb589a
+         atom   = U...U 1 0...0
cb589a
+         atom-1 = U...U 0 1...1
cb589a
+         ^ed    = 0...0 1 11111, which correctly describes which bits of |atom|
cb589a
+                                 actually influence the result
cb589a
+      A boundary case
cb589a
+         atom   = 0...0
cb589a
+         atom-1 = 1...1
cb589a
+         ^ed    = 11111, also a correct mask for the input: all input bits
cb589a
+                         are relevant
cb589a
+      Another boundary case
cb589a
+         atom   = 1..1 1
cb589a
+         atom-1 = 1..1 0
cb589a
+         ^ed    = 0..0 1, also a correct mask: only the rightmost input bit
cb589a
+                          is relevant
cb589a
+      Now with misc U bits interspersed:
cb589a
+         atom   = U...U 1 0 U...U 0 1 0...0
cb589a
+         atom-1 = U...U 1 0 U...U 0 0 1...1
cb589a
+         ^ed    = 0...0 0 0 0...0 0 1 1...1, also correct
cb589a
+      (Per re-check/analysis of 14 Nov 2018)
cb589a
+   */
cb589a
    improver = assignNew('V', mce,ty,
cb589a
                         binop(xorOp,
cb589a
                               atom,
cb589a
@@ -2242,8 +2315,96 @@ IRAtom* expensiveCountTrailingZeroes ( MCEnv* mce, IROp czop,
cb589a
 
cb589a
    // improved = vatom & improver
cb589a
    //
cb589a
-   // That is, treat any V bits above the first ctz(atom) bits as
cb589a
-   // "defined".
cb589a
+   // That is, treat any V bits to the left of the rightmost ctz(atom)+1
cb589a
+   // bits as "defined".
cb589a
+   improved = assignNew('V', mce, ty,
cb589a
+                        binop(andOp, vatom, improver));
cb589a
+
cb589a
+   // Return pessimizing cast of improved.
cb589a
+   return mkPCastTo(mce, ty, improved);
cb589a
+}
cb589a
+
cb589a
+static
cb589a
+IRAtom* expensiveCountLeadingZeroes ( MCEnv* mce, IROp czop,
cb589a
+                                      IRAtom* atom, IRAtom* vatom )
cb589a
+{
cb589a
+   IRType ty;
cb589a
+   IROp shrOp, notOp, andOp;
cb589a
+   IRAtom* (*mkRight)(MCEnv*, IRAtom*);
cb589a
+   IRAtom *improver, *improved;
cb589a
+   tl_assert(isShadowAtom(mce,vatom));
cb589a
+   tl_assert(isOriginalAtom(mce,atom));
cb589a
+   tl_assert(sameKindedAtoms(atom,vatom));
cb589a
+
cb589a
+   switch (czop) {
cb589a
+      case Iop_Clz32: case Iop_ClzNat32:
cb589a
+         ty = Ity_I32;
cb589a
+         shrOp = Iop_Shr32;
cb589a
+         notOp = Iop_Not32;
cb589a
+         andOp = Iop_And32;
cb589a
+         mkRight = mkRight32;
cb589a
+         break;
cb589a
+      case Iop_Clz64: case Iop_ClzNat64:
cb589a
+         ty = Ity_I64;
cb589a
+         shrOp = Iop_Shr64;
cb589a
+         notOp = Iop_Not64;
cb589a
+         andOp = Iop_And64;
cb589a
+         mkRight = mkRight64;
cb589a
+         break;
cb589a
+      default:
cb589a
+         ppIROp(czop);
cb589a
+         VG_(tool_panic)("memcheck:expensiveCountLeadingZeroes");
cb589a
+   }
cb589a
+
cb589a
+   // This is in principle very similar to how expensiveCountTrailingZeroes
cb589a
+   // works.  That function computed an "improver", which it used to mask
cb589a
+   // off all but the rightmost 1-bit and the zeroes to the right of it,
cb589a
+   // hence removing irrelevant bits from the input.  Here, we play the
cb589a
+   // exact same game but with the left-vs-right roles interchanged.
cb589a
+   // Unfortunately calculation of the improver in this case is
cb589a
+   // significantly more expensive.
cb589a
+   //
cb589a
+   // improver = ~(RIGHT(atom) >>u 1)
cb589a
+   //
cb589a
+   // That is, improver has its upper clz(atom)+1 bits equal to one;
cb589a
+   // lower bits (if any) equal to zero.  So it's exactly the right
cb589a
+   // mask to use to remove the irrelevant undefined input bits.
cb589a
+   /* Here are some examples:
cb589a
+         atom             = 0...0 1 U...U
cb589a
+         R(atom)          = 0...0 1 1...1
cb589a
+         R(atom) >>u 1    = 0...0 0 1...1
cb589a
+         ~(R(atom) >>u 1) = 1...1 1 0...0
cb589a
+                            which correctly describes which bits of |atom|
cb589a
+                            actually influence the result
cb589a
+      A boundary case
cb589a
+         atom             = 0...0
cb589a
+         R(atom)          = 0...0
cb589a
+         R(atom) >>u 1    = 0...0
cb589a
+         ~(R(atom) >>u 1) = 1...1
cb589a
+                            also a correct mask for the input: all input bits
cb589a
+                            are relevant
cb589a
+      Another boundary case
cb589a
+         atom             = 1 1..1
cb589a
+         R(atom)          = 1 1..1
cb589a
+         R(atom) >>u 1    = 0 1..1
cb589a
+         ~(R(atom) >>u 1) = 1 0..0
cb589a
+                            also a correct mask: only the leftmost input bit
cb589a
+                            is relevant
cb589a
+      Now with misc U bits interspersed:
cb589a
+         atom             = 0...0 1 U...U 0 1 U...U
cb589a
+         R(atom)          = 0...0 1 1...1 1 1 1...1
cb589a
+         R(atom) >>u 1    = 0...0 0 1...1 1 1 1...1
cb589a
+         ~(R(atom) >>u 1) = 1...1 1 0...0 0 0 0...0, also correct
cb589a
+      (Per initial implementation of 15 Nov 2018)
cb589a
+   */
cb589a
+   improver = mkRight(mce, atom);
cb589a
+   improver = assignNew('V', mce, ty, binop(shrOp, improver, mkU8(1)));
cb589a
+   improver = assignNew('V', mce, ty, unop(notOp, improver));
cb589a
+
cb589a
+   // improved = vatom & improver
cb589a
+   //
cb589a
+   // That is, treat any V bits to the right of the leftmost clz(atom)+1
cb589a
+   // bits as "defined".
cb589a
    improved = assignNew('V', mce, ty,
cb589a
                         binop(andOp, vatom, improver));
cb589a
 
cb589a
@@ -4705,6 +4866,7 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
cb589a
       case Iop_RecipEst32F0x4:
cb589a
          return unary32F0x4(mce, vatom);
cb589a
 
cb589a
+      // These are self-shadowing.
cb589a
       case Iop_32UtoV128:
cb589a
       case Iop_64UtoV128:
cb589a
       case Iop_Dup8x16:
cb589a
@@ -4745,6 +4907,7 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
cb589a
       case Iop_MulI128by10Carry:
cb589a
       case Iop_F16toF64x2:
cb589a
       case Iop_F64toF16x2:
cb589a
+         // FIXME JRS 2018-Nov-15.  This is surely not correct!
cb589a
          return vatom;
cb589a
 
cb589a
       case Iop_I32StoF128: /* signed I32 -> F128 */
cb589a
@@ -4770,7 +4933,6 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
cb589a
       case Iop_RoundF64toF64_NegINF:
cb589a
       case Iop_RoundF64toF64_PosINF:
cb589a
       case Iop_RoundF64toF64_ZERO:
cb589a
-      case Iop_Clz64:
cb589a
       case Iop_D32toD64:
cb589a
       case Iop_I32StoD64:
cb589a
       case Iop_I32UtoD64:
cb589a
@@ -4785,17 +4947,32 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
cb589a
       case Iop_D64toD128:
cb589a
          return mkPCastTo(mce, Ity_I128, vatom);
cb589a
 
cb589a
-      case Iop_Clz32:
cb589a
       case Iop_TruncF64asF32:
cb589a
       case Iop_NegF32:
cb589a
       case Iop_AbsF32:
cb589a
       case Iop_F16toF32: 
cb589a
          return mkPCastTo(mce, Ity_I32, vatom);
cb589a
 
cb589a
-      case Iop_Ctz32:
cb589a
-      case Iop_Ctz64:
cb589a
+      case Iop_Ctz32: case Iop_CtzNat32:
cb589a
+      case Iop_Ctz64: case Iop_CtzNat64:
cb589a
          return expensiveCountTrailingZeroes(mce, op, atom, vatom);
cb589a
 
cb589a
+      case Iop_Clz32: case Iop_ClzNat32:
cb589a
+      case Iop_Clz64: case Iop_ClzNat64:
cb589a
+         return expensiveCountLeadingZeroes(mce, op, atom, vatom);
cb589a
+
cb589a
+      // PopCount32: this is slightly pessimistic.  It is true that the
cb589a
+      // result depends on all input bits, so that aspect of the PCast is
cb589a
+      // correct.  However, regardless of the input, only the lowest 5 bits
cb589a
+      // out of the output can ever be undefined.  So we could actually
cb589a
+      // "improve" the results here by marking the top 27 bits of output as
cb589a
+      // defined.  A similar comment applies for PopCount64.
cb589a
+      case Iop_PopCount32:
cb589a
+         return mkPCastTo(mce, Ity_I32, vatom);
cb589a
+      case Iop_PopCount64:
cb589a
+         return mkPCastTo(mce, Ity_I64, vatom);
cb589a
+
cb589a
+      // These are self-shadowing.
cb589a
       case Iop_1Uto64:
cb589a
       case Iop_1Sto64:
cb589a
       case Iop_8Uto64:
cb589a
@@ -4821,6 +4998,7 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
cb589a
       case Iop_V256to64_2: case Iop_V256to64_3:
cb589a
          return assignNew('V', mce, Ity_I64, unop(op, vatom));
cb589a
 
cb589a
+      // These are self-shadowing.
cb589a
       case Iop_64to32:
cb589a
       case Iop_64HIto32:
cb589a
       case Iop_1Uto32:
cb589a
@@ -4830,8 +5008,10 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
cb589a
       case Iop_16Sto32:
cb589a
       case Iop_8Sto32:
cb589a
       case Iop_V128to32:
cb589a
+      case Iop_Reverse8sIn32_x1:
cb589a
          return assignNew('V', mce, Ity_I32, unop(op, vatom));
cb589a
 
cb589a
+      // These are self-shadowing.
cb589a
       case Iop_8Sto16:
cb589a
       case Iop_8Uto16:
cb589a
       case Iop_32to16:
cb589a
@@ -4840,6 +5020,7 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
cb589a
       case Iop_GetMSBs8x16:
cb589a
          return assignNew('V', mce, Ity_I16, unop(op, vatom));
cb589a
 
cb589a
+      // These are self-shadowing.
cb589a
       case Iop_1Uto8:
cb589a
       case Iop_1Sto8:
cb589a
       case Iop_16to8:
cb589a
@@ -4868,6 +5049,7 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
cb589a
       case Iop_Not16:
cb589a
       case Iop_Not8:
cb589a
       case Iop_Not1:
cb589a
+         // FIXME JRS 2018-Nov-15.  This is surely not correct!
cb589a
          return vatom;
cb589a
 
cb589a
       case Iop_CmpNEZ8x8:
cb589a
@@ -4929,6 +5111,7 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
cb589a
       case Iop_Ctz64x2:
cb589a
          return mkPCast64x2(mce, vatom);
cb589a
 
cb589a
+      // This is self-shadowing.
cb589a
       case Iop_PwBitMtxXpose64x2:
cb589a
          return assignNew('V', mce, Ity_V128, unop(op, vatom));
cb589a
 
cb589a
diff --git a/memcheck/tests/vbit-test/irops.c b/memcheck/tests/vbit-test/irops.c
cb589a
index bfd82fc..e8bf67d 100644
cb589a
--- a/memcheck/tests/vbit-test/irops.c
cb589a
+++ b/memcheck/tests/vbit-test/irops.c
cb589a
@@ -111,6 +111,12 @@ static irop_t irops[] = {
cb589a
   { DEFOP(Iop_Clz32,      UNDEF_ALL),  .s390x = 0, .amd64 = 0, .x86 = 1, .arm = 1, .ppc64 = 1, .ppc32 = 1, .mips32 =1, .mips64 = 1 },
cb589a
   { DEFOP(Iop_Ctz64,      UNDEF_ALL),  .s390x = 0, .amd64 = 1, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 =0, .mips64 = 0 },
cb589a
   { DEFOP(Iop_Ctz32,      UNDEF_ALL),  .s390x = 0, .amd64 = 0, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 =0, .mips64 = 0 },
cb589a
+  { DEFOP(Iop_ClzNat64,   UNDEF_ALL),  .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 0, .mips32 =0, .mips64 = 0 }, // ppc32 asserts
cb589a
+  { DEFOP(Iop_ClzNat32,   UNDEF_ALL),  .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 =0, .mips64 = 0 },
cb589a
+  { DEFOP(Iop_CtzNat64,   UNDEF_ALL),  .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 0, .mips32 =0, .mips64 = 0 },
cb589a
+  { DEFOP(Iop_CtzNat32,   UNDEF_ALL),  .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 1, .mips32 =0, .mips64 = 0 },
cb589a
+  { DEFOP(Iop_PopCount64, UNDEF_ALL),  .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 0, .mips32 =0, .mips64 = 0 },
cb589a
+  { DEFOP(Iop_PopCount32, UNDEF_ALL),  .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 =0, .mips64 = 0 },
cb589a
   { DEFOP(Iop_CmpLT32S,   UNDEF_ALL),  .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 1, .ppc64 = 1, .ppc32 = 1, .mips32 =1, .mips64 = 1 },
cb589a
   { DEFOP(Iop_CmpLT64S,   UNDEF_ALL),  .s390x = 1, .amd64 = 1, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 =0, .mips64 = 1 }, // ppc, mips assert
cb589a
   { DEFOP(Iop_CmpLE32S,   UNDEF_ALL),  .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 1, .ppc64 = 1, .ppc32 = 1, .mips32 =1, .mips64 = 1 },
cb589a
@@ -336,6 +342,7 @@ static irop_t irops[] = {
cb589a
   { DEFOP(Iop_Sad8Ux4, UNDEF_UNKNOWN), },
cb589a
   { DEFOP(Iop_CmpNEZ16x2, UNDEF_UNKNOWN), },
cb589a
   { DEFOP(Iop_CmpNEZ8x4, UNDEF_UNKNOWN), },
cb589a
+  { DEFOP(Iop_Reverse8sIn32_x1, UNDEF_UNKNOWN) },
cb589a
   /* ------------------ 64-bit SIMD FP ------------------------ */
cb589a
   { DEFOP(Iop_I32UtoFx2, UNDEF_UNKNOWN), },
cb589a
   { DEFOP(Iop_I32StoFx2, UNDEF_UNKNOWN), },