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 (54631B)


      1/*
      2 *  Xilinx MicroBlaze emulation for qemu: main translation routines.
      3 *
      4 *  Copyright (c) 2009 Edgar E. Iglesias.
      5 *  Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
      6 *
      7 * This library is free software; you can redistribute it and/or
      8 * modify it under the terms of the GNU Lesser General Public
      9 * License as published by the Free Software Foundation; either
     10 * version 2.1 of the License, or (at your option) any later version.
     11 *
     12 * This library is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15 * Lesser General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU Lesser General Public
     18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
     19 */
     20
     21#include "qemu/osdep.h"
     22#include "cpu.h"
     23#include "disas/disas.h"
     24#include "exec/exec-all.h"
     25#include "tcg/tcg-op.h"
     26#include "exec/helper-proto.h"
     27#include "exec/cpu_ldst.h"
     28#include "exec/helper-gen.h"
     29#include "exec/translator.h"
     30#include "qemu/qemu-print.h"
     31
     32#include "exec/log.h"
     33
     34#define EXTRACT_FIELD(src, start, end) \
     35            (((src) >> start) & ((1 << (end - start + 1)) - 1))
     36
     37/* is_jmp field values */
     38#define DISAS_JUMP    DISAS_TARGET_0 /* only pc was modified dynamically */
     39#define DISAS_EXIT    DISAS_TARGET_1 /* all cpu state modified dynamically */
     40
     41/* cpu state besides pc was modified dynamically; update pc to next */
     42#define DISAS_EXIT_NEXT DISAS_TARGET_2
     43/* cpu state besides pc was modified dynamically; update pc to btarget */
     44#define DISAS_EXIT_JUMP DISAS_TARGET_3
     45
     46static TCGv_i32 cpu_R[32];
     47static TCGv_i32 cpu_pc;
     48static TCGv_i32 cpu_msr;
     49static TCGv_i32 cpu_msr_c;
     50static TCGv_i32 cpu_imm;
     51static TCGv_i32 cpu_bvalue;
     52static TCGv_i32 cpu_btarget;
     53static TCGv_i32 cpu_iflags;
     54static TCGv cpu_res_addr;
     55static TCGv_i32 cpu_res_val;
     56
     57#include "exec/gen-icount.h"
     58
     59/* This is the state at translation time.  */
     60typedef struct DisasContext {
     61    DisasContextBase base;
     62    const MicroBlazeCPUConfig *cfg;
     63
     64    /* TCG op of the current insn_start.  */
     65    TCGOp *insn_start;
     66
     67    TCGv_i32 r0;
     68    bool r0_set;
     69
     70    /* Decoder.  */
     71    uint32_t ext_imm;
     72    unsigned int tb_flags;
     73    unsigned int tb_flags_to_set;
     74    int mem_index;
     75
     76    /* Condition under which to jump, including NEVER and ALWAYS. */
     77    TCGCond jmp_cond;
     78
     79    /* Immediate branch-taken destination, or -1 for indirect. */
     80    uint32_t jmp_dest;
     81} DisasContext;
     82
     83static int typeb_imm(DisasContext *dc, int x)
     84{
     85    if (dc->tb_flags & IMM_FLAG) {
     86        return deposit32(dc->ext_imm, 0, 16, x);
     87    }
     88    return x;
     89}
     90
     91/* Include the auto-generated decoder.  */
     92#include "decode-insns.c.inc"
     93
     94static void t_sync_flags(DisasContext *dc)
     95{
     96    /* Synch the tb dependent flags between translator and runtime.  */
     97    if ((dc->tb_flags ^ dc->base.tb->flags) & IFLAGS_TB_MASK) {
     98        tcg_gen_movi_i32(cpu_iflags, dc->tb_flags & IFLAGS_TB_MASK);
     99    }
    100}
    101
    102static void gen_raise_exception(DisasContext *dc, uint32_t index)
    103{
    104    TCGv_i32 tmp = tcg_const_i32(index);
    105
    106    gen_helper_raise_exception(cpu_env, tmp);
    107    tcg_temp_free_i32(tmp);
    108    dc->base.is_jmp = DISAS_NORETURN;
    109}
    110
    111static void gen_raise_exception_sync(DisasContext *dc, uint32_t index)
    112{
    113    t_sync_flags(dc);
    114    tcg_gen_movi_i32(cpu_pc, dc->base.pc_next);
    115    gen_raise_exception(dc, index);
    116}
    117
    118static void gen_raise_hw_excp(DisasContext *dc, uint32_t esr_ec)
    119{
    120    TCGv_i32 tmp = tcg_const_i32(esr_ec);
    121    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUMBState, esr));
    122    tcg_temp_free_i32(tmp);
    123
    124    gen_raise_exception_sync(dc, EXCP_HW_EXCP);
    125}
    126
    127static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
    128{
    129    if (dc->base.singlestep_enabled) {
    130        TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG);
    131        tcg_gen_movi_i32(cpu_pc, dest);
    132        gen_helper_raise_exception(cpu_env, tmp);
    133        tcg_temp_free_i32(tmp);
    134    } else if (translator_use_goto_tb(&dc->base, dest)) {
    135        tcg_gen_goto_tb(n);
    136        tcg_gen_movi_i32(cpu_pc, dest);
    137        tcg_gen_exit_tb(dc->base.tb, n);
    138    } else {
    139        tcg_gen_movi_i32(cpu_pc, dest);
    140        tcg_gen_lookup_and_goto_ptr();
    141    }
    142    dc->base.is_jmp = DISAS_NORETURN;
    143}
    144
    145/*
    146 * Returns true if the insn an illegal operation.
    147 * If exceptions are enabled, an exception is raised.
    148 */
    149static bool trap_illegal(DisasContext *dc, bool cond)
    150{
    151    if (cond && (dc->tb_flags & MSR_EE)
    152        && dc->cfg->illegal_opcode_exception) {
    153        gen_raise_hw_excp(dc, ESR_EC_ILLEGAL_OP);
    154    }
    155    return cond;
    156}
    157
    158/*
    159 * Returns true if the insn is illegal in userspace.
    160 * If exceptions are enabled, an exception is raised.
    161 */
    162static bool trap_userspace(DisasContext *dc, bool cond)
    163{
    164    bool cond_user = cond && dc->mem_index == MMU_USER_IDX;
    165
    166    if (cond_user && (dc->tb_flags & MSR_EE)) {
    167        gen_raise_hw_excp(dc, ESR_EC_PRIVINSN);
    168    }
    169    return cond_user;
    170}
    171
    172/*
    173 * Return true, and log an error, if the current insn is
    174 * within a delay slot.
    175 */
    176static bool invalid_delay_slot(DisasContext *dc, const char *insn_type)
    177{
    178    if (dc->tb_flags & D_FLAG) {
    179        qemu_log_mask(LOG_GUEST_ERROR,
    180                      "Invalid insn in delay slot: %s at %08x\n",
    181                      insn_type, (uint32_t)dc->base.pc_next);
    182        return true;
    183    }
    184    return false;
    185}
    186
    187static TCGv_i32 reg_for_read(DisasContext *dc, int reg)
    188{
    189    if (likely(reg != 0)) {
    190        return cpu_R[reg];
    191    }
    192    if (!dc->r0_set) {
    193        if (dc->r0 == NULL) {
    194            dc->r0 = tcg_temp_new_i32();
    195        }
    196        tcg_gen_movi_i32(dc->r0, 0);
    197        dc->r0_set = true;
    198    }
    199    return dc->r0;
    200}
    201
    202static TCGv_i32 reg_for_write(DisasContext *dc, int reg)
    203{
    204    if (likely(reg != 0)) {
    205        return cpu_R[reg];
    206    }
    207    if (dc->r0 == NULL) {
    208        dc->r0 = tcg_temp_new_i32();
    209    }
    210    return dc->r0;
    211}
    212
    213static bool do_typea(DisasContext *dc, arg_typea *arg, bool side_effects,
    214                     void (*fn)(TCGv_i32, TCGv_i32, TCGv_i32))
    215{
    216    TCGv_i32 rd, ra, rb;
    217
    218    if (arg->rd == 0 && !side_effects) {
    219        return true;
    220    }
    221
    222    rd = reg_for_write(dc, arg->rd);
    223    ra = reg_for_read(dc, arg->ra);
    224    rb = reg_for_read(dc, arg->rb);
    225    fn(rd, ra, rb);
    226    return true;
    227}
    228
    229static bool do_typea0(DisasContext *dc, arg_typea0 *arg, bool side_effects,
    230                      void (*fn)(TCGv_i32, TCGv_i32))
    231{
    232    TCGv_i32 rd, ra;
    233
    234    if (arg->rd == 0 && !side_effects) {
    235        return true;
    236    }
    237
    238    rd = reg_for_write(dc, arg->rd);
    239    ra = reg_for_read(dc, arg->ra);
    240    fn(rd, ra);
    241    return true;
    242}
    243
    244static bool do_typeb_imm(DisasContext *dc, arg_typeb *arg, bool side_effects,
    245                         void (*fni)(TCGv_i32, TCGv_i32, int32_t))
    246{
    247    TCGv_i32 rd, ra;
    248
    249    if (arg->rd == 0 && !side_effects) {
    250        return true;
    251    }
    252
    253    rd = reg_for_write(dc, arg->rd);
    254    ra = reg_for_read(dc, arg->ra);
    255    fni(rd, ra, arg->imm);
    256    return true;
    257}
    258
    259static bool do_typeb_val(DisasContext *dc, arg_typeb *arg, bool side_effects,
    260                         void (*fn)(TCGv_i32, TCGv_i32, TCGv_i32))
    261{
    262    TCGv_i32 rd, ra, imm;
    263
    264    if (arg->rd == 0 && !side_effects) {
    265        return true;
    266    }
    267
    268    rd = reg_for_write(dc, arg->rd);
    269    ra = reg_for_read(dc, arg->ra);
    270    imm = tcg_const_i32(arg->imm);
    271
    272    fn(rd, ra, imm);
    273
    274    tcg_temp_free_i32(imm);
    275    return true;
    276}
    277
    278#define DO_TYPEA(NAME, SE, FN) \
    279    static bool trans_##NAME(DisasContext *dc, arg_typea *a) \
    280    { return do_typea(dc, a, SE, FN); }
    281
    282#define DO_TYPEA_CFG(NAME, CFG, SE, FN) \
    283    static bool trans_##NAME(DisasContext *dc, arg_typea *a) \
    284    { return dc->cfg->CFG && do_typea(dc, a, SE, FN); }
    285
    286#define DO_TYPEA0(NAME, SE, FN) \
    287    static bool trans_##NAME(DisasContext *dc, arg_typea0 *a) \
    288    { return do_typea0(dc, a, SE, FN); }
    289
    290#define DO_TYPEA0_CFG(NAME, CFG, SE, FN) \
    291    static bool trans_##NAME(DisasContext *dc, arg_typea0 *a) \
    292    { return dc->cfg->CFG && do_typea0(dc, a, SE, FN); }
    293
    294#define DO_TYPEBI(NAME, SE, FNI) \
    295    static bool trans_##NAME(DisasContext *dc, arg_typeb *a) \
    296    { return do_typeb_imm(dc, a, SE, FNI); }
    297
    298#define DO_TYPEBI_CFG(NAME, CFG, SE, FNI) \
    299    static bool trans_##NAME(DisasContext *dc, arg_typeb *a) \
    300    { return dc->cfg->CFG && do_typeb_imm(dc, a, SE, FNI); }
    301
    302#define DO_TYPEBV(NAME, SE, FN) \
    303    static bool trans_##NAME(DisasContext *dc, arg_typeb *a) \
    304    { return do_typeb_val(dc, a, SE, FN); }
    305
    306#define ENV_WRAPPER2(NAME, HELPER) \
    307    static void NAME(TCGv_i32 out, TCGv_i32 ina) \
    308    { HELPER(out, cpu_env, ina); }
    309
    310#define ENV_WRAPPER3(NAME, HELPER) \
    311    static void NAME(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) \
    312    { HELPER(out, cpu_env, ina, inb); }
    313
    314/* No input carry, but output carry. */
    315static void gen_add(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
    316{
    317    TCGv_i32 zero = tcg_const_i32(0);
    318
    319    tcg_gen_add2_i32(out, cpu_msr_c, ina, zero, inb, zero);
    320
    321    tcg_temp_free_i32(zero);
    322}
    323
    324/* Input and output carry. */
    325static void gen_addc(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
    326{
    327    TCGv_i32 zero = tcg_const_i32(0);
    328    TCGv_i32 tmp = tcg_temp_new_i32();
    329
    330    tcg_gen_add2_i32(tmp, cpu_msr_c, ina, zero, cpu_msr_c, zero);
    331    tcg_gen_add2_i32(out, cpu_msr_c, tmp, cpu_msr_c, inb, zero);
    332
    333    tcg_temp_free_i32(tmp);
    334    tcg_temp_free_i32(zero);
    335}
    336
    337/* Input carry, but no output carry. */
    338static void gen_addkc(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
    339{
    340    tcg_gen_add_i32(out, ina, inb);
    341    tcg_gen_add_i32(out, out, cpu_msr_c);
    342}
    343
    344DO_TYPEA(add, true, gen_add)
    345DO_TYPEA(addc, true, gen_addc)
    346DO_TYPEA(addk, false, tcg_gen_add_i32)
    347DO_TYPEA(addkc, true, gen_addkc)
    348
    349DO_TYPEBV(addi, true, gen_add)
    350DO_TYPEBV(addic, true, gen_addc)
    351DO_TYPEBI(addik, false, tcg_gen_addi_i32)
    352DO_TYPEBV(addikc, true, gen_addkc)
    353
    354static void gen_andni(TCGv_i32 out, TCGv_i32 ina, int32_t imm)
    355{
    356    tcg_gen_andi_i32(out, ina, ~imm);
    357}
    358
    359DO_TYPEA(and, false, tcg_gen_and_i32)
    360DO_TYPEBI(andi, false, tcg_gen_andi_i32)
    361DO_TYPEA(andn, false, tcg_gen_andc_i32)
    362DO_TYPEBI(andni, false, gen_andni)
    363
    364static void gen_bsra(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
    365{
    366    TCGv_i32 tmp = tcg_temp_new_i32();
    367    tcg_gen_andi_i32(tmp, inb, 31);
    368    tcg_gen_sar_i32(out, ina, tmp);
    369    tcg_temp_free_i32(tmp);
    370}
    371
    372static void gen_bsrl(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
    373{
    374    TCGv_i32 tmp = tcg_temp_new_i32();
    375    tcg_gen_andi_i32(tmp, inb, 31);
    376    tcg_gen_shr_i32(out, ina, tmp);
    377    tcg_temp_free_i32(tmp);
    378}
    379
    380static void gen_bsll(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
    381{
    382    TCGv_i32 tmp = tcg_temp_new_i32();
    383    tcg_gen_andi_i32(tmp, inb, 31);
    384    tcg_gen_shl_i32(out, ina, tmp);
    385    tcg_temp_free_i32(tmp);
    386}
    387
    388static void gen_bsefi(TCGv_i32 out, TCGv_i32 ina, int32_t imm)
    389{
    390    /* Note that decodetree has extracted and reassembled imm_w/imm_s. */
    391    int imm_w = extract32(imm, 5, 5);
    392    int imm_s = extract32(imm, 0, 5);
    393
    394    if (imm_w + imm_s > 32 || imm_w == 0) {
    395        /* These inputs have an undefined behavior.  */
    396        qemu_log_mask(LOG_GUEST_ERROR, "bsefi: Bad input w=%d s=%d\n",
    397                      imm_w, imm_s);
    398    } else {
    399        tcg_gen_extract_i32(out, ina, imm_s, imm_w);
    400    }
    401}
    402
    403static void gen_bsifi(TCGv_i32 out, TCGv_i32 ina, int32_t imm)
    404{
    405    /* Note that decodetree has extracted and reassembled imm_w/imm_s. */
    406    int imm_w = extract32(imm, 5, 5);
    407    int imm_s = extract32(imm, 0, 5);
    408    int width = imm_w - imm_s + 1;
    409
    410    if (imm_w < imm_s) {
    411        /* These inputs have an undefined behavior.  */
    412        qemu_log_mask(LOG_GUEST_ERROR, "bsifi: Bad input w=%d s=%d\n",
    413                      imm_w, imm_s);
    414    } else {
    415        tcg_gen_deposit_i32(out, out, ina, imm_s, width);
    416    }
    417}
    418
    419DO_TYPEA_CFG(bsra, use_barrel, false, gen_bsra)
    420DO_TYPEA_CFG(bsrl, use_barrel, false, gen_bsrl)
    421DO_TYPEA_CFG(bsll, use_barrel, false, gen_bsll)
    422
    423DO_TYPEBI_CFG(bsrai, use_barrel, false, tcg_gen_sari_i32)
    424DO_TYPEBI_CFG(bsrli, use_barrel, false, tcg_gen_shri_i32)
    425DO_TYPEBI_CFG(bslli, use_barrel, false, tcg_gen_shli_i32)
    426
    427DO_TYPEBI_CFG(bsefi, use_barrel, false, gen_bsefi)
    428DO_TYPEBI_CFG(bsifi, use_barrel, false, gen_bsifi)
    429
    430static void gen_clz(TCGv_i32 out, TCGv_i32 ina)
    431{
    432    tcg_gen_clzi_i32(out, ina, 32);
    433}
    434
    435DO_TYPEA0_CFG(clz, use_pcmp_instr, false, gen_clz)
    436
    437static void gen_cmp(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
    438{
    439    TCGv_i32 lt = tcg_temp_new_i32();
    440
    441    tcg_gen_setcond_i32(TCG_COND_LT, lt, inb, ina);
    442    tcg_gen_sub_i32(out, inb, ina);
    443    tcg_gen_deposit_i32(out, out, lt, 31, 1);
    444    tcg_temp_free_i32(lt);
    445}
    446
    447static void gen_cmpu(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
    448{
    449    TCGv_i32 lt = tcg_temp_new_i32();
    450
    451    tcg_gen_setcond_i32(TCG_COND_LTU, lt, inb, ina);
    452    tcg_gen_sub_i32(out, inb, ina);
    453    tcg_gen_deposit_i32(out, out, lt, 31, 1);
    454    tcg_temp_free_i32(lt);
    455}
    456
    457DO_TYPEA(cmp, false, gen_cmp)
    458DO_TYPEA(cmpu, false, gen_cmpu)
    459
    460ENV_WRAPPER3(gen_fadd, gen_helper_fadd)
    461ENV_WRAPPER3(gen_frsub, gen_helper_frsub)
    462ENV_WRAPPER3(gen_fmul, gen_helper_fmul)
    463ENV_WRAPPER3(gen_fdiv, gen_helper_fdiv)
    464ENV_WRAPPER3(gen_fcmp_un, gen_helper_fcmp_un)
    465ENV_WRAPPER3(gen_fcmp_lt, gen_helper_fcmp_lt)
    466ENV_WRAPPER3(gen_fcmp_eq, gen_helper_fcmp_eq)
    467ENV_WRAPPER3(gen_fcmp_le, gen_helper_fcmp_le)
    468ENV_WRAPPER3(gen_fcmp_gt, gen_helper_fcmp_gt)
    469ENV_WRAPPER3(gen_fcmp_ne, gen_helper_fcmp_ne)
    470ENV_WRAPPER3(gen_fcmp_ge, gen_helper_fcmp_ge)
    471
    472DO_TYPEA_CFG(fadd, use_fpu, true, gen_fadd)
    473DO_TYPEA_CFG(frsub, use_fpu, true, gen_frsub)
    474DO_TYPEA_CFG(fmul, use_fpu, true, gen_fmul)
    475DO_TYPEA_CFG(fdiv, use_fpu, true, gen_fdiv)
    476DO_TYPEA_CFG(fcmp_un, use_fpu, true, gen_fcmp_un)
    477DO_TYPEA_CFG(fcmp_lt, use_fpu, true, gen_fcmp_lt)
    478DO_TYPEA_CFG(fcmp_eq, use_fpu, true, gen_fcmp_eq)
    479DO_TYPEA_CFG(fcmp_le, use_fpu, true, gen_fcmp_le)
    480DO_TYPEA_CFG(fcmp_gt, use_fpu, true, gen_fcmp_gt)
    481DO_TYPEA_CFG(fcmp_ne, use_fpu, true, gen_fcmp_ne)
    482DO_TYPEA_CFG(fcmp_ge, use_fpu, true, gen_fcmp_ge)
    483
    484ENV_WRAPPER2(gen_flt, gen_helper_flt)
    485ENV_WRAPPER2(gen_fint, gen_helper_fint)
    486ENV_WRAPPER2(gen_fsqrt, gen_helper_fsqrt)
    487
    488DO_TYPEA0_CFG(flt, use_fpu >= 2, true, gen_flt)
    489DO_TYPEA0_CFG(fint, use_fpu >= 2, true, gen_fint)
    490DO_TYPEA0_CFG(fsqrt, use_fpu >= 2, true, gen_fsqrt)
    491
    492/* Does not use ENV_WRAPPER3, because arguments are swapped as well. */
    493static void gen_idiv(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
    494{
    495    gen_helper_divs(out, cpu_env, inb, ina);
    496}
    497
    498static void gen_idivu(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
    499{
    500    gen_helper_divu(out, cpu_env, inb, ina);
    501}
    502
    503DO_TYPEA_CFG(idiv, use_div, true, gen_idiv)
    504DO_TYPEA_CFG(idivu, use_div, true, gen_idivu)
    505
    506static bool trans_imm(DisasContext *dc, arg_imm *arg)
    507{
    508    if (invalid_delay_slot(dc, "imm")) {
    509        return true;
    510    }
    511    dc->ext_imm = arg->imm << 16;
    512    tcg_gen_movi_i32(cpu_imm, dc->ext_imm);
    513    dc->tb_flags_to_set = IMM_FLAG;
    514    return true;
    515}
    516
    517static void gen_mulh(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
    518{
    519    TCGv_i32 tmp = tcg_temp_new_i32();
    520    tcg_gen_muls2_i32(tmp, out, ina, inb);
    521    tcg_temp_free_i32(tmp);
    522}
    523
    524static void gen_mulhu(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
    525{
    526    TCGv_i32 tmp = tcg_temp_new_i32();
    527    tcg_gen_mulu2_i32(tmp, out, ina, inb);
    528    tcg_temp_free_i32(tmp);
    529}
    530
    531static void gen_mulhsu(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
    532{
    533    TCGv_i32 tmp = tcg_temp_new_i32();
    534    tcg_gen_mulsu2_i32(tmp, out, ina, inb);
    535    tcg_temp_free_i32(tmp);
    536}
    537
    538DO_TYPEA_CFG(mul, use_hw_mul, false, tcg_gen_mul_i32)
    539DO_TYPEA_CFG(mulh, use_hw_mul >= 2, false, gen_mulh)
    540DO_TYPEA_CFG(mulhu, use_hw_mul >= 2, false, gen_mulhu)
    541DO_TYPEA_CFG(mulhsu, use_hw_mul >= 2, false, gen_mulhsu)
    542DO_TYPEBI_CFG(muli, use_hw_mul, false, tcg_gen_muli_i32)
    543
    544DO_TYPEA(or, false, tcg_gen_or_i32)
    545DO_TYPEBI(ori, false, tcg_gen_ori_i32)
    546
    547static void gen_pcmpeq(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
    548{
    549    tcg_gen_setcond_i32(TCG_COND_EQ, out, ina, inb);
    550}
    551
    552static void gen_pcmpne(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
    553{
    554    tcg_gen_setcond_i32(TCG_COND_NE, out, ina, inb);
    555}
    556
    557DO_TYPEA_CFG(pcmpbf, use_pcmp_instr, false, gen_helper_pcmpbf)
    558DO_TYPEA_CFG(pcmpeq, use_pcmp_instr, false, gen_pcmpeq)
    559DO_TYPEA_CFG(pcmpne, use_pcmp_instr, false, gen_pcmpne)
    560
    561/* No input carry, but output carry. */
    562static void gen_rsub(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
    563{
    564    tcg_gen_setcond_i32(TCG_COND_GEU, cpu_msr_c, inb, ina);
    565    tcg_gen_sub_i32(out, inb, ina);
    566}
    567
    568/* Input and output carry. */
    569static void gen_rsubc(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
    570{
    571    TCGv_i32 zero = tcg_const_i32(0);
    572    TCGv_i32 tmp = tcg_temp_new_i32();
    573
    574    tcg_gen_not_i32(tmp, ina);
    575    tcg_gen_add2_i32(tmp, cpu_msr_c, tmp, zero, cpu_msr_c, zero);
    576    tcg_gen_add2_i32(out, cpu_msr_c, tmp, cpu_msr_c, inb, zero);
    577
    578    tcg_temp_free_i32(zero);
    579    tcg_temp_free_i32(tmp);
    580}
    581
    582/* No input or output carry. */
    583static void gen_rsubk(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
    584{
    585    tcg_gen_sub_i32(out, inb, ina);
    586}
    587
    588/* Input carry, no output carry. */
    589static void gen_rsubkc(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
    590{
    591    TCGv_i32 nota = tcg_temp_new_i32();
    592
    593    tcg_gen_not_i32(nota, ina);
    594    tcg_gen_add_i32(out, inb, nota);
    595    tcg_gen_add_i32(out, out, cpu_msr_c);
    596
    597    tcg_temp_free_i32(nota);
    598}
    599
    600DO_TYPEA(rsub, true, gen_rsub)
    601DO_TYPEA(rsubc, true, gen_rsubc)
    602DO_TYPEA(rsubk, false, gen_rsubk)
    603DO_TYPEA(rsubkc, true, gen_rsubkc)
    604
    605DO_TYPEBV(rsubi, true, gen_rsub)
    606DO_TYPEBV(rsubic, true, gen_rsubc)
    607DO_TYPEBV(rsubik, false, gen_rsubk)
    608DO_TYPEBV(rsubikc, true, gen_rsubkc)
    609
    610DO_TYPEA0(sext8, false, tcg_gen_ext8s_i32)
    611DO_TYPEA0(sext16, false, tcg_gen_ext16s_i32)
    612
    613static void gen_sra(TCGv_i32 out, TCGv_i32 ina)
    614{
    615    tcg_gen_andi_i32(cpu_msr_c, ina, 1);
    616    tcg_gen_sari_i32(out, ina, 1);
    617}
    618
    619static void gen_src(TCGv_i32 out, TCGv_i32 ina)
    620{
    621    TCGv_i32 tmp = tcg_temp_new_i32();
    622
    623    tcg_gen_mov_i32(tmp, cpu_msr_c);
    624    tcg_gen_andi_i32(cpu_msr_c, ina, 1);
    625    tcg_gen_extract2_i32(out, ina, tmp, 1);
    626
    627    tcg_temp_free_i32(tmp);
    628}
    629
    630static void gen_srl(TCGv_i32 out, TCGv_i32 ina)
    631{
    632    tcg_gen_andi_i32(cpu_msr_c, ina, 1);
    633    tcg_gen_shri_i32(out, ina, 1);
    634}
    635
    636DO_TYPEA0(sra, false, gen_sra)
    637DO_TYPEA0(src, false, gen_src)
    638DO_TYPEA0(srl, false, gen_srl)
    639
    640static void gen_swaph(TCGv_i32 out, TCGv_i32 ina)
    641{
    642    tcg_gen_rotri_i32(out, ina, 16);
    643}
    644
    645DO_TYPEA0(swapb, false, tcg_gen_bswap32_i32)
    646DO_TYPEA0(swaph, false, gen_swaph)
    647
    648static bool trans_wdic(DisasContext *dc, arg_wdic *a)
    649{
    650    /* Cache operations are nops: only check for supervisor mode.  */
    651    trap_userspace(dc, true);
    652    return true;
    653}
    654
    655DO_TYPEA(xor, false, tcg_gen_xor_i32)
    656DO_TYPEBI(xori, false, tcg_gen_xori_i32)
    657
    658static TCGv compute_ldst_addr_typea(DisasContext *dc, int ra, int rb)
    659{
    660    TCGv ret = tcg_temp_new();
    661
    662    /* If any of the regs is r0, set t to the value of the other reg.  */
    663    if (ra && rb) {
    664        TCGv_i32 tmp = tcg_temp_new_i32();
    665        tcg_gen_add_i32(tmp, cpu_R[ra], cpu_R[rb]);
    666        tcg_gen_extu_i32_tl(ret, tmp);
    667        tcg_temp_free_i32(tmp);
    668    } else if (ra) {
    669        tcg_gen_extu_i32_tl(ret, cpu_R[ra]);
    670    } else if (rb) {
    671        tcg_gen_extu_i32_tl(ret, cpu_R[rb]);
    672    } else {
    673        tcg_gen_movi_tl(ret, 0);
    674    }
    675
    676    if ((ra == 1 || rb == 1) && dc->cfg->stackprot) {
    677        gen_helper_stackprot(cpu_env, ret);
    678    }
    679    return ret;
    680}
    681
    682static TCGv compute_ldst_addr_typeb(DisasContext *dc, int ra, int imm)
    683{
    684    TCGv ret = tcg_temp_new();
    685
    686    /* If any of the regs is r0, set t to the value of the other reg.  */
    687    if (ra) {
    688        TCGv_i32 tmp = tcg_temp_new_i32();
    689        tcg_gen_addi_i32(tmp, cpu_R[ra], imm);
    690        tcg_gen_extu_i32_tl(ret, tmp);
    691        tcg_temp_free_i32(tmp);
    692    } else {
    693        tcg_gen_movi_tl(ret, (uint32_t)imm);
    694    }
    695
    696    if (ra == 1 && dc->cfg->stackprot) {
    697        gen_helper_stackprot(cpu_env, ret);
    698    }
    699    return ret;
    700}
    701
    702#ifndef CONFIG_USER_ONLY
    703static TCGv compute_ldst_addr_ea(DisasContext *dc, int ra, int rb)
    704{
    705    int addr_size = dc->cfg->addr_size;
    706    TCGv ret = tcg_temp_new();
    707
    708    if (addr_size == 32 || ra == 0) {
    709        if (rb) {
    710            tcg_gen_extu_i32_tl(ret, cpu_R[rb]);
    711        } else {
    712            tcg_gen_movi_tl(ret, 0);
    713        }
    714    } else {
    715        if (rb) {
    716            tcg_gen_concat_i32_i64(ret, cpu_R[rb], cpu_R[ra]);
    717        } else {
    718            tcg_gen_extu_i32_tl(ret, cpu_R[ra]);
    719            tcg_gen_shli_tl(ret, ret, 32);
    720        }
    721        if (addr_size < 64) {
    722            /* Mask off out of range bits.  */
    723            tcg_gen_andi_i64(ret, ret, MAKE_64BIT_MASK(0, addr_size));
    724        }
    725    }
    726    return ret;
    727}
    728#endif
    729
    730static void record_unaligned_ess(DisasContext *dc, int rd,
    731                                 MemOp size, bool store)
    732{
    733    uint32_t iflags = tcg_get_insn_start_param(dc->insn_start, 1);
    734
    735    iflags |= ESR_ESS_FLAG;
    736    iflags |= rd << 5;
    737    iflags |= store * ESR_S;
    738    iflags |= (size == MO_32) * ESR_W;
    739
    740    tcg_set_insn_start_param(dc->insn_start, 1, iflags);
    741}
    742
    743static bool do_load(DisasContext *dc, int rd, TCGv addr, MemOp mop,
    744                    int mem_index, bool rev)
    745{
    746    MemOp size = mop & MO_SIZE;
    747
    748    /*
    749     * When doing reverse accesses we need to do two things.
    750     *
    751     * 1. Reverse the address wrt endianness.
    752     * 2. Byteswap the data lanes on the way back into the CPU core.
    753     */
    754    if (rev) {
    755        if (size > MO_8) {
    756            mop ^= MO_BSWAP;
    757        }
    758        if (size < MO_32) {
    759            tcg_gen_xori_tl(addr, addr, 3 - size);
    760        }
    761    }
    762
    763    if (size > MO_8 &&
    764        (dc->tb_flags & MSR_EE) &&
    765        dc->cfg->unaligned_exceptions) {
    766        record_unaligned_ess(dc, rd, size, false);
    767        mop |= MO_ALIGN;
    768    }
    769
    770    tcg_gen_qemu_ld_i32(reg_for_write(dc, rd), addr, mem_index, mop);
    771
    772    tcg_temp_free(addr);
    773    return true;
    774}
    775
    776static bool trans_lbu(DisasContext *dc, arg_typea *arg)
    777{
    778    TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
    779    return do_load(dc, arg->rd, addr, MO_UB, dc->mem_index, false);
    780}
    781
    782static bool trans_lbur(DisasContext *dc, arg_typea *arg)
    783{
    784    TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
    785    return do_load(dc, arg->rd, addr, MO_UB, dc->mem_index, true);
    786}
    787
    788static bool trans_lbuea(DisasContext *dc, arg_typea *arg)
    789{
    790    if (trap_userspace(dc, true)) {
    791        return true;
    792    }
    793#ifdef CONFIG_USER_ONLY
    794    return true;
    795#else
    796    TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb);
    797    return do_load(dc, arg->rd, addr, MO_UB, MMU_NOMMU_IDX, false);
    798#endif
    799}
    800
    801static bool trans_lbui(DisasContext *dc, arg_typeb *arg)
    802{
    803    TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm);
    804    return do_load(dc, arg->rd, addr, MO_UB, dc->mem_index, false);
    805}
    806
    807static bool trans_lhu(DisasContext *dc, arg_typea *arg)
    808{
    809    TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
    810    return do_load(dc, arg->rd, addr, MO_TEUW, dc->mem_index, false);
    811}
    812
    813static bool trans_lhur(DisasContext *dc, arg_typea *arg)
    814{
    815    TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
    816    return do_load(dc, arg->rd, addr, MO_TEUW, dc->mem_index, true);
    817}
    818
    819static bool trans_lhuea(DisasContext *dc, arg_typea *arg)
    820{
    821    if (trap_userspace(dc, true)) {
    822        return true;
    823    }
    824#ifdef CONFIG_USER_ONLY
    825    return true;
    826#else
    827    TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb);
    828    return do_load(dc, arg->rd, addr, MO_TEUW, MMU_NOMMU_IDX, false);
    829#endif
    830}
    831
    832static bool trans_lhui(DisasContext *dc, arg_typeb *arg)
    833{
    834    TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm);
    835    return do_load(dc, arg->rd, addr, MO_TEUW, dc->mem_index, false);
    836}
    837
    838static bool trans_lw(DisasContext *dc, arg_typea *arg)
    839{
    840    TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
    841    return do_load(dc, arg->rd, addr, MO_TEUL, dc->mem_index, false);
    842}
    843
    844static bool trans_lwr(DisasContext *dc, arg_typea *arg)
    845{
    846    TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
    847    return do_load(dc, arg->rd, addr, MO_TEUL, dc->mem_index, true);
    848}
    849
    850static bool trans_lwea(DisasContext *dc, arg_typea *arg)
    851{
    852    if (trap_userspace(dc, true)) {
    853        return true;
    854    }
    855#ifdef CONFIG_USER_ONLY
    856    return true;
    857#else
    858    TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb);
    859    return do_load(dc, arg->rd, addr, MO_TEUL, MMU_NOMMU_IDX, false);
    860#endif
    861}
    862
    863static bool trans_lwi(DisasContext *dc, arg_typeb *arg)
    864{
    865    TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm);
    866    return do_load(dc, arg->rd, addr, MO_TEUL, dc->mem_index, false);
    867}
    868
    869static bool trans_lwx(DisasContext *dc, arg_typea *arg)
    870{
    871    TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
    872
    873    /* lwx does not throw unaligned access errors, so force alignment */
    874    tcg_gen_andi_tl(addr, addr, ~3);
    875
    876    tcg_gen_qemu_ld_i32(cpu_res_val, addr, dc->mem_index, MO_TEUL);
    877    tcg_gen_mov_tl(cpu_res_addr, addr);
    878    tcg_temp_free(addr);
    879
    880    if (arg->rd) {
    881        tcg_gen_mov_i32(cpu_R[arg->rd], cpu_res_val);
    882    }
    883
    884    /* No support for AXI exclusive so always clear C */
    885    tcg_gen_movi_i32(cpu_msr_c, 0);
    886    return true;
    887}
    888
    889static bool do_store(DisasContext *dc, int rd, TCGv addr, MemOp mop,
    890                     int mem_index, bool rev)
    891{
    892    MemOp size = mop & MO_SIZE;
    893
    894    /*
    895     * When doing reverse accesses we need to do two things.
    896     *
    897     * 1. Reverse the address wrt endianness.
    898     * 2. Byteswap the data lanes on the way back into the CPU core.
    899     */
    900    if (rev) {
    901        if (size > MO_8) {
    902            mop ^= MO_BSWAP;
    903        }
    904        if (size < MO_32) {
    905            tcg_gen_xori_tl(addr, addr, 3 - size);
    906        }
    907    }
    908
    909    if (size > MO_8 &&
    910        (dc->tb_flags & MSR_EE) &&
    911        dc->cfg->unaligned_exceptions) {
    912        record_unaligned_ess(dc, rd, size, true);
    913        mop |= MO_ALIGN;
    914    }
    915
    916    tcg_gen_qemu_st_i32(reg_for_read(dc, rd), addr, mem_index, mop);
    917
    918    tcg_temp_free(addr);
    919    return true;
    920}
    921
    922static bool trans_sb(DisasContext *dc, arg_typea *arg)
    923{
    924    TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
    925    return do_store(dc, arg->rd, addr, MO_UB, dc->mem_index, false);
    926}
    927
    928static bool trans_sbr(DisasContext *dc, arg_typea *arg)
    929{
    930    TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
    931    return do_store(dc, arg->rd, addr, MO_UB, dc->mem_index, true);
    932}
    933
    934static bool trans_sbea(DisasContext *dc, arg_typea *arg)
    935{
    936    if (trap_userspace(dc, true)) {
    937        return true;
    938    }
    939#ifdef CONFIG_USER_ONLY
    940    return true;
    941#else
    942    TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb);
    943    return do_store(dc, arg->rd, addr, MO_UB, MMU_NOMMU_IDX, false);
    944#endif
    945}
    946
    947static bool trans_sbi(DisasContext *dc, arg_typeb *arg)
    948{
    949    TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm);
    950    return do_store(dc, arg->rd, addr, MO_UB, dc->mem_index, false);
    951}
    952
    953static bool trans_sh(DisasContext *dc, arg_typea *arg)
    954{
    955    TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
    956    return do_store(dc, arg->rd, addr, MO_TEUW, dc->mem_index, false);
    957}
    958
    959static bool trans_shr(DisasContext *dc, arg_typea *arg)
    960{
    961    TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
    962    return do_store(dc, arg->rd, addr, MO_TEUW, dc->mem_index, true);
    963}
    964
    965static bool trans_shea(DisasContext *dc, arg_typea *arg)
    966{
    967    if (trap_userspace(dc, true)) {
    968        return true;
    969    }
    970#ifdef CONFIG_USER_ONLY
    971    return true;
    972#else
    973    TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb);
    974    return do_store(dc, arg->rd, addr, MO_TEUW, MMU_NOMMU_IDX, false);
    975#endif
    976}
    977
    978static bool trans_shi(DisasContext *dc, arg_typeb *arg)
    979{
    980    TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm);
    981    return do_store(dc, arg->rd, addr, MO_TEUW, dc->mem_index, false);
    982}
    983
    984static bool trans_sw(DisasContext *dc, arg_typea *arg)
    985{
    986    TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
    987    return do_store(dc, arg->rd, addr, MO_TEUL, dc->mem_index, false);
    988}
    989
    990static bool trans_swr(DisasContext *dc, arg_typea *arg)
    991{
    992    TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
    993    return do_store(dc, arg->rd, addr, MO_TEUL, dc->mem_index, true);
    994}
    995
    996static bool trans_swea(DisasContext *dc, arg_typea *arg)
    997{
    998    if (trap_userspace(dc, true)) {
    999        return true;
   1000    }
   1001#ifdef CONFIG_USER_ONLY
   1002    return true;
   1003#else
   1004    TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb);
   1005    return do_store(dc, arg->rd, addr, MO_TEUL, MMU_NOMMU_IDX, false);
   1006#endif
   1007}
   1008
   1009static bool trans_swi(DisasContext *dc, arg_typeb *arg)
   1010{
   1011    TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm);
   1012    return do_store(dc, arg->rd, addr, MO_TEUL, dc->mem_index, false);
   1013}
   1014
   1015static bool trans_swx(DisasContext *dc, arg_typea *arg)
   1016{
   1017    TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
   1018    TCGLabel *swx_done = gen_new_label();
   1019    TCGLabel *swx_fail = gen_new_label();
   1020    TCGv_i32 tval;
   1021
   1022    /* swx does not throw unaligned access errors, so force alignment */
   1023    tcg_gen_andi_tl(addr, addr, ~3);
   1024
   1025    /*
   1026     * Compare the address vs the one we used during lwx.
   1027     * On mismatch, the operation fails.  On match, addr dies at the
   1028     * branch, but we know we can use the equal version in the global.
   1029     * In either case, addr is no longer needed.
   1030     */
   1031    tcg_gen_brcond_tl(TCG_COND_NE, cpu_res_addr, addr, swx_fail);
   1032    tcg_temp_free(addr);
   1033
   1034    /*
   1035     * Compare the value loaded during lwx with current contents of
   1036     * the reserved location.
   1037     */
   1038    tval = tcg_temp_new_i32();
   1039
   1040    tcg_gen_atomic_cmpxchg_i32(tval, cpu_res_addr, cpu_res_val,
   1041                               reg_for_write(dc, arg->rd),
   1042                               dc->mem_index, MO_TEUL);
   1043
   1044    tcg_gen_brcond_i32(TCG_COND_NE, cpu_res_val, tval, swx_fail);
   1045    tcg_temp_free_i32(tval);
   1046
   1047    /* Success */
   1048    tcg_gen_movi_i32(cpu_msr_c, 0);
   1049    tcg_gen_br(swx_done);
   1050
   1051    /* Failure */
   1052    gen_set_label(swx_fail);
   1053    tcg_gen_movi_i32(cpu_msr_c, 1);
   1054
   1055    gen_set_label(swx_done);
   1056
   1057    /*
   1058     * Prevent the saved address from working again without another ldx.
   1059     * Akin to the pseudocode setting reservation = 0.
   1060     */
   1061    tcg_gen_movi_tl(cpu_res_addr, -1);
   1062    return true;
   1063}
   1064
   1065static void setup_dslot(DisasContext *dc, bool type_b)
   1066{
   1067    dc->tb_flags_to_set |= D_FLAG;
   1068    if (type_b && (dc->tb_flags & IMM_FLAG)) {
   1069        dc->tb_flags_to_set |= BIMM_FLAG;
   1070    }
   1071}
   1072
   1073static bool do_branch(DisasContext *dc, int dest_rb, int dest_imm,
   1074                      bool delay, bool abs, int link)
   1075{
   1076    uint32_t add_pc;
   1077
   1078    if (invalid_delay_slot(dc, "branch")) {
   1079        return true;
   1080    }
   1081    if (delay) {
   1082        setup_dslot(dc, dest_rb < 0);
   1083    }
   1084
   1085    if (link) {
   1086        tcg_gen_movi_i32(cpu_R[link], dc->base.pc_next);
   1087    }
   1088
   1089    /* Store the branch taken destination into btarget.  */
   1090    add_pc = abs ? 0 : dc->base.pc_next;
   1091    if (dest_rb > 0) {
   1092        dc->jmp_dest = -1;
   1093        tcg_gen_addi_i32(cpu_btarget, cpu_R[dest_rb], add_pc);
   1094    } else {
   1095        dc->jmp_dest = add_pc + dest_imm;
   1096        tcg_gen_movi_i32(cpu_btarget, dc->jmp_dest);
   1097    }
   1098    dc->jmp_cond = TCG_COND_ALWAYS;
   1099    return true;
   1100}
   1101
   1102#define DO_BR(NAME, NAMEI, DELAY, ABS, LINK)                               \
   1103    static bool trans_##NAME(DisasContext *dc, arg_typea_br *arg)          \
   1104    { return do_branch(dc, arg->rb, 0, DELAY, ABS, LINK ? arg->rd : 0); }  \
   1105    static bool trans_##NAMEI(DisasContext *dc, arg_typeb_br *arg)         \
   1106    { return do_branch(dc, -1, arg->imm, DELAY, ABS, LINK ? arg->rd : 0); }
   1107
   1108DO_BR(br, bri, false, false, false)
   1109DO_BR(bra, brai, false, true, false)
   1110DO_BR(brd, brid, true, false, false)
   1111DO_BR(brad, braid, true, true, false)
   1112DO_BR(brld, brlid, true, false, true)
   1113DO_BR(brald, bralid, true, true, true)
   1114
   1115static bool do_bcc(DisasContext *dc, int dest_rb, int dest_imm,
   1116                   TCGCond cond, int ra, bool delay)
   1117{
   1118    TCGv_i32 zero, next;
   1119
   1120    if (invalid_delay_slot(dc, "bcc")) {
   1121        return true;
   1122    }
   1123    if (delay) {
   1124        setup_dslot(dc, dest_rb < 0);
   1125    }
   1126
   1127    dc->jmp_cond = cond;
   1128
   1129    /* Cache the condition register in cpu_bvalue across any delay slot.  */
   1130    tcg_gen_mov_i32(cpu_bvalue, reg_for_read(dc, ra));
   1131
   1132    /* Store the branch taken destination into btarget.  */
   1133    if (dest_rb > 0) {
   1134        dc->jmp_dest = -1;
   1135        tcg_gen_addi_i32(cpu_btarget, cpu_R[dest_rb], dc->base.pc_next);
   1136    } else {
   1137        dc->jmp_dest = dc->base.pc_next + dest_imm;
   1138        tcg_gen_movi_i32(cpu_btarget, dc->jmp_dest);
   1139    }
   1140
   1141    /* Compute the final destination into btarget.  */
   1142    zero = tcg_const_i32(0);
   1143    next = tcg_const_i32(dc->base.pc_next + (delay + 1) * 4);
   1144    tcg_gen_movcond_i32(dc->jmp_cond, cpu_btarget,
   1145                        reg_for_read(dc, ra), zero,
   1146                        cpu_btarget, next);
   1147    tcg_temp_free_i32(zero);
   1148    tcg_temp_free_i32(next);
   1149
   1150    return true;
   1151}
   1152
   1153#define DO_BCC(NAME, COND)                                              \
   1154    static bool trans_##NAME(DisasContext *dc, arg_typea_bc *arg)       \
   1155    { return do_bcc(dc, arg->rb, 0, COND, arg->ra, false); }            \
   1156    static bool trans_##NAME##d(DisasContext *dc, arg_typea_bc *arg)    \
   1157    { return do_bcc(dc, arg->rb, 0, COND, arg->ra, true); }             \
   1158    static bool trans_##NAME##i(DisasContext *dc, arg_typeb_bc *arg)    \
   1159    { return do_bcc(dc, -1, arg->imm, COND, arg->ra, false); }          \
   1160    static bool trans_##NAME##id(DisasContext *dc, arg_typeb_bc *arg)   \
   1161    { return do_bcc(dc, -1, arg->imm, COND, arg->ra, true); }
   1162
   1163DO_BCC(beq, TCG_COND_EQ)
   1164DO_BCC(bge, TCG_COND_GE)
   1165DO_BCC(bgt, TCG_COND_GT)
   1166DO_BCC(ble, TCG_COND_LE)
   1167DO_BCC(blt, TCG_COND_LT)
   1168DO_BCC(bne, TCG_COND_NE)
   1169
   1170static bool trans_brk(DisasContext *dc, arg_typea_br *arg)
   1171{
   1172    if (trap_userspace(dc, true)) {
   1173        return true;
   1174    }
   1175    if (invalid_delay_slot(dc, "brk")) {
   1176        return true;
   1177    }
   1178
   1179    tcg_gen_mov_i32(cpu_pc, reg_for_read(dc, arg->rb));
   1180    if (arg->rd) {
   1181        tcg_gen_movi_i32(cpu_R[arg->rd], dc->base.pc_next);
   1182    }
   1183    tcg_gen_ori_i32(cpu_msr, cpu_msr, MSR_BIP);
   1184    tcg_gen_movi_tl(cpu_res_addr, -1);
   1185
   1186    dc->base.is_jmp = DISAS_EXIT;
   1187    return true;
   1188}
   1189
   1190static bool trans_brki(DisasContext *dc, arg_typeb_br *arg)
   1191{
   1192    uint32_t imm = arg->imm;
   1193
   1194    if (trap_userspace(dc, imm != 0x8 && imm != 0x18)) {
   1195        return true;
   1196    }
   1197    if (invalid_delay_slot(dc, "brki")) {
   1198        return true;
   1199    }
   1200
   1201    tcg_gen_movi_i32(cpu_pc, imm);
   1202    if (arg->rd) {
   1203        tcg_gen_movi_i32(cpu_R[arg->rd], dc->base.pc_next);
   1204    }
   1205    tcg_gen_movi_tl(cpu_res_addr, -1);
   1206
   1207#ifdef CONFIG_USER_ONLY
   1208    switch (imm) {
   1209    case 0x8:  /* syscall trap */
   1210        gen_raise_exception_sync(dc, EXCP_SYSCALL);
   1211        break;
   1212    case 0x18: /* debug trap */
   1213        gen_raise_exception_sync(dc, EXCP_DEBUG);
   1214        break;
   1215    default:   /* eliminated with trap_userspace check */
   1216        g_assert_not_reached();
   1217    }
   1218#else
   1219    uint32_t msr_to_set = 0;
   1220
   1221    if (imm != 0x18) {
   1222        msr_to_set |= MSR_BIP;
   1223    }
   1224    if (imm == 0x8 || imm == 0x18) {
   1225        /* MSR_UM and MSR_VM are in tb_flags, so we know their value. */
   1226        msr_to_set |= (dc->tb_flags & (MSR_UM | MSR_VM)) << 1;
   1227        tcg_gen_andi_i32(cpu_msr, cpu_msr,
   1228                         ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM));
   1229    }
   1230    tcg_gen_ori_i32(cpu_msr, cpu_msr, msr_to_set);
   1231    dc->base.is_jmp = DISAS_EXIT;
   1232#endif
   1233
   1234    return true;
   1235}
   1236
   1237static bool trans_mbar(DisasContext *dc, arg_mbar *arg)
   1238{
   1239    int mbar_imm = arg->imm;
   1240
   1241    /* Note that mbar is a specialized branch instruction. */
   1242    if (invalid_delay_slot(dc, "mbar")) {
   1243        return true;
   1244    }
   1245
   1246    /* Data access memory barrier.  */
   1247    if ((mbar_imm & 2) == 0) {
   1248        tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL);
   1249    }
   1250
   1251    /* Sleep. */
   1252    if (mbar_imm & 16) {
   1253        TCGv_i32 tmp_1;
   1254
   1255        if (trap_userspace(dc, true)) {
   1256            /* Sleep is a privileged instruction.  */
   1257            return true;
   1258        }
   1259
   1260        t_sync_flags(dc);
   1261
   1262        tmp_1 = tcg_const_i32(1);
   1263        tcg_gen_st_i32(tmp_1, cpu_env,
   1264                       -offsetof(MicroBlazeCPU, env)
   1265                       +offsetof(CPUState, halted));
   1266        tcg_temp_free_i32(tmp_1);
   1267
   1268        tcg_gen_movi_i32(cpu_pc, dc->base.pc_next + 4);
   1269
   1270        gen_raise_exception(dc, EXCP_HLT);
   1271    }
   1272
   1273    /*
   1274     * If !(mbar_imm & 1), this is an instruction access memory barrier
   1275     * and we need to end the TB so that we recognize self-modified
   1276     * code immediately.
   1277     *
   1278     * However, there are some data mbars that need the TB break
   1279     * (and return to main loop) to recognize interrupts right away.
   1280     * E.g. recognizing a change to an interrupt controller register.
   1281     *
   1282     * Therefore, choose to end the TB always.
   1283     */
   1284    dc->base.is_jmp = DISAS_EXIT_NEXT;
   1285    return true;
   1286}
   1287
   1288static bool do_rts(DisasContext *dc, arg_typeb_bc *arg, int to_set)
   1289{
   1290    if (trap_userspace(dc, to_set)) {
   1291        return true;
   1292    }
   1293    if (invalid_delay_slot(dc, "rts")) {
   1294        return true;
   1295    }
   1296
   1297    dc->tb_flags_to_set |= to_set;
   1298    setup_dslot(dc, true);
   1299
   1300    dc->jmp_cond = TCG_COND_ALWAYS;
   1301    dc->jmp_dest = -1;
   1302    tcg_gen_addi_i32(cpu_btarget, reg_for_read(dc, arg->ra), arg->imm);
   1303    return true;
   1304}
   1305
   1306#define DO_RTS(NAME, IFLAG) \
   1307    static bool trans_##NAME(DisasContext *dc, arg_typeb_bc *arg) \
   1308    { return do_rts(dc, arg, IFLAG); }
   1309
   1310DO_RTS(rtbd, DRTB_FLAG)
   1311DO_RTS(rtid, DRTI_FLAG)
   1312DO_RTS(rted, DRTE_FLAG)
   1313DO_RTS(rtsd, 0)
   1314
   1315static bool trans_zero(DisasContext *dc, arg_zero *arg)
   1316{
   1317    /* If opcode_0_illegal, trap.  */
   1318    if (dc->cfg->opcode_0_illegal) {
   1319        trap_illegal(dc, true);
   1320        return true;
   1321    }
   1322    /*
   1323     * Otherwise, this is "add r0, r0, r0".
   1324     * Continue to trans_add so that MSR[C] gets cleared.
   1325     */
   1326    return false;
   1327}
   1328
   1329static void msr_read(DisasContext *dc, TCGv_i32 d)
   1330{
   1331    TCGv_i32 t;
   1332
   1333    /* Replicate the cpu_msr_c boolean into the proper bit and the copy. */
   1334    t = tcg_temp_new_i32();
   1335    tcg_gen_muli_i32(t, cpu_msr_c, MSR_C | MSR_CC);
   1336    tcg_gen_or_i32(d, cpu_msr, t);
   1337    tcg_temp_free_i32(t);
   1338}
   1339
   1340static bool do_msrclrset(DisasContext *dc, arg_type_msr *arg, bool set)
   1341{
   1342    uint32_t imm = arg->imm;
   1343
   1344    if (trap_userspace(dc, imm != MSR_C)) {
   1345        return true;
   1346    }
   1347
   1348    if (arg->rd) {
   1349        msr_read(dc, cpu_R[arg->rd]);
   1350    }
   1351
   1352    /*
   1353     * Handle the carry bit separately.
   1354     * This is the only bit that userspace can modify.
   1355     */
   1356    if (imm & MSR_C) {
   1357        tcg_gen_movi_i32(cpu_msr_c, set);
   1358    }
   1359
   1360    /*
   1361     * MSR_C and MSR_CC set above.
   1362     * MSR_PVR is not writable, and is always clear.
   1363     */
   1364    imm &= ~(MSR_C | MSR_CC | MSR_PVR);
   1365
   1366    if (imm != 0) {
   1367        if (set) {
   1368            tcg_gen_ori_i32(cpu_msr, cpu_msr, imm);
   1369        } else {
   1370            tcg_gen_andi_i32(cpu_msr, cpu_msr, ~imm);
   1371        }
   1372        dc->base.is_jmp = DISAS_EXIT_NEXT;
   1373    }
   1374    return true;
   1375}
   1376
   1377static bool trans_msrclr(DisasContext *dc, arg_type_msr *arg)
   1378{
   1379    return do_msrclrset(dc, arg, false);
   1380}
   1381
   1382static bool trans_msrset(DisasContext *dc, arg_type_msr *arg)
   1383{
   1384    return do_msrclrset(dc, arg, true);
   1385}
   1386
   1387static bool trans_mts(DisasContext *dc, arg_mts *arg)
   1388{
   1389    if (trap_userspace(dc, true)) {
   1390        return true;
   1391    }
   1392
   1393#ifdef CONFIG_USER_ONLY
   1394    g_assert_not_reached();
   1395#else
   1396    if (arg->e && arg->rs != 0x1003) {
   1397        qemu_log_mask(LOG_GUEST_ERROR,
   1398                      "Invalid extended mts reg 0x%x\n", arg->rs);
   1399        return true;
   1400    }
   1401
   1402    TCGv_i32 src = reg_for_read(dc, arg->ra);
   1403    switch (arg->rs) {
   1404    case SR_MSR:
   1405        /* Install MSR_C.  */
   1406        tcg_gen_extract_i32(cpu_msr_c, src, 2, 1);
   1407        /*
   1408         * Clear MSR_C and MSR_CC;
   1409         * MSR_PVR is not writable, and is always clear.
   1410         */
   1411        tcg_gen_andi_i32(cpu_msr, src, ~(MSR_C | MSR_CC | MSR_PVR));
   1412        break;
   1413    case SR_FSR:
   1414        tcg_gen_st_i32(src, cpu_env, offsetof(CPUMBState, fsr));
   1415        break;
   1416    case 0x800:
   1417        tcg_gen_st_i32(src, cpu_env, offsetof(CPUMBState, slr));
   1418        break;
   1419    case 0x802:
   1420        tcg_gen_st_i32(src, cpu_env, offsetof(CPUMBState, shr));
   1421        break;
   1422
   1423    case 0x1000: /* PID */
   1424    case 0x1001: /* ZPR */
   1425    case 0x1002: /* TLBX */
   1426    case 0x1003: /* TLBLO */
   1427    case 0x1004: /* TLBHI */
   1428    case 0x1005: /* TLBSX */
   1429        {
   1430            TCGv_i32 tmp_ext = tcg_const_i32(arg->e);
   1431            TCGv_i32 tmp_reg = tcg_const_i32(arg->rs & 7);
   1432
   1433            gen_helper_mmu_write(cpu_env, tmp_ext, tmp_reg, src);
   1434            tcg_temp_free_i32(tmp_reg);
   1435            tcg_temp_free_i32(tmp_ext);
   1436        }
   1437        break;
   1438
   1439    default:
   1440        qemu_log_mask(LOG_GUEST_ERROR, "Invalid mts reg 0x%x\n", arg->rs);
   1441        return true;
   1442    }
   1443    dc->base.is_jmp = DISAS_EXIT_NEXT;
   1444    return true;
   1445#endif
   1446}
   1447
   1448static bool trans_mfs(DisasContext *dc, arg_mfs *arg)
   1449{
   1450    TCGv_i32 dest = reg_for_write(dc, arg->rd);
   1451
   1452    if (arg->e) {
   1453        switch (arg->rs) {
   1454        case SR_EAR:
   1455            {
   1456                TCGv_i64 t64 = tcg_temp_new_i64();
   1457                tcg_gen_ld_i64(t64, cpu_env, offsetof(CPUMBState, ear));
   1458                tcg_gen_extrh_i64_i32(dest, t64);
   1459                tcg_temp_free_i64(t64);
   1460            }
   1461            return true;
   1462#ifndef CONFIG_USER_ONLY
   1463        case 0x1003: /* TLBLO */
   1464            /* Handled below. */
   1465            break;
   1466#endif
   1467        case 0x2006 ... 0x2009:
   1468            /* High bits of PVR6-9 not implemented. */
   1469            tcg_gen_movi_i32(dest, 0);
   1470            return true;
   1471        default:
   1472            qemu_log_mask(LOG_GUEST_ERROR,
   1473                          "Invalid extended mfs reg 0x%x\n", arg->rs);
   1474            return true;
   1475        }
   1476    }
   1477
   1478    switch (arg->rs) {
   1479    case SR_PC:
   1480        tcg_gen_movi_i32(dest, dc->base.pc_next);
   1481        break;
   1482    case SR_MSR:
   1483        msr_read(dc, dest);
   1484        break;
   1485    case SR_EAR:
   1486        {
   1487            TCGv_i64 t64 = tcg_temp_new_i64();
   1488            tcg_gen_ld_i64(t64, cpu_env, offsetof(CPUMBState, ear));
   1489            tcg_gen_extrl_i64_i32(dest, t64);
   1490            tcg_temp_free_i64(t64);
   1491        }
   1492        break;
   1493    case SR_ESR:
   1494        tcg_gen_ld_i32(dest, cpu_env, offsetof(CPUMBState, esr));
   1495        break;
   1496    case SR_FSR:
   1497        tcg_gen_ld_i32(dest, cpu_env, offsetof(CPUMBState, fsr));
   1498        break;
   1499    case SR_BTR:
   1500        tcg_gen_ld_i32(dest, cpu_env, offsetof(CPUMBState, btr));
   1501        break;
   1502    case SR_EDR:
   1503        tcg_gen_ld_i32(dest, cpu_env, offsetof(CPUMBState, edr));
   1504        break;
   1505    case 0x800:
   1506        tcg_gen_ld_i32(dest, cpu_env, offsetof(CPUMBState, slr));
   1507        break;
   1508    case 0x802:
   1509        tcg_gen_ld_i32(dest, cpu_env, offsetof(CPUMBState, shr));
   1510        break;
   1511
   1512#ifndef CONFIG_USER_ONLY
   1513    case 0x1000: /* PID */
   1514    case 0x1001: /* ZPR */
   1515    case 0x1002: /* TLBX */
   1516    case 0x1003: /* TLBLO */
   1517    case 0x1004: /* TLBHI */
   1518    case 0x1005: /* TLBSX */
   1519        {
   1520            TCGv_i32 tmp_ext = tcg_const_i32(arg->e);
   1521            TCGv_i32 tmp_reg = tcg_const_i32(arg->rs & 7);
   1522
   1523            gen_helper_mmu_read(dest, cpu_env, tmp_ext, tmp_reg);
   1524            tcg_temp_free_i32(tmp_reg);
   1525            tcg_temp_free_i32(tmp_ext);
   1526        }
   1527        break;
   1528#endif
   1529
   1530    case 0x2000 ... 0x200c:
   1531        tcg_gen_ld_i32(dest, cpu_env,
   1532                       offsetof(MicroBlazeCPU, cfg.pvr_regs[arg->rs - 0x2000])
   1533                       - offsetof(MicroBlazeCPU, env));
   1534        break;
   1535    default:
   1536        qemu_log_mask(LOG_GUEST_ERROR, "Invalid mfs reg 0x%x\n", arg->rs);
   1537        break;
   1538    }
   1539    return true;
   1540}
   1541
   1542static void do_rti(DisasContext *dc)
   1543{
   1544    TCGv_i32 tmp = tcg_temp_new_i32();
   1545
   1546    tcg_gen_shri_i32(tmp, cpu_msr, 1);
   1547    tcg_gen_ori_i32(cpu_msr, cpu_msr, MSR_IE);
   1548    tcg_gen_andi_i32(tmp, tmp, MSR_VM | MSR_UM);
   1549    tcg_gen_andi_i32(cpu_msr, cpu_msr, ~(MSR_VM | MSR_UM));
   1550    tcg_gen_or_i32(cpu_msr, cpu_msr, tmp);
   1551
   1552    tcg_temp_free_i32(tmp);
   1553}
   1554
   1555static void do_rtb(DisasContext *dc)
   1556{
   1557    TCGv_i32 tmp = tcg_temp_new_i32();
   1558
   1559    tcg_gen_shri_i32(tmp, cpu_msr, 1);
   1560    tcg_gen_andi_i32(cpu_msr, cpu_msr, ~(MSR_VM | MSR_UM | MSR_BIP));
   1561    tcg_gen_andi_i32(tmp, tmp, (MSR_VM | MSR_UM));
   1562    tcg_gen_or_i32(cpu_msr, cpu_msr, tmp);
   1563
   1564    tcg_temp_free_i32(tmp);
   1565}
   1566
   1567static void do_rte(DisasContext *dc)
   1568{
   1569    TCGv_i32 tmp = tcg_temp_new_i32();
   1570
   1571    tcg_gen_shri_i32(tmp, cpu_msr, 1);
   1572    tcg_gen_ori_i32(cpu_msr, cpu_msr, MSR_EE);
   1573    tcg_gen_andi_i32(tmp, tmp, (MSR_VM | MSR_UM));
   1574    tcg_gen_andi_i32(cpu_msr, cpu_msr, ~(MSR_VM | MSR_UM | MSR_EIP));
   1575    tcg_gen_or_i32(cpu_msr, cpu_msr, tmp);
   1576
   1577    tcg_temp_free_i32(tmp);
   1578}
   1579
   1580/* Insns connected to FSL or AXI stream attached devices.  */
   1581static bool do_get(DisasContext *dc, int rd, int rb, int imm, int ctrl)
   1582{
   1583    TCGv_i32 t_id, t_ctrl;
   1584
   1585    if (trap_userspace(dc, true)) {
   1586        return true;
   1587    }
   1588
   1589    t_id = tcg_temp_new_i32();
   1590    if (rb) {
   1591        tcg_gen_andi_i32(t_id, cpu_R[rb], 0xf);
   1592    } else {
   1593        tcg_gen_movi_i32(t_id, imm);
   1594    }
   1595
   1596    t_ctrl = tcg_const_i32(ctrl);
   1597    gen_helper_get(reg_for_write(dc, rd), t_id, t_ctrl);
   1598    tcg_temp_free_i32(t_id);
   1599    tcg_temp_free_i32(t_ctrl);
   1600    return true;
   1601}
   1602
   1603static bool trans_get(DisasContext *dc, arg_get *arg)
   1604{
   1605    return do_get(dc, arg->rd, 0, arg->imm, arg->ctrl);
   1606}
   1607
   1608static bool trans_getd(DisasContext *dc, arg_getd *arg)
   1609{
   1610    return do_get(dc, arg->rd, arg->rb, 0, arg->ctrl);
   1611}
   1612
   1613static bool do_put(DisasContext *dc, int ra, int rb, int imm, int ctrl)
   1614{
   1615    TCGv_i32 t_id, t_ctrl;
   1616
   1617    if (trap_userspace(dc, true)) {
   1618        return true;
   1619    }
   1620
   1621    t_id = tcg_temp_new_i32();
   1622    if (rb) {
   1623        tcg_gen_andi_i32(t_id, cpu_R[rb], 0xf);
   1624    } else {
   1625        tcg_gen_movi_i32(t_id, imm);
   1626    }
   1627
   1628    t_ctrl = tcg_const_i32(ctrl);
   1629    gen_helper_put(t_id, t_ctrl, reg_for_read(dc, ra));
   1630    tcg_temp_free_i32(t_id);
   1631    tcg_temp_free_i32(t_ctrl);
   1632    return true;
   1633}
   1634
   1635static bool trans_put(DisasContext *dc, arg_put *arg)
   1636{
   1637    return do_put(dc, arg->ra, 0, arg->imm, arg->ctrl);
   1638}
   1639
   1640static bool trans_putd(DisasContext *dc, arg_putd *arg)
   1641{
   1642    return do_put(dc, arg->ra, arg->rb, 0, arg->ctrl);
   1643}
   1644
   1645static void mb_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs)
   1646{
   1647    DisasContext *dc = container_of(dcb, DisasContext, base);
   1648    MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
   1649    int bound;
   1650
   1651    dc->cfg = &cpu->cfg;
   1652    dc->tb_flags = dc->base.tb->flags;
   1653    dc->ext_imm = dc->base.tb->cs_base;
   1654    dc->r0 = NULL;
   1655    dc->r0_set = false;
   1656    dc->mem_index = cpu_mmu_index(&cpu->env, false);
   1657    dc->jmp_cond = dc->tb_flags & D_FLAG ? TCG_COND_ALWAYS : TCG_COND_NEVER;
   1658    dc->jmp_dest = -1;
   1659
   1660    bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
   1661    dc->base.max_insns = MIN(dc->base.max_insns, bound);
   1662}
   1663
   1664static void mb_tr_tb_start(DisasContextBase *dcb, CPUState *cs)
   1665{
   1666}
   1667
   1668static void mb_tr_insn_start(DisasContextBase *dcb, CPUState *cs)
   1669{
   1670    DisasContext *dc = container_of(dcb, DisasContext, base);
   1671
   1672    tcg_gen_insn_start(dc->base.pc_next, dc->tb_flags & ~MSR_TB_MASK);
   1673    dc->insn_start = tcg_last_op();
   1674}
   1675
   1676static void mb_tr_translate_insn(DisasContextBase *dcb, CPUState *cs)
   1677{
   1678    DisasContext *dc = container_of(dcb, DisasContext, base);
   1679    CPUMBState *env = cs->env_ptr;
   1680    uint32_t ir;
   1681
   1682    /* TODO: This should raise an exception, not terminate qemu. */
   1683    if (dc->base.pc_next & 3) {
   1684        cpu_abort(cs, "Microblaze: unaligned PC=%x\n",
   1685                  (uint32_t)dc->base.pc_next);
   1686    }
   1687
   1688    dc->tb_flags_to_set = 0;
   1689
   1690    ir = cpu_ldl_code(env, dc->base.pc_next);
   1691    if (!decode(dc, ir)) {
   1692        trap_illegal(dc, true);
   1693    }
   1694
   1695    if (dc->r0) {
   1696        tcg_temp_free_i32(dc->r0);
   1697        dc->r0 = NULL;
   1698        dc->r0_set = false;
   1699    }
   1700
   1701    /* Discard the imm global when its contents cannot be used. */
   1702    if ((dc->tb_flags & ~dc->tb_flags_to_set) & IMM_FLAG) {
   1703        tcg_gen_discard_i32(cpu_imm);
   1704    }
   1705
   1706    dc->tb_flags &= ~(IMM_FLAG | BIMM_FLAG | D_FLAG);
   1707    dc->tb_flags |= dc->tb_flags_to_set;
   1708    dc->base.pc_next += 4;
   1709
   1710    if (dc->jmp_cond != TCG_COND_NEVER && !(dc->tb_flags & D_FLAG)) {
   1711        /*
   1712         * Finish any return-from branch.
   1713         */
   1714        uint32_t rt_ibe = dc->tb_flags & (DRTI_FLAG | DRTB_FLAG | DRTE_FLAG);
   1715        if (unlikely(rt_ibe != 0)) {
   1716            dc->tb_flags &= ~(DRTI_FLAG | DRTB_FLAG | DRTE_FLAG);
   1717            if (rt_ibe & DRTI_FLAG) {
   1718                do_rti(dc);
   1719            } else if (rt_ibe & DRTB_FLAG) {
   1720                do_rtb(dc);
   1721            } else {
   1722                do_rte(dc);
   1723            }
   1724        }
   1725
   1726        /* Complete the branch, ending the TB. */
   1727        switch (dc->base.is_jmp) {
   1728        case DISAS_NORETURN:
   1729            /*
   1730             * E.g. illegal insn in a delay slot.  We've already exited
   1731             * and will handle D_FLAG in mb_cpu_do_interrupt.
   1732             */
   1733            break;
   1734        case DISAS_NEXT:
   1735            /*
   1736             * Normal insn a delay slot.
   1737             * However, the return-from-exception type insns should
   1738             * return to the main loop, as they have adjusted MSR.
   1739             */
   1740            dc->base.is_jmp = (rt_ibe ? DISAS_EXIT_JUMP : DISAS_JUMP);
   1741            break;
   1742        case DISAS_EXIT_NEXT:
   1743            /*
   1744             * E.g. mts insn in a delay slot.  Continue with btarget,
   1745             * but still return to the main loop.
   1746             */
   1747            dc->base.is_jmp = DISAS_EXIT_JUMP;
   1748            break;
   1749        default:
   1750            g_assert_not_reached();
   1751        }
   1752    }
   1753}
   1754
   1755static void mb_tr_tb_stop(DisasContextBase *dcb, CPUState *cs)
   1756{
   1757    DisasContext *dc = container_of(dcb, DisasContext, base);
   1758
   1759    if (dc->base.is_jmp == DISAS_NORETURN) {
   1760        /* We have already exited the TB. */
   1761        return;
   1762    }
   1763
   1764    t_sync_flags(dc);
   1765
   1766    switch (dc->base.is_jmp) {
   1767    case DISAS_TOO_MANY:
   1768        gen_goto_tb(dc, 0, dc->base.pc_next);
   1769        return;
   1770
   1771    case DISAS_EXIT:
   1772        break;
   1773    case DISAS_EXIT_NEXT:
   1774        tcg_gen_movi_i32(cpu_pc, dc->base.pc_next);
   1775        break;
   1776    case DISAS_EXIT_JUMP:
   1777        tcg_gen_mov_i32(cpu_pc, cpu_btarget);
   1778        tcg_gen_discard_i32(cpu_btarget);
   1779        break;
   1780
   1781    case DISAS_JUMP:
   1782        if (dc->jmp_dest != -1 && !cs->singlestep_enabled) {
   1783            /* Direct jump. */
   1784            tcg_gen_discard_i32(cpu_btarget);
   1785
   1786            if (dc->jmp_cond != TCG_COND_ALWAYS) {
   1787                /* Conditional direct jump. */
   1788                TCGLabel *taken = gen_new_label();
   1789                TCGv_i32 tmp = tcg_temp_new_i32();
   1790
   1791                /*
   1792                 * Copy bvalue to a temp now, so we can discard bvalue.
   1793                 * This can avoid writing bvalue to memory when the
   1794                 * delay slot cannot raise an exception.
   1795                 */
   1796                tcg_gen_mov_i32(tmp, cpu_bvalue);
   1797                tcg_gen_discard_i32(cpu_bvalue);
   1798
   1799                tcg_gen_brcondi_i32(dc->jmp_cond, tmp, 0, taken);
   1800                gen_goto_tb(dc, 1, dc->base.pc_next);
   1801                gen_set_label(taken);
   1802            }
   1803            gen_goto_tb(dc, 0, dc->jmp_dest);
   1804            return;
   1805        }
   1806
   1807        /* Indirect jump (or direct jump w/ singlestep) */
   1808        tcg_gen_mov_i32(cpu_pc, cpu_btarget);
   1809        tcg_gen_discard_i32(cpu_btarget);
   1810
   1811        if (unlikely(cs->singlestep_enabled)) {
   1812            gen_raise_exception(dc, EXCP_DEBUG);
   1813        } else {
   1814            tcg_gen_lookup_and_goto_ptr();
   1815        }
   1816        return;
   1817
   1818    default:
   1819        g_assert_not_reached();
   1820    }
   1821
   1822    /* Finish DISAS_EXIT_* */
   1823    if (unlikely(cs->singlestep_enabled)) {
   1824        gen_raise_exception(dc, EXCP_DEBUG);
   1825    } else {
   1826        tcg_gen_exit_tb(NULL, 0);
   1827    }
   1828}
   1829
   1830static void mb_tr_disas_log(const DisasContextBase *dcb, CPUState *cs)
   1831{
   1832    qemu_log("IN: %s\n", lookup_symbol(dcb->pc_first));
   1833    log_target_disas(cs, dcb->pc_first, dcb->tb->size);
   1834}
   1835
   1836static const TranslatorOps mb_tr_ops = {
   1837    .init_disas_context = mb_tr_init_disas_context,
   1838    .tb_start           = mb_tr_tb_start,
   1839    .insn_start         = mb_tr_insn_start,
   1840    .translate_insn     = mb_tr_translate_insn,
   1841    .tb_stop            = mb_tr_tb_stop,
   1842    .disas_log          = mb_tr_disas_log,
   1843};
   1844
   1845void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
   1846{
   1847    DisasContext dc;
   1848    translator_loop(&mb_tr_ops, &dc.base, cpu, tb, max_insns);
   1849}
   1850
   1851void mb_cpu_dump_state(CPUState *cs, FILE *f, int flags)
   1852{
   1853    MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
   1854    CPUMBState *env = &cpu->env;
   1855    uint32_t iflags;
   1856    int i;
   1857
   1858    qemu_fprintf(f, "pc=0x%08x msr=0x%05x mode=%s(saved=%s) eip=%d ie=%d\n",
   1859                 env->pc, env->msr,
   1860                 (env->msr & MSR_UM) ? "user" : "kernel",
   1861                 (env->msr & MSR_UMS) ? "user" : "kernel",
   1862                 (bool)(env->msr & MSR_EIP),
   1863                 (bool)(env->msr & MSR_IE));
   1864
   1865    iflags = env->iflags;
   1866    qemu_fprintf(f, "iflags: 0x%08x", iflags);
   1867    if (iflags & IMM_FLAG) {
   1868        qemu_fprintf(f, " IMM(0x%08x)", env->imm);
   1869    }
   1870    if (iflags & BIMM_FLAG) {
   1871        qemu_fprintf(f, " BIMM");
   1872    }
   1873    if (iflags & D_FLAG) {
   1874        qemu_fprintf(f, " D(btarget=0x%08x)", env->btarget);
   1875    }
   1876    if (iflags & DRTI_FLAG) {
   1877        qemu_fprintf(f, " DRTI");
   1878    }
   1879    if (iflags & DRTE_FLAG) {
   1880        qemu_fprintf(f, " DRTE");
   1881    }
   1882    if (iflags & DRTB_FLAG) {
   1883        qemu_fprintf(f, " DRTB");
   1884    }
   1885    if (iflags & ESR_ESS_FLAG) {
   1886        qemu_fprintf(f, " ESR_ESS(0x%04x)", iflags & ESR_ESS_MASK);
   1887    }
   1888
   1889    qemu_fprintf(f, "\nesr=0x%04x fsr=0x%02x btr=0x%08x edr=0x%x\n"
   1890                 "ear=0x" TARGET_FMT_lx " slr=0x%x shr=0x%x\n",
   1891                 env->esr, env->fsr, env->btr, env->edr,
   1892                 env->ear, env->slr, env->shr);
   1893
   1894    for (i = 0; i < 32; i++) {
   1895        qemu_fprintf(f, "r%2.2d=%08x%c",
   1896                     i, env->regs[i], i % 4 == 3 ? '\n' : ' ');
   1897    }
   1898    qemu_fprintf(f, "\n");
   1899}
   1900
   1901void mb_tcg_init(void)
   1902{
   1903#define R(X)  { &cpu_R[X], offsetof(CPUMBState, regs[X]), "r" #X }
   1904#define SP(X) { &cpu_##X, offsetof(CPUMBState, X), #X }
   1905
   1906    static const struct {
   1907        TCGv_i32 *var; int ofs; char name[8];
   1908    } i32s[] = {
   1909        /*
   1910         * Note that r0 is handled specially in reg_for_read
   1911         * and reg_for_write.  Nothing should touch cpu_R[0].
   1912         * Leave that element NULL, which will assert quickly
   1913         * inside the tcg generator functions.
   1914         */
   1915               R(1),  R(2),  R(3),  R(4),  R(5),  R(6),  R(7),
   1916        R(8),  R(9),  R(10), R(11), R(12), R(13), R(14), R(15),
   1917        R(16), R(17), R(18), R(19), R(20), R(21), R(22), R(23),
   1918        R(24), R(25), R(26), R(27), R(28), R(29), R(30), R(31),
   1919
   1920        SP(pc),
   1921        SP(msr),
   1922        SP(msr_c),
   1923        SP(imm),
   1924        SP(iflags),
   1925        SP(bvalue),
   1926        SP(btarget),
   1927        SP(res_val),
   1928    };
   1929
   1930#undef R
   1931#undef SP
   1932
   1933    for (int i = 0; i < ARRAY_SIZE(i32s); ++i) {
   1934        *i32s[i].var =
   1935          tcg_global_mem_new_i32(cpu_env, i32s[i].ofs, i32s[i].name);
   1936    }
   1937
   1938    cpu_res_addr =
   1939        tcg_global_mem_new(cpu_env, offsetof(CPUMBState, res_addr), "res_addr");
   1940}
   1941
   1942void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb,
   1943                          target_ulong *data)
   1944{
   1945    env->pc = data[0];
   1946    env->iflags = data[1];
   1947}