/*
 * Power ISA decode for Storage Control instructions
 *
 * Copyright (c) 2022 Instituto de Pesquisas Eldorado (eldorado.org.br)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */

/*
 * Store Control Instructions
 */

#include "mmu-book3s-v3.h"

static bool trans_SLBIE(DisasContext *ctx, arg_SLBIE *a)
{
    REQUIRE_64BIT(ctx);
    REQUIRE_INSNS_FLAGS(ctx, SLBI);
    REQUIRE_SV(ctx);

#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
    gen_helper_SLBIE(tcg_env, cpu_gpr[a->rb]);
#else
    qemu_build_not_reached();
#endif
    return true;
}

static bool trans_SLBIEG(DisasContext *ctx, arg_SLBIEG *a)
{
    REQUIRE_64BIT(ctx);
    REQUIRE_INSNS_FLAGS2(ctx, ISA300);
    REQUIRE_SV(ctx);

#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
    gen_helper_SLBIEG(tcg_env, cpu_gpr[a->rb]);
#else
    qemu_build_not_reached();
#endif
    return true;
}

static bool trans_SLBIA(DisasContext *ctx, arg_SLBIA *a)
{
    REQUIRE_64BIT(ctx);
    REQUIRE_INSNS_FLAGS(ctx, SLBI);
    REQUIRE_SV(ctx);

#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
    gen_helper_SLBIA(tcg_env, tcg_constant_i32(a->ih));
#else
    qemu_build_not_reached();
#endif
    return true;
}

static bool trans_SLBIAG(DisasContext *ctx, arg_SLBIAG *a)
{
    REQUIRE_64BIT(ctx);
    REQUIRE_INSNS_FLAGS2(ctx, ISA300);
    REQUIRE_SV(ctx);

#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
    gen_helper_SLBIAG(tcg_env, cpu_gpr[a->rs], tcg_constant_i32(a->l));
#else
    qemu_build_not_reached();
#endif
    return true;
}

static bool trans_SLBMTE(DisasContext *ctx, arg_SLBMTE *a)
{
    REQUIRE_64BIT(ctx);
    REQUIRE_INSNS_FLAGS(ctx, SEGMENT_64B);
    REQUIRE_SV(ctx);

#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
    gen_helper_SLBMTE(tcg_env, cpu_gpr[a->rb], cpu_gpr[a->rt]);
#else
    qemu_build_not_reached();
#endif
    return true;
}

static bool trans_SLBMFEV(DisasContext *ctx, arg_SLBMFEV *a)
{
    REQUIRE_64BIT(ctx);
    REQUIRE_INSNS_FLAGS(ctx, SEGMENT_64B);
    REQUIRE_SV(ctx);

#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
    gen_helper_SLBMFEV(cpu_gpr[a->rt], tcg_env, cpu_gpr[a->rb]);
#else
    qemu_build_not_reached();
#endif
    return true;
}

static bool trans_SLBMFEE(DisasContext *ctx, arg_SLBMFEE *a)
{
    REQUIRE_64BIT(ctx);
    REQUIRE_INSNS_FLAGS(ctx, SEGMENT_64B);
    REQUIRE_SV(ctx);

#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
    gen_helper_SLBMFEE(cpu_gpr[a->rt], tcg_env, cpu_gpr[a->rb]);
#else
    qemu_build_not_reached();
#endif
    return true;
}

static bool trans_SLBFEE(DisasContext *ctx, arg_SLBFEE *a)
{
    REQUIRE_64BIT(ctx);
    REQUIRE_INSNS_FLAGS(ctx, SEGMENT_64B);

#if defined(CONFIG_USER_ONLY)
    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
#else

#if defined(TARGET_PPC64)
    TCGLabel *l1, *l2;

    if (unlikely(ctx->pr)) {
        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
        return true;
    }
    gen_helper_SLBFEE(cpu_gpr[a->rt], tcg_env,
                             cpu_gpr[a->rb]);
    l1 = gen_new_label();
    l2 = gen_new_label();
    tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[a->rt], -1, l1);
    tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], CRF_EQ);
    tcg_gen_br(l2);
    gen_set_label(l1);
    tcg_gen_movi_tl(cpu_gpr[a->rt], 0);
    gen_set_label(l2);
#else
    qemu_build_not_reached();
#endif
#endif
    return true;
}

static bool trans_SLBSYNC(DisasContext *ctx, arg_SLBSYNC *a)
{
    REQUIRE_64BIT(ctx);
    REQUIRE_INSNS_FLAGS2(ctx, ISA300);
    REQUIRE_SV(ctx);

#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
    gen_check_tlb_flush(ctx, true);
#else
    qemu_build_not_reached();
#endif
    return true;
}

static bool do_tlbie(DisasContext *ctx, arg_X_tlbie *a, bool local)
{
#if defined(CONFIG_USER_ONLY)
    gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC);
    return true;
#else
    TCGv_i32 t1;
    int rb;

    rb = a->rb;

    if ((ctx->insns_flags2 & PPC2_ISA300) == 0) {
        /*
         * Before Power ISA 3.0, the corresponding bits of RIC, PRS, and R
         * (and RS for tlbiel) were reserved fields and should be ignored.
         */
        a->ric = 0;
        a->prs = false;
        a->r = false;
        if (local) {
            a->rs = 0;
        }
    }

    if (ctx->pr) {
        /* tlbie[l] is privileged... */
        gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC);
        return true;
    } else if (!ctx->hv) {
        if ((!a->prs && ctx->hr) || (!local && !ctx->gtse)) {
            /*
             * ... except when PRS=0 and HR=1, or when GTSE=0 for tlbie,
             * making it hypervisor privileged.
             */
            gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC);
            return true;
        }
    }

    if (!local && NARROW_MODE(ctx)) {
        TCGv t0 = tcg_temp_new();
        tcg_gen_ext32u_tl(t0, cpu_gpr[rb]);
        gen_helper_tlbie(tcg_env, t0);

#if defined(TARGET_PPC64)
    /*
     * ISA 3.1B says that MSR SF must be 1 when this instruction is executed;
     * otherwise the results are undefined.
     */
    } else if (a->r) {
        gen_helper_tlbie_isa300(tcg_env, cpu_gpr[rb], cpu_gpr[a->rs],
                tcg_constant_i32(a->ric << TLBIE_F_RIC_SHIFT |
                                 a->prs << TLBIE_F_PRS_SHIFT |
                                 a->r << TLBIE_F_R_SHIFT |
                                 local << TLBIE_F_LOCAL_SHIFT));
        return true;
#endif

    } else {
        gen_helper_tlbie(tcg_env, cpu_gpr[rb]);
    }

    if (local) {
        return true;
    }

    t1 = tcg_temp_new_i32();
    tcg_gen_ld_i32(t1, tcg_env, offsetof(CPUPPCState, tlb_need_flush));
    tcg_gen_ori_i32(t1, t1, TLB_NEED_GLOBAL_FLUSH);
    tcg_gen_st_i32(t1, tcg_env, offsetof(CPUPPCState, tlb_need_flush));

    return true;
#endif
}

TRANS_FLAGS(MEM_TLBIE, TLBIE, do_tlbie, false)
TRANS_FLAGS(MEM_TLBIE, TLBIEL, do_tlbie, true)
