Commit 7a5e4488 authored by Blue Swirl's avatar Blue Swirl
Browse files

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: default avatarRichard Henderson <rth@twiddle.net>
Signed-off-by: default avatarBlue Swirl <blauwirbel@gmail.com>
parent 79227036
Loading
Loading
Loading
Loading
+76 −0
Original line number Diff line number Diff line
@@ -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);
}
+4 −4
Original line number Diff line number Diff line
@@ -35,10 +35,10 @@ DEF_HELPER_2(check_align, void, tl, i32)
DEF_HELPER_1(debug, void, env)
DEF_HELPER_1(save, void, env)
DEF_HELPER_1(restore, void, env)
DEF_HELPER_2(udiv, tl, tl, tl)
DEF_HELPER_2(udiv_cc, tl, tl, tl)
DEF_HELPER_2(sdiv, tl, tl, tl)
DEF_HELPER_2(sdiv_cc, tl, tl, tl)
DEF_HELPER_3(udiv, tl, env, tl, tl)
DEF_HELPER_3(udiv_cc, tl, env, tl, tl)
DEF_HELPER_3(sdiv, tl, env, tl, tl)
DEF_HELPER_3(sdiv_cc, tl, env, tl, tl)
DEF_HELPER_2(stdf, void, tl, int)
DEF_HELPER_2(lddf, void, tl, int)
DEF_HELPER_2(ldqf, void, tl, int)
+0 −74
Original line number Diff line number Diff line
@@ -2195,80 +2195,6 @@ target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
}
#endif /* TARGET_SPARC64 */

static target_ulong helper_udiv_common(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(target_ulong a, target_ulong b)
{
    return helper_udiv_common(a, b, 0);
}

target_ulong helper_udiv_cc(target_ulong a, target_ulong b)
{
    return helper_udiv_common(a, b, 1);
}

static target_ulong helper_sdiv_common(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(target_ulong a, target_ulong b)
{
    return helper_sdiv_common(a, b, 0);
}

target_ulong helper_sdiv_cc(target_ulong a, target_ulong b)
{
    return helper_sdiv_common(a, b, 1);
}

void helper_stdf(target_ulong addr, int mem_idx)
{
    helper_check_align(addr, 7);
+8 −4
Original line number Diff line number Diff line
@@ -3271,19 +3271,23 @@ static void disas_sparc_insn(DisasContext * dc)
                    case 0xe: /* udiv */
                        CHECK_IU_FEATURE(dc, DIV);
                        if (xop & 0x10) {
                            gen_helper_udiv_cc(cpu_dst, cpu_src1, cpu_src2);
                            gen_helper_udiv_cc(cpu_dst, cpu_env, cpu_src1,
                                               cpu_src2);
                            dc->cc_op = CC_OP_DIV;
                        } else {
                            gen_helper_udiv(cpu_dst, cpu_src1, cpu_src2);
                            gen_helper_udiv(cpu_dst, cpu_env, cpu_src1,
                                            cpu_src2);
                        }
                        break;
                    case 0xf: /* sdiv */
                        CHECK_IU_FEATURE(dc, DIV);
                        if (xop & 0x10) {
                            gen_helper_sdiv_cc(cpu_dst, cpu_src1, cpu_src2);
                            gen_helper_sdiv_cc(cpu_dst, cpu_env, cpu_src1,
                                               cpu_src2);
                            dc->cc_op = CC_OP_DIV;
                        } else {
                            gen_helper_sdiv(cpu_dst, cpu_src1, cpu_src2);
                            gen_helper_sdiv(cpu_dst, cpu_env, cpu_src1,
                                            cpu_src2);
                        }
                        break;
                    default: