qemu/target/nios2/translate.c
<<
>>
Prefs
   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-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
  36/* is_jmp field values */
  37#define DISAS_JUMP    DISAS_TARGET_0 /* only pc was modified dynamically */
  38#define DISAS_UPDATE  DISAS_TARGET_1 /* cpu state was modified dynamically */
  39#define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */
  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    TCGv_ptr          cpu_env;
 101    TCGv             *cpu_R;
 102    TCGv_i32          zero;
 103    int               is_jmp;
 104    target_ulong      pc;
 105    TranslationBlock *tb;
 106    int               mem_idx;
 107    bool              singlestep_enabled;
 108} DisasContext;
 109
 110typedef struct Nios2Instruction {
 111    void     (*handler)(DisasContext *dc, uint32_t code, uint32_t flags);
 112    uint32_t  flags;
 113} Nios2Instruction;
 114
 115static uint8_t get_opcode(uint32_t code)
 116{
 117    I_TYPE(instr, code);
 118    return instr.op;
 119}
 120
 121static uint8_t get_opxcode(uint32_t code)
 122{
 123    R_TYPE(instr, code);
 124    return instr.opx;
 125}
 126
 127static TCGv load_zero(DisasContext *dc)
 128{
 129    if (!dc->zero) {
 130        dc->zero = tcg_const_i32(0);
 131    }
 132    return dc->zero;
 133}
 134
 135static TCGv load_gpr(DisasContext *dc, uint8_t reg)
 136{
 137    if (likely(reg != R_ZERO)) {
 138        return dc->cpu_R[reg];
 139    } else {
 140        return load_zero(dc);
 141    }
 142}
 143
 144static void t_gen_helper_raise_exception(DisasContext *dc,
 145                                         uint32_t index)
 146{
 147    TCGv_i32 tmp = tcg_const_i32(index);
 148
 149    tcg_gen_movi_tl(dc->cpu_R[R_PC], dc->pc);
 150    gen_helper_raise_exception(dc->cpu_env, tmp);
 151    tcg_temp_free_i32(tmp);
 152    dc->is_jmp = DISAS_UPDATE;
 153}
 154
 155static bool use_goto_tb(DisasContext *dc, uint32_t dest)
 156{
 157    if (unlikely(dc->singlestep_enabled)) {
 158        return false;
 159    }
 160
 161#ifndef CONFIG_USER_ONLY
 162    return (dc->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
 163#else
 164    return true;
 165#endif
 166}
 167
 168static void gen_goto_tb(DisasContext *dc, int n, uint32_t dest)
 169{
 170    TranslationBlock *tb = dc->tb;
 171
 172    if (use_goto_tb(dc, dest)) {
 173        tcg_gen_goto_tb(n);
 174        tcg_gen_movi_tl(dc->cpu_R[R_PC], dest);
 175        tcg_gen_exit_tb(tb, n);
 176    } else {
 177        tcg_gen_movi_tl(dc->cpu_R[R_PC], dest);
 178        tcg_gen_exit_tb(NULL, 0);
 179    }
 180}
 181
 182static void gen_excp(DisasContext *dc, uint32_t code, uint32_t flags)
 183{
 184    t_gen_helper_raise_exception(dc, flags);
 185}
 186
 187static void gen_check_supervisor(DisasContext *dc)
 188{
 189    if (dc->tb->flags & CR_STATUS_U) {
 190        /* CPU in user mode, privileged instruction called, stop. */
 191        t_gen_helper_raise_exception(dc, EXCP_SUPERI);
 192    }
 193}
 194
 195/*
 196 * Used as a placeholder for all instructions which do not have
 197 * an effect on the simulator (e.g. flush, sync)
 198 */
 199static void nop(DisasContext *dc, uint32_t code, uint32_t flags)
 200{
 201    /* Nothing to do here */
 202}
 203
 204/*
 205 * J-Type instructions
 206 */
 207static void jmpi(DisasContext *dc, uint32_t code, uint32_t flags)
 208{
 209    J_TYPE(instr, code);
 210    gen_goto_tb(dc, 0, (dc->pc & 0xF0000000) | (instr.imm26 << 2));
 211    dc->is_jmp = DISAS_TB_JUMP;
 212}
 213
 214static void call(DisasContext *dc, uint32_t code, uint32_t flags)
 215{
 216    tcg_gen_movi_tl(dc->cpu_R[R_RA], dc->pc + 4);
 217    jmpi(dc, code, flags);
 218}
 219
 220/*
 221 * I-Type instructions
 222 */
 223/* Load instructions */
 224static void gen_ldx(DisasContext *dc, uint32_t code, uint32_t flags)
 225{
 226    I_TYPE(instr, code);
 227
 228    TCGv addr = tcg_temp_new();
 229    TCGv data;
 230
 231    /*
 232     * WARNING: Loads into R_ZERO are ignored, but we must generate the
 233     *          memory access itself to emulate the CPU precisely. Load
 234     *          from a protected page to R_ZERO will cause SIGSEGV on
 235     *          the Nios2 CPU.
 236     */
 237    if (likely(instr.b != R_ZERO)) {
 238        data = dc->cpu_R[instr.b];
 239    } else {
 240        data = tcg_temp_new();
 241    }
 242
 243    tcg_gen_addi_tl(addr, load_gpr(dc, instr.a), instr.imm16.s);
 244    tcg_gen_qemu_ld_tl(data, addr, dc->mem_idx, flags);
 245
 246    if (unlikely(instr.b == R_ZERO)) {
 247        tcg_temp_free(data);
 248    }
 249
 250    tcg_temp_free(addr);
 251}
 252
 253/* Store instructions */
 254static void gen_stx(DisasContext *dc, uint32_t code, uint32_t flags)
 255{
 256    I_TYPE(instr, code);
 257    TCGv val = load_gpr(dc, instr.b);
 258
 259    TCGv addr = tcg_temp_new();
 260    tcg_gen_addi_tl(addr, load_gpr(dc, instr.a), instr.imm16.s);
 261    tcg_gen_qemu_st_tl(val, addr, dc->mem_idx, flags);
 262    tcg_temp_free(addr);
 263}
 264
 265/* Branch instructions */
 266static void br(DisasContext *dc, uint32_t code, uint32_t flags)
 267{
 268    I_TYPE(instr, code);
 269
 270    gen_goto_tb(dc, 0, dc->pc + 4 + (instr.imm16.s & -4));
 271    dc->is_jmp = DISAS_TB_JUMP;
 272}
 273
 274static void gen_bxx(DisasContext *dc, uint32_t code, uint32_t flags)
 275{
 276    I_TYPE(instr, code);
 277
 278    TCGLabel *l1 = gen_new_label();
 279    tcg_gen_brcond_tl(flags, dc->cpu_R[instr.a], dc->cpu_R[instr.b], l1);
 280    gen_goto_tb(dc, 0, dc->pc + 4);
 281    gen_set_label(l1);
 282    gen_goto_tb(dc, 1, dc->pc + 4 + (instr.imm16.s & -4));
 283    dc->is_jmp = DISAS_TB_JUMP;
 284}
 285
 286/* Comparison instructions */
 287#define gen_i_cmpxx(fname, op3)                                              \
 288static void (fname)(DisasContext *dc, uint32_t code, uint32_t flags)         \
 289{                                                                            \
 290    I_TYPE(instr, (code));                                                   \
 291    tcg_gen_setcondi_tl(flags, (dc)->cpu_R[instr.b], (dc)->cpu_R[instr.a],   \
 292                        (op3));                                              \
 293}
 294
 295gen_i_cmpxx(gen_cmpxxsi, instr.imm16.s)
 296gen_i_cmpxx(gen_cmpxxui, instr.imm16.u)
 297
 298/* Math/logic instructions */
 299#define gen_i_math_logic(fname, insn, resimm, op3)                          \
 300static void (fname)(DisasContext *dc, uint32_t code, uint32_t flags)        \
 301{                                                                           \
 302    I_TYPE(instr, (code));                                                  \
 303    if (unlikely(instr.b == R_ZERO)) { /* Store to R_ZERO is ignored */     \
 304        return;                                                             \
 305    } else if (instr.a == R_ZERO) { /* MOVxI optimizations */               \
 306        tcg_gen_movi_tl(dc->cpu_R[instr.b], (resimm) ? (op3) : 0);          \
 307    } else {                                                                \
 308        tcg_gen_##insn##_tl((dc)->cpu_R[instr.b], (dc)->cpu_R[instr.a],     \
 309                            (op3));                                         \
 310    }                                                                       \
 311}
 312
 313gen_i_math_logic(addi,  addi, 1, instr.imm16.s)
 314gen_i_math_logic(muli,  muli, 0, instr.imm16.s)
 315
 316gen_i_math_logic(andi,  andi, 0, instr.imm16.u)
 317gen_i_math_logic(ori,   ori,  1, instr.imm16.u)
 318gen_i_math_logic(xori,  xori, 1, instr.imm16.u)
 319
 320gen_i_math_logic(andhi, andi, 0, instr.imm16.u << 16)
 321gen_i_math_logic(orhi , ori,  1, instr.imm16.u << 16)
 322gen_i_math_logic(xorhi, xori, 1, instr.imm16.u << 16)
 323
 324/* Prototype only, defined below */
 325static void handle_r_type_instr(DisasContext *dc, uint32_t code,
 326                                uint32_t flags);
 327
 328static const Nios2Instruction i_type_instructions[] = {
 329    INSTRUCTION(call),                                /* call */
 330    INSTRUCTION(jmpi),                                /* jmpi */
 331    INSTRUCTION_ILLEGAL(),
 332    INSTRUCTION_FLG(gen_ldx, MO_UB),                  /* ldbu */
 333    INSTRUCTION(addi),                                /* addi */
 334    INSTRUCTION_FLG(gen_stx, MO_UB),                  /* stb */
 335    INSTRUCTION(br),                                  /* br */
 336    INSTRUCTION_FLG(gen_ldx, MO_SB),                  /* ldb */
 337    INSTRUCTION_FLG(gen_cmpxxsi, TCG_COND_GE),        /* cmpgei */
 338    INSTRUCTION_ILLEGAL(),
 339    INSTRUCTION_ILLEGAL(),
 340    INSTRUCTION_FLG(gen_ldx, MO_UW),                  /* ldhu */
 341    INSTRUCTION(andi),                                /* andi */
 342    INSTRUCTION_FLG(gen_stx, MO_UW),                  /* sth */
 343    INSTRUCTION_FLG(gen_bxx, TCG_COND_GE),            /* bge */
 344    INSTRUCTION_FLG(gen_ldx, MO_SW),                  /* ldh */
 345    INSTRUCTION_FLG(gen_cmpxxsi, TCG_COND_LT),        /* cmplti */
 346    INSTRUCTION_ILLEGAL(),
 347    INSTRUCTION_ILLEGAL(),
 348    INSTRUCTION_NOP(),                                /* initda */
 349    INSTRUCTION(ori),                                 /* ori */
 350    INSTRUCTION_FLG(gen_stx, MO_UL),                  /* stw */
 351    INSTRUCTION_FLG(gen_bxx, TCG_COND_LT),            /* blt */
 352    INSTRUCTION_FLG(gen_ldx, MO_UL),                  /* ldw */
 353    INSTRUCTION_FLG(gen_cmpxxsi, TCG_COND_NE),        /* cmpnei */
 354    INSTRUCTION_ILLEGAL(),
 355    INSTRUCTION_ILLEGAL(),
 356    INSTRUCTION_NOP(),                                /* flushda */
 357    INSTRUCTION(xori),                                /* xori */
 358    INSTRUCTION_ILLEGAL(),
 359    INSTRUCTION_FLG(gen_bxx, TCG_COND_NE),            /* bne */
 360    INSTRUCTION_ILLEGAL(),
 361    INSTRUCTION_FLG(gen_cmpxxsi, TCG_COND_EQ),        /* cmpeqi */
 362    INSTRUCTION_ILLEGAL(),
 363    INSTRUCTION_ILLEGAL(),
 364    INSTRUCTION_FLG(gen_ldx, MO_UB),                  /* ldbuio */
 365    INSTRUCTION(muli),                                /* muli */
 366    INSTRUCTION_FLG(gen_stx, MO_UB),                  /* stbio */
 367    INSTRUCTION_FLG(gen_bxx, TCG_COND_EQ),            /* beq */
 368    INSTRUCTION_FLG(gen_ldx, MO_SB),                  /* ldbio */
 369    INSTRUCTION_FLG(gen_cmpxxui, TCG_COND_GEU),       /* cmpgeui */
 370    INSTRUCTION_ILLEGAL(),
 371    INSTRUCTION_ILLEGAL(),
 372    INSTRUCTION_FLG(gen_ldx, MO_UW),                  /* ldhuio */
 373    INSTRUCTION(andhi),                               /* andhi */
 374    INSTRUCTION_FLG(gen_stx, MO_UW),                  /* sthio */
 375    INSTRUCTION_FLG(gen_bxx, TCG_COND_GEU),           /* bgeu */
 376    INSTRUCTION_FLG(gen_ldx, MO_SW),                  /* ldhio */
 377    INSTRUCTION_FLG(gen_cmpxxui, TCG_COND_LTU),       /* cmpltui */
 378    INSTRUCTION_ILLEGAL(),
 379    INSTRUCTION_UNIMPLEMENTED(),                      /* custom */
 380    INSTRUCTION_NOP(),                                /* initd */
 381    INSTRUCTION(orhi),                                /* orhi */
 382    INSTRUCTION_FLG(gen_stx, MO_SL),                  /* stwio */
 383    INSTRUCTION_FLG(gen_bxx, TCG_COND_LTU),           /* bltu */
 384    INSTRUCTION_FLG(gen_ldx, MO_UL),                  /* ldwio */
 385    INSTRUCTION_UNIMPLEMENTED(),                      /* rdprs */
 386    INSTRUCTION_ILLEGAL(),
 387    INSTRUCTION_FLG(handle_r_type_instr, 0),          /* R-Type */
 388    INSTRUCTION_NOP(),                                /* flushd */
 389    INSTRUCTION(xorhi),                               /* xorhi */
 390    INSTRUCTION_ILLEGAL(),
 391    INSTRUCTION_ILLEGAL(),
 392    INSTRUCTION_ILLEGAL(),
 393};
 394
 395/*
 396 * R-Type instructions
 397 */
 398/*
 399 * status <- estatus
 400 * PC <- ea
 401 */
 402static void eret(DisasContext *dc, uint32_t code, uint32_t flags)
 403{
 404    tcg_gen_mov_tl(dc->cpu_R[CR_STATUS], dc->cpu_R[CR_ESTATUS]);
 405    tcg_gen_mov_tl(dc->cpu_R[R_PC], dc->cpu_R[R_EA]);
 406
 407    dc->is_jmp = DISAS_JUMP;
 408}
 409
 410/* PC <- ra */
 411static void ret(DisasContext *dc, uint32_t code, uint32_t flags)
 412{
 413    tcg_gen_mov_tl(dc->cpu_R[R_PC], dc->cpu_R[R_RA]);
 414
 415    dc->is_jmp = DISAS_JUMP;
 416}
 417
 418/* PC <- ba */
 419static void bret(DisasContext *dc, uint32_t code, uint32_t flags)
 420{
 421    tcg_gen_mov_tl(dc->cpu_R[R_PC], dc->cpu_R[R_BA]);
 422
 423    dc->is_jmp = DISAS_JUMP;
 424}
 425
 426/* PC <- rA */
 427static void jmp(DisasContext *dc, uint32_t code, uint32_t flags)
 428{
 429    R_TYPE(instr, code);
 430
 431    tcg_gen_mov_tl(dc->cpu_R[R_PC], load_gpr(dc, instr.a));
 432
 433    dc->is_jmp = DISAS_JUMP;
 434}
 435
 436/* rC <- PC + 4 */
 437static void nextpc(DisasContext *dc, uint32_t code, uint32_t flags)
 438{
 439    R_TYPE(instr, code);
 440
 441    if (likely(instr.c != R_ZERO)) {
 442        tcg_gen_movi_tl(dc->cpu_R[instr.c], dc->pc + 4);
 443    }
 444}
 445
 446/*
 447 * ra <- PC + 4
 448 * PC <- rA
 449 */
 450static void callr(DisasContext *dc, uint32_t code, uint32_t flags)
 451{
 452    R_TYPE(instr, code);
 453
 454    tcg_gen_mov_tl(dc->cpu_R[R_PC], load_gpr(dc, instr.a));
 455    tcg_gen_movi_tl(dc->cpu_R[R_RA], dc->pc + 4);
 456
 457    dc->is_jmp = DISAS_JUMP;
 458}
 459
 460/* rC <- ctlN */
 461static void rdctl(DisasContext *dc, uint32_t code, uint32_t flags)
 462{
 463    R_TYPE(instr, code);
 464
 465    gen_check_supervisor(dc);
 466
 467    switch (instr.imm5 + CR_BASE) {
 468    case CR_PTEADDR:
 469    case CR_TLBACC:
 470    case CR_TLBMISC:
 471    {
 472#if !defined(CONFIG_USER_ONLY)
 473        if (likely(instr.c != R_ZERO)) {
 474            tcg_gen_mov_tl(dc->cpu_R[instr.c], dc->cpu_R[instr.imm5 + CR_BASE]);
 475#ifdef DEBUG_MMU
 476            TCGv_i32 tmp = tcg_const_i32(instr.imm5 + CR_BASE);
 477            gen_helper_mmu_read_debug(dc->cpu_R[instr.c], dc->cpu_env, tmp);
 478            tcg_temp_free_i32(tmp);
 479#endif
 480        }
 481#endif
 482        break;
 483    }
 484
 485    default:
 486        if (likely(instr.c != R_ZERO)) {
 487            tcg_gen_mov_tl(dc->cpu_R[instr.c], dc->cpu_R[instr.imm5 + CR_BASE]);
 488        }
 489        break;
 490    }
 491}
 492
 493/* ctlN <- rA */
 494static void wrctl(DisasContext *dc, uint32_t code, uint32_t flags)
 495{
 496    R_TYPE(instr, code);
 497
 498    gen_check_supervisor(dc);
 499
 500    switch (instr.imm5 + CR_BASE) {
 501    case CR_PTEADDR:
 502    case CR_TLBACC:
 503    case CR_TLBMISC:
 504    {
 505#if !defined(CONFIG_USER_ONLY)
 506        TCGv_i32 tmp = tcg_const_i32(instr.imm5 + CR_BASE);
 507        gen_helper_mmu_write(dc->cpu_env, tmp, load_gpr(dc, instr.a));
 508        tcg_temp_free_i32(tmp);
 509#endif
 510        break;
 511    }
 512
 513    default:
 514        tcg_gen_mov_tl(dc->cpu_R[instr.imm5 + CR_BASE], load_gpr(dc, instr.a));
 515        break;
 516    }
 517
 518    /* If interrupts were enabled using WRCTL, trigger them. */
 519#if !defined(CONFIG_USER_ONLY)
 520    if ((instr.imm5 + CR_BASE) == CR_STATUS) {
 521        gen_helper_check_interrupts(dc->cpu_env);
 522    }
 523#endif
 524}
 525
 526/* Comparison instructions */
 527static void gen_cmpxx(DisasContext *dc, uint32_t code, uint32_t flags)
 528{
 529    R_TYPE(instr, code);
 530    if (likely(instr.c != R_ZERO)) {
 531        tcg_gen_setcond_tl(flags, dc->cpu_R[instr.c], dc->cpu_R[instr.a],
 532                           dc->cpu_R[instr.b]);
 533    }
 534}
 535
 536/* Math/logic instructions */
 537#define gen_r_math_logic(fname, insn, op3)                                 \
 538static void (fname)(DisasContext *dc, uint32_t code, uint32_t flags)       \
 539{                                                                          \
 540    R_TYPE(instr, (code));                                                 \
 541    if (likely(instr.c != R_ZERO)) {                                       \
 542        tcg_gen_##insn((dc)->cpu_R[instr.c], load_gpr((dc), instr.a),      \
 543                       (op3));                                             \
 544    }                                                                      \
 545}
 546
 547gen_r_math_logic(add,  add_tl,   load_gpr(dc, instr.b))
 548gen_r_math_logic(sub,  sub_tl,   load_gpr(dc, instr.b))
 549gen_r_math_logic(mul,  mul_tl,   load_gpr(dc, instr.b))
 550
 551gen_r_math_logic(and,  and_tl,   load_gpr(dc, instr.b))
 552gen_r_math_logic(or,   or_tl,    load_gpr(dc, instr.b))
 553gen_r_math_logic(xor,  xor_tl,   load_gpr(dc, instr.b))
 554gen_r_math_logic(nor,  nor_tl,   load_gpr(dc, instr.b))
 555
 556gen_r_math_logic(srai, sari_tl,  instr.imm5)
 557gen_r_math_logic(srli, shri_tl,  instr.imm5)
 558gen_r_math_logic(slli, shli_tl,  instr.imm5)
 559gen_r_math_logic(roli, rotli_tl, instr.imm5)
 560
 561#define gen_r_mul(fname, insn)                                         \
 562static void (fname)(DisasContext *dc, uint32_t code, uint32_t flags)   \
 563{                                                                      \
 564    R_TYPE(instr, (code));                                             \
 565    if (likely(instr.c != R_ZERO)) {                                   \
 566        TCGv t0 = tcg_temp_new();                                      \
 567        tcg_gen_##insn(t0, dc->cpu_R[instr.c],                         \
 568                       load_gpr(dc, instr.a), load_gpr(dc, instr.b)); \
 569        tcg_temp_free(t0);                                             \
 570    }                                                                  \
 571}
 572
 573gen_r_mul(mulxss, muls2_tl)
 574gen_r_mul(mulxuu, mulu2_tl)
 575gen_r_mul(mulxsu, mulsu2_tl)
 576
 577#define gen_r_shift_s(fname, insn)                                         \
 578static void (fname)(DisasContext *dc, uint32_t code, uint32_t flags)       \
 579{                                                                          \
 580    R_TYPE(instr, (code));                                                 \
 581    if (likely(instr.c != R_ZERO)) {                                       \
 582        TCGv t0 = tcg_temp_new();                                          \
 583        tcg_gen_andi_tl(t0, load_gpr((dc), instr.b), 31);                  \
 584        tcg_gen_##insn((dc)->cpu_R[instr.c], load_gpr((dc), instr.a), t0); \
 585        tcg_temp_free(t0);                                                 \
 586    }                                                                      \
 587}
 588
 589gen_r_shift_s(sra, sar_tl)
 590gen_r_shift_s(srl, shr_tl)
 591gen_r_shift_s(sll, shl_tl)
 592gen_r_shift_s(rol, rotl_tl)
 593gen_r_shift_s(ror, rotr_tl)
 594
 595static void divs(DisasContext *dc, uint32_t code, uint32_t flags)
 596{
 597    R_TYPE(instr, (code));
 598
 599    /* Stores into R_ZERO are ignored */
 600    if (unlikely(instr.c == R_ZERO)) {
 601        return;
 602    }
 603
 604    TCGv t0 = tcg_temp_new();
 605    TCGv t1 = tcg_temp_new();
 606    TCGv t2 = tcg_temp_new();
 607    TCGv t3 = tcg_temp_new();
 608
 609    tcg_gen_ext32s_tl(t0, load_gpr(dc, instr.a));
 610    tcg_gen_ext32s_tl(t1, load_gpr(dc, instr.b));
 611    tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
 612    tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
 613    tcg_gen_and_tl(t2, t2, t3);
 614    tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
 615    tcg_gen_or_tl(t2, t2, t3);
 616    tcg_gen_movi_tl(t3, 0);
 617    tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
 618    tcg_gen_div_tl(dc->cpu_R[instr.c], t0, t1);
 619    tcg_gen_ext32s_tl(dc->cpu_R[instr.c], dc->cpu_R[instr.c]);
 620
 621    tcg_temp_free(t3);
 622    tcg_temp_free(t2);
 623    tcg_temp_free(t1);
 624    tcg_temp_free(t0);
 625}
 626
 627static void divu(DisasContext *dc, uint32_t code, uint32_t flags)
 628{
 629    R_TYPE(instr, (code));
 630
 631    /* Stores into R_ZERO are ignored */
 632    if (unlikely(instr.c == R_ZERO)) {
 633        return;
 634    }
 635
 636    TCGv t0 = tcg_temp_new();
 637    TCGv t1 = tcg_temp_new();
 638    TCGv t2 = tcg_const_tl(0);
 639    TCGv t3 = tcg_const_tl(1);
 640
 641    tcg_gen_ext32u_tl(t0, load_gpr(dc, instr.a));
 642    tcg_gen_ext32u_tl(t1, load_gpr(dc, instr.b));
 643    tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
 644    tcg_gen_divu_tl(dc->cpu_R[instr.c], t0, t1);
 645    tcg_gen_ext32s_tl(dc->cpu_R[instr.c], dc->cpu_R[instr.c]);
 646
 647    tcg_temp_free(t3);
 648    tcg_temp_free(t2);
 649    tcg_temp_free(t1);
 650    tcg_temp_free(t0);
 651}
 652
 653static const Nios2Instruction r_type_instructions[] = {
 654    INSTRUCTION_ILLEGAL(),
 655    INSTRUCTION(eret),                                /* eret */
 656    INSTRUCTION(roli),                                /* roli */
 657    INSTRUCTION(rol),                                 /* rol */
 658    INSTRUCTION_NOP(),                                /* flushp */
 659    INSTRUCTION(ret),                                 /* ret */
 660    INSTRUCTION(nor),                                 /* nor */
 661    INSTRUCTION(mulxuu),                              /* mulxuu */
 662    INSTRUCTION_FLG(gen_cmpxx, TCG_COND_GE),          /* cmpge */
 663    INSTRUCTION(bret),                                /* bret */
 664    INSTRUCTION_ILLEGAL(),
 665    INSTRUCTION(ror),                                 /* ror */
 666    INSTRUCTION_NOP(),                                /* flushi */
 667    INSTRUCTION(jmp),                                 /* jmp */
 668    INSTRUCTION(and),                                 /* and */
 669    INSTRUCTION_ILLEGAL(),
 670    INSTRUCTION_FLG(gen_cmpxx, TCG_COND_LT),          /* cmplt */
 671    INSTRUCTION_ILLEGAL(),
 672    INSTRUCTION(slli),                                /* slli */
 673    INSTRUCTION(sll),                                 /* sll */
 674    INSTRUCTION_UNIMPLEMENTED(),                      /* wrprs */
 675    INSTRUCTION_ILLEGAL(),
 676    INSTRUCTION(or),                                  /* or */
 677    INSTRUCTION(mulxsu),                              /* mulxsu */
 678    INSTRUCTION_FLG(gen_cmpxx, TCG_COND_NE),          /* cmpne */
 679    INSTRUCTION_ILLEGAL(),
 680    INSTRUCTION(srli),                                /* srli */
 681    INSTRUCTION(srl),                                 /* srl */
 682    INSTRUCTION(nextpc),                              /* nextpc */
 683    INSTRUCTION(callr),                               /* callr */
 684    INSTRUCTION(xor),                                 /* xor */
 685    INSTRUCTION(mulxss),                              /* mulxss */
 686    INSTRUCTION_FLG(gen_cmpxx, TCG_COND_EQ),          /* cmpeq */
 687    INSTRUCTION_ILLEGAL(),
 688    INSTRUCTION_ILLEGAL(),
 689    INSTRUCTION_ILLEGAL(),
 690    INSTRUCTION(divu),                                /* divu */
 691    INSTRUCTION(divs),                                /* div */
 692    INSTRUCTION(rdctl),                               /* rdctl */
 693    INSTRUCTION(mul),                                 /* mul */
 694    INSTRUCTION_FLG(gen_cmpxx, TCG_COND_GEU),         /* cmpgeu */
 695    INSTRUCTION_NOP(),                                /* initi */
 696    INSTRUCTION_ILLEGAL(),
 697    INSTRUCTION_ILLEGAL(),
 698    INSTRUCTION_ILLEGAL(),
 699    INSTRUCTION_FLG(gen_excp, EXCP_TRAP),             /* trap */
 700    INSTRUCTION(wrctl),                               /* wrctl */
 701    INSTRUCTION_ILLEGAL(),
 702    INSTRUCTION_FLG(gen_cmpxx, TCG_COND_LTU),         /* cmpltu */
 703    INSTRUCTION(add),                                 /* add */
 704    INSTRUCTION_ILLEGAL(),
 705    INSTRUCTION_ILLEGAL(),
 706    INSTRUCTION_FLG(gen_excp, EXCP_BREAK),            /* break */
 707    INSTRUCTION_ILLEGAL(),
 708    INSTRUCTION(nop),                                 /* nop */
 709    INSTRUCTION_ILLEGAL(),
 710    INSTRUCTION_ILLEGAL(),
 711    INSTRUCTION(sub),                                 /* sub */
 712    INSTRUCTION(srai),                                /* srai */
 713    INSTRUCTION(sra),                                 /* sra */
 714    INSTRUCTION_ILLEGAL(),
 715    INSTRUCTION_ILLEGAL(),
 716    INSTRUCTION_ILLEGAL(),
 717    INSTRUCTION_ILLEGAL(),
 718};
 719
 720static void handle_r_type_instr(DisasContext *dc, uint32_t code, uint32_t flags)
 721{
 722    uint8_t opx;
 723    const Nios2Instruction *instr;
 724
 725    opx = get_opxcode(code);
 726    if (unlikely(opx >= ARRAY_SIZE(r_type_instructions))) {
 727        goto illegal_op;
 728    }
 729
 730    instr = &r_type_instructions[opx];
 731    instr->handler(dc, code, instr->flags);
 732
 733    return;
 734
 735illegal_op:
 736    t_gen_helper_raise_exception(dc, EXCP_ILLEGAL);
 737}
 738
 739static void handle_instruction(DisasContext *dc, CPUNios2State *env)
 740{
 741    uint32_t code;
 742    uint8_t op;
 743    const Nios2Instruction *instr;
 744#if defined(CONFIG_USER_ONLY)
 745    /* FIXME: Is this needed ? */
 746    if (dc->pc >= 0x1000 && dc->pc < 0x2000) {
 747        env->regs[R_PC] = dc->pc;
 748        t_gen_helper_raise_exception(dc, 0xaa);
 749        return;
 750    }
 751#endif
 752    code = cpu_ldl_code(env, dc->pc);
 753    op = get_opcode(code);
 754
 755    if (unlikely(op >= ARRAY_SIZE(i_type_instructions))) {
 756        goto illegal_op;
 757    }
 758
 759    dc->zero = NULL;
 760
 761    instr = &i_type_instructions[op];
 762    instr->handler(dc, code, instr->flags);
 763
 764    if (dc->zero) {
 765        tcg_temp_free(dc->zero);
 766    }
 767
 768    return;
 769
 770illegal_op:
 771    t_gen_helper_raise_exception(dc, EXCP_ILLEGAL);
 772}
 773
 774static const char * const regnames[] = {
 775    "zero",       "at",         "r2",         "r3",
 776    "r4",         "r5",         "r6",         "r7",
 777    "r8",         "r9",         "r10",        "r11",
 778    "r12",        "r13",        "r14",        "r15",
 779    "r16",        "r17",        "r18",        "r19",
 780    "r20",        "r21",        "r22",        "r23",
 781    "et",         "bt",         "gp",         "sp",
 782    "fp",         "ea",         "ba",         "ra",
 783    "status",     "estatus",    "bstatus",    "ienable",
 784    "ipending",   "cpuid",      "reserved0",  "exception",
 785    "pteaddr",    "tlbacc",     "tlbmisc",    "reserved1",
 786    "badaddr",    "config",     "mpubase",    "mpuacc",
 787    "reserved2",  "reserved3",  "reserved4",  "reserved5",
 788    "reserved6",  "reserved7",  "reserved8",  "reserved9",
 789    "reserved10", "reserved11", "reserved12", "reserved13",
 790    "reserved14", "reserved15", "reserved16", "reserved17",
 791    "rpc"
 792};
 793
 794static TCGv cpu_R[NUM_CORE_REGS];
 795
 796#include "exec/gen-icount.h"
 797
 798static void gen_exception(DisasContext *dc, uint32_t excp)
 799{
 800    TCGv_i32 tmp = tcg_const_i32(excp);
 801
 802    tcg_gen_movi_tl(cpu_R[R_PC], dc->pc);
 803    gen_helper_raise_exception(cpu_env, tmp);
 804    tcg_temp_free_i32(tmp);
 805    dc->is_jmp = DISAS_UPDATE;
 806}
 807
 808/* generate intermediate code for basic block 'tb'.  */
 809void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
 810{
 811    CPUNios2State *env = cs->env_ptr;
 812    DisasContext dc1, *dc = &dc1;
 813    int num_insns;
 814
 815    /* Initialize DC */
 816    dc->cpu_env = cpu_env;
 817    dc->cpu_R   = cpu_R;
 818    dc->is_jmp  = DISAS_NEXT;
 819    dc->pc      = tb->pc;
 820    dc->tb      = tb;
 821    dc->mem_idx = cpu_mmu_index(env, false);
 822    dc->singlestep_enabled = cs->singlestep_enabled;
 823
 824    /* Set up instruction counts */
 825    num_insns = 0;
 826    if (max_insns > 1) {
 827        int page_insns = (TARGET_PAGE_SIZE - (tb->pc & TARGET_PAGE_MASK)) / 4;
 828        if (max_insns > page_insns) {
 829            max_insns = page_insns;
 830        }
 831    }
 832
 833    gen_tb_start(tb);
 834    do {
 835        tcg_gen_insn_start(dc->pc);
 836        num_insns++;
 837
 838        if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
 839            gen_exception(dc, EXCP_DEBUG);
 840            /* The address covered by the breakpoint must be included in
 841               [tb->pc, tb->pc + tb->size) in order to for it to be
 842               properly cleared -- thus we increment the PC here so that
 843               the logic setting tb->size below does the right thing.  */
 844            dc->pc += 4;
 845            break;
 846        }
 847
 848        if (num_insns == max_insns && (tb_cflags(tb) & CF_LAST_IO)) {
 849            gen_io_start();
 850        }
 851
 852        /* Decode an instruction */
 853        handle_instruction(dc, env);
 854
 855        dc->pc += 4;
 856
 857        /* Translation stops when a conditional branch is encountered.
 858         * Otherwise the subsequent code could get translated several times.
 859         * Also stop translation when a page boundary is reached.  This
 860         * ensures prefetch aborts occur at the right place.  */
 861    } while (!dc->is_jmp &&
 862             !tcg_op_buf_full() &&
 863             num_insns < max_insns);
 864
 865    if (tb_cflags(tb) & CF_LAST_IO) {
 866        gen_io_end();
 867    }
 868
 869    /* Indicate where the next block should start */
 870    switch (dc->is_jmp) {
 871    case DISAS_NEXT:
 872        /* Save the current PC back into the CPU register */
 873        tcg_gen_movi_tl(cpu_R[R_PC], dc->pc);
 874        tcg_gen_exit_tb(NULL, 0);
 875        break;
 876
 877    default:
 878    case DISAS_JUMP:
 879    case DISAS_UPDATE:
 880        /* The jump will already have updated the PC register */
 881        tcg_gen_exit_tb(NULL, 0);
 882        break;
 883
 884    case DISAS_TB_JUMP:
 885        /* nothing more to generate */
 886        break;
 887    }
 888
 889    /* End off the block */
 890    gen_tb_end(tb, num_insns);
 891
 892    /* Mark instruction starts for the final generated instruction */
 893    tb->size = dc->pc - tb->pc;
 894    tb->icount = num_insns;
 895
 896#ifdef DEBUG_DISAS
 897    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
 898        && qemu_log_in_addr_range(tb->pc)) {
 899        qemu_log_lock();
 900        qemu_log("IN: %s\n", lookup_symbol(tb->pc));
 901        log_target_disas(cs, tb->pc, dc->pc - tb->pc);
 902        qemu_log("\n");
 903        qemu_log_unlock();
 904    }
 905#endif
 906}
 907
 908void nios2_cpu_dump_state(CPUState *cs, FILE *f, int flags)
 909{
 910    Nios2CPU *cpu = NIOS2_CPU(cs);
 911    CPUNios2State *env = &cpu->env;
 912    int i;
 913
 914    if (!env) {
 915        return;
 916    }
 917
 918    qemu_fprintf(f, "IN: PC=%x %s\n",
 919                 env->regs[R_PC], lookup_symbol(env->regs[R_PC]));
 920
 921    for (i = 0; i < NUM_CORE_REGS; i++) {
 922        qemu_fprintf(f, "%9s=%8.8x ", regnames[i], env->regs[i]);
 923        if ((i + 1) % 4 == 0) {
 924            qemu_fprintf(f, "\n");
 925        }
 926    }
 927#if !defined(CONFIG_USER_ONLY)
 928    qemu_fprintf(f, " mmu write: VPN=%05X PID %02X TLBACC %08X\n",
 929                 env->mmu.pteaddr_wr & CR_PTEADDR_VPN_MASK,
 930                 (env->mmu.tlbmisc_wr & CR_TLBMISC_PID_MASK) >> 4,
 931                 env->mmu.tlbacc_wr);
 932#endif
 933    qemu_fprintf(f, "\n\n");
 934}
 935
 936void nios2_tcg_init(void)
 937{
 938    int i;
 939
 940    for (i = 0; i < NUM_CORE_REGS; i++) {
 941        cpu_R[i] = tcg_global_mem_new(cpu_env,
 942                                      offsetof(CPUNios2State, regs[i]),
 943                                      regnames[i]);
 944    }
 945}
 946
 947void restore_state_to_opc(CPUNios2State *env, TranslationBlock *tb,
 948                          target_ulong *data)
 949{
 950    env->regs[R_PC] = data[0];
 951}
 952