100 lines
2.7 KiB
Diff
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
|
|
|