Add valgrind-3.11.0-ppc-bcd-addsub.patch

This commit is contained in:
Mark Wielaard 2016-04-29 00:14:10 +02:00
parent 05e63997d5
commit f9c9f28c47
2 changed files with 388 additions and 0 deletions

View File

@ -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:

View File

@ -157,6 +157,9 @@ Patch35: valgrind-3.11.0-s390x-risbgn.patch
# KDE#359133 m_deduppoolalloc.c:258 (vgPlain_allocEltDedupPA): Assertion failed # KDE#359133 m_deduppoolalloc.c:258 (vgPlain_allocEltDedupPA): Assertion failed
Patch36: valgrind-3.11.0-deduppoolalloc.patch 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} %if %{build_multilib}
# Ensure glibc{,-devel} is installed for both multilib arches # 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 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 %patch34 -p1
%patch35 -p1 %patch35 -p1
%patch36 -p1 %patch36 -p1
%patch37 -p1
%build %build
# We need to use the software collection compiler and binutils if available. # We need to use the software collection compiler and binutils if available.
@ -495,6 +499,7 @@ echo ===============END TESTING===============
%changelog %changelog
* Thu Apr 28 2016 Mark Wielaard <mjw@redhat.com> * Thu Apr 28 2016 Mark Wielaard <mjw@redhat.com>
- Add valgrind-3.11.0-deduppoolalloc.patch - 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 * 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) - Update valgrind-3.11.0-cxx-freeres.patch (x86 final_tidyup fix)