aboutsummaryrefslogtreecommitdiff
path: root/target-s390x/cc_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-s390x/cc_helper.c')
-rw-r--r--target-s390x/cc_helper.c56
1 files changed, 42 insertions, 14 deletions
diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index 575f7c3e75..be4202a78e 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -345,34 +345,59 @@ static uint32_t cc_calc_icm(uint64_t mask, uint64_t val)
}
}
-static uint32_t cc_calc_slag(uint64_t src, uint64_t shift)
+static uint32_t cc_calc_sla_32(uint32_t src, int shift)
{
- uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift);
- uint64_t match, r;
+ 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 & (1ULL << 63)) {
+ /* Check if the sign bit stays the same. */
+ if (src & sign) {
match = mask;
} else {
match = 0;
}
-
if ((src & mask) != match) {
- /* overflow */
+ /* Overflow. */
return 3;
}
- r = ((src << shift) & ((1ULL << 63) - 1)) | (src & (1ULL << 63));
-
- if ((int64_t)r == 0) {
+ r = ((src << shift) & ~sign) | (src & sign);
+ if (r == 0) {
return 0;
- } else if ((int64_t)r < 0) {
+ } else if (r < 0) {
return 1;
}
-
return 2;
}
+static uint32_t cc_calc_sla_64(uint64_t src, int shift)
+{
+ uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift);
+ uint64_t sign = 1ULL << 63;
+ uint64_t match;
+ int64_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 do_calc_cc(CPUS390XState *env, uint32_t cc_op,
uint64_t src, uint64_t dst, uint64_t vr)
@@ -473,8 +498,11 @@ 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_SLAG:
- r = cc_calc_slag(src, dst);
+ 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);
break;
case CC_OP_LTGT_F32: