Revision b4e2bd35
b/target-s390x/cpu.h | ||
---|---|---|
931 | 931 |
|
932 | 932 |
/* misc_helper.c */ |
933 | 933 |
void program_interrupt(CPUS390XState *env, uint32_t code, int ilen); |
934 |
void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp, |
|
935 |
uintptr_t retaddr); |
|
934 | 936 |
|
935 | 937 |
#endif |
b/target-s390x/int_helper.c | ||
---|---|---|
38 | 38 |
} |
39 | 39 |
|
40 | 40 |
/* 64/32 -> 32 signed division */ |
41 |
int64_t HELPER(divs32)(CPUS390XState *env, int64_t a, int64_t b) |
|
41 |
int64_t HELPER(divs32)(CPUS390XState *env, int64_t a, int64_t b64)
|
|
42 | 42 |
{ |
43 |
env->retxl = a % (int32_t)b; |
|
44 |
return a / (int32_t)b; |
|
43 |
int32_t ret, b = b64; |
|
44 |
int64_t q; |
|
45 |
|
|
46 |
if (b == 0) { |
|
47 |
runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC()); |
|
48 |
} |
|
49 |
|
|
50 |
ret = q = a / b; |
|
51 |
env->retxl = a % b; |
|
52 |
|
|
53 |
/* Catch non-representable quotient. */ |
|
54 |
if (ret != q) { |
|
55 |
runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC()); |
|
56 |
} |
|
57 |
|
|
58 |
return ret; |
|
45 | 59 |
} |
46 | 60 |
|
47 | 61 |
/* 64/32 -> 32 unsigned division */ |
48 |
uint64_t HELPER(divu32)(CPUS390XState *env, uint64_t a, uint64_t b) |
|
62 |
uint64_t HELPER(divu32)(CPUS390XState *env, uint64_t a, uint64_t b64)
|
|
49 | 63 |
{ |
50 |
env->retxl = a % (uint32_t)b; |
|
51 |
return a / (uint32_t)b; |
|
64 |
uint32_t ret, b = b64; |
|
65 |
uint64_t q; |
|
66 |
|
|
67 |
if (b == 0) { |
|
68 |
runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC()); |
|
69 |
} |
|
70 |
|
|
71 |
ret = q = a / b; |
|
72 |
env->retxl = a % b; |
|
73 |
|
|
74 |
/* Catch non-representable quotient. */ |
|
75 |
if (ret != q) { |
|
76 |
runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC()); |
|
77 |
} |
|
78 |
|
|
79 |
return ret; |
|
52 | 80 |
} |
53 | 81 |
|
54 | 82 |
/* 64/64 -> 64 signed division */ |
55 | 83 |
int64_t HELPER(divs64)(CPUS390XState *env, int64_t a, int64_t b) |
56 | 84 |
{ |
85 |
/* Catch divide by zero, and non-representable quotient (MIN / -1). */ |
|
86 |
if (b == 0 || (b == -1 && a == (1ll << 63))) { |
|
87 |
runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC()); |
|
88 |
} |
|
57 | 89 |
env->retxl = a % b; |
58 | 90 |
return a / b; |
59 | 91 |
} |
... | ... | |
63 | 95 |
uint64_t b) |
64 | 96 |
{ |
65 | 97 |
uint64_t ret; |
98 |
/* Signal divide by zero. */ |
|
99 |
if (b == 0) { |
|
100 |
runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC()); |
|
101 |
} |
|
66 | 102 |
if (ah == 0) { |
67 | 103 |
/* 64 -> 64/64 case */ |
68 | 104 |
env->retxl = al % b; |
... | ... | |
75 | 111 |
__uint128_t q = a / b; |
76 | 112 |
env->retxl = a % b; |
77 | 113 |
ret = q; |
114 |
if (ret != q) { |
|
115 |
runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC()); |
|
116 |
} |
|
78 | 117 |
#else |
79 | 118 |
/* 32-bit hosts would need special wrapper functionality - just abort if |
80 | 119 |
we encounter such a case; it's very unlikely anyways. */ |
b/target-s390x/misc_helper.c | ||
---|---|---|
41 | 41 |
#define HELPER_LOG(x...) |
42 | 42 |
#endif |
43 | 43 |
|
44 |
/* Raise an exception dynamically from a helper function. */ |
|
45 |
void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp, |
|
46 |
uintptr_t retaddr) |
|
47 |
{ |
|
48 |
int t; |
|
49 |
|
|
50 |
env->exception_index = EXCP_PGM; |
|
51 |
env->int_pgm_code = excp; |
|
52 |
|
|
53 |
/* Use the (ultimate) callers address to find the insn that trapped. */ |
|
54 |
cpu_restore_state(env, retaddr); |
|
55 |
|
|
56 |
/* Advance past the insn. */ |
|
57 |
t = cpu_ldub_code(env, env->psw.addr); |
|
58 |
env->int_pgm_ilen = t = get_ilen(t); |
|
59 |
env->psw.addr += 2 * t; |
|
60 |
|
|
61 |
cpu_loop_exit(env); |
|
62 |
} |
|
63 |
|
|
44 | 64 |
/* Raise an exception statically from a TB. */ |
45 | 65 |
void HELPER(exception)(CPUS390XState *env, uint32_t excp) |
46 | 66 |
{ |
Also available in: Unified diff