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