1016b6e1dSLeandro Lupori/*
2016b6e1dSLeandro Lupori * Power ISA decode for Storage Control instructions
3016b6e1dSLeandro Lupori *
4016b6e1dSLeandro Lupori * Copyright (c) 2022 Instituto de Pesquisas Eldorado (eldorado.org.br)
5016b6e1dSLeandro Lupori *
6016b6e1dSLeandro Lupori * This library is free software; you can redistribute it and/or
7016b6e1dSLeandro Lupori * modify it under the terms of the GNU Lesser General Public
8016b6e1dSLeandro Lupori * License as published by the Free Software Foundation; either
9016b6e1dSLeandro Lupori * version 2.1 of the License, or (at your option) any later version.
10016b6e1dSLeandro Lupori *
11016b6e1dSLeandro Lupori * This library is distributed in the hope that it will be useful,
12016b6e1dSLeandro Lupori * but WITHOUT ANY WARRANTY; without even the implied warranty of
13016b6e1dSLeandro Lupori * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14016b6e1dSLeandro Lupori * Lesser General Public License for more details.
15016b6e1dSLeandro Lupori *
16016b6e1dSLeandro Lupori * You should have received a copy of the GNU Lesser General Public
17016b6e1dSLeandro Lupori * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18016b6e1dSLeandro Lupori */
19016b6e1dSLeandro Lupori
20016b6e1dSLeandro Lupori/*
21016b6e1dSLeandro Lupori * Store Control Instructions
22016b6e1dSLeandro Lupori */
23016b6e1dSLeandro Lupori
24e7beaea5SLeandro Lupori#include "mmu-book3s-v3.h"
25e7beaea5SLeandro Lupori
2643507e47SLucas Coutinhostatic bool trans_SLBIE(DisasContext *ctx, arg_SLBIE *a)
2743507e47SLucas Coutinho{
2843507e47SLucas Coutinho    REQUIRE_64BIT(ctx);
2943507e47SLucas Coutinho    REQUIRE_INSNS_FLAGS(ctx, SLBI);
3043507e47SLucas Coutinho    REQUIRE_SV(ctx);
3143507e47SLucas Coutinho
3243507e47SLucas Coutinho#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
33ad75a51eSRichard Henderson    gen_helper_SLBIE(tcg_env, cpu_gpr[a->rb]);
3443507e47SLucas Coutinho#else
3543507e47SLucas Coutinho    qemu_build_not_reached();
3643507e47SLucas Coutinho#endif
3743507e47SLucas Coutinho    return true;
3843507e47SLucas Coutinho}
3943507e47SLucas Coutinho
40a1b05c06SLucas Coutinhostatic bool trans_SLBIEG(DisasContext *ctx, arg_SLBIEG *a)
41a1b05c06SLucas Coutinho{
42a1b05c06SLucas Coutinho    REQUIRE_64BIT(ctx);
43a1b05c06SLucas Coutinho    REQUIRE_INSNS_FLAGS2(ctx, ISA300);
44a1b05c06SLucas Coutinho    REQUIRE_SV(ctx);
45a1b05c06SLucas Coutinho
46a1b05c06SLucas Coutinho#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
47ad75a51eSRichard Henderson    gen_helper_SLBIEG(tcg_env, cpu_gpr[a->rb]);
48a1b05c06SLucas Coutinho#else
49a1b05c06SLucas Coutinho    qemu_build_not_reached();
50a1b05c06SLucas Coutinho#endif
51a1b05c06SLucas Coutinho    return true;
52a1b05c06SLucas Coutinho}
53a1b05c06SLucas Coutinho
542bfcb7a3SLucas Coutinhostatic bool trans_SLBIA(DisasContext *ctx, arg_SLBIA *a)
552bfcb7a3SLucas Coutinho{
562bfcb7a3SLucas Coutinho    REQUIRE_64BIT(ctx);
572bfcb7a3SLucas Coutinho    REQUIRE_INSNS_FLAGS(ctx, SLBI);
582bfcb7a3SLucas Coutinho    REQUIRE_SV(ctx);
592bfcb7a3SLucas Coutinho
602bfcb7a3SLucas Coutinho#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
61ad75a51eSRichard Henderson    gen_helper_SLBIA(tcg_env, tcg_constant_i32(a->ih));
622bfcb7a3SLucas Coutinho#else
632bfcb7a3SLucas Coutinho    qemu_build_not_reached();
642bfcb7a3SLucas Coutinho#endif
652bfcb7a3SLucas Coutinho    return true;
662bfcb7a3SLucas Coutinho}
672bfcb7a3SLucas Coutinho
68491a2553SLucas Coutinhostatic bool trans_SLBIAG(DisasContext *ctx, arg_SLBIAG *a)
69491a2553SLucas Coutinho{
70491a2553SLucas Coutinho    REQUIRE_64BIT(ctx);
71491a2553SLucas Coutinho    REQUIRE_INSNS_FLAGS2(ctx, ISA300);
72491a2553SLucas Coutinho    REQUIRE_SV(ctx);
73491a2553SLucas Coutinho
74491a2553SLucas Coutinho#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
75ad75a51eSRichard Henderson    gen_helper_SLBIAG(tcg_env, cpu_gpr[a->rs], tcg_constant_i32(a->l));
76491a2553SLucas Coutinho#else
77491a2553SLucas Coutinho    qemu_build_not_reached();
78491a2553SLucas Coutinho#endif
79491a2553SLucas Coutinho    return true;
80491a2553SLucas Coutinho}
81491a2553SLucas Coutinho
820b0ba40fSLucas Coutinhostatic bool trans_SLBMTE(DisasContext *ctx, arg_SLBMTE *a)
830b0ba40fSLucas Coutinho{
840b0ba40fSLucas Coutinho    REQUIRE_64BIT(ctx);
850b0ba40fSLucas Coutinho    REQUIRE_INSNS_FLAGS(ctx, SEGMENT_64B);
860b0ba40fSLucas Coutinho    REQUIRE_SV(ctx);
870b0ba40fSLucas Coutinho
880b0ba40fSLucas Coutinho#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
89ad75a51eSRichard Henderson    gen_helper_SLBMTE(tcg_env, cpu_gpr[a->rb], cpu_gpr[a->rt]);
900b0ba40fSLucas Coutinho#else
910b0ba40fSLucas Coutinho    qemu_build_not_reached();
920b0ba40fSLucas Coutinho#endif
930b0ba40fSLucas Coutinho    return true;
940b0ba40fSLucas Coutinho}
950b0ba40fSLucas Coutinho
9674a15384SLucas Coutinhostatic bool trans_SLBMFEV(DisasContext *ctx, arg_SLBMFEV *a)
9774a15384SLucas Coutinho{
9874a15384SLucas Coutinho    REQUIRE_64BIT(ctx);
9974a15384SLucas Coutinho    REQUIRE_INSNS_FLAGS(ctx, SEGMENT_64B);
10074a15384SLucas Coutinho    REQUIRE_SV(ctx);
10174a15384SLucas Coutinho
10274a15384SLucas Coutinho#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
103ad75a51eSRichard Henderson    gen_helper_SLBMFEV(cpu_gpr[a->rt], tcg_env, cpu_gpr[a->rb]);
10474a15384SLucas Coutinho#else
10574a15384SLucas Coutinho    qemu_build_not_reached();
10674a15384SLucas Coutinho#endif
10774a15384SLucas Coutinho    return true;
10874a15384SLucas Coutinho}
10974a15384SLucas Coutinho
11041b60e46SLucas Coutinhostatic bool trans_SLBMFEE(DisasContext *ctx, arg_SLBMFEE *a)
11141b60e46SLucas Coutinho{
11241b60e46SLucas Coutinho    REQUIRE_64BIT(ctx);
11341b60e46SLucas Coutinho    REQUIRE_INSNS_FLAGS(ctx, SEGMENT_64B);
11441b60e46SLucas Coutinho    REQUIRE_SV(ctx);
11541b60e46SLucas Coutinho
11641b60e46SLucas Coutinho#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
117ad75a51eSRichard Henderson    gen_helper_SLBMFEE(cpu_gpr[a->rt], tcg_env, cpu_gpr[a->rb]);
11841b60e46SLucas Coutinho#else
11941b60e46SLucas Coutinho    qemu_build_not_reached();
12041b60e46SLucas Coutinho#endif
12141b60e46SLucas Coutinho    return true;
12241b60e46SLucas Coutinho}
12341b60e46SLucas Coutinho
12426d02c9dSLucas Coutinhostatic bool trans_SLBFEE(DisasContext *ctx, arg_SLBFEE *a)
12526d02c9dSLucas Coutinho{
12626d02c9dSLucas Coutinho    REQUIRE_64BIT(ctx);
12726d02c9dSLucas Coutinho    REQUIRE_INSNS_FLAGS(ctx, SEGMENT_64B);
12826d02c9dSLucas Coutinho
12926d02c9dSLucas Coutinho#if defined(CONFIG_USER_ONLY)
13026d02c9dSLucas Coutinho    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
13126d02c9dSLucas Coutinho#else
13226d02c9dSLucas Coutinho
13326d02c9dSLucas Coutinho#if defined(TARGET_PPC64)
13426d02c9dSLucas Coutinho    TCGLabel *l1, *l2;
13526d02c9dSLucas Coutinho
13626d02c9dSLucas Coutinho    if (unlikely(ctx->pr)) {
13726d02c9dSLucas Coutinho        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
13826d02c9dSLucas Coutinho        return true;
13926d02c9dSLucas Coutinho    }
140ad75a51eSRichard Henderson    gen_helper_SLBFEE(cpu_gpr[a->rt], tcg_env,
14126d02c9dSLucas Coutinho                             cpu_gpr[a->rb]);
14226d02c9dSLucas Coutinho    l1 = gen_new_label();
14326d02c9dSLucas Coutinho    l2 = gen_new_label();
14426d02c9dSLucas Coutinho    tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
14526d02c9dSLucas Coutinho    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[a->rt], -1, l1);
14626d02c9dSLucas Coutinho    tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], CRF_EQ);
14726d02c9dSLucas Coutinho    tcg_gen_br(l2);
14826d02c9dSLucas Coutinho    gen_set_label(l1);
14926d02c9dSLucas Coutinho    tcg_gen_movi_tl(cpu_gpr[a->rt], 0);
15026d02c9dSLucas Coutinho    gen_set_label(l2);
15126d02c9dSLucas Coutinho#else
15226d02c9dSLucas Coutinho    qemu_build_not_reached();
15326d02c9dSLucas Coutinho#endif
15426d02c9dSLucas Coutinho#endif
15526d02c9dSLucas Coutinho    return true;
15626d02c9dSLucas Coutinho}
15726d02c9dSLucas Coutinho
158acc130cfSLucas Coutinhostatic bool trans_SLBSYNC(DisasContext *ctx, arg_SLBSYNC *a)
159acc130cfSLucas Coutinho{
160acc130cfSLucas Coutinho    REQUIRE_64BIT(ctx);
161acc130cfSLucas Coutinho    REQUIRE_INSNS_FLAGS2(ctx, ISA300);
162acc130cfSLucas Coutinho    REQUIRE_SV(ctx);
163acc130cfSLucas Coutinho
164acc130cfSLucas Coutinho#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
165acc130cfSLucas Coutinho    gen_check_tlb_flush(ctx, true);
166acc130cfSLucas Coutinho#else
167acc130cfSLucas Coutinho    qemu_build_not_reached();
168acc130cfSLucas Coutinho#endif
169acc130cfSLucas Coutinho    return true;
170acc130cfSLucas Coutinho}
171acc130cfSLucas Coutinho
172016b6e1dSLeandro Luporistatic bool do_tlbie(DisasContext *ctx, arg_X_tlbie *a, bool local)
173016b6e1dSLeandro Lupori{
174016b6e1dSLeandro Lupori#if defined(CONFIG_USER_ONLY)
175016b6e1dSLeandro Lupori    gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC);
176016b6e1dSLeandro Lupori    return true;
177016b6e1dSLeandro Lupori#else
178016b6e1dSLeandro Lupori    TCGv_i32 t1;
179016b6e1dSLeandro Lupori    int rb;
180016b6e1dSLeandro Lupori
181016b6e1dSLeandro Lupori    rb = a->rb;
182016b6e1dSLeandro Lupori
183016b6e1dSLeandro Lupori    if ((ctx->insns_flags2 & PPC2_ISA300) == 0) {
184016b6e1dSLeandro Lupori        /*
185016b6e1dSLeandro Lupori         * Before Power ISA 3.0, the corresponding bits of RIC, PRS, and R
186016b6e1dSLeandro Lupori         * (and RS for tlbiel) were reserved fields and should be ignored.
187016b6e1dSLeandro Lupori         */
188016b6e1dSLeandro Lupori        a->ric = 0;
189016b6e1dSLeandro Lupori        a->prs = false;
190016b6e1dSLeandro Lupori        a->r = false;
191016b6e1dSLeandro Lupori        if (local) {
192016b6e1dSLeandro Lupori            a->rs = 0;
193016b6e1dSLeandro Lupori        }
194016b6e1dSLeandro Lupori    }
195016b6e1dSLeandro Lupori
196016b6e1dSLeandro Lupori    if (ctx->pr) {
197016b6e1dSLeandro Lupori        /* tlbie[l] is privileged... */
198016b6e1dSLeandro Lupori        gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC);
199016b6e1dSLeandro Lupori        return true;
200016b6e1dSLeandro Lupori    } else if (!ctx->hv) {
201016b6e1dSLeandro Lupori        if ((!a->prs && ctx->hr) || (!local && !ctx->gtse)) {
202016b6e1dSLeandro Lupori            /*
203016b6e1dSLeandro Lupori             * ... except when PRS=0 and HR=1, or when GTSE=0 for tlbie,
204016b6e1dSLeandro Lupori             * making it hypervisor privileged.
205016b6e1dSLeandro Lupori             */
206016b6e1dSLeandro Lupori            gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC);
207016b6e1dSLeandro Lupori            return true;
208016b6e1dSLeandro Lupori        }
209016b6e1dSLeandro Lupori    }
210016b6e1dSLeandro Lupori
211016b6e1dSLeandro Lupori    if (!local && NARROW_MODE(ctx)) {
212016b6e1dSLeandro Lupori        TCGv t0 = tcg_temp_new();
213016b6e1dSLeandro Lupori        tcg_gen_ext32u_tl(t0, cpu_gpr[rb]);
214ad75a51eSRichard Henderson        gen_helper_tlbie(tcg_env, t0);
215e7beaea5SLeandro Lupori
216e7beaea5SLeandro Lupori#if defined(TARGET_PPC64)
217e7beaea5SLeandro Lupori    /*
218e7beaea5SLeandro Lupori     * ISA 3.1B says that MSR SF must be 1 when this instruction is executed;
219e7beaea5SLeandro Lupori     * otherwise the results are undefined.
220e7beaea5SLeandro Lupori     */
221e7beaea5SLeandro Lupori    } else if (a->r) {
222ad75a51eSRichard Henderson        gen_helper_tlbie_isa300(tcg_env, cpu_gpr[rb], cpu_gpr[a->rs],
223e7beaea5SLeandro Lupori                tcg_constant_i32(a->ric << TLBIE_F_RIC_SHIFT |
224e7beaea5SLeandro Lupori                                 a->prs << TLBIE_F_PRS_SHIFT |
225e7beaea5SLeandro Lupori                                 a->r << TLBIE_F_R_SHIFT |
226e7beaea5SLeandro Lupori                                 local << TLBIE_F_LOCAL_SHIFT));
227e7beaea5SLeandro Lupori        return true;
228e7beaea5SLeandro Lupori#endif
229e7beaea5SLeandro Lupori
230016b6e1dSLeandro Lupori    } else {
231ad75a51eSRichard Henderson        gen_helper_tlbie(tcg_env, cpu_gpr[rb]);
232016b6e1dSLeandro Lupori    }
233016b6e1dSLeandro Lupori
234016b6e1dSLeandro Lupori    if (local) {
235016b6e1dSLeandro Lupori        return true;
236016b6e1dSLeandro Lupori    }
237016b6e1dSLeandro Lupori
238016b6e1dSLeandro Lupori    t1 = tcg_temp_new_i32();
239ad75a51eSRichard Henderson    tcg_gen_ld_i32(t1, tcg_env, offsetof(CPUPPCState, tlb_need_flush));
240016b6e1dSLeandro Lupori    tcg_gen_ori_i32(t1, t1, TLB_NEED_GLOBAL_FLUSH);
241ad75a51eSRichard Henderson    tcg_gen_st_i32(t1, tcg_env, offsetof(CPUPPCState, tlb_need_flush));
242016b6e1dSLeandro Lupori
243016b6e1dSLeandro Lupori    return true;
244016b6e1dSLeandro Lupori#endif
245016b6e1dSLeandro Lupori}
246016b6e1dSLeandro Lupori
247016b6e1dSLeandro LuporiTRANS_FLAGS(MEM_TLBIE, TLBIE, do_tlbie, false)
248016b6e1dSLeandro LuporiTRANS_FLAGS(MEM_TLBIE, TLBIEL, do_tlbie, true)
249