From b4e2bd3563af75ba5b9fe809c8cf79d2d34aecf3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 5 Sep 2012 17:27:40 -0700 Subject: target-s390: Send signals for divide Signed-off-by: Richard Henderson --- target-s390x/int_helper.c | 51 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 6 deletions(-) (limited to 'target-s390x/int_helper.c') diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c index 80e17f5b1f..839c0e1500 100644 --- a/target-s390x/int_helper.c +++ b/target-s390x/int_helper.c @@ -38,22 +38,54 @@ uint64_t HELPER(mul128)(CPUS390XState *env, uint64_t v1, uint64_t v2) } /* 64/32 -> 32 signed division */ -int64_t HELPER(divs32)(CPUS390XState *env, int64_t a, int64_t b) +int64_t HELPER(divs32)(CPUS390XState *env, int64_t a, int64_t b64) { - env->retxl = a % (int32_t)b; - return a / (int32_t)b; + int32_t ret, b = b64; + int64_t q; + + if (b == 0) { + runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC()); + } + + ret = q = a / b; + env->retxl = a % b; + + /* Catch non-representable quotient. */ + if (ret != q) { + runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC()); + } + + return ret; } /* 64/32 -> 32 unsigned division */ -uint64_t HELPER(divu32)(CPUS390XState *env, uint64_t a, uint64_t b) +uint64_t HELPER(divu32)(CPUS390XState *env, uint64_t a, uint64_t b64) { - env->retxl = a % (uint32_t)b; - return a / (uint32_t)b; + uint32_t ret, b = b64; + uint64_t q; + + if (b == 0) { + runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC()); + } + + ret = q = a / b; + env->retxl = a % b; + + /* Catch non-representable quotient. */ + if (ret != q) { + runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC()); + } + + return ret; } /* 64/64 -> 64 signed division */ int64_t HELPER(divs64)(CPUS390XState *env, int64_t a, int64_t b) { + /* Catch divide by zero, and non-representable quotient (MIN / -1). */ + if (b == 0 || (b == -1 && a == (1ll << 63))) { + runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC()); + } env->retxl = a % b; return a / b; } @@ -63,6 +95,10 @@ uint64_t HELPER(divu64)(CPUS390XState *env, uint64_t ah, uint64_t al, uint64_t b) { uint64_t ret; + /* Signal divide by zero. */ + if (b == 0) { + runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC()); + } if (ah == 0) { /* 64 -> 64/64 case */ env->retxl = al % b; @@ -75,6 +111,9 @@ uint64_t HELPER(divu64)(CPUS390XState *env, uint64_t ah, uint64_t al, __uint128_t q = a / b; env->retxl = a % b; ret = q; + if (ret != q) { + runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC()); + } #else /* 32-bit hosts would need special wrapper functionality - just abort if we encounter such a case; it's very unlikely anyways. */ -- cgit v1.2.1