qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

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)