diff options
author | Blue Swirl <blauwirbel@gmail.com> | 2011-07-04 18:15:42 +0000 |
---|---|---|
committer | Blue Swirl <blauwirbel@gmail.com> | 2011-10-26 17:18:52 +0000 |
commit | 7a5e4488cd1d0e80500be4781010ac4873a9585b (patch) | |
tree | 07c16246818715be34b696320469c7136c9ebf5f /target-sparc/helper.c | |
parent | 7922703623a989b59ce7f7b57a3c8ebe5c0f6b53 (diff) |
Sparc: avoid AREG0 for division op helpers
Make [su]div{,cc} helpers take a parameter for CPUState instead
of relying on global env. Move the functions to helper.c.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Diffstat (limited to 'target-sparc/helper.c')
-rw-r--r-- | target-sparc/helper.c | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/target-sparc/helper.c b/target-sparc/helper.c index 7a25605fa7..5f8cf314f1 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -919,3 +919,79 @@ void helper_tick_set_limit(void *opaque, uint64_t limit) #endif } #endif + +static target_ulong helper_udiv_common(CPUState *env, target_ulong a, + target_ulong b, int cc) +{ + int overflow = 0; + uint64_t x0; + uint32_t x1; + + x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32); + x1 = (b & 0xffffffff); + + if (x1 == 0) { + helper_raise_exception(env, TT_DIV_ZERO); + } + + x0 = x0 / x1; + if (x0 > 0xffffffff) { + x0 = 0xffffffff; + overflow = 1; + } + + if (cc) { + env->cc_dst = x0; + env->cc_src2 = overflow; + env->cc_op = CC_OP_DIV; + } + return x0; +} + +target_ulong helper_udiv(CPUState *env, target_ulong a, target_ulong b) +{ + return helper_udiv_common(env, a, b, 0); +} + +target_ulong helper_udiv_cc(CPUState *env, target_ulong a, target_ulong b) +{ + return helper_udiv_common(env, a, b, 1); +} + +static target_ulong helper_sdiv_common(CPUState *env, target_ulong a, + target_ulong b, int cc) +{ + int overflow = 0; + int64_t x0; + int32_t x1; + + x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32); + x1 = (b & 0xffffffff); + + if (x1 == 0) { + helper_raise_exception(env, TT_DIV_ZERO); + } + + x0 = x0 / x1; + if ((int32_t) x0 != x0) { + x0 = x0 < 0 ? 0x80000000 : 0x7fffffff; + overflow = 1; + } + + if (cc) { + env->cc_dst = x0; + env->cc_src2 = overflow; + env->cc_op = CC_OP_DIV; + } + return x0; +} + +target_ulong helper_sdiv(CPUState *env, target_ulong a, target_ulong b) +{ + return helper_sdiv_common(env, a, b, 0); +} + +target_ulong helper_sdiv_cc(CPUState *env, target_ulong a, target_ulong b) +{ + return helper_sdiv_common(env, a, b, 1); +} |