cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

trans_rvi.c.inc (14523B)


      1/*
      2 * RISC-V translation routines for the RVXI Base Integer Instruction Set.
      3 *
      4 * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
      5 * Copyright (c) 2018 Peer Adelt, peer.adelt@hni.uni-paderborn.de
      6 *                    Bastian Koppelmann, kbastian@mail.uni-paderborn.de
      7 *
      8 * This program is free software; you can redistribute it and/or modify it
      9 * under the terms and conditions of the GNU General Public License,
     10 * version 2 or later, as published by the Free Software Foundation.
     11 *
     12 * This program is distributed in the hope it will be useful, but WITHOUT
     13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     15 * more details.
     16 *
     17 * You should have received a copy of the GNU General Public License along with
     18 * this program.  If not, see <http://www.gnu.org/licenses/>.
     19 */
     20
     21static bool trans_illegal(DisasContext *ctx, arg_empty *a)
     22{
     23    gen_exception_illegal(ctx);
     24    return true;
     25}
     26
     27static bool trans_c64_illegal(DisasContext *ctx, arg_empty *a)
     28{
     29     REQUIRE_64BIT(ctx);
     30     return trans_illegal(ctx, a);
     31}
     32
     33static bool trans_lui(DisasContext *ctx, arg_lui *a)
     34{
     35    if (a->rd != 0) {
     36        tcg_gen_movi_tl(cpu_gpr[a->rd], a->imm);
     37    }
     38    return true;
     39}
     40
     41static bool trans_auipc(DisasContext *ctx, arg_auipc *a)
     42{
     43    if (a->rd != 0) {
     44        tcg_gen_movi_tl(cpu_gpr[a->rd], a->imm + ctx->base.pc_next);
     45    }
     46    return true;
     47}
     48
     49static bool trans_jal(DisasContext *ctx, arg_jal *a)
     50{
     51    gen_jal(ctx, a->rd, a->imm);
     52    return true;
     53}
     54
     55static bool trans_jalr(DisasContext *ctx, arg_jalr *a)
     56{
     57    TCGLabel *misaligned = NULL;
     58
     59    tcg_gen_addi_tl(cpu_pc, get_gpr(ctx, a->rs1, EXT_NONE), a->imm);
     60    tcg_gen_andi_tl(cpu_pc, cpu_pc, (target_ulong)-2);
     61
     62    if (!has_ext(ctx, RVC)) {
     63        TCGv t0 = tcg_temp_new();
     64
     65        misaligned = gen_new_label();
     66        tcg_gen_andi_tl(t0, cpu_pc, 0x2);
     67        tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x0, misaligned);
     68        tcg_temp_free(t0);
     69    }
     70
     71    if (a->rd != 0) {
     72        tcg_gen_movi_tl(cpu_gpr[a->rd], ctx->pc_succ_insn);
     73    }
     74
     75    /* No chaining with JALR. */
     76    lookup_and_goto_ptr(ctx);
     77
     78    if (misaligned) {
     79        gen_set_label(misaligned);
     80        gen_exception_inst_addr_mis(ctx);
     81    }
     82    ctx->base.is_jmp = DISAS_NORETURN;
     83
     84    return true;
     85}
     86
     87static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond cond)
     88{
     89    TCGLabel *l = gen_new_label();
     90    TCGv src1 = get_gpr(ctx, a->rs1, EXT_SIGN);
     91    TCGv src2 = get_gpr(ctx, a->rs2, EXT_SIGN);
     92
     93    tcg_gen_brcond_tl(cond, src1, src2, l);
     94    gen_goto_tb(ctx, 1, ctx->pc_succ_insn);
     95
     96    gen_set_label(l); /* branch taken */
     97
     98    if (!has_ext(ctx, RVC) && ((ctx->base.pc_next + a->imm) & 0x3)) {
     99        /* misaligned */
    100        gen_exception_inst_addr_mis(ctx);
    101    } else {
    102        gen_goto_tb(ctx, 0, ctx->base.pc_next + a->imm);
    103    }
    104    ctx->base.is_jmp = DISAS_NORETURN;
    105
    106    return true;
    107}
    108
    109static bool trans_beq(DisasContext *ctx, arg_beq *a)
    110{
    111    return gen_branch(ctx, a, TCG_COND_EQ);
    112}
    113
    114static bool trans_bne(DisasContext *ctx, arg_bne *a)
    115{
    116    return gen_branch(ctx, a, TCG_COND_NE);
    117}
    118
    119static bool trans_blt(DisasContext *ctx, arg_blt *a)
    120{
    121    return gen_branch(ctx, a, TCG_COND_LT);
    122}
    123
    124static bool trans_bge(DisasContext *ctx, arg_bge *a)
    125{
    126    return gen_branch(ctx, a, TCG_COND_GE);
    127}
    128
    129static bool trans_bltu(DisasContext *ctx, arg_bltu *a)
    130{
    131    return gen_branch(ctx, a, TCG_COND_LTU);
    132}
    133
    134static bool trans_bgeu(DisasContext *ctx, arg_bgeu *a)
    135{
    136    return gen_branch(ctx, a, TCG_COND_GEU);
    137}
    138
    139static bool gen_load(DisasContext *ctx, arg_lb *a, MemOp memop)
    140{
    141    TCGv dest = dest_gpr(ctx, a->rd);
    142    TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
    143
    144    if (a->imm) {
    145        TCGv temp = temp_new(ctx);
    146        tcg_gen_addi_tl(temp, addr, a->imm);
    147        addr = temp;
    148    }
    149
    150    tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, memop);
    151    gen_set_gpr(ctx, a->rd, dest);
    152    return true;
    153}
    154
    155static bool trans_lb(DisasContext *ctx, arg_lb *a)
    156{
    157    return gen_load(ctx, a, MO_SB);
    158}
    159
    160static bool trans_lh(DisasContext *ctx, arg_lh *a)
    161{
    162    return gen_load(ctx, a, MO_TESW);
    163}
    164
    165static bool trans_lw(DisasContext *ctx, arg_lw *a)
    166{
    167    return gen_load(ctx, a, MO_TESL);
    168}
    169
    170static bool trans_lbu(DisasContext *ctx, arg_lbu *a)
    171{
    172    return gen_load(ctx, a, MO_UB);
    173}
    174
    175static bool trans_lhu(DisasContext *ctx, arg_lhu *a)
    176{
    177    return gen_load(ctx, a, MO_TEUW);
    178}
    179
    180static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop)
    181{
    182    TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
    183    TCGv data = get_gpr(ctx, a->rs2, EXT_NONE);
    184
    185    if (a->imm) {
    186        TCGv temp = temp_new(ctx);
    187        tcg_gen_addi_tl(temp, addr, a->imm);
    188        addr = temp;
    189    }
    190
    191    tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, memop);
    192    return true;
    193}
    194
    195static bool trans_sb(DisasContext *ctx, arg_sb *a)
    196{
    197    return gen_store(ctx, a, MO_SB);
    198}
    199
    200static bool trans_sh(DisasContext *ctx, arg_sh *a)
    201{
    202    return gen_store(ctx, a, MO_TESW);
    203}
    204
    205static bool trans_sw(DisasContext *ctx, arg_sw *a)
    206{
    207    return gen_store(ctx, a, MO_TESL);
    208}
    209
    210static bool trans_lwu(DisasContext *ctx, arg_lwu *a)
    211{
    212    REQUIRE_64BIT(ctx);
    213    return gen_load(ctx, a, MO_TEUL);
    214}
    215
    216static bool trans_ld(DisasContext *ctx, arg_ld *a)
    217{
    218    REQUIRE_64BIT(ctx);
    219    return gen_load(ctx, a, MO_TEQ);
    220}
    221
    222static bool trans_sd(DisasContext *ctx, arg_sd *a)
    223{
    224    REQUIRE_64BIT(ctx);
    225    return gen_store(ctx, a, MO_TEQ);
    226}
    227
    228static bool trans_addi(DisasContext *ctx, arg_addi *a)
    229{
    230    return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_addi_tl);
    231}
    232
    233static void gen_slt(TCGv ret, TCGv s1, TCGv s2)
    234{
    235    tcg_gen_setcond_tl(TCG_COND_LT, ret, s1, s2);
    236}
    237
    238static void gen_sltu(TCGv ret, TCGv s1, TCGv s2)
    239{
    240    tcg_gen_setcond_tl(TCG_COND_LTU, ret, s1, s2);
    241}
    242
    243static bool trans_slti(DisasContext *ctx, arg_slti *a)
    244{
    245    return gen_arith_imm_tl(ctx, a, EXT_SIGN, gen_slt);
    246}
    247
    248static bool trans_sltiu(DisasContext *ctx, arg_sltiu *a)
    249{
    250    return gen_arith_imm_tl(ctx, a, EXT_SIGN, gen_sltu);
    251}
    252
    253static bool trans_xori(DisasContext *ctx, arg_xori *a)
    254{
    255    return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_xori_tl);
    256}
    257
    258static bool trans_ori(DisasContext *ctx, arg_ori *a)
    259{
    260    return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_ori_tl);
    261}
    262
    263static bool trans_andi(DisasContext *ctx, arg_andi *a)
    264{
    265    return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_andi_tl);
    266}
    267
    268static bool trans_slli(DisasContext *ctx, arg_slli *a)
    269{
    270    return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shli_tl);
    271}
    272
    273static bool trans_srli(DisasContext *ctx, arg_srli *a)
    274{
    275    return gen_shift_imm_fn(ctx, a, EXT_ZERO, tcg_gen_shri_tl);
    276}
    277
    278static bool trans_srai(DisasContext *ctx, arg_srai *a)
    279{
    280    return gen_shift_imm_fn(ctx, a, EXT_SIGN, tcg_gen_sari_tl);
    281}
    282
    283static bool trans_add(DisasContext *ctx, arg_add *a)
    284{
    285    return gen_arith(ctx, a, EXT_NONE, tcg_gen_add_tl);
    286}
    287
    288static bool trans_sub(DisasContext *ctx, arg_sub *a)
    289{
    290    return gen_arith(ctx, a, EXT_NONE, tcg_gen_sub_tl);
    291}
    292
    293static bool trans_sll(DisasContext *ctx, arg_sll *a)
    294{
    295    return gen_shift(ctx, a, EXT_NONE, tcg_gen_shl_tl);
    296}
    297
    298static bool trans_slt(DisasContext *ctx, arg_slt *a)
    299{
    300    return gen_arith(ctx, a, EXT_SIGN, gen_slt);
    301}
    302
    303static bool trans_sltu(DisasContext *ctx, arg_sltu *a)
    304{
    305    return gen_arith(ctx, a, EXT_SIGN, gen_sltu);
    306}
    307
    308static bool trans_xor(DisasContext *ctx, arg_xor *a)
    309{
    310    return gen_arith(ctx, a, EXT_NONE, tcg_gen_xor_tl);
    311}
    312
    313static bool trans_srl(DisasContext *ctx, arg_srl *a)
    314{
    315    return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl);
    316}
    317
    318static bool trans_sra(DisasContext *ctx, arg_sra *a)
    319{
    320    return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl);
    321}
    322
    323static bool trans_or(DisasContext *ctx, arg_or *a)
    324{
    325    return gen_arith(ctx, a, EXT_NONE, tcg_gen_or_tl);
    326}
    327
    328static bool trans_and(DisasContext *ctx, arg_and *a)
    329{
    330    return gen_arith(ctx, a, EXT_NONE, tcg_gen_and_tl);
    331}
    332
    333static bool trans_addiw(DisasContext *ctx, arg_addiw *a)
    334{
    335    REQUIRE_64BIT(ctx);
    336    ctx->w = true;
    337    return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_addi_tl);
    338}
    339
    340static bool trans_slliw(DisasContext *ctx, arg_slliw *a)
    341{
    342    REQUIRE_64BIT(ctx);
    343    ctx->w = true;
    344    return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shli_tl);
    345}
    346
    347static void gen_srliw(TCGv dst, TCGv src, target_long shamt)
    348{
    349    tcg_gen_extract_tl(dst, src, shamt, 32 - shamt);
    350}
    351
    352static bool trans_srliw(DisasContext *ctx, arg_srliw *a)
    353{
    354    REQUIRE_64BIT(ctx);
    355    ctx->w = true;
    356    return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_srliw);
    357}
    358
    359static void gen_sraiw(TCGv dst, TCGv src, target_long shamt)
    360{
    361    tcg_gen_sextract_tl(dst, src, shamt, 32 - shamt);
    362}
    363
    364static bool trans_sraiw(DisasContext *ctx, arg_sraiw *a)
    365{
    366    REQUIRE_64BIT(ctx);
    367    ctx->w = true;
    368    return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_sraiw);
    369}
    370
    371static bool trans_addw(DisasContext *ctx, arg_addw *a)
    372{
    373    REQUIRE_64BIT(ctx);
    374    ctx->w = true;
    375    return gen_arith(ctx, a, EXT_NONE, tcg_gen_add_tl);
    376}
    377
    378static bool trans_subw(DisasContext *ctx, arg_subw *a)
    379{
    380    REQUIRE_64BIT(ctx);
    381    ctx->w = true;
    382    return gen_arith(ctx, a, EXT_NONE, tcg_gen_sub_tl);
    383}
    384
    385static bool trans_sllw(DisasContext *ctx, arg_sllw *a)
    386{
    387    REQUIRE_64BIT(ctx);
    388    ctx->w = true;
    389    return gen_shift(ctx, a, EXT_NONE, tcg_gen_shl_tl);
    390}
    391
    392static bool trans_srlw(DisasContext *ctx, arg_srlw *a)
    393{
    394    REQUIRE_64BIT(ctx);
    395    ctx->w = true;
    396    return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl);
    397}
    398
    399static bool trans_sraw(DisasContext *ctx, arg_sraw *a)
    400{
    401    REQUIRE_64BIT(ctx);
    402    ctx->w = true;
    403    return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl);
    404}
    405
    406static bool trans_fence(DisasContext *ctx, arg_fence *a)
    407{
    408    /* FENCE is a full memory barrier. */
    409    tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
    410    return true;
    411}
    412
    413static bool trans_fence_i(DisasContext *ctx, arg_fence_i *a)
    414{
    415    if (!ctx->ext_ifencei) {
    416        return false;
    417    }
    418
    419    /*
    420     * FENCE_I is a no-op in QEMU,
    421     * however we need to end the translation block
    422     */
    423    tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn);
    424    exit_tb(ctx);
    425    ctx->base.is_jmp = DISAS_NORETURN;
    426    return true;
    427}
    428
    429static bool do_csr_post(DisasContext *ctx)
    430{
    431    /* We may have changed important cpu state -- exit to main loop. */
    432    tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn);
    433    exit_tb(ctx);
    434    ctx->base.is_jmp = DISAS_NORETURN;
    435    return true;
    436}
    437
    438static bool do_csrr(DisasContext *ctx, int rd, int rc)
    439{
    440    TCGv dest = dest_gpr(ctx, rd);
    441    TCGv_i32 csr = tcg_constant_i32(rc);
    442
    443    if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
    444        gen_io_start();
    445    }
    446    gen_helper_csrr(dest, cpu_env, csr);
    447    gen_set_gpr(ctx, rd, dest);
    448    return do_csr_post(ctx);
    449}
    450
    451static bool do_csrw(DisasContext *ctx, int rc, TCGv src)
    452{
    453    TCGv_i32 csr = tcg_constant_i32(rc);
    454
    455    if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
    456        gen_io_start();
    457    }
    458    gen_helper_csrw(cpu_env, csr, src);
    459    return do_csr_post(ctx);
    460}
    461
    462static bool do_csrrw(DisasContext *ctx, int rd, int rc, TCGv src, TCGv mask)
    463{
    464    TCGv dest = dest_gpr(ctx, rd);
    465    TCGv_i32 csr = tcg_constant_i32(rc);
    466
    467    if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
    468        gen_io_start();
    469    }
    470    gen_helper_csrrw(dest, cpu_env, csr, src, mask);
    471    gen_set_gpr(ctx, rd, dest);
    472    return do_csr_post(ctx);
    473}
    474
    475static bool trans_csrrw(DisasContext *ctx, arg_csrrw *a)
    476{
    477    TCGv src = get_gpr(ctx, a->rs1, EXT_NONE);
    478
    479    /*
    480     * If rd == 0, the insn shall not read the csr, nor cause any of the
    481     * side effects that might occur on a csr read.
    482     */
    483    if (a->rd == 0) {
    484        return do_csrw(ctx, a->csr, src);
    485    }
    486
    487    TCGv mask = tcg_constant_tl(-1);
    488    return do_csrrw(ctx, a->rd, a->csr, src, mask);
    489}
    490
    491static bool trans_csrrs(DisasContext *ctx, arg_csrrs *a)
    492{
    493    /*
    494     * If rs1 == 0, the insn shall not write to the csr at all, nor
    495     * cause any of the side effects that might occur on a csr write.
    496     * Note that if rs1 specifies a register other than x0, holding
    497     * a zero value, the instruction will still attempt to write the
    498     * unmodified value back to the csr and will cause side effects.
    499     */
    500    if (a->rs1 == 0) {
    501        return do_csrr(ctx, a->rd, a->csr);
    502    }
    503
    504    TCGv ones = tcg_constant_tl(-1);
    505    TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO);
    506    return do_csrrw(ctx, a->rd, a->csr, ones, mask);
    507}
    508
    509static bool trans_csrrc(DisasContext *ctx, arg_csrrc *a)
    510{
    511    /*
    512     * If rs1 == 0, the insn shall not write to the csr at all, nor
    513     * cause any of the side effects that might occur on a csr write.
    514     * Note that if rs1 specifies a register other than x0, holding
    515     * a zero value, the instruction will still attempt to write the
    516     * unmodified value back to the csr and will cause side effects.
    517     */
    518    if (a->rs1 == 0) {
    519        return do_csrr(ctx, a->rd, a->csr);
    520    }
    521
    522    TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO);
    523    return do_csrrw(ctx, a->rd, a->csr, ctx->zero, mask);
    524}
    525
    526static bool trans_csrrwi(DisasContext *ctx, arg_csrrwi *a)
    527{
    528    TCGv src = tcg_constant_tl(a->rs1);
    529
    530    /*
    531     * If rd == 0, the insn shall not read the csr, nor cause any of the
    532     * side effects that might occur on a csr read.
    533     */
    534    if (a->rd == 0) {
    535        return do_csrw(ctx, a->csr, src);
    536    }
    537
    538    TCGv mask = tcg_constant_tl(-1);
    539    return do_csrrw(ctx, a->rd, a->csr, src, mask);
    540}
    541
    542static bool trans_csrrsi(DisasContext *ctx, arg_csrrsi *a)
    543{
    544    /*
    545     * If rs1 == 0, the insn shall not write to the csr at all, nor
    546     * cause any of the side effects that might occur on a csr write.
    547     * Note that if rs1 specifies a register other than x0, holding
    548     * a zero value, the instruction will still attempt to write the
    549     * unmodified value back to the csr and will cause side effects.
    550     */
    551    if (a->rs1 == 0) {
    552        return do_csrr(ctx, a->rd, a->csr);
    553    }
    554
    555    TCGv ones = tcg_constant_tl(-1);
    556    TCGv mask = tcg_constant_tl(a->rs1);
    557    return do_csrrw(ctx, a->rd, a->csr, ones, mask);
    558}
    559
    560static bool trans_csrrci(DisasContext *ctx, arg_csrrci *a)
    561{
    562    /*
    563     * If rs1 == 0, the insn shall not write to the csr at all, nor
    564     * cause any of the side effects that might occur on a csr write.
    565     * Note that if rs1 specifies a register other than x0, holding
    566     * a zero value, the instruction will still attempt to write the
    567     * unmodified value back to the csr and will cause side effects.
    568     */
    569    if (a->rs1 == 0) {
    570        return do_csrr(ctx, a->rd, a->csr);
    571    }
    572
    573    TCGv mask = tcg_constant_tl(a->rs1);
    574    return do_csrrw(ctx, a->rd, a->csr, ctx->zero, mask);
    575}