Commit e0a42ebc authored by Edgar E. Iglesias's avatar Edgar E. Iglesias
Browse files

microblaze: Improve subkc



Move code from the helper into the translator. The remaining
helper parts can reuse helper_addkc, making it possible to
remove helper_subkc entirely.

Signed-off-by: default avatarEdgar E. Iglesias <edgar.iglesias@gmail.com>
parent 7e9e4330
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -3,7 +3,6 @@
DEF_HELPER_1(raise_exception, void, i32)
DEF_HELPER_0(debug, void)
DEF_HELPER_FLAGS_3(addkc, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32, i32)
DEF_HELPER_4(subkc, i32, i32, i32, i32, i32)
DEF_HELPER_2(cmp, i32, i32, i32)
DEF_HELPER_2(cmpu, i32, i32, i32)

+0 −22
Original line number Diff line number Diff line
@@ -138,28 +138,6 @@ uint32_t helper_addkc(uint32_t a, uint32_t b, uint32_t cf)
    return ncf;
}

uint32_t helper_subkc(uint32_t a, uint32_t b, uint32_t k, uint32_t c)
{
    uint32_t d, cf = 1, ncf;

    if (c)
        cf = env->sregs[SR_MSR] >> 31; 
    assert(cf == 0 || cf == 1);
    d = b + ~a + cf;

    if (!k) {
        ncf = compute_carry(b, ~a, cf);
        assert(ncf == 0 || ncf == 1);
        if (ncf)
            env->sregs[SR_MSR] |= MSR_C | MSR_CC;
        else
            env->sregs[SR_MSR] &= ~(MSR_C | MSR_CC);
    }
    D(qemu_log("%x = %x + %x cf=%d ncf=%d k=%d c=%d\n",
               d, a, b, cf, ncf, k, c));
    return d;
}

static inline int div_prepare(uint32_t a, uint32_t b)
{
    if (b == 0) {
+49 −15
Original line number Diff line number Diff line
@@ -247,6 +247,7 @@ static void dec_add(DisasContext *dc)
static void dec_sub(DisasContext *dc)
{
    unsigned int u, cmp, k, c;
    TCGv cf, na;

    u = dc->imm & 2;
    k = dc->opcode & 4;
@@ -261,25 +262,58 @@ static void dec_sub(DisasContext *dc)
            else
                gen_helper_cmp(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
        }
    } else {
        return;
    }

    LOG_DIS("sub%s%s r%d, r%d r%d\n",
             k ? "k" : "",  c ? "c" : "", dc->rd, dc->ra, dc->rb);

        if (!k || c) {
            TCGv t;
            t = tcg_temp_new();
            if (dc->rd)
                gen_helper_subkc(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)),
                                 tcg_const_tl(k), tcg_const_tl(c));
            else
                gen_helper_subkc(t, cpu_R[dc->ra], *(dec_alu_op_b(dc)),
                                 tcg_const_tl(k), tcg_const_tl(c));
            tcg_temp_free(t);
        }
        else if (dc->rd)
    /* Take care of the easy cases first.  */
    if (k) {
        /* k - keep carry, no need to update MSR.  */
        /* If rd == r0, it's a nop.  */
        if (dc->rd) {
            tcg_gen_sub_tl(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);

            if (c) {
                /* c - Add carry into the result.  */
                cf = tcg_temp_new();

                read_carry(dc, cf);
                tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
                tcg_temp_free(cf);
            }
        }
        return;
    }

    /* From now on, we can assume k is zero.  So we need to update MSR.  */
    /* Extract carry. And complement a into na.  */
    cf = tcg_temp_new();
    na = tcg_temp_new();
    if (c) {
        read_carry(dc, cf);
    } else {
        tcg_gen_movi_tl(cf, 1);
    }

    /* d = b + ~a + c. carry defaults to 1.  */
    tcg_gen_not_tl(na, cpu_R[dc->ra]);

    if (dc->rd) {
        TCGv ncf = tcg_temp_new();
        gen_helper_addkc(ncf, na, *(dec_alu_op_b(dc)), cf);
        tcg_gen_add_tl(cpu_R[dc->rd], na, *(dec_alu_op_b(dc)));
        tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
        write_carry(dc, ncf);
        tcg_temp_free(ncf);
    } else {
        gen_helper_addkc(cf, na, *(dec_alu_op_b(dc)), cf);
        write_carry(dc, cf);
    }
    tcg_temp_free(cf);
    tcg_temp_free(na);
}

static void dec_pattern(DisasContext *dc)
{