From 70ef4417837b690755feede0088331a28b102c65 Mon Sep 17 00:00:00 2001 From: Andreas Arnez Date: Mon, 22 May 2023 18:57:35 +0200 Subject: [PATCH 1/2] Bug 470132 - s390x: Fix the wrap-around case in VGM Valgrind's implementation of VGM is incomplete: * It doesn't support generating a wrap-around bit mask. Such a mask should result when the ending bit position is smaller than the starting bit position. Valgrind runs into an assertion failure instead. * It doesn't ignore unused bits in the I2 and I3 fields of the instruction, as it should. Fix this by re-implementing the main logic in s390_irgen_VGM(). --- VEX/priv/guest_s390_toIR.c | 57 +++++++++++++++----------------------- 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/VEX/priv/guest_s390_toIR.c b/VEX/priv/guest_s390_toIR.c index 11dda41ef..d9d746c38 100644 --- a/VEX/priv/guest_s390_toIR.c +++ b/VEX/priv/guest_s390_toIR.c @@ -16388,50 +16388,37 @@ s390_irgen_VGBM(UChar v1, UShort i2, UChar m3 __attribute__((unused))) static const HChar * s390_irgen_VGM(UChar v1, UShort i2, UChar m3) { - UChar from = (i2 & 0xff00) >> 8; - UChar to = (i2 & 0x00ff); - ULong value = 0UL; - IRType type = s390_vr_get_type(m3); - vassert(from <= to); - - UChar maxIndex = 0; - switch (type) { - case Ity_I8: - maxIndex = 7; - break; - case Ity_I16: - maxIndex = 15; - break; - case Ity_I32: - maxIndex = 31; - break; - case Ity_I64: - maxIndex = 63; - break; - default: - vpanic("s390_irgen_VGM: unknown type"); - } - - for(UChar index = from; index <= to; index++) { - value |= (1ULL << (maxIndex - index)); - } - - IRExpr *fillValue; - switch (type) { - case Ity_I8: + s390_insn_assert("vgm", m3 <= 3); + + UChar max_idx = (8 << m3) - 1; + UChar from = max_idx & (i2 >> 8); + UChar to = max_idx & i2; + ULong all_one = (1ULL << max_idx << 1) - 1; + ULong value = (all_one >> from) ^ (all_one >> to >> 1); + + /* In case of wrap-around we now have a value that needs inverting: + to from + V V + 00000111111111110000000000000000 */ + if (to < from) + value ^= all_one; + + IRExpr* fillValue; + switch (m3) { + case 0: fillValue = mkU8(value); break; - case Ity_I16: + case 1: fillValue = mkU16(value); break; - case Ity_I32: + case 2: fillValue = mkU32(value); break; - case Ity_I64: + case 3: fillValue = mkU64(value); break; default: - vpanic("s390_irgen_VGM: unknown type"); + vpanic("s390_irgen_VGM: unknown element size"); } s390_vr_fill(v1, fillValue); -- 2.40.1