target-s390: Send signals for divide
Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
parent
891452e5e2
commit
b4e2bd3563
@ -931,5 +931,7 @@ uint32_t set_cc_nz_f64(float64 v);
|
|||||||
|
|
||||||
/* misc_helper.c */
|
/* misc_helper.c */
|
||||||
void program_interrupt(CPUS390XState *env, uint32_t code, int ilen);
|
void program_interrupt(CPUS390XState *env, uint32_t code, int ilen);
|
||||||
|
void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp,
|
||||||
|
uintptr_t retaddr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -38,22 +38,54 @@ uint64_t HELPER(mul128)(CPUS390XState *env, uint64_t v1, uint64_t v2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 64/32 -> 32 signed division */
|
/* 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;
|
int32_t ret, b = b64;
|
||||||
return a / (int32_t)b;
|
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 */
|
/* 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;
|
uint32_t ret, b = b64;
|
||||||
return a / (uint32_t)b;
|
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 */
|
/* 64/64 -> 64 signed division */
|
||||||
int64_t HELPER(divs64)(CPUS390XState *env, int64_t a, int64_t b)
|
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;
|
env->retxl = a % b;
|
||||||
return 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 b)
|
||||||
{
|
{
|
||||||
uint64_t ret;
|
uint64_t ret;
|
||||||
|
/* Signal divide by zero. */
|
||||||
|
if (b == 0) {
|
||||||
|
runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
|
||||||
|
}
|
||||||
if (ah == 0) {
|
if (ah == 0) {
|
||||||
/* 64 -> 64/64 case */
|
/* 64 -> 64/64 case */
|
||||||
env->retxl = al % b;
|
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;
|
__uint128_t q = a / b;
|
||||||
env->retxl = a % b;
|
env->retxl = a % b;
|
||||||
ret = q;
|
ret = q;
|
||||||
|
if (ret != q) {
|
||||||
|
runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
/* 32-bit hosts would need special wrapper functionality - just abort if
|
/* 32-bit hosts would need special wrapper functionality - just abort if
|
||||||
we encounter such a case; it's very unlikely anyways. */
|
we encounter such a case; it's very unlikely anyways. */
|
||||||
|
@ -41,6 +41,26 @@
|
|||||||
#define HELPER_LOG(x...)
|
#define HELPER_LOG(x...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Raise an exception dynamically from a helper function. */
|
||||||
|
void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp,
|
||||||
|
uintptr_t retaddr)
|
||||||
|
{
|
||||||
|
int t;
|
||||||
|
|
||||||
|
env->exception_index = EXCP_PGM;
|
||||||
|
env->int_pgm_code = excp;
|
||||||
|
|
||||||
|
/* Use the (ultimate) callers address to find the insn that trapped. */
|
||||||
|
cpu_restore_state(env, retaddr);
|
||||||
|
|
||||||
|
/* Advance past the insn. */
|
||||||
|
t = cpu_ldub_code(env, env->psw.addr);
|
||||||
|
env->int_pgm_ilen = t = get_ilen(t);
|
||||||
|
env->psw.addr += 2 * t;
|
||||||
|
|
||||||
|
cpu_loop_exit(env);
|
||||||
|
}
|
||||||
|
|
||||||
/* Raise an exception statically from a TB. */
|
/* Raise an exception statically from a TB. */
|
||||||
void HELPER(exception)(CPUS390XState *env, uint32_t excp)
|
void HELPER(exception)(CPUS390XState *env, uint32_t excp)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user