[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH for-6.2 06/34] target/arm: Fix 48-bit saturating shifts
From: |
Peter Maydell |
Subject: |
[PATCH for-6.2 06/34] target/arm: Fix 48-bit saturating shifts |
Date: |
Tue, 13 Jul 2021 14:36:58 +0100 |
In do_sqrshl48_d() and do_uqrshl48_d() we got some of the edge
cases wrong and failed to saturate correctly:
(1) In do_sqrshl48_d() we used the same code that do_shrshl_bhs()
does to obtain the saturated most-negative and most-positive 48-bit
signed values for the large-shift-left case. This gives (1 << 47)
for saturate-to-most-negative, but we weren't sign-extending this
value to the 64-bit output as the pseudocode requires.
(2) For left shifts by less than 48, we copied the "8/16 bit" code
from do_sqrshl_bhs() and do_uqrshl_bhs(). This doesn't do the right
thing because it assumes the C type we're working with is at least
twice the number of bits we're saturating to (so that a shift left by
bits-1 can't shift anything off the top of the value). This isn't
true for bits == 48, so we would incorrectly return 0 rather than the
most-positive value for situations like "shift (1 << 44) right by
20". Instead check for saturation by doing the shift and signextend
and then testing whether shifting back left again gives the original
value.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target/arm/mve_helper.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
index 8cbfd3a8c53..f17e5a413fd 100644
--- a/target/arm/mve_helper.c
+++ b/target/arm/mve_helper.c
@@ -1579,9 +1579,8 @@ static inline int64_t do_sqrshl48_d(int64_t src, int64_t
shift,
}
return src >> -shift;
} else if (shift < 48) {
- int64_t val = src << shift;
- int64_t extval = sextract64(val, 0, 48);
- if (!sat || val == extval) {
+ int64_t extval = sextract64(src << shift, 0, 48);
+ if (!sat || src == (extval >> shift)) {
return extval;
}
} else if (!sat || src == 0) {
@@ -1589,7 +1588,7 @@ static inline int64_t do_sqrshl48_d(int64_t src, int64_t
shift,
}
*sat = 1;
- return (1ULL << 47) - (src >= 0);
+ return sextract64((1ULL << 47) - (src >= 0), 0, 48);
}
/* Operate on 64-bit values, but saturate at 48 bits */
@@ -1612,9 +1611,8 @@ static inline uint64_t do_uqrshl48_d(uint64_t src,
int64_t shift,
return extval;
}
} else if (shift < 48) {
- uint64_t val = src << shift;
- uint64_t extval = extract64(val, 0, 48);
- if (!sat || val == extval) {
+ uint64_t extval = extract64(src << shift, 0, 48);
+ if (!sat || src == (extval >> shift)) {
return extval;
}
} else if (!sat || src == 0) {
--
2.20.1
- Re: [PATCH for-6.2 07/34] target/arm: Fix calculation of LTP mask when LR is 0, (continued)
- [PATCH for-6.2 08/34] target/arm: Fix VPT advance when ECI is non-zero, Peter Maydell, 2021/07/13
- [PATCH for-6.2 09/34] target/arm: Factor out mve_eci_mask(), Peter Maydell, 2021/07/13
- [PATCH for-6.2 12/34] target/arm: Implement MVE incrementing/decrementing dup insns, Peter Maydell, 2021/07/13
- [PATCH for-6.2 06/34] target/arm: Fix 48-bit saturating shifts,
Peter Maydell <=
- [PATCH for-6.2 10/34] target/arm: Fix VLDRB/H/W for predicated elements, Peter Maydell, 2021/07/13
- [PATCH for-6.2 05/34] target/arm: Fix mask handling for MVE narrowing operations, Peter Maydell, 2021/07/13
- [PATCH for-6.2 16/34] target/arm: Implement MVE VPSEL, Peter Maydell, 2021/07/13
- [PATCH for-6.2 11/34] target/arm: Implement MVE VMULL (polynomial), Peter Maydell, 2021/07/13