qemu

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

trans_rvh.c.inc (4577B)


      1 /*
      2  * RISC-V translation routines for the RVXI Base Integer Instruction Set.
      3  *
      4  * Copyright (c) 2020 Western Digital
      5  *
      6  * This program is free software; you can redistribute it and/or modify it
      7  * under the terms and conditions of the GNU General Public License,
      8  * version 2 or later, as published by the Free Software Foundation.
      9  *
     10  * This program is distributed in the hope it will be useful, but WITHOUT
     11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     13  * more details.
     14  *
     15  * You should have received a copy of the GNU General Public License along with
     16  * this program.  If not, see <http://www.gnu.org/licenses/>.
     17  */
     18 
     19 #ifndef CONFIG_USER_ONLY
     20 static bool check_access(DisasContext *ctx)
     21 {
     22     if (!ctx->hlsx) {
     23         if (ctx->virt_enabled) {
     24             generate_exception(ctx, RISCV_EXCP_VIRT_INSTRUCTION_FAULT);
     25         } else {
     26             generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST);
     27         }
     28         return false;
     29     }
     30     return true;
     31 }
     32 #endif
     33 
     34 static bool do_hlv(DisasContext *ctx, arg_r2 *a, MemOp mop)
     35 {
     36 #ifdef CONFIG_USER_ONLY
     37     return false;
     38 #else
     39     if (check_access(ctx)) {
     40         TCGv dest = dest_gpr(ctx, a->rd);
     41         TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
     42         int mem_idx = ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
     43         tcg_gen_qemu_ld_tl(dest, addr, mem_idx, mop);
     44         gen_set_gpr(ctx, a->rd, dest);
     45     }
     46     return true;
     47 #endif
     48 }
     49 
     50 static bool trans_hlv_b(DisasContext *ctx, arg_hlv_b *a)
     51 {
     52     REQUIRE_EXT(ctx, RVH);
     53     return do_hlv(ctx, a, MO_SB);
     54 }
     55 
     56 static bool trans_hlv_h(DisasContext *ctx, arg_hlv_h *a)
     57 {
     58     REQUIRE_EXT(ctx, RVH);
     59     return do_hlv(ctx, a, MO_TESW);
     60 }
     61 
     62 static bool trans_hlv_w(DisasContext *ctx, arg_hlv_w *a)
     63 {
     64     REQUIRE_EXT(ctx, RVH);
     65     return do_hlv(ctx, a, MO_TESL);
     66 }
     67 
     68 static bool trans_hlv_bu(DisasContext *ctx, arg_hlv_bu *a)
     69 {
     70     REQUIRE_EXT(ctx, RVH);
     71     return do_hlv(ctx, a, MO_UB);
     72 }
     73 
     74 static bool trans_hlv_hu(DisasContext *ctx, arg_hlv_hu *a)
     75 {
     76     REQUIRE_EXT(ctx, RVH);
     77     return do_hlv(ctx, a, MO_TEUW);
     78 }
     79 
     80 static bool do_hsv(DisasContext *ctx, arg_r2_s *a, MemOp mop)
     81 {
     82 #ifdef CONFIG_USER_ONLY
     83     return false;
     84 #else
     85     if (check_access(ctx)) {
     86         TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
     87         TCGv data = get_gpr(ctx, a->rs2, EXT_NONE);
     88         int mem_idx = ctx->mem_idx | TB_FLAGS_PRIV_HYP_ACCESS_MASK;
     89         tcg_gen_qemu_st_tl(data, addr, mem_idx, mop);
     90     }
     91     return true;
     92 #endif
     93 }
     94 
     95 static bool trans_hsv_b(DisasContext *ctx, arg_hsv_b *a)
     96 {
     97     REQUIRE_EXT(ctx, RVH);
     98     return do_hsv(ctx, a, MO_SB);
     99 }
    100 
    101 static bool trans_hsv_h(DisasContext *ctx, arg_hsv_h *a)
    102 {
    103     REQUIRE_EXT(ctx, RVH);
    104     return do_hsv(ctx, a, MO_TESW);
    105 }
    106 
    107 static bool trans_hsv_w(DisasContext *ctx, arg_hsv_w *a)
    108 {
    109     REQUIRE_EXT(ctx, RVH);
    110     return do_hsv(ctx, a, MO_TESL);
    111 }
    112 
    113 static bool trans_hlv_wu(DisasContext *ctx, arg_hlv_wu *a)
    114 {
    115     REQUIRE_64BIT(ctx);
    116     REQUIRE_EXT(ctx, RVH);
    117     return do_hlv(ctx, a, MO_TEUL);
    118 }
    119 
    120 static bool trans_hlv_d(DisasContext *ctx, arg_hlv_d *a)
    121 {
    122     REQUIRE_64BIT(ctx);
    123     REQUIRE_EXT(ctx, RVH);
    124     return do_hlv(ctx, a, MO_TEUQ);
    125 }
    126 
    127 static bool trans_hsv_d(DisasContext *ctx, arg_hsv_d *a)
    128 {
    129     REQUIRE_64BIT(ctx);
    130     REQUIRE_EXT(ctx, RVH);
    131     return do_hsv(ctx, a, MO_TEUQ);
    132 }
    133 
    134 #ifndef CONFIG_USER_ONLY
    135 static bool do_hlvx(DisasContext *ctx, arg_r2 *a,
    136                     void (*func)(TCGv, TCGv_env, TCGv))
    137 {
    138     if (check_access(ctx)) {
    139         TCGv dest = dest_gpr(ctx, a->rd);
    140         TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
    141         func(dest, cpu_env, addr);
    142         gen_set_gpr(ctx, a->rd, dest);
    143     }
    144     return true;
    145 }
    146 #endif
    147 
    148 static bool trans_hlvx_hu(DisasContext *ctx, arg_hlvx_hu *a)
    149 {
    150     REQUIRE_EXT(ctx, RVH);
    151 #ifndef CONFIG_USER_ONLY
    152     return do_hlvx(ctx, a, gen_helper_hyp_hlvx_hu);
    153 #else
    154     return false;
    155 #endif
    156 }
    157 
    158 static bool trans_hlvx_wu(DisasContext *ctx, arg_hlvx_wu *a)
    159 {
    160     REQUIRE_EXT(ctx, RVH);
    161 #ifndef CONFIG_USER_ONLY
    162     return do_hlvx(ctx, a, gen_helper_hyp_hlvx_wu);
    163 #else
    164     return false;
    165 #endif
    166 }
    167 
    168 static bool trans_hfence_gvma(DisasContext *ctx, arg_sfence_vma *a)
    169 {
    170     REQUIRE_EXT(ctx, RVH);
    171 #ifndef CONFIG_USER_ONLY
    172     decode_save_opc(ctx);
    173     gen_helper_hyp_gvma_tlb_flush(cpu_env);
    174     return true;
    175 #endif
    176     return false;
    177 }
    178 
    179 static bool trans_hfence_vvma(DisasContext *ctx, arg_sfence_vma *a)
    180 {
    181     REQUIRE_EXT(ctx, RVH);
    182 #ifndef CONFIG_USER_ONLY
    183     decode_save_opc(ctx);
    184     gen_helper_hyp_tlb_flush(cpu_env);
    185     return true;
    186 #endif
    187     return false;
    188 }