Commit d80bff19 authored by Richard Henderson's avatar Richard Henderson
Browse files

target/openrisc: Convert memory insns

parent 136e13ae
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -38,3 +38,27 @@ l_bf 000100 n:s26

l_jr            010001 ---------- b:5 -----------
l_jalr          010010 ---------- b:5 -----------

####
# Memory Instructions
####

&load           d a i
@load           ...... d:5 a:5 i:s16                    &load

%store_i        21:s5 0:11
&store          a b i
@store          ...... ..... a:5 b:5 ...........        &store i=%store_i

l_lwa           011011 ..... ..... ........ ........    @load
l_lwz           100001 ..... ..... ........ ........    @load
l_lws           100010 ..... ..... ........ ........    @load
l_lbz           100011 ..... ..... ........ ........    @load
l_lbs           100100 ..... ..... ........ ........    @load
l_lhz           100101 ..... ..... ........ ........    @load
l_lhs           100110 ..... ..... ........ ........    @load

l_swa           110011 ..... ..... ........ ........    @store
l_sw            110101 ..... ..... ........ ........    @store
l_sb            110110 ..... ..... ........ ........    @store
l_sh            110111 ..... ..... ........ ........    @store
+136 −139
Original line number Diff line number Diff line
@@ -455,51 +455,6 @@ static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb)
    gen_ove_cy(dc);
}

static void gen_lwa(DisasContext *dc, TCGv rd, TCGv ra, int32_t ofs)
{
    TCGv ea = tcg_temp_new();

    tcg_gen_addi_tl(ea, ra, ofs);
    tcg_gen_qemu_ld_tl(rd, ea, dc->mem_idx, MO_TEUL);
    tcg_gen_mov_tl(cpu_lock_addr, ea);
    tcg_gen_mov_tl(cpu_lock_value, rd);
    tcg_temp_free(ea);
}

static void gen_swa(DisasContext *dc, int b, TCGv ra, int32_t ofs)
{
    TCGv ea, val;
    TCGLabel *lab_fail, *lab_done;

    ea = tcg_temp_new();
    tcg_gen_addi_tl(ea, ra, ofs);

    /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned
       to cpu_R[0].  Since l.swa is quite often immediately followed by a
       branch, don't bother reallocating; finish the TB using the "real" R0.
       This also takes care of RB input across the branch.  */
    cpu_R[0] = cpu_R0;

    lab_fail = gen_new_label();
    lab_done = gen_new_label();
    tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail);
    tcg_temp_free(ea);

    val = tcg_temp_new();
    tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value,
                              cpu_R[b], dc->mem_idx, MO_TEUL);
    tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value);
    tcg_temp_free(val);

    tcg_gen_br(lab_done);

    gen_set_label(lab_fail);
    tcg_gen_movi_tl(cpu_sr_f, 0);

    gen_set_label(lab_done);
    tcg_gen_movi_tl(cpu_lock_addr, -1);
}

static void dec_calc(DisasContext *dc, uint32_t insn)
{
    uint32_t op0, op1, op2;
@@ -738,13 +693,147 @@ static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a, uint32_t insn)
    return true;
}

static bool trans_l_lwa(DisasContext *dc, arg_load *a, uint32_t insn)
{
    TCGv ea;

    LOG_DIS("l.lwa r%d, r%d, %d\n", a->d, a->a, a->i);

    check_r0_write(a->d);
    ea = tcg_temp_new();
    tcg_gen_addi_tl(ea, cpu_R[a->a], a->i);
    tcg_gen_qemu_ld_tl(cpu_R[a->d], ea, dc->mem_idx, MO_TEUL);
    tcg_gen_mov_tl(cpu_lock_addr, ea);
    tcg_gen_mov_tl(cpu_lock_value, cpu_R[a->d]);
    tcg_temp_free(ea);
    return true;
}

static void do_load(DisasContext *dc, arg_load *a, TCGMemOp mop)
{
    TCGv ea;

    check_r0_write(a->d);
    ea = tcg_temp_new();
    tcg_gen_addi_tl(ea, cpu_R[a->a], a->i);
    tcg_gen_qemu_ld_tl(cpu_R[a->d], ea, dc->mem_idx, mop);
    tcg_temp_free(ea);
}

