From 9bd78ebd8bb5cd4ebb3f081ceba46836cc485551 Mon Sep 17 00:00:00 2001 From: Andreas Arnez Date: Tue, 27 Apr 2021 20:13:26 +0200 Subject: [PATCH] Bug 434296 - s390x: Rework IR conversion of VISTR The z/Architecture instruction VISTR is currently transformed to a dirty helper that executes the instruction. This can cause false positives with memcheck if the input string contains undefined characters after the string terminator. Implement without a dirty helper and emulate the instruction instead. --- VEX/priv/guest_s390_defs.h | 1 - VEX/priv/guest_s390_helpers.c | 9 ------- VEX/priv/guest_s390_toIR.c | 48 +++++++++++++++-------------------- 3 files changed, 21 insertions(+), 37 deletions(-) diff --git a/VEX/priv/guest_s390_defs.h b/VEX/priv/guest_s390_defs.h index caec3108e..24f3798c1 100644 --- a/VEX/priv/guest_s390_defs.h +++ b/VEX/priv/guest_s390_defs.h @@ -265,7 +265,6 @@ typedef enum { S390_VEC_OP_INVALID = 0, S390_VEC_OP_VPKS, S390_VEC_OP_VPKLS, - S390_VEC_OP_VISTR, S390_VEC_OP_VCEQ, S390_VEC_OP_VTM, S390_VEC_OP_VGFM, diff --git a/VEX/priv/guest_s390_helpers.c b/VEX/priv/guest_s390_helpers.c index 2188ce5c1..1e04f601a 100644 --- a/VEX/priv/guest_s390_helpers.c +++ b/VEX/priv/guest_s390_helpers.c @@ -2538,7 +2538,6 @@ s390x_dirtyhelper_vec_op(VexGuestS390XState *guest_state, {0x00, 0x00}, /* invalid */ [S390_VEC_OP_VPKS] = {0xe7, 0x97}, [S390_VEC_OP_VPKLS] = {0xe7, 0x95}, - [S390_VEC_OP_VISTR] = {0xe7, 0x5c}, [S390_VEC_OP_VCEQ] = {0xe7, 0xf8}, [S390_VEC_OP_VTM] = {0xe7, 0xd8}, [S390_VEC_OP_VGFM] = {0xe7, 0xb4}, @@ -2610,14 +2609,6 @@ s390x_dirtyhelper_vec_op(VexGuestS390XState *guest_state, the_insn.VRR.op2 = opcodes[d->op][1]; switch(d->op) { - case S390_VEC_OP_VISTR: - the_insn.VRR.v1 = 1; - the_insn.VRR.v2 = 2; - the_insn.VRR.rxb = 0b1100; - the_insn.VRR.m4 = d->m4; - the_insn.VRR.m5 = d->m5; - break; - case S390_VEC_OP_VTM: the_insn.VRR.v1 = 2; the_insn.VRR.v2 = 3; diff --git a/VEX/priv/guest_s390_toIR.c b/VEX/priv/guest_s390_toIR.c index c8dc3ec18..dfea54259 100644 --- a/VEX/priv/guest_s390_toIR.c +++ b/VEX/priv/guest_s390_toIR.c @@ -17447,40 +17447,34 @@ s390_irgen_VFENE(UChar v1, UChar v2, UChar v3, UChar m4, UChar m5) static const HChar * s390_irgen_VISTR(UChar v1, UChar v2, UChar m3, UChar m5) { - IRDirty* d; - IRTemp cc = newTemp(Ity_I64); + s390_insn_assert("vistr", m3 < 3 && m5 == (m5 & 1)); - /* Check for specification exception */ - vassert(m3 < 3); - vassert((m5 & 0b1110) == 0); + static const IROp compare_op[3] = { + Iop_CmpEQ8x16, Iop_CmpEQ16x8, Iop_CmpEQ32x4 + }; + IRExpr* t; + IRTemp op2 = newTemp(Ity_V128); + IRTemp op2term = newTemp(Ity_V128); + IRTemp mask = newTemp(Ity_V128); - s390x_vec_op_details_t details = { .serialized = 0ULL }; - details.op = S390_VEC_OP_VISTR; - details.v1 = v1; - details.v2 = v2; - details.m4 = m3; - details.m5 = m5; + assign(op2, get_vr_qw(v2)); + assign(op2term, binop(compare_op[m3], mkexpr(op2), mkV128(0))); + t = mkexpr(op2term); - d = unsafeIRDirty_1_N(cc, 0, "s390x_dirtyhelper_vec_op", - &s390x_dirtyhelper_vec_op, - mkIRExprVec_2(IRExpr_GSPTR(), - mkU64(details.serialized))); - - d->nFxState = 2; - vex_bzero(&d->fxState, sizeof(d->fxState)); - d->fxState[0].fx = Ifx_Read; - d->fxState[0].offset = S390X_GUEST_OFFSET(guest_v0) + v2 * sizeof(V128); - d->fxState[0].size = sizeof(V128); - d->fxState[1].fx = Ifx_Write; - d->fxState[1].offset = S390X_GUEST_OFFSET(guest_v0) + v1 * sizeof(V128); - d->fxState[1].size = sizeof(V128); - - stmt(IRStmt_Dirty(d)); + for (UChar i = m3; i < 4; i++) { + IRTemp s = newTemp(Ity_V128); + assign(s, binop(Iop_OrV128, t, binop(Iop_ShrV128, t, mkU8(8 << i)))); + t = mkexpr(s); + } + assign(mask, unop(Iop_NotV128, t)); + put_vr_qw(v1, binop(Iop_AndV128, mkexpr(op2), mkexpr(mask))); if (s390_vr_is_cs_set(m5)) { + IRTemp cc = newTemp(Ity_I64); + assign(cc, binop(Iop_And64, mkU64(3), unop(Iop_V128to64, mkexpr(mask)))); s390_cc_set(cc); } - + dis_res->hint = Dis_HintVerbose; return "vistr"; }