diff --git a/valgrind-3.11.0-ppc-bcd-addsub.patch b/valgrind-3.11.0-ppc-bcd-addsub.patch
new file mode 100644
index 0000000..04f45f6
--- /dev/null
+++ b/valgrind-3.11.0-ppc-bcd-addsub.patch
@@ -0,0 +1,383 @@
+Fix without v-bit test program changes which changed too much since 3.11.0.
+
+commit 568f3ab3f7a4c074fe9ce6f4f395fb25b6fa375b
+Author: carll <carll@8f6e269a-dfd6-0310-a8e1-e2731360e62c>
+Date:   Tue Apr 26 19:52:56 2016 +0000
+
+    Power PC  Fix V bit error in 128-bit BCD add and subtract instructions
+    
+    The original code was using the bcdadd / bcdsub instruction on the operand
+    shadow bits to calculate the shadow bits for the result.  This introduced
+    non-zero bits shadow bits in the result.   The shadow bits for these
+    instructions should be set to all valid or all invalid.  If one of the
+    argument shadow bits was one, then all of the shadow bits of the result should
+    be one.  Otherwise the result shadow bits should be zero.
+    
+    This patch fixes the above bug in memcheck/mc_translate.c
+    
+    Fixing the above bug broke the v-bit test.  The issue is the v-bit tester
+    assumes the shadow bits for the operands of a given Iop can be set to one
+    for testing purposes.  The implementation of the bcdadd and bcdsub was passing
+    a constant value for the variable ps.  The ps value is an argument to the
+    instruction that specifies how to set the sign code of the result.  The
+    implementation of the instructions was changed to issue the instruction with
+    ps=0.  Then the result of the instruction is updated in the VEX code if ps=1.
+    This changed also results in cleaning up the vbit test code.
+    
+    This patch also fixes the issues with the v-bit test program.
+    
+    Bugzilla 360035
+    
+    
+    git-svn-id: svn://svn.valgrind.org/vex/trunk@3218 8f6e269a-dfd6-0310-a8e1-e2731360e62c
+
+diff --git a/VEX/priv/guest_ppc_toIR.c b/VEX/priv/guest_ppc_toIR.c
+index 034a766..44304df 100644
+--- a/VEX/priv/guest_ppc_toIR.c
++++ b/VEX/priv/guest_ppc_toIR.c
+@@ -21297,6 +21297,43 @@ static Bool dis_av_quad ( UInt theInstr )
+    return True;
+ }
+ 
++static IRExpr * bcd_sign_code_adjust( UInt ps, IRExpr * tmp)
++{
++   /* The Iop_BCDAdd and Iop_BCDSub will result in the corresponding Power PC
++    * instruction being issued with ps = 0.  If ps = 1, the sign code, which
++    * is in the least significant four bits of the result, needs to be updated
++    * per the ISA:
++    *
++    *    If PS=0, the sign code of the result is set to 0b1100.
++    *    If PS=1, the sign code of the result is set to 0b1111.
++    *
++    * Note, the ps value is NOT being passed down to the instruction issue
++    * because passing a constant via triop() breaks the vbit-test test.  The
++    * vbit-tester assumes it can set non-zero shadow bits for the triop()
++    * arguments.  Thus they have to be expressions not a constant.
++    */
++   IRTemp mask  = newTemp(Ity_I64);
++   IRExpr *rtn;
++
++   if ( ps == 0 ) {
++      /* sign code is correct, just return it.  */
++      rtn = tmp;
++
++   } else {
++      /* check if lower four bits are 0b1100, if so, change to 0b1111 */
++      assign( mask, unop( Iop_1Sto64,
++                          binop( Iop_CmpEQ64, mkU64( 0xC ),
++                                 binop( Iop_And64, mkU64( 0xF ),
++                                        unop( Iop_V128to64, tmp ) ) ) ) );
++      rtn = binop( Iop_64HLtoV128,
++                   unop( Iop_V128HIto64, tmp ),
++                   binop( Iop_Or64,
++                          binop( Iop_And64, mkU64( 0xF ), mkexpr( mask ) ),
++                          unop( Iop_V128to64, tmp ) ) );
++   }
++
++   return rtn;
++}
+ 
+ /*
+   AltiVec BCD Arithmetic instructions.
+@@ -21329,15 +21366,19 @@ static Bool dis_av_bcd ( UInt theInstr )
+    switch (opc2) {
+    case 0x1:  // bcdadd
+      DIP("bcdadd. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
+-     assign( dst, triop( Iop_BCDAdd, mkexpr( vA ),
+-                         mkexpr( vB ), mkU8( ps ) ) );
++     assign( dst, bcd_sign_code_adjust( ps,
++                                        binop( Iop_BCDAdd,
++                                               mkexpr( vA ),
++                                               mkexpr( vB ) ) ) );
+      putVReg( vRT_addr, mkexpr(dst));
+      return True;
+ 
+    case 0x41:  // bcdsub
+      DIP("bcdsub. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
+-     assign( dst, triop( Iop_BCDSub, mkexpr( vA ),
+-                         mkexpr( vB ), mkU8( ps ) ) );
++     assign( dst, bcd_sign_code_adjust( ps,
++                                        binop( Iop_BCDSub,
++                                               mkexpr( vA ),
++                                               mkexpr( vB ) ) ) );
+      putVReg( vRT_addr, mkexpr(dst));
+      return True;
+ 
+diff --git a/VEX/priv/host_ppc_defs.c b/VEX/priv/host_ppc_defs.c
+index 13b193c..06487b5 100644
+--- a/VEX/priv/host_ppc_defs.c
++++ b/VEX/priv/host_ppc_defs.c
+@@ -1415,15 +1415,14 @@ PPCInstr* PPCInstr_AvHashV128Binary ( PPCAvOp op, HReg dst,
+    i->Pin.AvHashV128Binary.s_field = s_field;
+    return i;
+ }
+-PPCInstr* PPCInstr_AvBCDV128Trinary ( PPCAvOp op, HReg dst,
+-                                      HReg src1, HReg src2, PPCRI* ps ) {
++PPCInstr* PPCInstr_AvBCDV128Binary ( PPCAvOp op, HReg dst,
++                                     HReg src1, HReg src2 ) {
+    PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
+-   i->tag      = Pin_AvBCDV128Trinary;
+-   i->Pin.AvBCDV128Trinary.op   = op;
+-   i->Pin.AvBCDV128Trinary.dst  = dst;
+-   i->Pin.AvBCDV128Trinary.src1 = src1;
+-   i->Pin.AvBCDV128Trinary.src2 = src2;
+-   i->Pin.AvBCDV128Trinary.ps   = ps;
++   i->tag      = Pin_AvBCDV128Binary;
++   i->Pin.AvBCDV128Binary.op   = op;
++   i->Pin.AvBCDV128Binary.dst  = dst;
++   i->Pin.AvBCDV128Binary.src1 = src1;
++   i->Pin.AvBCDV128Binary.src2 = src2;
+    return i;
+ }
+ 
+@@ -2038,15 +2037,13 @@ void ppPPCInstr ( const PPCInstr* i, Bool mode64 )
+       ppPPCRI(i->Pin.AvHashV128Binary.s_field);
+       return;
+ 
+-   case Pin_AvBCDV128Trinary:
+-      vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvBCDV128Trinary.op));
+-      ppHRegPPC(i->Pin.AvBCDV128Trinary.dst);
++   case Pin_AvBCDV128Binary:
++      vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvBCDV128Binary.op));
++      ppHRegPPC(i->Pin.AvBCDV128Binary.dst);
+       vex_printf(",");
+-      ppHRegPPC(i->Pin.AvBCDV128Trinary.src1);
++      ppHRegPPC(i->Pin.AvBCDV128Binary.src1);
+       vex_printf(",");
+-      ppHRegPPC(i->Pin.AvBCDV128Trinary.src2);
+-      vex_printf(",");
+-      ppPPCRI(i->Pin.AvBCDV128Trinary.ps);
++      ppHRegPPC(i->Pin.AvBCDV128Binary.src2);
+       return;
+ 
+    case Pin_Dfp64Unary:
+@@ -2511,11 +2508,10 @@ void getRegUsage_PPCInstr ( HRegUsage* u, const PPCInstr* i, Bool mode64 )
+       addHRegUse(u, HRmRead,  i->Pin.AvHashV128Binary.src);
+       addRegUsage_PPCRI(u,    i->Pin.AvHashV128Binary.s_field);
+       return;
+-   case Pin_AvBCDV128Trinary:
+-      addHRegUse(u, HRmWrite, i->Pin.AvBCDV128Trinary.dst);
+-      addHRegUse(u, HRmRead,  i->Pin.AvBCDV128Trinary.src1);
+-      addHRegUse(u, HRmRead,  i->Pin.AvBCDV128Trinary.src2);
+-      addRegUsage_PPCRI(u,    i->Pin.AvBCDV128Trinary.ps);
++   case Pin_AvBCDV128Binary:
++      addHRegUse(u, HRmWrite, i->Pin.AvBCDV128Binary.dst);
++      addHRegUse(u, HRmRead,  i->Pin.AvBCDV128Binary.src1);
++      addHRegUse(u, HRmRead,  i->Pin.AvBCDV128Binary.src2);
+       return;
+    case Pin_Dfp64Unary:
+       addHRegUse(u, HRmWrite, i->Pin.Dfp64Unary.dst);
+@@ -2844,11 +2840,10 @@ void mapRegs_PPCInstr ( HRegRemap* m, PPCInstr* i, Bool mode64 )
+       mapReg(m, &i->Pin.AvHashV128Binary.dst);
+       mapReg(m, &i->Pin.AvHashV128Binary.src);
+       return;
+-   case Pin_AvBCDV128Trinary:
+-      mapReg(m, &i->Pin.AvBCDV128Trinary.dst);
+-      mapReg(m, &i->Pin.AvBCDV128Trinary.src1);
+-      mapReg(m, &i->Pin.AvBCDV128Trinary.src2);
+-      mapRegs_PPCRI(m, i->Pin.AvBCDV128Trinary.ps);
++   case Pin_AvBCDV128Binary:
++      mapReg(m, &i->Pin.AvBCDV128Binary.dst);
++      mapReg(m, &i->Pin.AvBCDV128Binary.src1);
++      mapReg(m, &i->Pin.AvBCDV128Binary.src2);
+       return;
+    case Pin_Dfp64Unary:
+       mapReg(m, &i->Pin.Dfp64Unary.dst);
+@@ -5104,20 +5099,22 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
+       p = mkFormVX( p, 4, v_dst, v_src, s_field->Pri.Imm, opc2, endness_host );
+       goto done;
+    }
+-   case Pin_AvBCDV128Trinary: {
+-      UInt v_dst  = vregEnc(i->Pin.AvBCDV128Trinary.dst);
+-      UInt v_src1 = vregEnc(i->Pin.AvBCDV128Trinary.src1);
+-      UInt v_src2 = vregEnc(i->Pin.AvBCDV128Trinary.src2);
+-      PPCRI* ps   = i->Pin.AvBCDV128Trinary.ps;
++   case Pin_AvBCDV128Binary: {
++      UInt v_dst  = vregEnc(i->Pin.AvBCDV128Binary.dst);
++      UInt v_src1 = vregEnc(i->Pin.AvBCDV128Binary.src1);
++      UInt v_src2 = vregEnc(i->Pin.AvBCDV128Binary.src2);
++      UInt ps = 0;    /* Issue the instruction with ps=0.  The IR code will
++                       * fix up the result if ps=1.
++                       */
+       UInt opc2;
+-      switch (i->Pin.AvBCDV128Trinary.op) {
++      switch (i->Pin.AvBCDV128Binary.op) {
+       case Pav_BCDAdd:   opc2 =  1; break; // bcdadd
+       case Pav_BCDSub:   opc2 = 65; break; // bcdsub
+       default:
+          goto bad;
+       }
+       p = mkFormVXR( p, 4, v_dst, v_src1, v_src2,
+-                     0x1, (ps->Pri.Imm << 9) | opc2, endness_host );
++                     0x1, ps | opc2, endness_host );
+       goto done;
+    }
+    case Pin_AvBin32Fx4: {
+diff --git a/VEX/priv/host_ppc_defs.h b/VEX/priv/host_ppc_defs.h
+index c04c994..0b1939d 100644
+--- a/VEX/priv/host_ppc_defs.h
++++ b/VEX/priv/host_ppc_defs.h
+@@ -499,7 +499,7 @@ typedef
+       Pin_AvCipherV128Unary,  /* AV Vector unary Cipher */
+       Pin_AvCipherV128Binary, /* AV Vector binary Cipher */
+       Pin_AvHashV128Binary, /* AV Vector binary Hash */
+-      Pin_AvBCDV128Trinary, /* BCD Arithmetic */
++      Pin_AvBCDV128Binary,  /* BCD Arithmetic */
+       Pin_Dfp64Unary,   /* DFP64  unary op */
+       Pin_Dfp128Unary,  /* DFP128 unary op */
+       Pin_DfpShift,     /* Decimal floating point shift by immediate value */
+@@ -867,8 +867,7 @@ typedef
+             HReg       dst;
+             HReg      src1;
+             HReg      src2;
+-            PPCRI*      ps;
+-         } AvBCDV128Trinary;
++         } AvBCDV128Binary;
+          struct {
+             PPCAvOp   op;
+             HReg      dst;
+@@ -1063,9 +1062,8 @@ extern PPCInstr* PPCInstr_AvCipherV128Binary ( PPCAvOp op, HReg dst,
+                                                HReg srcL, HReg srcR );
+ extern PPCInstr* PPCInstr_AvHashV128Binary ( PPCAvOp op, HReg dst,
+                                              HReg src, PPCRI* s_field );
+-extern PPCInstr* PPCInstr_AvBCDV128Trinary ( PPCAvOp op, HReg dst,
+-                                             HReg src1, HReg src2,
+-                                             PPCRI* ps );
++extern PPCInstr* PPCInstr_AvBCDV128Binary ( PPCAvOp op, HReg dst,
++                                            HReg src1, HReg src2 );
+ extern PPCInstr* PPCInstr_Dfp64Unary  ( PPCFpOp op, HReg dst, HReg src );
+ extern PPCInstr* PPCInstr_Dfp64Binary ( PPCFpOp op, HReg dst, HReg srcL,
+                                         HReg srcR );
+diff --git a/VEX/priv/host_ppc_isel.c b/VEX/priv/host_ppc_isel.c
+index 11a9943..5a701ed 100644
+--- a/VEX/priv/host_ppc_isel.c
++++ b/VEX/priv/host_ppc_isel.c
+@@ -5392,25 +5392,25 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e, IREndness IEndianess )
+          addInstr(env, PPCInstr_AvHashV128Binary(op, dst, arg1, s_field));
+          return dst;
+       }
+-      default:
+-         break;
+-      } /* switch (e->Iex.Binop.op) */
+-   } /* if (e->tag == Iex_Binop) */
+ 
+-   if (e->tag == Iex_Triop) {
+-      IRTriop *triop = e->Iex.Triop.details;
+-      switch (triop->op) {
+       case Iop_BCDAdd:op = Pav_BCDAdd; goto do_AvBCDV128;
+       case Iop_BCDSub:op = Pav_BCDSub; goto do_AvBCDV128;
+       do_AvBCDV128: {
+-         HReg arg1 = iselVecExpr(env, triop->arg1, IEndianess);
+-         HReg arg2 = iselVecExpr(env, triop->arg2, IEndianess);
++         HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
++         HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
+          HReg dst  = newVRegV(env);
+-         PPCRI* ps = iselWordExpr_RI(env, triop->arg3, IEndianess);
+-         addInstr(env, PPCInstr_AvBCDV128Trinary(op, dst, arg1, arg2, ps));
++         addInstr(env, PPCInstr_AvBCDV128Binary(op, dst, arg1, arg2));
+          return dst;
+       }
+ 
++      default:
++         break;
++      } /* switch (e->Iex.Binop.op) */
++   } /* if (e->tag == Iex_Binop) */
++
++   if (e->tag == Iex_Triop) {
++      IRTriop *triop = e->Iex.Triop.details;
++      switch (triop->op) {
+       case Iop_Add32Fx4: fpop = Pavfp_ADDF; goto do_32Fx4_with_rm;
+       case Iop_Sub32Fx4: fpop = Pavfp_SUBF; goto do_32Fx4_with_rm;
+       case Iop_Mul32Fx4: fpop = Pavfp_MULF; goto do_32Fx4_with_rm;
+diff --git a/VEX/priv/ir_defs.c b/VEX/priv/ir_defs.c
+index 4a7b770..8fdfcab 100644
+--- a/VEX/priv/ir_defs.c
++++ b/VEX/priv/ir_defs.c
+@@ -3122,7 +3122,8 @@ void typeOfPrimop ( IROp op,
+ 
+       case Iop_BCDAdd:
+       case Iop_BCDSub:
+-         TERNARY(Ity_V128,Ity_V128, Ity_I8, Ity_V128);
++         BINARY(Ity_V128, Ity_V128, Ity_V128);
++
+       case Iop_QDMull16Sx4: case Iop_QDMull32Sx2:
+          BINARY(Ity_I64, Ity_I64, Ity_V128);
+ 
+commit c8da12c274b2d94c42c07676139378b57fa7b31b
+Author: carll <carll@a5019735-40e9-0310-863c-91ae7b9d1cf9>
+Date:   Tue Apr 26 19:53:56 2016 +0000
+
+    Power PC  Fix V bit error in 128-bit BCD add and subtract instructions
+    
+    The original code was using the bcdadd / bcdsub instruction on the operand
+    shadow bits to calculate the shadow bits for the result.  This introduced
+    non-zero bits shadow bits in the result.   The shadow bits for these
+    instructions should be set to all valid or all invalid.  If one of the
+    argument shadow bits was one, then all of the shadow bits of the result should
+    be one.  Otherwise the result shadow bits should be zero.
+    
+    This patch fixes the above bug in memcheck/mc_translate.c
+    
+    Fixing the above bug broke the v-bit test.  The issue is the v-bit tester
+    assumes the shadow bits for the operands of a given Iop can be set to one
+    for testing purposes.  The implementation of the bcdadd and bcdsub was passing
+    a constant value for the variable ps.  The ps value is an argument to the
+    instruction that specifies how to set the sign code of the result.  The
+    implementation of the instructions was changed to issue the instruction with
+    ps=0.  Then the result of the instruction is updated in the VEX code if ps=1.
+    This changed also results in cleaning up the vbit test code.
+    
+    This patch also fixes the issues with the v-bit test program.
+    
+    Valgrind commit 3218
+    
+    Bugzilla 360035
+    
+    
+    git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15871 a5019735-40e9-0310-863c-91ae7b9d1cf9
+
+diff --git a/memcheck/mc_translate.c b/memcheck/mc_translate.c
+index c239e46..d50b53d 100644
+--- a/memcheck/mc_translate.c
++++ b/memcheck/mc_translate.c
+@@ -852,6 +852,17 @@ static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
+                                        unop(Iop_CmpNEZ64, tmp4));
+          break;
+       }
++      case Ity_V128: {
++         /* Chop it in half, OR the halves together, and compare that
++          * with zero.
++          */
++         IRAtom* tmp2 = assignNew('V', mce, Ity_I64, unop(Iop_V128HIto64, vbits));
++         IRAtom* tmp3 = assignNew('V', mce, Ity_I64, unop(Iop_V128to64, vbits));
++         IRAtom* tmp4 = assignNew('V', mce, Ity_I64, binop(Iop_Or64, tmp2, tmp3));
++         tmp1         = assignNew('V', mce, Ity_I1,
++                                       unop(Iop_CmpNEZ64, tmp4));
++         break;
++      }
+       default:
+          ppIRType(src_ty);
+          VG_(tool_panic)("mkPCastTo(1)");
+@@ -2888,11 +2899,6 @@ IRAtom* expr2vbits_Triop ( MCEnv* mce,
+       case Iop_SetElem32x2:
+          complainIfUndefined(mce, atom2, NULL);
+          return assignNew('V', mce, Ity_I64, triop(op, vatom1, atom2, vatom3));
+-      /* BCDIops */
+-      case Iop_BCDAdd:
+-      case Iop_BCDSub:
+-         complainIfUndefined(mce, atom3, NULL);
+-         return assignNew('V', mce, Ity_V128, triop(op, vatom1, vatom2, atom3));
+ 
+       /* Vector FP with rounding mode as the first arg */
+       case Iop_Add64Fx2:
+@@ -3723,6 +3729,10 @@ IRAtom* expr2vbits_Binop ( MCEnv* mce,
+          complainIfUndefined(mce, atom2, NULL);
+          return assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2));
+ 
++      case Iop_BCDAdd:
++      case Iop_BCDSub:
++         return mkLazy2(mce, Ity_V128, vatom1, vatom2);
++
+       /* SHA Iops */
+       case Iop_SHA256:
+       case Iop_SHA512:
diff --git a/valgrind.spec b/valgrind.spec
index ad4337b..8e2d8a7 100644
--- a/valgrind.spec
+++ b/valgrind.spec
@@ -157,6 +157,9 @@ Patch35: valgrind-3.11.0-s390x-risbgn.patch
 # KDE#359133 m_deduppoolalloc.c:258 (vgPlain_allocEltDedupPA): Assertion failed 
 Patch36: valgrind-3.11.0-deduppoolalloc.patch
 
+# KDE#360035 - POWER PC bcdadd and bcdsubtract generate non-zero shadow bits 
+Patch37: valgrind-3.11.0-ppc-bcd-addsub.patch
+
 %if %{build_multilib}
 # Ensure glibc{,-devel} is installed for both multilib arches
 BuildRequires: /lib/libc.so.6 /usr/lib/libc.so /lib64/libc.so.6 /usr/lib64/libc.so
@@ -301,6 +304,7 @@ chmod 755 memcheck/tests/arm64-linux/filter_stderr
 %patch34 -p1
 %patch35 -p1
 %patch36 -p1
+%patch37 -p1
 
 %build
 # We need to use the software collection compiler and binutils if available.
@@ -495,6 +499,7 @@ echo ===============END TESTING===============
 %changelog
 * Thu Apr 28 2016 Mark Wielaard <mjw@redhat.com>
 - Add valgrind-3.11.0-deduppoolalloc.patch
+- Add valgrind-3.11.0-ppc-bcd-addsub.patch
 
 * Fri Apr 15 2016 Mark Wielaard <mjw@redhat.com> - 3.11.0-20
 - Update valgrind-3.11.0-cxx-freeres.patch (x86 final_tidyup fix)