aboutsummaryrefslogtreecommitdiff
path: root/target-arm
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2010-12-07 14:13:45 +0000
committerAurelien Jarno <aurelien@aurel32.net>2010-12-27 21:07:24 +0100
commita5d88f3e030f9f83e63b0cb3c09a3293d8057f4a (patch)
tree33b2f15964f11879bbe137e3a6830f57181816a3 /target-arm
parent620d791e341fe0b36e6c2a5659b2cc9f7866948f (diff)
target-arm: Correct result in saturating cases for VQSHL of s8/16/32
Where VQSHL of a signed 8/16/32 bit value saturated, the result value was not being calculated correctly (it should be either the minimum or maximum value for the size of the signed type). Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Diffstat (limited to 'target-arm')
-rw-r--r--target-arm/neon_helper.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index 48b9f5b5b5..dae063ea1a 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -580,9 +580,15 @@ uint64_t HELPER(neon_qshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
int8_t tmp; \
tmp = (int8_t)src2; \
if (tmp >= (ssize_t)sizeof(src1) * 8) { \
- if (src1) \
+ if (src1) { \
SET_QC(); \
- dest = src1 >> 31; \
+ dest = (uint32_t)(1 << (sizeof(src1) * 8 - 1)); \
+ if (src1 > 0) { \
+ dest--; \
+ } \
+ } else { \
+ dest = src1; \
+ } \
} else if (tmp <= -(ssize_t)sizeof(src1) * 8) { \
dest = src1 >> 31; \
} else if (tmp < 0) { \
@@ -591,7 +597,10 @@ uint64_t HELPER(neon_qshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
dest = src1 << tmp; \
if ((dest >> tmp) != src1) { \
SET_QC(); \
- dest = src2 >> 31; \
+ dest = (uint32_t)(1 << (sizeof(src1) * 8 - 1)); \
+ if (src1 > 0) { \
+ dest--; \
+ } \
} \
}} while (0)
NEON_VOP_ENV(qshl_s8, neon_s8, 4)