storage-ctrl-impl.c.inc (6573B)
1 /* 2 * Power ISA decode for Storage Control instructions 3 * 4 * Copyright (c) 2022 Instituto de Pesquisas Eldorado (eldorado.org.br) 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 /* 21 * Store Control Instructions 22 */ 23 24 #include "mmu-book3s-v3.h" 25 26 static bool trans_SLBIE(DisasContext *ctx, arg_SLBIE *a) 27 { 28 REQUIRE_64BIT(ctx); 29 REQUIRE_INSNS_FLAGS(ctx, SLBI); 30 REQUIRE_SV(ctx); 31 32 #if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64) 33 gen_helper_SLBIE(cpu_env, cpu_gpr[a->rb]); 34 #else 35 qemu_build_not_reached(); 36 #endif 37 return true; 38 } 39 40 static bool trans_SLBIEG(DisasContext *ctx, arg_SLBIEG *a) 41 { 42 REQUIRE_64BIT(ctx); 43 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 44 REQUIRE_SV(ctx); 45 46 #if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64) 47 gen_helper_SLBIEG(cpu_env, cpu_gpr[a->rb]); 48 #else 49 qemu_build_not_reached(); 50 #endif 51 return true; 52 } 53 54 static bool trans_SLBIA(DisasContext *ctx, arg_SLBIA *a) 55 { 56 REQUIRE_64BIT(ctx); 57 REQUIRE_INSNS_FLAGS(ctx, SLBI); 58 REQUIRE_SV(ctx); 59 60 #if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64) 61 gen_helper_SLBIA(cpu_env, tcg_constant_i32(a->ih)); 62 #else 63 qemu_build_not_reached(); 64 #endif 65 return true; 66 } 67 68 static bool trans_SLBIAG(DisasContext *ctx, arg_SLBIAG *a) 69 { 70 REQUIRE_64BIT(ctx); 71 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 72 REQUIRE_SV(ctx); 73 74 #if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64) 75 gen_helper_SLBIAG(cpu_env, cpu_gpr[a->rs], tcg_constant_i32(a->l)); 76 #else 77 qemu_build_not_reached(); 78 #endif 79 return true; 80 } 81 82 static bool trans_SLBMTE(DisasContext *ctx, arg_SLBMTE *a) 83 { 84 REQUIRE_64BIT(ctx); 85 REQUIRE_INSNS_FLAGS(ctx, SEGMENT_64B); 86 REQUIRE_SV(ctx); 87 88 #if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64) 89 gen_helper_SLBMTE(cpu_env, cpu_gpr[a->rb], cpu_gpr[a->rt]); 90 #else 91 qemu_build_not_reached(); 92 #endif 93 return true; 94 } 95 96 static bool trans_SLBMFEV(DisasContext *ctx, arg_SLBMFEV *a) 97 { 98 REQUIRE_64BIT(ctx); 99 REQUIRE_INSNS_FLAGS(ctx, SEGMENT_64B); 100 REQUIRE_SV(ctx); 101 102 #if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64) 103 gen_helper_SLBMFEV(cpu_gpr[a->rt], cpu_env, cpu_gpr[a->rb]); 104 #else 105 qemu_build_not_reached(); 106 #endif 107 return true; 108 } 109 110 static bool trans_SLBMFEE(DisasContext *ctx, arg_SLBMFEE *a) 111 { 112 REQUIRE_64BIT(ctx); 113 REQUIRE_INSNS_FLAGS(ctx, SEGMENT_64B); 114 REQUIRE_SV(ctx); 115 116 #if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64) 117 gen_helper_SLBMFEE(cpu_gpr[a->rt], cpu_env, cpu_gpr[a->rb]); 118 #else 119 qemu_build_not_reached(); 120 #endif 121 return true; 122 } 123 124 static bool trans_SLBFEE(DisasContext *ctx, arg_SLBFEE *a) 125 { 126 REQUIRE_64BIT(ctx); 127 REQUIRE_INSNS_FLAGS(ctx, SEGMENT_64B); 128 129 #if defined(CONFIG_USER_ONLY) 130 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); 131 #else 132 133 #if defined(TARGET_PPC64) 134 TCGLabel *l1, *l2; 135 136 if (unlikely(ctx->pr)) { 137 gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); 138 return true; 139 } 140 gen_helper_SLBFEE(cpu_gpr[a->rt], cpu_env, 141 cpu_gpr[a->rb]); 142 l1 = gen_new_label(); 143 l2 = gen_new_label(); 144 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so); 145 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[a->rt], -1, l1); 146 tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], CRF_EQ); 147 tcg_gen_br(l2); 148 gen_set_label(l1); 149 tcg_gen_movi_tl(cpu_gpr[a->rt], 0); 150 gen_set_label(l2); 151 #else 152 qemu_build_not_reached(); 153 #endif 154 #endif 155 return true; 156 } 157 158 static bool trans_SLBSYNC(DisasContext *ctx, arg_SLBSYNC *a) 159 { 160 REQUIRE_64BIT(ctx); 161 REQUIRE_INSNS_FLAGS2(ctx, ISA300); 162 REQUIRE_SV(ctx); 163 164 #if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64) 165 gen_check_tlb_flush(ctx, true); 166 #else 167 qemu_build_not_reached(); 168 #endif 169 return true; 170 } 171 172 static bool do_tlbie(DisasContext *ctx, arg_X_tlbie *a, bool local) 173 { 174 #if defined(CONFIG_USER_ONLY) 175 gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC); 176 return true; 177 #else 178 TCGv_i32 t1; 179 int rb; 180 181 rb = a->rb; 182 183 if ((ctx->insns_flags2 & PPC2_ISA300) == 0) { 184 /* 185 * Before Power ISA 3.0, the corresponding bits of RIC, PRS, and R 186 * (and RS for tlbiel) were reserved fields and should be ignored. 187 */ 188 a->ric = 0; 189 a->prs = false; 190 a->r = false; 191 if (local) { 192 a->rs = 0; 193 } 194 } 195 196 if (ctx->pr) { 197 /* tlbie[l] is privileged... */ 198 gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC); 199 return true; 200 } else if (!ctx->hv) { 201 if ((!a->prs && ctx->hr) || (!local && !ctx->gtse)) { 202 /* 203 * ... except when PRS=0 and HR=1, or when GTSE=0 for tlbie, 204 * making it hypervisor privileged. 205 */ 206 gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC); 207 return true; 208 } 209 } 210 211 if (!local && NARROW_MODE(ctx)) { 212 TCGv t0 = tcg_temp_new(); 213 tcg_gen_ext32u_tl(t0, cpu_gpr[rb]); 214 gen_helper_tlbie(cpu_env, t0); 215 tcg_temp_free(t0); 216 217 #if defined(TARGET_PPC64) 218 /* 219 * ISA 3.1B says that MSR SF must be 1 when this instruction is executed; 220 * otherwise the results are undefined. 221 */ 222 } else if (a->r) { 223 gen_helper_tlbie_isa300(cpu_env, cpu_gpr[rb], cpu_gpr[a->rs], 224 tcg_constant_i32(a->ric << TLBIE_F_RIC_SHIFT | 225 a->prs << TLBIE_F_PRS_SHIFT | 226 a->r << TLBIE_F_R_SHIFT | 227 local << TLBIE_F_LOCAL_SHIFT)); 228 return true; 229 #endif 230 231 } else { 232 gen_helper_tlbie(cpu_env, cpu_gpr[rb]); 233 } 234 235 if (local) { 236 return true; 237 } 238 239 t1 = tcg_temp_new_i32(); 240 tcg_gen_ld_i32(t1, cpu_env, offsetof(CPUPPCState, tlb_need_flush)); 241 tcg_gen_ori_i32(t1, t1, TLB_NEED_GLOBAL_FLUSH); 242 tcg_gen_st_i32(t1, cpu_env, offsetof(CPUPPCState, tlb_need_flush)); 243 tcg_temp_free_i32(t1); 244 245 return true; 246 #endif 247 } 248 249 TRANS_FLAGS(MEM_TLBIE, TLBIE, do_tlbie, false) 250 TRANS_FLAGS(MEM_TLBIE, TLBIEL, do_tlbie, true)