static bool trans_l_lwz(DisasContext *dc, arg_load *a, uint32_t insn)
{
    LOG_DIS("l.lwz r%d, r%d, %d\n", a->d, a->a, a->i);
    do_load(dc, a, MO_TEUL);
    return true;
}

static bool trans_l_lws(DisasContext *dc, arg_load *a, uint32_t insn)
{
    LOG_DIS("l.lws r%d, r%d, %d\n", a->d, a->a, a->i);
    do_load(dc, a, MO_TESL);
    return true;
}

static bool trans_l_lbz(DisasContext *dc, arg_load *a, uint32_t insn)
{
    LOG_DIS("l.lbz r%d, r%d, %d\n", a->d, a->a, a->i);
    do_load(dc, a, MO_UB);
    return true;
}

static bool trans_l_lbs(DisasContext *dc, arg_load *a, uint32_t insn)
{
    LOG_DIS("l.lbs r%d, r%d, %d\n", a->d, a->a, a->i);
    do_load(dc, a, MO_SB);
    return true;
}

static bool trans_l_lhz(DisasContext *dc, arg_load *a, uint32_t insn)
{
    LOG_DIS("l.lhz r%d, r%d, %d\n", a->d, a->a, a->i);
    do_load(dc, a, MO_TEUW);
    return true;
}

static bool trans_l_lhs(DisasContext *dc, arg_load *a, uint32_t insn)
{
    LOG_DIS("l.lhs r%d, r%d, %d\n", a->d, a->a, a->i);
    do_load(dc, a, MO_TESW);
    return true;
}

static bool trans_l_swa(DisasContext *dc, arg_store *a, uint32_t insn)
{
    TCGv ea, val;
    TCGLabel *lab_fail, *lab_done;

    LOG_DIS("l.swa r%d, r%d, %d\n", a->a, a->b, a->i);

    ea = tcg_temp_new();
    tcg_gen_addi_tl(ea, cpu_R[a->a], a->i);

    /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned
       to cpu_R[0].  Since l.swa is quite often immediately followed by a
       branch, don't bother reallocating; finish the TB using the "real" R0.
       This also takes care of RB input across the branch.  */
    cpu_R[0] = cpu_R0;

    lab_fail = gen_new_label();
    lab_done = gen_new_label();
    tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail);
    tcg_temp_free(ea);

    val = tcg_temp_new();
    tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value,
                              cpu_R[a->b], dc->mem_idx, MO_TEUL);
    tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value);
    tcg_temp_free(val);

    tcg_gen_br(lab_done);

    gen_set_label(lab_fail);
    tcg_gen_movi_tl(cpu_sr_f, 0);

    gen_set_label(lab_done);
    tcg_gen_movi_tl(cpu_lock_addr, -1);
    return true;
}

static void do_store(DisasContext *dc, arg_store *a, TCGMemOp mop)
{
    TCGv t0 = tcg_temp_new();
    tcg_gen_addi_tl(t0, cpu_R[a->a], a->i);
    tcg_gen_qemu_st_tl(cpu_R[a->b], t0, dc->mem_idx, mop);
    tcg_temp_free(t0);
}

static bool trans_l_sw(DisasContext *dc, arg_store *a, uint32_t insn)
{
    LOG_DIS("l.sw r%d, r%d, %d\n", a->a, a->b, a->i);
    do_store(dc, a, MO_TEUL);
    return true;
}

static bool trans_l_sb(DisasContext *dc, arg_store *a, uint32_t insn)
{
    LOG_DIS("l.sb r%d, r%d, %d\n", a->a, a->b, a->i);
    do_store(dc, a, MO_UB);
    return true;
}

static bool trans_l_sh(DisasContext *dc, arg_store *a, uint32_t insn)
{
    LOG_DIS("l.sh r%d, r%d, %d\n", a->a, a->b, a->i);
    do_store(dc, a, MO_TEUW);
    return true;
}

