valgrind/valgrind-3.21.0-vgm.patch

100 lines
2.7 KiB
Diff

From 70ef4417837b690755feede0088331a28b102c65 Mon Sep 17 00:00:00 2001
From: Andreas Arnez <arnez@linux.ibm.com>
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