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

translate.c (30182B)


      1/*
      2 * Altera Nios II emulation for qemu: main translation routines.
      3 *
      4 * Copyright (C) 2016 Marek Vasut <marex@denx.de>
      5 * Copyright (C) 2012 Chris Wulff <crwulff@gmail.com>
      6 * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
      7 *  (Portions of this file that were originally from nios2sim-ng.)
      8 *
      9 * This library is free software; you can redistribute it and/or
     10 * modify it under the terms of the GNU Lesser General Public
     11 * License as published by the Free Software Foundation; either
     12 * version 2.1 of the License, or (at your option) any later version.
     13 *
     14 * This library is distributed in the hope that it will be useful,
     15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     17 * Lesser General Public License for more details.
     18 *
     19 * You should have received a copy of the GNU Lesser General Public
     20 * License along with this library; if not, see
     21 * <http://www.gnu.org/licenses/lgpl-2.1.html>
     22 */
     23
     24#include "qemu/osdep.h"
     25#include "cpu.h"
     26#include "tcg/tcg-op.h"
     27#include "exec/exec-all.h"
     28#include "disas/disas.h"
     29#include "exec/helper-proto.h"
     30#include "exec/helper-gen.h"
     31#include "exec/log.h"
     32#include "exec/cpu_ldst.h"
     33#include "exec/translator.h"
     34#include "qemu/qemu-print.h"
     35#include "exec/gen-icount.h"
     36
     37/* is_jmp field values */
     38#define DISAS_JUMP    DISAS_TARGET_0 /* only pc was modified dynamically */
     39#define DISAS_UPDATE  DISAS_TARGET_1 /* cpu state was modified dynamically */
     40
     41#define INSTRUCTION_FLG(func, flags) { (func), (flags) }
     42#define INSTRUCTION(func)                  \
     43        INSTRUCTION_FLG(func, 0)
     44#define INSTRUCTION_NOP()                  \
     45        INSTRUCTION_FLG(nop, 0)
     46#define INSTRUCTION_UNIMPLEMENTED()        \
     47        INSTRUCTION_FLG(gen_excp, EXCP_UNIMPL)
     48#define INSTRUCTION_ILLEGAL()              \
     49        INSTRUCTION_FLG(gen_excp, EXCP_ILLEGAL)
     50
     51/* Special R-Type instruction opcode */
     52#define INSN_R_TYPE 0x3A
     53
     54/* I-Type instruction parsing */
     55#define I_TYPE(instr, code)                \
     56    struct {                               \
     57        uint8_t op;                        \
     58        union {                            \
     59            uint16_t u;                    \
     60            int16_t s;                     \
     61        } imm16;                           \
     62        uint8_t b;                         \
     63        uint8_t a;                         \
     64    } (instr) = {                          \
     65        .op    = extract32((code), 0, 6),  \
     66        .imm16.u = extract32((code), 6, 16), \
     67        .b     = extract32((code), 22, 5), \
     68        .a     = extract32((code), 27, 5), \
     69    }
     70
     71/* R-Type instruction parsing */
     72#define R_TYPE(instr, code)                \
     73    struct {                               \
     74        uint8_t op;                        \
     75        uint8_t imm5;                      \
     76        uint8_t opx;                       \
     77        uint8_t c;                         \
     78        uint8_t b;                         \
     79        uint8_t a;                         \
     80    } (instr) = {                          \
     81        .op    = extract32((code), 0, 6),  \
     82        .imm5  = extract32((code), 6, 5),  \
     83        .opx   = extract32((code), 11, 6), \
     84        .c     = extract32((code), 17, 5), \
     85        .b     = extract32((code), 22, 5), \
     86        .a     = extract32((code), 27, 5), \
     87    }
     88
     89/* J-Type instruction parsing */
     90#define J_TYPE(instr, code)                \
     91    struct {                               \
     92        uint8_t op;                        \
     93        uint32_t imm26;                    \
     94    } (instr) = {                          \
     95        .op    = extract32((code), 0, 6),  \
     96        .imm26 = extract32((code), 6, 26), \
     97    }
     98
     99typedef struct DisasContext {
    100    DisasContextBase  base;
    101    TCGv_i32          zero;
    102    target_ulong      pc;
    103    int               mem_idx;
    104} DisasContext;
    105
    106static TCGv cpu_R[NUM_CORE_REGS];
    107
    108typedef struct Nios2Instruction {
    109    void     (*handler)(DisasContext *dc, uint32_t code, uint32_t flags);
    110    uint32_t  flags;
    111} Nios2Instruction;
    112
    113static uint8_t get_opcode(uint32_t code)
    114{
    115    I_TYPE(instr, code);
    116    return instr.op;
    117}
    118
    119static uint8_t get_opxcode(uint32_t code)
    120{
    121    R_TYPE(instr, code);
    122    return instr.opx;
    123}
    124
    125static TCGv load_zero(DisasContext *dc)
    126{
    127    if (!dc->zero) {
    128        dc->zero = tcg_const_i32(0);
    129    }
    130    return dc->zero;
    131}
    132
    133static TCGv load_gpr(DisasContext *dc, uint8_t reg)
    134{
    135    if (likely(reg != R_ZERO)) {
    136        return cpu_R[reg];
    137    } else {
    138        return load_zero(dc);
    139    }
    140}
    141
    142static void t_gen_helper_raise_exception(DisasContext *dc,
    143                                         uint32_t index)
    144{
    145    TCGv_i32 tmp = tcg_const_i32(index);
    146
    147    tcg_gen_movi_tl(cpu_R[R_PC], dc->pc);
    148    gen_helper_raise_exception(cpu_env, tmp);
    149    tcg_temp_free_i32(tmp);
    150    dc->base.is_jmp = DISAS_NORETURN;
    151}
    152
    153static void gen_goto_tb(DisasContext *dc, int n, uint32_t dest)
    154{
    155    const TranslationBlock *tb = dc->base.tb;
    156
    157    if (translator_use_goto_tb(&dc->base, dest)) {
    158        tcg_gen_goto_tb(n);
    159        tcg_gen_movi_tl(cpu_R[R_PC], dest);
    160        tcg_gen_exit_tb(tb, n);
    161    } else {
    162        tcg_gen_movi_tl(cpu_R[R_PC], dest);
    163        tcg_gen_exit_tb(NULL, 0);
    164    }
    165}
    166
    167static void gen_excp(DisasContext *dc, uint32_t code, uint32_t flags)
    168{
    169    t_gen_helper_raise_exception(dc, flags);
    170}
    171
    172static void gen_check_supervisor(DisasContext *dc)
    173{
    174    if (dc->base.tb->flags & CR_STATUS_U) {
    175        /* CPU in user mode, privileged instruction called, stop. */
    176        t_gen_helper_raise_exception(dc, EXCP_SUPERI);
    177    }
    178}
    179
    180/*
    181 * Used as a placeholder for all instructions which do not have
    182 * an effect on the simulator (e.g. flush, sync)
    183 */
    184static void nop(DisasContext *dc, uint32_t code, uint32_t flags)
    185{
    186    /* Nothing to do here */
    187}
    188
    189/*
    190 * J-Type instructions
    191 */
    192static void jmpi(DisasContext *dc, uint32_t code, uint32_t flags)
    193{
    194    J_TYPE(instr, code);
    195    gen_goto_tb(dc, 0, (dc->pc & 0xF0000000) | (instr.imm26 << 2));
    196    dc->base.is_jmp = DISAS_NORETURN;
    197}
    198
    199static void call(DisasContext *dc, uint32_t code, uint32_t flags)
    200{
    201    tcg_gen_movi_tl(cpu_R[R_RA], dc->base.pc_next);
    202    jmpi(dc, code, flags);
    203}
    204
    205/*
    206 * I-Type instructions
    207 */
    208/* Load instructions */
    209static void gen_ldx(DisasContext *dc, uint32_t code, uint32_t flags)
    210{
    211    I_TYPE(instr, code);
    212
    213    TCGv addr = tcg_temp_new();
    214    TCGv data;
    215
    216    /*
    217     * WARNING: Loads into R_ZERO are ignored, but we must generate the
    218     *          memory access itself to emulate the CPU precisely. Load
    219     *          from a protected page to R_ZERO will cause SIGSEGV on
    220     *          the Nios2 CPU.
    221     */
    222    if (likely(instr.b != R_ZERO)) {
    223        data = cpu_R[instr.b];
    224    } else {
    225        data = tcg_temp_new();
    226    }
    227
    228    tcg_gen_addi_tl(addr, load_gpr(dc, instr.a), instr.imm16.s);
    229    tcg_gen_qemu_ld_tl(data, addr, dc->mem_idx, flags);
    230
    231    if (unlikely(instr.b == R_ZERO)) {
    232        tcg_temp_free(data);
    233    }
    234
    235    tcg_temp_free(addr);
    236}
    237
    238/* Store instructions */
    239static void gen_stx(DisasContext *dc, uint32_t code, uint32_t flags)
    240{
    241    I_TYPE(instr, code);
    242    TCGv val = load_gpr(dc, instr.b);
    243
    244    TCGv addr = tcg_temp_new();
    245    tcg_gen_addi_tl(addr, load_gpr(dc, instr.a), instr.imm16.s);
    246    tcg_gen_qemu_st_tl(val, addr, dc->mem_idx, flags);
    247    tcg_temp_free(addr);
    248}
    249
    250/* Branch instructions */
    251static void br(DisasContext *dc, uint32_t code, uint32_t flags)
    252{
    253    I_TYPE(instr, code);
    254
    255    gen_goto_tb(dc, 0, dc->base.pc_next + (instr.imm16.s & -4));
    256    dc->base.is_jmp = DISAS_NORETURN;
    257}
    258
    259static void gen_bxx(DisasContext *dc, uint32_t code, uint32_t flags)
    260{
    261    I_TYPE(instr, code);
    262
    263    TCGLabel *l1 = gen_new_label();
    264    tcg_gen_brcond_tl(flags, cpu_R[instr.a], cpu_R[instr.b], l1);
    265    gen_goto_tb(dc, 0, dc->base.pc_next);
    266    gen_set_label(l1);
    267    gen_goto_tb(dc, 1, dc->base.pc_next + (instr.imm16.s & -4));
    268    dc->base.is_jmp = DISAS_NORETURN;
    269}
    270
    271/* Comparison instructions */
    272#define gen_i_cmpxx(fname, op3)                                              \
    273static void (fname)(DisasContext *dc, uint32_t code, uint32_t flags)         \
    274{                                                                            \
    275    I_TYPE(instr, (code));                                                   \
    276    tcg_gen_setcondi_tl(flags, cpu_R[instr.b], cpu_R[instr.a], (op3));       \
    277}
    278
    279gen_i_cmpxx(gen_cmpxxsi, instr.imm16.s)
    280gen_i_cmpxx(gen_cmpxxui, instr.imm16.u)
    281
    282/* Math/logic instructions */
    283#define gen_i_math_logic(fname, insn, resimm, op3)                          \
    284static void (fname)(DisasContext *dc, uint32_t code, uint32_t flags)        \
    285{                                                                           \
    286    I_TYPE(instr, (code));                                                  \
    287    if (unlikely(instr.b == R_ZERO)) { /* Store to R_ZERO is ignored */     \
    288        return;                                                             \
    289    } else if (instr.a == R_ZERO) { /* MOVxI optimizations */               \
    290        tcg_gen_movi_tl(cpu_R[instr.b], (resimm) ? (op3) : 0);              \
    291    } else {                                                                \
    292        tcg_gen_##insn##_tl(cpu_R[instr.b], cpu_R[instr.a], (op3));         \
    293    }                                                                       \
    294}
    295
    296gen_i_math_logic(addi,  addi, 1, instr.imm16.s)
    297gen_i_math_logic(muli,  muli, 0, instr.imm16.s)
    298
    299gen_i_math_logic(andi,  andi, 0, instr.imm16.u)
    300gen_i_math_logic(ori,   ori,  1, instr.imm16.u)
    301gen_i_math_logic(xori,  xori, 1, instr.imm16.u)
    302
    303gen_i_math_logic(andhi, andi, 0, instr.imm16.u << 16)
    304gen_i_math_logic(orhi , ori,  1, instr.imm16.u << 16)
    305gen_i_math_logic(xorhi, xori, 1, instr.imm16.u << 16)
    306
    307/* Prototype only, defined below */
    308static void handle_r_type_instr(DisasContext *dc, uint32_t code,
    309                                uint32_t flags);
    310
    311static const Nios2Instruction i_type_instructions[] = {
    312    INSTRUCTION(call),                                /* call */
    313    INSTRUCTION(jmpi),                                /* jmpi */
    314    INSTRUCTION_ILLEGAL(),
    315    INSTRUCTION_FLG(gen_ldx, MO_UB),                  /* ldbu */
    316    INSTRUCTION(addi),                                /* addi */
    317    INSTRUCTION_FLG(gen_stx, MO_UB),                  /* stb */
    318    INSTRUCTION(br),                                  /* br */
    319    INSTRUCTION_FLG(gen_ldx, MO_SB),                  /* ldb */
    320    INSTRUCTION_FLG(gen_cmpxxsi, TCG_COND_GE),        /* cmpgei */
    321    INSTRUCTION_ILLEGAL(),
    322    INSTRUCTION_ILLEGAL(),
    323    INSTRUCTION_FLG(gen_ldx, MO_UW),                  /* ldhu */
    324    INSTRUCTION(andi),                                /* andi */
    325    INSTRUCTION_FLG(gen_stx, MO_UW),                  /* sth */
    326    INSTRUCTION_FLG(gen_bxx, TCG_COND_GE),            /* bge */
    327    INSTRUCTION_FLG(gen_ldx, MO_SW),                  /* ldh */
    328    INSTRUCTION_FLG(gen_cmpxxsi, TCG_COND_LT),        /* cmplti */
    329    INSTRUCTION_ILLEGAL(),
    330    INSTRUCTION_ILLEGAL(),
    331    INSTRUCTION_NOP(),                                /* initda */
    332    INSTRUCTION(ori),                                 /* ori */
    333    INSTRUCTION_FLG(gen_stx, MO_UL),                  /* stw */
    334    INSTRUCTION_FLG(gen_bxx, TCG_COND_LT),            /* blt */
    335    INSTRUCTION_FLG(gen_ldx, MO_UL),                  /* ldw */
    336    INSTRUCTION_FLG(gen_cmpxxsi, TCG_COND_NE),        /* cmpnei */
    337    INSTRUCTION_ILLEGAL(),
    338    INSTRUCTION_ILLEGAL(),
    339    INSTRUCTION_NOP(),                                /* flushda */
    340    INSTRUCTION(xori),                                /* xori */
    341    INSTRUCTION_ILLEGAL(),
    342    INSTRUCTION_FLG(gen_bxx, TCG_COND_NE),            /* bne */
    343    INSTRUCTION_ILLEGAL(),
    344    INSTRUCTION_FLG(gen_cmpxxsi, TCG_COND_EQ),        /* cmpeqi */
    345    INSTRUCTION_ILLEGAL(),
    346    INSTRUCTION_ILLEGAL(),
    347    INSTRUCTION_FLG(gen_ldx, MO_UB),                  /* ldbuio */
    348    INSTRUCTION(muli),                                /* muli */
    349    INSTRUCTION_FLG(gen_stx, MO_UB),                  /* stbio */
    350    INSTRUCTION_FLG(gen_bxx, TCG_COND_EQ),            /* beq */
    351    INSTRUCTION_FLG(gen_ldx, MO_SB),                  /* ldbio */
    352    INSTRUCTION_FLG(gen_cmpxxui, TCG_COND_GEU),       /* cmpgeui */
    353    INSTRUCTION_ILLEGAL(),
    354    INSTRUCTION_ILLEGAL(),
    355    INSTRUCTION_FLG(gen_ldx, MO_UW),                  /* ldhuio */
    356    INSTRUCTION(andhi),                               /* andhi */
    357    INSTRUCTION_FLG(gen_stx, MO_UW),                  /* sthio */
    358    INSTRUCTION_FLG(gen_bxx, TCG_COND_GEU),           /* bgeu */
    359    INSTRUCTION_FLG(gen_ldx, MO_SW),                  /* ldhio */
    360    INSTRUCTION_FLG(gen_cmpxxui, TCG_COND_LTU),       /* cmpltui */
    361    INSTRUCTION_ILLEGAL(),
    362    INSTRUCTION_UNIMPLEMENTED(),                      /* custom */
    363    INSTRUCTION_NOP(),                                /* initd */
    364    INSTRUCTION(orhi),                                /* orhi */
    365    INSTRUCTION_FLG(gen_stx, MO_SL),                  /* stwio */
    366    INSTRUCTION_FLG(gen_bxx, TCG_COND_LTU),           /* bltu */
    367    INSTRUCTION_FLG(gen_ldx, MO_UL),                  /* ldwio */
    368    INSTRUCTION_UNIMPLEMENTED(),                      /* rdprs */
    369    INSTRUCTION_ILLEGAL(),
    370    INSTRUCTION_FLG(handle_r_type_instr, 0),          /* R-Type */
    371    INSTRUCTION_NOP(),                                /* flushd */
    372    INSTRUCTION(xorhi),                               /* xorhi */
    373    INSTRUCTION_ILLEGAL(),
    374    INSTRUCTION_ILLEGAL(),
    375    INSTRUCTION_ILLEGAL(),
    376};
    377
    378/*
    379 * R-Type instructions
    380 */
    381/*
    382 * status <- estatus
    383 * PC <- ea
    384 */
    385static void eret(DisasContext *dc, uint32_t code, uint32_t flags)
    386{
    387    tcg_gen_mov_tl(cpu_R[CR_STATUS], cpu_R[CR_ESTATUS]);
    388    tcg_gen_mov_tl(cpu_R[R_PC], cpu_R[R_EA]);
    389
    390    dc->base.is_jmp = DISAS_JUMP;
    391}
    392
    393/* PC <- ra */
    394static void ret(DisasContext *dc, uint32_t code, uint32_t flags)
    395{
    396    tcg_gen_mov_tl(cpu_R[R_PC], cpu_R[R_RA]);
    397
    398    dc->base.is_jmp = DISAS_JUMP;
    399}
    400
    401/* PC <- ba */
    402static void bret(DisasContext *dc, uint32_t code, uint32_t flags)
    403{
    404    tcg_gen_mov_tl(cpu_R[R_PC], cpu_R[R_BA]);
    405
    406    dc->base.is_jmp = DISAS_JUMP;
    407}
    408
    409/* PC <- rA */
    410static void jmp(DisasContext *dc, uint32_t code, uint32_t flags)
    411{
    412    R_TYPE(instr, code);
    413
    414    tcg_gen_mov_tl(cpu_R[R_PC], load_gpr(dc, instr.a));
    415
    416    dc->base.is_jmp = DISAS_JUMP;
    417}
    418
    419/* rC <- PC + 4 */
    420static void nextpc(DisasContext *dc, uint32_t code, uint32_t flags)
    421{
    422    R_TYPE(instr, code);
    423
    424    if (likely(instr.c != R_ZERO)) {
    425        tcg_gen_movi_tl(cpu_R[instr.c], dc->base.pc_next);
    426    }
    427}
    428
    429/*
    430 * ra <- PC + 4
    431 * PC <- rA
    432 */
    433static void callr(DisasContext *dc, uint32_t code, uint32_t flags)
    434{
    435    R_TYPE(instr, code);
    436
    437    tcg_gen_mov_tl(cpu_R[R_PC], load_gpr(dc, instr.a));
    438    tcg_gen_movi_tl(cpu_R[R_RA], dc->base.pc_next);
    439
    440    dc->base.is_jmp = DISAS_JUMP;
    441}
    442
    443/* rC <- ctlN */
    444static void rdctl(DisasContext *dc, uint32_t code, uint32_t flags)
    445{
    446    R_TYPE(instr, code);
    447
    448    gen_check_supervisor(dc);
    449
    450    switch (instr.imm5 + CR_BASE) {
    451    case CR_PTEADDR:
    452    case CR_TLBACC:
    453    case CR_TLBMISC:
    454    {
    455#if !defined(CONFIG_USER_ONLY)
    456        if (likely(instr.c != R_ZERO)) {
    457            tcg_gen_mov_tl(cpu_R[instr.c], cpu_R[instr.imm5 + CR_BASE]);
    458#ifdef DEBUG_MMU
    459            TCGv_i32 tmp = tcg_const_i32(instr.imm5 + CR_BASE);
    460            gen_helper_mmu_read_debug(cpu_R[instr.c], cpu_env, tmp);
    461            tcg_temp_free_i32(tmp);
    462#endif
    463        }
    464#endif
    465        break;
    466    }
    467
    468    default:
    469        if (likely(instr.c != R_ZERO)) {
    470            tcg_gen_mov_tl(cpu_R[instr.c], cpu_R[instr.imm5 + CR_BASE]);
    471        }
    472        break;
    473    }
    474}
    475
    476/* ctlN <- rA */
    477static void wrctl(DisasContext *dc, uint32_t code, uint32_t flags)
    478{
    479    R_TYPE(instr, code);
    480
    481    gen_check_supervisor(dc);
    482
    483    switch (instr.imm5 + CR_BASE) {
    484    case CR_PTEADDR:
    485    case CR_TLBACC:
    486    case CR_TLBMISC:
    487    {
    488#if !defined(CONFIG_USER_ONLY)
    489        TCGv_i32 tmp = tcg_const_i32(instr.imm5 + CR_BASE);
    490        gen_helper_mmu_write(cpu_env, tmp, load_gpr(dc, instr.a));
    491        tcg_temp_free_i32(tmp);
    492#endif
    493        break;
    494    }
    495
    496    default:
    497        tcg_gen_mov_tl(cpu_R[instr.imm5 + CR_BASE], load_gpr(dc, instr.a));
    498        break;
    499    }
    500
    501    /* If interrupts were enabled using WRCTL, trigger them. */
    502#if !defined(CONFIG_USER_ONLY)
    503    if ((instr.imm5 + CR_BASE) == CR_STATUS) {
    504        if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
    505            gen_io_start();
    506        }
    507        gen_helper_check_interrupts(cpu_env);
    508        dc->base.is_jmp = DISAS_UPDATE;
    509    }
    510#endif
    511}
    512
    513/* Comparison instructions */
    514static void gen_cmpxx(DisasContext *dc, uint32_t code, uint32_t flags)
    515{
    516    R_TYPE(instr, code);
    517    if (likely(instr.c != R_ZERO)) {
    518        tcg_gen_setcond_tl(flags, cpu_R[instr.c], cpu_R[instr.a],
    519                           cpu_R[instr.b]);
    520    }
    521}
    522
    523/* Math/logic instructions */
    524#define gen_r_math_logic(fname, insn, op3)                                 \
    525static void (fname)(DisasContext *dc, uint32_t code, uint32_t flags)       \
    526{                                                                          \
    527    R_TYPE(instr, (code));                                                 \
    528    if (likely(instr.c != R_ZERO)) {                                       \
    529        tcg_gen_##insn(cpu_R[instr.c], load_gpr((dc), instr.a), (op3));    \
    530    }                                                                      \
    531}
    532
    533gen_r_math_logic(add,  add_tl,   load_gpr(dc, instr.b))
    534gen_r_math_logic(sub,  sub_tl,   load_gpr(dc, instr.b))
    535gen_r_math_logic(mul,  mul_tl,   load_gpr(dc, instr.b))
    536
    537gen_r_math_logic(and,  and_tl,   load_gpr(dc, instr.b))
    538gen_r_math_logic(or,   or_tl,    load_gpr(dc, instr.b))
    539gen_r_math_logic(xor,  xor_tl,   load_gpr(dc, instr.b))
    540gen_r_math_logic(nor,  nor_tl,   load_gpr(dc, instr.b))
    541
    542gen_r_math_logic(srai, sari_tl,  instr.imm5)
    543gen_r_math_logic(srli, shri_tl,  instr.imm5)
    544gen_r_math_logic(slli, shli_tl,  instr.imm5)
    545gen_r_math_logic(roli, rotli_tl, instr.imm5)
    546
    547#define gen_r_mul(fname, insn)                                         \
    548static void (fname)(DisasContext *dc, uint32_t code, uint32_t flags)   \
    549{                                                                      \
    550    R_TYPE(instr, (code));                                             \
    551    if (likely(instr.c != R_ZERO)) {                                   \
    552        TCGv t0 = tcg_temp_new();                                      \
    553        tcg_gen_##insn(t0, cpu_R[instr.c],                             \
    554                       load_gpr(dc, instr.a), load_gpr(dc, instr.b));  \
    555        tcg_temp_free(t0);                                             \
    556    }                                                                  \
    557}
    558
    559gen_r_mul(mulxss, muls2_tl)
    560gen_r_mul(mulxuu, mulu2_tl)
    561gen_r_mul(mulxsu, mulsu2_tl)
    562
    563#define gen_r_shift_s(fname, insn)                                         \
    564static void (fname)(DisasContext *dc, uint32_t code, uint32_t flags)       \
    565{                                                                          \
    566    R_TYPE(instr, (code));                                                 \
    567    if (likely(instr.c != R_ZERO)) {                                       \
    568        TCGv t0 = tcg_temp_new();                                          \
    569        tcg_gen_andi_tl(t0, load_gpr((dc), instr.b), 31);                  \
    570        tcg_gen_##insn(cpu_R[instr.c], load_gpr((dc), instr.a), t0);       \
    571        tcg_temp_free(t0);                                                 \
    572    }                                                                      \
    573}
    574
    575gen_r_shift_s(sra, sar_tl)
    576gen_r_shift_s(srl, shr_tl)
    577gen_r_shift_s(sll, shl_tl)
    578gen_r_shift_s(rol, rotl_tl)
    579gen_r_shift_s(ror, rotr_tl)
    580
    581static void divs(DisasContext *dc, uint32_t code, uint32_t flags)
    582{
    583    R_TYPE(instr, (code));
    584
    585    /* Stores into R_ZERO are ignored */
    586    if (unlikely(instr.c == R_ZERO)) {
    587        return;
    588    }
    589
    590    TCGv t0 = tcg_temp_new();
    591    TCGv t1 = tcg_temp_new();
    592    TCGv t2 = tcg_temp_new();
    593    TCGv t3 = tcg_temp_new();
    594
    595    tcg_gen_ext32s_tl(t0, load_gpr(dc, instr.a));
    596    tcg_gen_ext32s_tl(t1, load_gpr(dc, instr.b));
    597    tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
    598    tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
    599    tcg_gen_and_tl(t2, t2, t3);
    600    tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
    601    tcg_gen_or_tl(t2, t2, t3);
    602    tcg_gen_movi_tl(t3, 0);
    603    tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
    604    tcg_gen_div_tl(cpu_R[instr.c], t0, t1);
    605    tcg_gen_ext32s_tl(cpu_R[instr.c], cpu_R[instr.c]);
    606
    607    tcg_temp_free(t3);
    608    tcg_temp_free(t2);
    609    tcg_temp_free(t1);
    610    tcg_temp_free(t0);
    611}
    612
    613static void divu(DisasContext *dc, uint32_t code, uint32_t flags)
    614{
    615    R_TYPE(instr, (code));
    616
    617    /* Stores into R_ZERO are ignored */
    618    if (unlikely(instr.c == R_ZERO)) {
    619        return;
    620    }
    621
    622    TCGv t0 = tcg_temp_new();
    623    TCGv t1 = tcg_temp_new();
    624    TCGv t2 = tcg_const_tl(0);
    625    TCGv t3 = tcg_const_tl(1);
    626
    627    tcg_gen_ext32u_tl(t0, load_gpr(dc, instr.a));
    628    tcg_gen_ext32u_tl(t1, load_gpr(dc, instr.b));
    629    tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
    630    tcg_gen_divu_tl(cpu_R[instr.c], t0, t1);
    631    tcg_gen_ext32s_tl(cpu_R[instr.c], cpu_R[instr.c]);
    632
    633    tcg_temp_free(t3);
    634    tcg_temp_free(t2);
    635    tcg_temp_free(t1);
    636    tcg_temp_free(t0);
    637}
    638
    639static const Nios2Instruction r_type_instructions[] = {
    640    INSTRUCTION_ILLEGAL(),
    641    INSTRUCTION(eret),                                /* eret */
    642    INSTRUCTION(roli),                                /* roli */
    643    INSTRUCTION(rol),                                 /* rol */
    644    INSTRUCTION_NOP(),                                /* flushp */
    645    INSTRUCTION(ret),                                 /* ret */
    646    INSTRUCTION(nor),                                 /* nor */
    647    INSTRUCTION(mulxuu),                              /* mulxuu */
    648    INSTRUCTION_FLG(gen_cmpxx, TCG_COND_GE),          /* cmpge */
    649    INSTRUCTION(bret),                                /* bret */
    650    INSTRUCTION_ILLEGAL(),
    651    INSTRUCTION(ror),                                 /* ror */
    652    INSTRUCTION_NOP(),                                /* flushi */
    653    INSTRUCTION(jmp),                                 /* jmp */
    654    INSTRUCTION(and),                                 /* and */
    655    INSTRUCTION_ILLEGAL(),
    656    INSTRUCTION_FLG(gen_cmpxx, TCG_COND_LT),          /* cmplt */
    657    INSTRUCTION_ILLEGAL(),
    658    INSTRUCTION(slli),                                /* slli */
    659    INSTRUCTION(sll),                                 /* sll */
    660    INSTRUCTION_UNIMPLEMENTED(),                      /* wrprs */
    661    INSTRUCTION_ILLEGAL(),
    662    INSTRUCTION(or),                                  /* or */
    663    INSTRUCTION(mulxsu),                              /* mulxsu */
    664    INSTRUCTION_FLG(gen_cmpxx, TCG_COND_NE),          /* cmpne */
    665    INSTRUCTION_ILLEGAL(),
    666    INSTRUCTION(srli),                                /* srli */
    667    INSTRUCTION(srl),                                 /* srl */
    668    INSTRUCTION(nextpc),                              /* nextpc */
    669    INSTRUCTION(callr),                               /* callr */
    670    INSTRUCTION(xor),                                 /* xor */
    671    INSTRUCTION(mulxss),                              /* mulxss */
    672    INSTRUCTION_FLG(gen_cmpxx, TCG_COND_EQ),          /* cmpeq */
    673    INSTRUCTION_ILLEGAL(),
    674    INSTRUCTION_ILLEGAL(),
    675    INSTRUCTION_ILLEGAL(),
    676    INSTRUCTION(divu),                                /* divu */
    677    INSTRUCTION(divs),                                /* div */
    678    INSTRUCTION(rdctl),                               /* rdctl */
    679    INSTRUCTION(mul),                                 /* mul */
    680    INSTRUCTION_FLG(gen_cmpxx, TCG_COND_GEU),         /* cmpgeu */
    681    INSTRUCTION_NOP(),                                /* initi */
    682    INSTRUCTION_ILLEGAL(),
    683    INSTRUCTION_ILLEGAL(),
    684    INSTRUCTION_ILLEGAL(),
    685    INSTRUCTION_FLG(gen_excp, EXCP_TRAP),             /* trap */
    686    INSTRUCTION(wrctl),                               /* wrctl */
    687    INSTRUCTION_ILLEGAL(),
    688    INSTRUCTION_FLG(gen_cmpxx, TCG_COND_LTU),         /* cmpltu */
    689    INSTRUCTION(add),                                 /* add */
    690    INSTRUCTION_ILLEGAL(),
    691    INSTRUCTION_ILLEGAL(),
    692    INSTRUCTION_FLG(gen_excp, EXCP_BREAK),            /* break */
    693    INSTRUCTION_ILLEGAL(),
    694    INSTRUCTION(nop),                                 /* nop */
    695    INSTRUCTION_ILLEGAL(),
    696    INSTRUCTION_ILLEGAL(),
    697    INSTRUCTION(sub),                                 /* sub */
    698    INSTRUCTION(srai),                                /* srai */
    699    INSTRUCTION(sra),                                 /* sra */
    700    INSTRUCTION_ILLEGAL(),
    701    INSTRUCTION_ILLEGAL(),
    702    INSTRUCTION_ILLEGAL(),
    703    INSTRUCTION_ILLEGAL(),
    704};
    705
    706static void handle_r_type_instr(DisasContext *dc, uint32_t code, uint32_t flags)
    707{
    708    uint8_t opx;
    709    const Nios2Instruction *instr;
    710
    711    opx = get_opxcode(code);
    712    if (unlikely(opx >= ARRAY_SIZE(r_type_instructions))) {
    713        goto illegal_op;
    714    }
    715
    716    instr = &r_type_instructions[opx];
    717    instr->handler(dc, code, instr->flags);
    718
    719    return;
    720
    721illegal_op:
    722    t_gen_helper_raise_exception(dc, EXCP_ILLEGAL);
    723}
    724
    725static const char * const regnames[] = {
    726    "zero",       "at",         "r2",         "r3",
    727    "r4",         "r5",         "r6",         "r7",
    728    "r8",         "r9",         "r10",        "r11",
    729    "r12",        "r13",        "r14",        "r15",
    730    "r16",        "r17",        "r18",        "r19",
    731    "r20",        "r21",        "r22",        "r23",
    732    "et",         "bt",         "gp",         "sp",
    733    "fp",         "ea",         "ba",         "ra",
    734    "status",     "estatus",    "bstatus",    "ienable",
    735    "ipending",   "cpuid",      "reserved0",  "exception",
    736    "pteaddr",    "tlbacc",     "tlbmisc",    "reserved1",
    737    "badaddr",    "config",     "mpubase",    "mpuacc",
    738    "reserved2",  "reserved3",  "reserved4",  "reserved5",
    739    "reserved6",  "reserved7",  "reserved8",  "reserved9",
    740    "reserved10", "reserved11", "reserved12", "reserved13",
    741    "reserved14", "reserved15", "reserved16", "reserved17",
    742    "rpc"
    743};
    744
    745#include "exec/gen-icount.h"
    746
    747/* generate intermediate code for basic block 'tb'.  */
    748static void nios2_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
    749{
    750    DisasContext *dc = container_of(dcbase, DisasContext, base);
    751    CPUNios2State *env = cs->env_ptr;
    752    int page_insns;
    753
    754    dc->mem_idx = cpu_mmu_index(env, false);
    755
    756    /* Bound the number of insns to execute to those left on the page.  */
    757    page_insns = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
    758    dc->base.max_insns = MIN(page_insns, dc->base.max_insns);
    759}
    760
    761static void nios2_tr_tb_start(DisasContextBase *db, CPUState *cs)
    762{
    763}
    764
    765static void nios2_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
    766{
    767    tcg_gen_insn_start(dcbase->pc_next);
    768}
    769
    770static void nios2_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
    771{
    772    DisasContext *dc = container_of(dcbase, DisasContext, base);
    773    CPUNios2State *env = cs->env_ptr;
    774    const Nios2Instruction *instr;
    775    uint32_t code, pc;
    776    uint8_t op;
    777
    778    pc = dc->base.pc_next;
    779    dc->pc = pc;
    780    dc->base.pc_next = pc + 4;
    781
    782    /* Decode an instruction */
    783
    784#if defined(CONFIG_USER_ONLY)
    785    /* FIXME: Is this needed ? */
    786    if (pc >= 0x1000 && pc < 0x2000) {
    787        t_gen_helper_raise_exception(dc, 0xaa);
    788        return;
    789    }
    790#endif
    791
    792    code = cpu_ldl_code(env, pc);
    793    op = get_opcode(code);
    794
    795    if (unlikely(op >= ARRAY_SIZE(i_type_instructions))) {
    796        t_gen_helper_raise_exception(dc, EXCP_ILLEGAL);
    797        return;
    798    }
    799
    800    dc->zero = NULL;
    801
    802    instr = &i_type_instructions[op];
    803    instr->handler(dc, code, instr->flags);
    804
    805    if (dc->zero) {
    806        tcg_temp_free(dc->zero);
    807    }
    808}
    809
    810static void nios2_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
    811{
    812    DisasContext *dc = container_of(dcbase, DisasContext, base);
    813
    814    /* Indicate where the next block should start */
    815    switch (dc->base.is_jmp) {
    816    case DISAS_TOO_MANY:
    817    case DISAS_UPDATE:
    818        /* Save the current PC back into the CPU register */
    819        tcg_gen_movi_tl(cpu_R[R_PC], dc->base.pc_next);
    820        tcg_gen_exit_tb(NULL, 0);
    821        break;
    822
    823    case DISAS_JUMP:
    824        /* The jump will already have updated the PC register */
    825        tcg_gen_exit_tb(NULL, 0);
    826        break;
    827
    828    case DISAS_NORETURN:
    829        /* nothing more to generate */
    830        break;
    831
    832    default:
    833        g_assert_not_reached();
    834    }
    835}
    836
    837static void nios2_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
    838{
    839    qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
    840    log_target_disas(cpu, dcbase->pc_first, dcbase->tb->size);
    841}
    842
    843static const TranslatorOps nios2_tr_ops = {
    844    .init_disas_context = nios2_tr_init_disas_context,
    845    .tb_start           = nios2_tr_tb_start,
    846    .insn_start         = nios2_tr_insn_start,
    847    .translate_insn     = nios2_tr_translate_insn,
    848    .tb_stop            = nios2_tr_tb_stop,
    849    .disas_log          = nios2_tr_disas_log,
    850};
    851
    852void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
    853{
    854    DisasContext dc;
    855    translator_loop(&nios2_tr_ops, &dc.base, cs, tb, max_insns);
    856}
    857
    858void nios2_cpu_dump_state(CPUState *cs, FILE *f, int flags)
    859{
    860    Nios2CPU *cpu = NIOS2_CPU(cs);
    861    CPUNios2State *env = &cpu->env;
    862    int i;
    863
    864    if (!env) {
    865        return;
    866    }
    867
    868    qemu_fprintf(f, "IN: PC=%x %s\n",
    869                 env->regs[R_PC], lookup_symbol(env->regs[R_PC]));
    870
    871    for (i = 0; i < NUM_CORE_REGS; i++) {
    872        qemu_fprintf(f, "%9s=%8.8x ", regnames[i], env->regs[i]);
    873        if ((i + 1) % 4 == 0) {
    874            qemu_fprintf(f, "\n");
    875        }
    876    }
    877#if !defined(CONFIG_USER_ONLY)
    878    qemu_fprintf(f, " mmu write: VPN=%05X PID %02X TLBACC %08X\n",
    879                 env->mmu.pteaddr_wr & CR_PTEADDR_VPN_MASK,
    880                 (env->mmu.tlbmisc_wr & CR_TLBMISC_PID_MASK) >> 4,
    881                 env->mmu.tlbacc_wr);
    882#endif
    883    qemu_fprintf(f, "\n\n");
    884}
    885
    886void nios2_tcg_init(void)
    887{
    888    int i;
    889
    890    for (i = 0; i < NUM_CORE_REGS; i++) {
    891        cpu_R[i] = tcg_global_mem_new(cpu_env,
    892                                      offsetof(CPUNios2State, regs[i]),
    893                                      regnames[i]);
    894    }
    895}
    896
    897void restore_state_to_opc(CPUNios2State *env, TranslationBlock *tb,
    898                          target_ulong *data)
    899{
    900    env->regs[R_PC] = data[0];
    901}