static void dec_misc(DisasContext *dc, uint32_t insn)
{
    uint32_t op0, op1;
    uint32_t ra, rb, rd;
    uint32_t L6, K5, K16, K5_11;
    int32_t I16, I5_11;
    TCGMemOp mop;
    int32_t I16;
    TCGv t0;

    op0 = extract32(insn, 26, 6);
@@ -757,7 +846,6 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
    K16 = extract32(insn, 0, 16);
    I16 = (int16_t)K16;
    K5_11 = (extract32(insn, 21, 5) << 11) | extract32(insn, 0, 11);
    I5_11 = (int16_t)K5_11;

    switch (op0) {
    case 0x05:
@@ -795,12 +883,6 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
        }
        break;

    case 0x1b: /* l.lwa */
        LOG_DIS("l.lwa r%d, r%d, %d\n", rd, ra, I16);
        check_r0_write(rd);
        gen_lwa(dc, cpu_R[rd], cpu_R[ra], I16);
        break;

    case 0x1c:    /* l.cust1 */
        LOG_DIS("l.cust1\n");
        break;
@@ -833,53 +915,6 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
        LOG_DIS("l.cust8\n");
        break;

/* not used yet, open it when we need or64.  */
/*#ifdef TARGET_OPENRISC64
    case 0x20:     l.ld
        LOG_DIS("l.ld r%d, r%d, %d\n", rd, ra, I16);
        check_ob64s(dc);
        mop = MO_TEQ;
        goto do_load;
#endif*/

    case 0x21:    /* l.lwz */
        LOG_DIS("l.lwz r%d, r%d, %d\n", rd, ra, I16);
        mop = MO_TEUL;
        goto do_load;

    case 0x22:    /* l.lws */
        LOG_DIS("l.lws r%d, r%d, %d\n", rd, ra, I16);
        mop = MO_TESL;
        goto do_load;

    case 0x23:    /* l.lbz */
        LOG_DIS("l.lbz r%d, r%d, %d\n", rd, ra, I16);
        mop = MO_UB;
        goto do_load;

    case 0x24:    /* l.lbs */
        LOG_DIS("l.lbs r%d, r%d, %d\n", rd, ra, I16);
        mop = MO_SB;
        goto do_load;

    case 0x25:    /* l.lhz */
        LOG_DIS("l.lhz r%d, r%d, %d\n", rd, ra, I16);
        mop = MO_TEUW;
        goto do_load;

    case 0x26:    /* l.lhs */
        LOG_DIS("l.lhs r%d, r%d, %d\n", rd, ra, I16);
        mop = MO_TESW;
        goto do_load;

    do_load:
        check_r0_write(rd);
        t0 = tcg_temp_new();
        tcg_gen_addi_tl(t0, cpu_R[ra], I16);
        tcg_gen_qemu_ld_tl(cpu_R[rd], t0, dc->mem_idx, mop);
        tcg_temp_free(t0);
        break;

    case 0x27:    /* l.addi */
        LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16);
        check_r0_write(rd);
@@ -957,44 +992,6 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
        }
        break;

    case 0x33: /* l.swa */
        LOG_DIS("l.swa r%d, r%d, %d\n", ra, rb, I5_11);
        gen_swa(dc, rb, cpu_R[ra], I5_11);
        break;

/* not used yet, open it when we need or64.  */
/*#ifdef TARGET_OPENRISC64
    case 0x34:     l.sd
        LOG_DIS("l.sd r%d, r%d, %d\n", ra, rb, I5_11);
        check_ob64s(dc);
        mop = MO_TEQ;
        goto do_store;
#endif*/

    case 0x35:    /* l.sw */
        LOG_DIS("l.sw r%d, r%d, %d\n", ra, rb, I5_11);
        mop = MO_TEUL;
        goto do_store;

    case 0x36:    /* l.sb */
        LOG_DIS("l.sb r%d, r%d, %d\n", ra, rb, I5_11);
        mop = MO_UB;
        goto do_store;

    case 0x37:    /* l.sh */
        LOG_DIS("l.sh r%d, r%d, %d\n", ra, rb, I5_11);
        mop = MO_TEUW;
        goto do_store;

    do_store:
        {
            TCGv t0 = tcg_temp_new();
            tcg_gen_addi_tl(t0, cpu_R[ra], I5_11);
            tcg_gen_qemu_st_tl(cpu_R[rb], t0, dc->mem_idx, mop);
            tcg_temp_free(t0);
        }
        break;

    default:
        gen_illegal_exception(dc);
        break;