Commit 7268adeb authored by Richard Henderson's avatar Richard Henderson
Browse files

target-sparc: Implement cas_asi/casx_asi inline

parent fbb4bbb6
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ DEF_HELPER_2(wrcwp, void, env, tl)
DEF_HELPER_FLAGS_2(array8, TCG_CALL_NO_RWG_SE, tl, tl, tl)
DEF_HELPER_FLAGS_1(popc, TCG_CALL_NO_RWG_SE, tl, tl)
DEF_HELPER_FLAGS_3(ldda_asi, TCG_CALL_NO_WG, void, env, tl, int)
DEF_HELPER_FLAGS_5(casx_asi, TCG_CALL_NO_WG, tl, env, tl, tl, tl, i32)
DEF_HELPER_FLAGS_2(set_softint, TCG_CALL_NO_RWG, void, env, i64)
DEF_HELPER_FLAGS_2(clear_softint, TCG_CALL_NO_RWG, void, env, i64)
DEF_HELPER_FLAGS_2(write_softint, TCG_CALL_NO_RWG, void, env, i64)
@@ -26,9 +25,6 @@ DEF_HELPER_FLAGS_2(tick_set_count, TCG_CALL_NO_RWG, void, ptr, i64)
DEF_HELPER_FLAGS_3(tick_get_count, TCG_CALL_NO_WG, i64, env, ptr, int)
DEF_HELPER_FLAGS_2(tick_set_limit, TCG_CALL_NO_RWG, void, ptr, i64)
#endif
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
DEF_HELPER_FLAGS_5(cas_asi, TCG_CALL_NO_WG, tl, env, tl, tl, tl, i32)
#endif
DEF_HELPER_FLAGS_3(check_align, TCG_CALL_NO_WG, void, env, tl, i32)
DEF_HELPER_1(debug, void, env)
DEF_HELPER_1(save, void, env)
+0 −29
Original line number Diff line number Diff line
@@ -2150,37 +2150,8 @@ void helper_ldda_asi(CPUSPARCState *env, target_ulong addr, int asi)
    QT0.high = h;
    QT0.low = l;
}

target_ulong helper_casx_asi(CPUSPARCState *env, target_ulong addr,
                             target_ulong val1, target_ulong val2,
                             uint32_t asi)
{
    target_ulong ret;

    ret = helper_ld_asi(env, addr, asi, MO_Q);
    if (val2 == ret) {
        helper_st_asi(env, addr, val1, asi, MO_Q);
    }
    return ret;
}
#endif /* TARGET_SPARC64 */

#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
target_ulong helper_cas_asi(CPUSPARCState *env, target_ulong addr,
                            target_ulong val1, target_ulong val2, uint32_t asi)
{
    target_ulong ret;

    val2 &= 0xffffffffUL;
    ret = helper_ld_asi(env, addr, asi, MO_UL);
    ret &= 0xffffffffUL;
    if (val2 == ret) {
        helper_st_asi(env, addr, val1 & 0xffffffffUL, asi, MO_UL);
    }
    return ret;
}
#endif /* !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) */

void helper_ldqf(CPUSPARCState *env, target_ulong addr, int mem_idx)
{
    /* XXX add 128 bit load */
+47 −23
Original line number Diff line number Diff line
@@ -2338,24 +2338,37 @@ static void gen_swap_asi(DisasContext *dc, TCGv dst, TCGv src,
    }
}

static void gen_cas_asi(DisasContext *dc, TCGv addr, TCGv val2,
static void gen_cas_asi(DisasContext *dc, TCGv addr, TCGv cmpr,
                        int insn, int rd)
{
    DisasASI da = get_asi(dc, insn, MO_TEUL);
    TCGv val1, dst;
    TCGv_i32 r_asi;
    TCGv cmpv, oldv, tmpv;

    if (da.type == GET_ASI_EXCP) {
    switch (da.type) {
    case GET_ASI_EXCP:
        return;
    }
    case GET_ASI_DIRECT:
        cmpv = tcg_temp_new();
        oldv = tcg_temp_new();
        tmpv = tcg_temp_new();
        tcg_gen_ext32u_tl(cmpv, cmpr);

    save_state(dc);
    val1 = gen_load_gpr(dc, rd);
    dst = gen_dest_gpr(dc, rd);
    r_asi = tcg_const_i32(da.asi);
    gen_helper_cas_asi(dst, cpu_env, addr, val1, val2, r_asi);
    tcg_temp_free_i32(r_asi);
    gen_store_gpr(dc, rd, dst);
        /* ??? Should be atomic.  */
        tcg_gen_qemu_ld_tl(oldv, addr, da.mem_idx, da.memop);
        tcg_gen_movcond_tl(TCG_COND_EQ, tmpv, oldv, cmpv,
                           gen_load_gpr(dc, rd), oldv);
        tcg_gen_qemu_st_tl(tmpv, addr, da.mem_idx, da.memop);

        gen_store_gpr(dc, rd, oldv);
        tcg_temp_free(cmpv);
        tcg_temp_free(oldv);
        tcg_temp_free(tmpv);
        break;
    default:
        /* ??? Should be DAE_invalid_asi.  */
        gen_exception(dc, TT_DATA_ACCESS);
        break;
    }
}

static void gen_ldstub_asi(DisasContext *dc, TCGv dst, TCGv addr, int insn)
@@ -2668,23 +2681,34 @@ static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
    }
}

static void gen_casx_asi(DisasContext *dc, TCGv addr, TCGv val2,
static void gen_casx_asi(DisasContext *dc, TCGv addr, TCGv cmpv,
                         int insn, int rd)
{
    DisasASI da = get_asi(dc, insn, MO_TEQ);
    TCGv val1 = gen_load_gpr(dc, rd);
    TCGv dst = gen_dest_gpr(dc, rd);
    TCGv_i32 r_asi;
    TCGv oldv, tmpv;

    if (da.type == GET_ASI_EXCP) {
    switch (da.type) {
    case GET_ASI_EXCP:
        return;
    }
    case GET_ASI_DIRECT:
        oldv = tcg_temp_new();
        tmpv = tcg_temp_new();

    save_state(dc);
    r_asi = tcg_const_i32(da.asi);
    gen_helper_casx_asi(dst, cpu_env, addr, val1, val2, r_asi);
    tcg_temp_free_i32(r_asi);
    gen_store_gpr(dc, rd, dst);
        /* ??? Should be atomic.  */
        tcg_gen_qemu_ld_tl(oldv, addr, da.mem_idx, da.memop);
        tcg_gen_movcond_tl(TCG_COND_EQ, tmpv, oldv, cmpv,
                           gen_load_gpr(dc, rd), oldv);
        tcg_gen_qemu_st_tl(tmpv, addr, da.mem_idx, da.memop);

        gen_store_gpr(dc, rd, oldv);
        tcg_temp_free(oldv);
        tcg_temp_free(tmpv);
        break;
    default:
        /* ??? Should be DAE_invalid_asi.  */
        gen_exception(dc, TT_DATA_ACCESS);
        break;
    }
}

#elif !defined(CONFIG_USER_ONLY)