]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Powerpc, re-implement the vbpermq instruction support
authorCarl Love <cel@us.ibm.com>
Wed, 23 Mar 2022 18:41:16 +0000 (13:41 -0500)
committerCarl Love <cel@us.ibm.com>
Fri, 25 Mar 2022 15:11:51 +0000 (15:11 +0000)
The instruction support generates too many Iops when multiple vbpermq
instructions occur together in the binary. This patch changes the
implementation to use a clean helper and thus avoid overflowing the
internal Valgrind buffer.

bugzilla 451827

NEWS
VEX/priv/guest_ppc_defs.h
VEX/priv/guest_ppc_helpers.c
VEX/priv/guest_ppc_toIR.c

diff --git a/NEWS b/NEWS
index 404467180ed7cd7ee4e94d1fcc125b1cdaf42e3f..709f287842ccbc333beb334281e926fccb29fe95 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -72,6 +72,7 @@ are not entered into bugzilla tend to get forgotten about or ignored.
         registers.
 450536  Powerpc: valgrind throws 'facility scv unavailable exception'
 451626  Syscall param bpf(attr->raw_tracepoint.name) points to unaddressable byte(s)
+451827  [ppc64le] VEX temporary storage exhausted with several vbpermq instructions
 
 To see details of a given bug, visit
   https://bugs.kde.org/show_bug.cgi?id=XXXXXX
index 93ada1ba988cb52a31e2e0ebe0fd4bb2ff238005..e79b86cd76ca8d7d3b4428740527f1a90c3c7c25 100644 (file)
@@ -164,6 +164,8 @@ extern UInt count_bits_under_mask_helper( ULong src, ULong mask,
                                           UInt flag );
 extern ULong deposit_bits_under_mask_helper( ULong src, ULong mask );
 extern ULong population_count64_helper( ULong src );
+extern ULong vbpermq_clean_helper( ULong vA_high, ULong vA_low,
+                                   ULong vB_high, ULong vB_low );
 extern ULong vector_evaluate64_helper( ULong srcA, ULong srcB, ULong srcC,
                                        ULong IMM );
 void write_ACC_entry (VexGuestPPC64State* gst, UInt offset, UInt acc,
index 0ae3a5aa17eb76cbf16fe0455b13da9e533ce4dd..a6f63f5d26f425338f9bc7be33dd18c7ac49470b 100644 (file)
@@ -701,6 +701,36 @@ ULong vector_evaluate64_helper( ULong srcA, ULong srcB, ULong srcC,
 #undef MAX_IMM_BITS
 }
 
+/*---------------------------------------------------------------*/
+/* --- Clean helper for vbpermq instruction                   ---*/
+/*---------------------------------------------------------------*/
+ULong vbpermq_clean_helper( ULong vA_high, ULong vA_low,
+                            ULong vB_high, ULong vB_low) {
+   ULong bit, result = 0x0;
+   UInt i, index;
+
+   /* IBM numbering bit 0 on is MSB, bit 63 is LSB */
+   for ( i = 0; i < 16; i++) {
+      if (i < 8)
+         index = 0xFFULL & (vB_high >> (56 - 8*i) );
+      else
+         index = 0xFFULL & (vB_low  >> (56 - 8*(i-8)));
+
+      if (index < 64) {
+         bit = 0x1 & (vA_high >> (63 - index));
+
+      } else if (index < 128) {
+         bit = 0x1 & (vA_low >> (127 - index));
+
+      } else
+         bit = 0;
+
+      result |= bit << (15 - i);
+   }
+   return result;
+}
+
+
 /*--------------------------------------------------*/
 /*---- VSX Vector Generate PCV from Mask helpers ---*/
 /*--------------------------------------------------*/
index e340562bf04bf9edfb86ad2fe478e815f0704e52..94bf79872609e3b433788f73ac8fc10d26c49077 100644 (file)
@@ -31771,7 +31771,7 @@ static Bool dis_VSR_byte_mask ( UInt prefix, UInt theInstr,
    }
 }
 
