diff options
author | Ilya Leoshkevich <iii@linux.ibm.com> | 2022-01-12 17:50:15 +0100 |
---|---|---|
committer | Thomas Huth <thuth@redhat.com> | 2022-01-17 08:36:33 +0100 |
commit | 6da170beda33f3e7f1d9242814acd9f428f0f0fb (patch) | |
tree | 2c7f85c0db55a58be39a94a9ecd9467d7bf79ea8 /target/s390x/tcg/cc_helper.c | |
parent | df103c09bc2f549d36ba6313a69c18fc003ef1ee (diff) | |
download | qemu-6da170beda33f3e7f1d9242814acd9f428f0f0fb.zip qemu-6da170beda33f3e7f1d9242814acd9f428f0f0fb.tar.gz qemu-6da170beda33f3e7f1d9242814acd9f428f0f0fb.tar.bz2 |
target/s390x: Fix shifting 32-bit values for more than 31 bits
According to PoP, both 32- and 64-bit shifts use lowest 6 address
bits. The current code special-cases 32-bit shifts to use only 5 bits,
which is not correct. For example, shifting by 32 bits currently
preserves the initial value, however, it's supposed zero it out
instead.
Fix by merging sh32 and sh64 and adapting CC calculation to shift
values greater than 31.
Fixes: cbe24bfa91d2 ("target-s390: Convert SHIFT, ROTATE SINGLE")
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Message-Id: <20220112165016.226996-5-iii@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Diffstat (limited to 'target/s390x/tcg/cc_helper.c')
-rw-r--r-- | target/s390x/tcg/cc_helper.c | 36 |
1 files changed, 3 insertions, 33 deletions
diff --git a/target/s390x/tcg/cc_helper.c b/target/s390x/tcg/cc_helper.c index c9b7b0e..8d04097 100644 --- a/target/s390x/tcg/cc_helper.c +++ b/target/s390x/tcg/cc_helper.c @@ -268,34 +268,7 @@ static uint32_t cc_calc_icm(uint64_t mask, uint64_t val) } } -static uint32_t cc_calc_sla_32(uint32_t src, int shift) -{ - uint32_t mask = ((1U << shift) - 1U) << (32 - shift); - uint32_t sign = 1U << 31; - uint32_t match; - int32_t r; - - /* Check if the sign bit stays the same. */ - if (src & sign) { - match = mask; - } else { - match = 0; - } - if ((src & mask) != match) { - /* Overflow. */ - return 3; - } - - r = ((src << shift) & ~sign) | (src & sign); - if (r == 0) { - return 0; - } else if (r < 0) { - return 1; - } - return 2; -} - -static uint32_t cc_calc_sla_64(uint64_t src, int shift) +static uint32_t cc_calc_sla(uint64_t src, int shift) { uint64_t mask = -1ULL << (63 - shift); uint64_t sign = 1ULL << 63; @@ -459,11 +432,8 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, case CC_OP_ICM: r = cc_calc_icm(src, dst); break; - case CC_OP_SLA_32: - r = cc_calc_sla_32(src, dst); - break; - case CC_OP_SLA_64: - r = cc_calc_sla_64(src, dst); + case CC_OP_SLA: + r = cc_calc_sla(src, dst); break; case CC_OP_FLOGR: r = cc_calc_flogr(dst); |