-static Bool dis_av_quad ( UInt prefix, UInt theInstr )
+static Bool dis_av_quad ( UInt prefix, UInt theInstr, const VexAbiInfo* vbi )
 {
    /* VX-Form */
    UChar opc1     = ifieldOPC(theInstr);
@@ -31828,71 +31828,27 @@ static Bool dis_av_quad ( UInt prefix, UInt theInstr )
       return True;
    case 0x054C: // vbpermq
    {
-#define BPERMD_IDX_MASK 0x00000000000000FFULL
-#define BPERMD_BIT_MASK 0x8000000000000000ULL
-      int i;
-      IRExpr * vB_expr = mkexpr(vB);
-      IRExpr * res = binop(Iop_AndV128, mkV128(0), mkV128(0));
-      DIP("vbpermq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
-      for (i = 0; i < 16; i++) {
-         IRTemp idx_tmp = newTemp( Ity_V128 );
-         IRTemp perm_bit = newTemp( Ity_V128 );
-         IRTemp idx = newTemp( Ity_I8 );
-         IRTemp idx_LT127 = newTemp( Ity_I1 );
-         IRTemp idx_LT127_ity128 = newTemp( Ity_V128 );
-
-         assign( idx_tmp,
-                 binop( Iop_AndV128,
-                        binop( Iop_64HLtoV128,
-                               mkU64(0),
-                               mkU64(BPERMD_IDX_MASK) ),
-                        vB_expr ) );
-         assign( idx_LT127,
-                 binop( Iop_CmpEQ32,
-                        unop ( Iop_64to32,
-                               unop( Iop_V128to64, binop( Iop_ShrV128,
-                                                          mkexpr(idx_tmp),
-                                                          mkU8(7) ) ) ),
-                        mkU32(0) ) );
-
-         /* Below, we set idx to determine which bit of vA to use for the
-          * perm bit.  If idx_LT127 is 0, the perm bit is forced to '0'.
-          */
-         assign( idx,
-                 binop( Iop_And8,
-                        unop( Iop_1Sto8,
-                              mkexpr(idx_LT127) ),
-                        unop( Iop_32to8,
-                              unop( Iop_V128to32, mkexpr( idx_tmp ) ) ) ) );
+      /* The original supports was done with Iops but it caused the internal
+         temorary storage to be exhausted if there were three or more vbpermq
+         instructions in a row. Changed to a clean helper on 3/24/2022  */
+      IRTemp res_hi = newTemp( Ity_I64 );
+      IRExpr * res_low = mkU64(0);
+      assign( res_hi,
+              mkIRExprCCall( Ity_I64, 0 /*regparms*/,
+                             "vbpermq_clean_helper",
+                             fnptr_to_fnentry( vbi,
+                                               &vbpermq_clean_helper ),
+                             mkIRExprVec_4( unop( Iop_V128HIto64,
+                                                  mkexpr(vA) ),
+                                            unop( Iop_V128to64,
+                                                  mkexpr(vA) ),
+                                            unop( Iop_V128HIto64,
+                                                  mkexpr(vB) ),
+                                            unop( Iop_V128to64,
+                                                  mkexpr(vB) ) ) ) );
 
-         assign( idx_LT127_ity128,
-                 binop( Iop_64HLtoV128,
-                        mkU64(0),
-                        unop( Iop_32Uto64,
-                              unop( Iop_1Uto32, mkexpr(idx_LT127 ) ) ) ) );
-         assign( perm_bit,
-                 binop( Iop_AndV128,
-                        mkexpr( idx_LT127_ity128 ),
-                        binop( Iop_ShrV128,
-                               binop( Iop_AndV128,
-                                      binop (Iop_64HLtoV128,
-                                             mkU64( BPERMD_BIT_MASK ),
-                                             mkU64(0)),
-                                      binop( Iop_ShlV128,
-                                             mkexpr( vA ),
-                                             mkexpr( idx ) ) ),
-                               mkU8( 127 ) ) ) );
-         res = binop( Iop_OrV128,
-                      res,
-                      binop( Iop_ShlV128,
-                             mkexpr( perm_bit ),
-                             mkU8( i + 64 ) ) );
-         vB_expr = binop( Iop_ShrV128, vB_expr, mkU8( 8 ) );
-      }
-      putVReg( vRT_addr, res);
+      putVReg( vRT_addr, binop( Iop_64HLtoV128, mkexpr( res_hi ), res_low ) );
       return True;
-#undef BPERMD_IDX_MASK
-#undef BPERMD_BIT_MASK
    }
 
    default:
@@ -37680,7 +37636,7 @@ DisResult disInstr_PPC_WRK (
       case 0x3D: case 0x3C:            // vaddecuq, vaddeuqm
       case 0x3F: case 0x3E:            // vsubecuq, vsubeuqm
          if (!allow_V) goto decode_noV;
-         if (dis_av_quad( prefix, theInstr)) goto decode_success;
+         if (dis_av_quad( prefix, theInstr, abiinfo)) goto decode_success;
          goto decode_failure;
 
       default:
@@ -38026,7 +37982,7 @@ DisResult disInstr_PPC_WRK (
       case 0x540: case 0x500:             // vsubcuq, vsubuqm
       case 0x54C:                         // vbpermq
          if (!allow_V) goto decode_noV;
-         if (dis_av_quad( prefix, theInstr)) goto decode_success;
+         if (dis_av_quad( prefix, theInstr, abiinfo)) goto decode_success;
          goto decode_failure;
 
       default: