Annotation of qemu/target-microblaze/translate.c, revision 1.1.1.5

1.1       root        1: /*
                      2:  *  Xilinx MicroBlaze emulation for qemu: main translation routines.
                      3:  *
                      4:  *  Copyright (c) 2009 Edgar E. Iglesias.
                      5:  *
                      6:  * This library is free software; you can redistribute it and/or
                      7:  * modify it under the terms of the GNU Lesser General Public
                      8:  * License as published by the Free Software Foundation; either
                      9:  * version 2 of the License, or (at your option) any later version.
                     10:  *
                     11:  * This library is distributed in the hope that it will be useful,
                     12:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     14:  * Lesser General Public License for more details.
                     15:  *
                     16:  * You should have received a copy of the GNU Lesser General Public
                     17:  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
                     18:  */
                     19: 
                     20: #include <stdarg.h>
                     21: #include <stdlib.h>
                     22: #include <stdio.h>
                     23: #include <string.h>
                     24: #include <inttypes.h>
                     25: #include <assert.h>
                     26: 
                     27: #include "cpu.h"
                     28: #include "disas.h"
                     29: #include "tcg-op.h"
                     30: #include "helper.h"
                     31: #include "microblaze-decode.h"
                     32: #include "qemu-common.h"
                     33: 
                     34: #define GEN_HELPER 1
                     35: #include "helper.h"
                     36: 
                     37: #define SIM_COMPAT 0
                     38: #define DISAS_GNU 1
                     39: #define DISAS_MB 1
                     40: #if DISAS_MB && !SIM_COMPAT
                     41: #  define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
                     42: #else
                     43: #  define LOG_DIS(...) do { } while (0)
                     44: #endif
                     45: 
                     46: #define D(x)
                     47: 
                     48: #define EXTRACT_FIELD(src, start, end) \
                     49:             (((src) >> start) & ((1 << (end - start + 1)) - 1))
                     50: 
                     51: static TCGv env_debug;
                     52: static TCGv_ptr cpu_env;
                     53: static TCGv cpu_R[32];
                     54: static TCGv cpu_SR[18];
                     55: static TCGv env_imm;
                     56: static TCGv env_btaken;
                     57: static TCGv env_btarget;
                     58: static TCGv env_iflags;
                     59: 
                     60: #include "gen-icount.h"
                     61: 
                     62: /* This is the state at translation time.  */
                     63: typedef struct DisasContext {
                     64:     CPUState *env;
1.1.1.3   root       65:     target_ulong pc;
1.1       root       66: 
                     67:     /* Decoder.  */
                     68:     int type_b;
                     69:     uint32_t ir;
                     70:     uint8_t opcode;
                     71:     uint8_t rd, ra, rb;
                     72:     uint16_t imm;
                     73: 
                     74:     unsigned int cpustate_changed;
                     75:     unsigned int delayed_branch;
                     76:     unsigned int tb_flags, synced_flags; /* tb dependent flags.  */
                     77:     unsigned int clear_imm;
                     78:     int is_jmp;
                     79: 
1.1.1.4   root       80: #define JMP_NOJMP     0
                     81: #define JMP_DIRECT    1
                     82: #define JMP_DIRECT_CC 2
                     83: #define JMP_INDIRECT  3
1.1       root       84:     unsigned int jmp;
                     85:     uint32_t jmp_pc;
                     86: 
                     87:     int abort_at_next_insn;
                     88:     int nr_nops;
                     89:     struct TranslationBlock *tb;
                     90:     int singlestep_enabled;
                     91: } DisasContext;
                     92: 
1.1.1.2   root       93: static const char *regnames[] =
1.1       root       94: {
                     95:     "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
                     96:     "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
                     97:     "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
                     98:     "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
                     99: };
                    100: 
1.1.1.2   root      101: static const char *special_regnames[] =
1.1       root      102: {
                    103:     "rpc", "rmsr", "sr2", "sr3", "sr4", "sr5", "sr6", "sr7",
                    104:     "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15",
                    105:     "sr16", "sr17", "sr18"
                    106: };
                    107: 
                    108: /* Sign extend at translation time.  */
                    109: static inline int sign_extend(unsigned int val, unsigned int width)
                    110: {
                    111:         int sval;
                    112: 
                    113:         /* LSL.  */
                    114:         val <<= 31 - width;
                    115:         sval = val;
                    116:         /* ASR.  */
                    117:         sval >>= 31 - width;
                    118:         return sval;
                    119: }
                    120: 
                    121: static inline void t_sync_flags(DisasContext *dc)
                    122: {
                    123:     /* Synch the tb dependant flags between translator and runtime.  */
                    124:     if (dc->tb_flags != dc->synced_flags) {
                    125:         tcg_gen_movi_tl(env_iflags, dc->tb_flags);
                    126:         dc->synced_flags = dc->tb_flags;
                    127:     }
                    128: }
                    129: 
                    130: static inline void t_gen_raise_exception(DisasContext *dc, uint32_t index)
                    131: {
                    132:     TCGv_i32 tmp = tcg_const_i32(index);
                    133: 
                    134:     t_sync_flags(dc);
                    135:     tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
                    136:     gen_helper_raise_exception(tmp);
                    137:     tcg_temp_free_i32(tmp);
                    138:     dc->is_jmp = DISAS_UPDATE;
                    139: }
                    140: 
                    141: static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
                    142: {
                    143:     TranslationBlock *tb;
                    144:     tb = dc->tb;
                    145:     if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
                    146:         tcg_gen_goto_tb(n);
                    147:         tcg_gen_movi_tl(cpu_SR[SR_PC], dest);
1.1.1.5 ! root      148:         tcg_gen_exit_tb((tcg_target_long)tb + n);
1.1       root      149:     } else {
                    150:         tcg_gen_movi_tl(cpu_SR[SR_PC], dest);
                    151:         tcg_gen_exit_tb(0);
                    152:     }
                    153: }
                    154: 
1.1.1.4   root      155: static void read_carry(DisasContext *dc, TCGv d)
                    156: {
                    157:     tcg_gen_shri_tl(d, cpu_SR[SR_MSR], 31);
                    158: }
                    159: 
                    160: static void write_carry(DisasContext *dc, TCGv v)
                    161: {
                    162:     TCGv t0 = tcg_temp_new();
                    163:     tcg_gen_shli_tl(t0, v, 31);
                    164:     tcg_gen_sari_tl(t0, t0, 31);
                    165:     tcg_gen_andi_tl(t0, t0, (MSR_C | MSR_CC));
                    166:     tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR],
                    167:                     ~(MSR_C | MSR_CC));
                    168:     tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t0);
                    169:     tcg_temp_free(t0);
                    170: }
                    171: 
1.1.1.3   root      172: /* True if ALU operand b is a small immediate that may deserve
                    173:    faster treatment.  */
                    174: static inline int dec_alu_op_b_is_small_imm(DisasContext *dc)
                    175: {
                    176:     /* Immediate insn without the imm prefix ?  */
                    177:     return dc->type_b && !(dc->tb_flags & IMM_FLAG);
                    178: }
                    179: 
1.1       root      180: static inline TCGv *dec_alu_op_b(DisasContext *dc)
                    181: {
                    182:     if (dc->type_b) {
                    183:         if (dc->tb_flags & IMM_FLAG)
                    184:             tcg_gen_ori_tl(env_imm, env_imm, dc->imm);
                    185:         else
                    186:             tcg_gen_movi_tl(env_imm, (int32_t)((int16_t)dc->imm));
                    187:         return &env_imm;
                    188:     } else
                    189:         return &cpu_R[dc->rb];
                    190: }
                    191: 
                    192: static void dec_add(DisasContext *dc)
                    193: {
                    194:     unsigned int k, c;
1.1.1.4   root      195:     TCGv cf;
1.1       root      196: 
                    197:     k = dc->opcode & 4;
                    198:     c = dc->opcode & 2;
                    199: 
                    200:     LOG_DIS("add%s%s%s r%d r%d r%d\n",
                    201:             dc->type_b ? "i" : "", k ? "k" : "", c ? "c" : "",
                    202:             dc->rd, dc->ra, dc->rb);
                    203: 
1.1.1.4   root      204:     /* Take care of the easy cases first.  */
                    205:     if (k) {
                    206:         /* k - keep carry, no need to update MSR.  */
                    207:         /* If rd == r0, it's a nop.  */
                    208:         if (dc->rd) {
                    209:             tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
                    210: 
                    211:             if (c) {
                    212:                 /* c - Add carry into the result.  */
                    213:                 cf = tcg_temp_new();
                    214: 
                    215:                 read_carry(dc, cf);
                    216:                 tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
                    217:                 tcg_temp_free(cf);
                    218:             }
                    219:         }
                    220:         return;
                    221:     }
                    222: 
                    223:     /* From now on, we can assume k is zero.  So we need to update MSR.  */
                    224:     /* Extract carry.  */
                    225:     cf = tcg_temp_new();
                    226:     if (c) {
                    227:         read_carry(dc, cf);
                    228:     } else {
                    229:         tcg_gen_movi_tl(cf, 0);
                    230:     }
                    231: 
                    232:     if (dc->rd) {
                    233:         TCGv ncf = tcg_temp_new();
                    234:         gen_helper_carry(ncf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf);
1.1       root      235:         tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
1.1.1.4   root      236:         tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
                    237:         write_carry(dc, ncf);
                    238:         tcg_temp_free(ncf);
                    239:     } else {
                    240:         gen_helper_carry(cf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf);
                    241:         write_carry(dc, cf);
1.1       root      242:     }
1.1.1.4   root      243:     tcg_temp_free(cf);
1.1       root      244: }
                    245: 
                    246: static void dec_sub(DisasContext *dc)
                    247: {
                    248:     unsigned int u, cmp, k, c;
1.1.1.4   root      249:     TCGv cf, na;
1.1       root      250: 
                    251:     u = dc->imm & 2;
                    252:     k = dc->opcode & 4;
                    253:     c = dc->opcode & 2;
                    254:     cmp = (dc->imm & 1) && (!dc->type_b) && k;
                    255: 
                    256:     if (cmp) {
                    257:         LOG_DIS("cmp%s r%d, r%d ir=%x\n", u ? "u" : "", dc->rd, dc->ra, dc->ir);
                    258:         if (dc->rd) {
                    259:             if (u)
                    260:                 gen_helper_cmpu(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                    261:             else
                    262:                 gen_helper_cmp(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                    263:         }
1.1.1.4   root      264:         return;
                    265:     }
1.1       root      266: 
1.1.1.4   root      267:     LOG_DIS("sub%s%s r%d, r%d r%d\n",
                    268:              k ? "k" : "",  c ? "c" : "", dc->rd, dc->ra, dc->rb);
                    269: 
                    270:     /* Take care of the easy cases first.  */
                    271:     if (k) {
                    272:         /* k - keep carry, no need to update MSR.  */
                    273:         /* If rd == r0, it's a nop.  */
                    274:         if (dc->rd) {
1.1       root      275:             tcg_gen_sub_tl(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
1.1.1.4   root      276: 
                    277:             if (c) {
                    278:                 /* c - Add carry into the result.  */
                    279:                 cf = tcg_temp_new();
                    280: 
                    281:                 read_carry(dc, cf);
                    282:                 tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
                    283:                 tcg_temp_free(cf);
                    284:             }
                    285:         }
                    286:         return;
1.1       root      287:     }
1.1.1.4   root      288: 
                    289:     /* From now on, we can assume k is zero.  So we need to update MSR.  */
                    290:     /* Extract carry. And complement a into na.  */
                    291:     cf = tcg_temp_new();
                    292:     na = tcg_temp_new();
                    293:     if (c) {
                    294:         read_carry(dc, cf);
                    295:     } else {
                    296:         tcg_gen_movi_tl(cf, 1);
                    297:     }
                    298: 
                    299:     /* d = b + ~a + c. carry defaults to 1.  */
                    300:     tcg_gen_not_tl(na, cpu_R[dc->ra]);
                    301: 
                    302:     if (dc->rd) {
                    303:         TCGv ncf = tcg_temp_new();
                    304:         gen_helper_carry(ncf, na, *(dec_alu_op_b(dc)), cf);
                    305:         tcg_gen_add_tl(cpu_R[dc->rd], na, *(dec_alu_op_b(dc)));
                    306:         tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
                    307:         write_carry(dc, ncf);
                    308:         tcg_temp_free(ncf);
                    309:     } else {
                    310:         gen_helper_carry(cf, na, *(dec_alu_op_b(dc)), cf);
                    311:         write_carry(dc, cf);
                    312:     }
                    313:     tcg_temp_free(cf);
                    314:     tcg_temp_free(na);
1.1       root      315: }
                    316: 
                    317: static void dec_pattern(DisasContext *dc)
                    318: {
                    319:     unsigned int mode;
                    320:     int l1;
                    321: 
1.1.1.2   root      322:     if ((dc->tb_flags & MSR_EE_FLAG)
                    323:           && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
                    324:           && !((dc->env->pvr.regs[2] & PVR2_USE_PCMP_INSTR))) {
                    325:         tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
                    326:         t_gen_raise_exception(dc, EXCP_HW_EXCP);
                    327:     }
                    328: 
1.1       root      329:     mode = dc->opcode & 3;
                    330:     switch (mode) {
                    331:         case 0:
                    332:             /* pcmpbf.  */
                    333:             LOG_DIS("pcmpbf r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
                    334:             if (dc->rd)
                    335:                 gen_helper_pcmpbf(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                    336:             break;
                    337:         case 2:
                    338:             LOG_DIS("pcmpeq r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
                    339:             if (dc->rd) {
                    340:                 TCGv t0 = tcg_temp_local_new();
                    341:                 l1 = gen_new_label();
                    342:                 tcg_gen_movi_tl(t0, 1);
                    343:                 tcg_gen_brcond_tl(TCG_COND_EQ,
                    344:                                   cpu_R[dc->ra], cpu_R[dc->rb], l1);
                    345:                 tcg_gen_movi_tl(t0, 0);
                    346:                 gen_set_label(l1);
                    347:                 tcg_gen_mov_tl(cpu_R[dc->rd], t0);
                    348:                 tcg_temp_free(t0);
                    349:             }
                    350:             break;
                    351:         case 3:
                    352:             LOG_DIS("pcmpne r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
                    353:             l1 = gen_new_label();
                    354:             if (dc->rd) {
                    355:                 TCGv t0 = tcg_temp_local_new();
                    356:                 tcg_gen_movi_tl(t0, 1);
                    357:                 tcg_gen_brcond_tl(TCG_COND_NE,
                    358:                                   cpu_R[dc->ra], cpu_R[dc->rb], l1);
                    359:                 tcg_gen_movi_tl(t0, 0);
                    360:                 gen_set_label(l1);
                    361:                 tcg_gen_mov_tl(cpu_R[dc->rd], t0);
                    362:                 tcg_temp_free(t0);
                    363:             }
                    364:             break;
                    365:         default:
                    366:             cpu_abort(dc->env,
                    367:                       "unsupported pattern insn opcode=%x\n", dc->opcode);
                    368:             break;
                    369:     }
                    370: }
                    371: 
                    372: static void dec_and(DisasContext *dc)
                    373: {
                    374:     unsigned int not;
                    375: 
                    376:     if (!dc->type_b && (dc->imm & (1 << 10))) {
                    377:         dec_pattern(dc);
                    378:         return;
                    379:     }
                    380: 
                    381:     not = dc->opcode & (1 << 1);
                    382:     LOG_DIS("and%s\n", not ? "n" : "");
                    383: 
                    384:     if (!dc->rd)
                    385:         return;
                    386: 
                    387:     if (not) {
                    388:         TCGv t = tcg_temp_new();
                    389:         tcg_gen_not_tl(t, *(dec_alu_op_b(dc)));
                    390:         tcg_gen_and_tl(cpu_R[dc->rd], cpu_R[dc->ra], t);
                    391:         tcg_temp_free(t);
                    392:     } else
                    393:         tcg_gen_and_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
                    394: }
                    395: 
                    396: static void dec_or(DisasContext *dc)
                    397: {
                    398:     if (!dc->type_b && (dc->imm & (1 << 10))) {
                    399:         dec_pattern(dc);
                    400:         return;
                    401:     }
                    402: 
                    403:     LOG_DIS("or r%d r%d r%d imm=%x\n", dc->rd, dc->ra, dc->rb, dc->imm);
                    404:     if (dc->rd)
                    405:         tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
                    406: }
                    407: 
                    408: static void dec_xor(DisasContext *dc)
                    409: {
                    410:     if (!dc->type_b && (dc->imm & (1 << 10))) {
                    411:         dec_pattern(dc);
                    412:         return;
                    413:     }
                    414: 
                    415:     LOG_DIS("xor r%d\n", dc->rd);
                    416:     if (dc->rd)
                    417:         tcg_gen_xor_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
                    418: }
                    419: 
                    420: static inline void msr_read(DisasContext *dc, TCGv d)
                    421: {
                    422:     tcg_gen_mov_tl(d, cpu_SR[SR_MSR]);
                    423: }
                    424: 
                    425: static inline void msr_write(DisasContext *dc, TCGv v)
                    426: {
                    427:     dc->cpustate_changed = 1;
                    428:     tcg_gen_mov_tl(cpu_SR[SR_MSR], v);
                    429:     /* PVR, we have a processor version register.  */
                    430:     tcg_gen_ori_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], (1 << 10));
                    431: }
                    432: 
                    433: static void dec_msr(DisasContext *dc)
                    434: {
                    435:     TCGv t0, t1;
                    436:     unsigned int sr, to, rn;
1.1.1.2   root      437:     int mem_index = cpu_mmu_index(dc->env);
1.1       root      438: 
                    439:     sr = dc->imm & ((1 << 14) - 1);
                    440:     to = dc->imm & (1 << 14);
                    441:     dc->type_b = 1;
                    442:     if (to)
                    443:         dc->cpustate_changed = 1;
                    444: 
                    445:     /* msrclr and msrset.  */
                    446:     if (!(dc->imm & (1 << 15))) {
                    447:         unsigned int clr = dc->ir & (1 << 16);
                    448: 
                    449:         LOG_DIS("msr%s r%d imm=%x\n", clr ? "clr" : "set",
                    450:                 dc->rd, dc->imm);
1.1.1.2   root      451: 
                    452:         if (!(dc->env->pvr.regs[2] & PVR2_USE_MSR_INSTR)) {
                    453:             /* nop??? */
                    454:             return;
                    455:         }
                    456: 
                    457:         if ((dc->tb_flags & MSR_EE_FLAG)
                    458:             && mem_index == MMU_USER_IDX && (dc->imm != 4 && dc->imm != 0)) {
                    459:             tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
                    460:             t_gen_raise_exception(dc, EXCP_HW_EXCP);
                    461:             return;
                    462:         }
                    463: 
1.1       root      464:         if (dc->rd)
                    465:             msr_read(dc, cpu_R[dc->rd]);
                    466: 
                    467:         t0 = tcg_temp_new();
                    468:         t1 = tcg_temp_new();
                    469:         msr_read(dc, t0);
                    470:         tcg_gen_mov_tl(t1, *(dec_alu_op_b(dc)));
                    471: 
                    472:         if (clr) {
                    473:             tcg_gen_not_tl(t1, t1);
                    474:             tcg_gen_and_tl(t0, t0, t1);
                    475:         } else
                    476:             tcg_gen_or_tl(t0, t0, t1);
                    477:         msr_write(dc, t0);
                    478:         tcg_temp_free(t0);
                    479:         tcg_temp_free(t1);
                    480:        tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc + 4);
                    481:         dc->is_jmp = DISAS_UPDATE;
                    482:         return;
                    483:     }
                    484: 
1.1.1.2   root      485:     if (to) {
                    486:         if ((dc->tb_flags & MSR_EE_FLAG)
                    487:              && mem_index == MMU_USER_IDX) {
                    488:             tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
                    489:             t_gen_raise_exception(dc, EXCP_HW_EXCP);
                    490:             return;
                    491:         }
                    492:     }
                    493: 
1.1       root      494: #if !defined(CONFIG_USER_ONLY)
                    495:     /* Catch read/writes to the mmu block.  */
                    496:     if ((sr & ~0xff) == 0x1000) {
                    497:         sr &= 7;
                    498:         LOG_DIS("m%ss sr%d r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm);
                    499:         if (to)
                    500:             gen_helper_mmu_write(tcg_const_tl(sr), cpu_R[dc->ra]);
                    501:         else
                    502:             gen_helper_mmu_read(cpu_R[dc->rd], tcg_const_tl(sr));
                    503:         return;
                    504:     }
                    505: #endif
                    506: 
                    507:     if (to) {
                    508:         LOG_DIS("m%ss sr%x r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm);
                    509:         switch (sr) {
                    510:             case 0:
                    511:                 break;
                    512:             case 1:
                    513:                 msr_write(dc, cpu_R[dc->ra]);
                    514:                 break;
                    515:             case 0x3:
                    516:                 tcg_gen_mov_tl(cpu_SR[SR_EAR], cpu_R[dc->ra]);
                    517:                 break;
                    518:             case 0x5:
                    519:                 tcg_gen_mov_tl(cpu_SR[SR_ESR], cpu_R[dc->ra]);
                    520:                 break;
                    521:             case 0x7:
1.1.1.4   root      522:                 tcg_gen_andi_tl(cpu_SR[SR_FSR], cpu_R[dc->ra], 31);
1.1       root      523:                 break;
                    524:             default:
                    525:                 cpu_abort(dc->env, "unknown mts reg %x\n", sr);
                    526:                 break;
                    527:         }
                    528:     } else {
                    529:         LOG_DIS("m%ss r%d sr%x imm=%x\n", to ? "t" : "f", dc->rd, sr, dc->imm);
                    530: 
                    531:         switch (sr) {
                    532:             case 0:
                    533:                 tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc);
                    534:                 break;
                    535:             case 1:
                    536:                 msr_read(dc, cpu_R[dc->rd]);
                    537:                 break;
                    538:             case 0x3:
                    539:                 tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_EAR]);
                    540:                 break;
                    541:             case 0x5:
                    542:                 tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_ESR]);
                    543:                 break;
                    544:              case 0x7:
1.1.1.4   root      545:                 tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_FSR]);
1.1       root      546:                 break;
                    547:             case 0xb:
                    548:                 tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_BTR]);
                    549:                 break;
                    550:             case 0x2000:
                    551:             case 0x2001:
                    552:             case 0x2002:
                    553:             case 0x2003:
                    554:             case 0x2004:
                    555:             case 0x2005:
                    556:             case 0x2006:
                    557:             case 0x2007:
                    558:             case 0x2008:
                    559:             case 0x2009:
                    560:             case 0x200a:
                    561:             case 0x200b:
                    562:             case 0x200c:
                    563:                 rn = sr & 0xf;
                    564:                 tcg_gen_ld_tl(cpu_R[dc->rd],
                    565:                               cpu_env, offsetof(CPUState, pvr.regs[rn]));
                    566:                 break;
                    567:             default:
                    568:                 cpu_abort(dc->env, "unknown mfs reg %x\n", sr);
                    569:                 break;
                    570:         }
                    571:     }
1.1.1.2   root      572: 
                    573:     if (dc->rd == 0) {
                    574:         tcg_gen_movi_tl(cpu_R[0], 0);
                    575:     }
1.1       root      576: }
                    577: 
                    578: /* 64-bit signed mul, lower result in d and upper in d2.  */
                    579: static void t_gen_muls(TCGv d, TCGv d2, TCGv a, TCGv b)
                    580: {
                    581:     TCGv_i64 t0, t1;
                    582: 
                    583:     t0 = tcg_temp_new_i64();
                    584:     t1 = tcg_temp_new_i64();
                    585: 
                    586:     tcg_gen_ext_i32_i64(t0, a);
                    587:     tcg_gen_ext_i32_i64(t1, b);
                    588:     tcg_gen_mul_i64(t0, t0, t1);
                    589: 
                    590:     tcg_gen_trunc_i64_i32(d, t0);
                    591:     tcg_gen_shri_i64(t0, t0, 32);
                    592:     tcg_gen_trunc_i64_i32(d2, t0);
                    593: 
                    594:     tcg_temp_free_i64(t0);
                    595:     tcg_temp_free_i64(t1);
                    596: }
                    597: 
                    598: /* 64-bit unsigned muls, lower result in d and upper in d2.  */
                    599: static void t_gen_mulu(TCGv d, TCGv d2, TCGv a, TCGv b)
                    600: {
                    601:     TCGv_i64 t0, t1;
                    602: 
                    603:     t0 = tcg_temp_new_i64();
                    604:     t1 = tcg_temp_new_i64();
                    605: 
                    606:     tcg_gen_extu_i32_i64(t0, a);
                    607:     tcg_gen_extu_i32_i64(t1, b);
                    608:     tcg_gen_mul_i64(t0, t0, t1);
                    609: 
                    610:     tcg_gen_trunc_i64_i32(d, t0);
                    611:     tcg_gen_shri_i64(t0, t0, 32);
                    612:     tcg_gen_trunc_i64_i32(d2, t0);
                    613: 
                    614:     tcg_temp_free_i64(t0);
                    615:     tcg_temp_free_i64(t1);
                    616: }
                    617: 
                    618: /* Multiplier unit.  */
                    619: static void dec_mul(DisasContext *dc)
                    620: {
                    621:     TCGv d[2];
                    622:     unsigned int subcode;
                    623: 
1.1.1.2   root      624:     if ((dc->tb_flags & MSR_EE_FLAG)
                    625:          && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
                    626:          && !(dc->env->pvr.regs[0] & PVR0_USE_HW_MUL_MASK)) {
                    627:         tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
                    628:         t_gen_raise_exception(dc, EXCP_HW_EXCP);
                    629:         return;
                    630:     }
                    631: 
1.1       root      632:     subcode = dc->imm & 3;
                    633:     d[0] = tcg_temp_new();
                    634:     d[1] = tcg_temp_new();
                    635: 
                    636:     if (dc->type_b) {
                    637:         LOG_DIS("muli r%d r%d %x\n", dc->rd, dc->ra, dc->imm);
                    638:         t_gen_mulu(cpu_R[dc->rd], d[1], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
                    639:         goto done;
                    640:     }
                    641: 
1.1.1.2   root      642:     /* mulh, mulhsu and mulhu are not available if C_USE_HW_MUL is < 2.  */
                    643:     if (subcode >= 1 && subcode <= 3
                    644:         && !((dc->env->pvr.regs[2] & PVR2_USE_MUL64_MASK))) {
                    645:         /* nop??? */
                    646:     }
                    647: 
1.1       root      648:     switch (subcode) {
                    649:         case 0:
                    650:             LOG_DIS("mul r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
                    651:             t_gen_mulu(cpu_R[dc->rd], d[1], cpu_R[dc->ra], cpu_R[dc->rb]);
                    652:             break;
                    653:         case 1:
                    654:             LOG_DIS("mulh r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
                    655:             t_gen_muls(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                    656:             break;
                    657:         case 2:
                    658:             LOG_DIS("mulhsu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
                    659:             t_gen_muls(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                    660:             break;
                    661:         case 3:
                    662:             LOG_DIS("mulhu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
                    663:             t_gen_mulu(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                    664:             break;
                    665:         default:
                    666:             cpu_abort(dc->env, "unknown MUL insn %x\n", subcode);
                    667:             break;
                    668:     }
                    669: done:
                    670:     tcg_temp_free(d[0]);
                    671:     tcg_temp_free(d[1]);
                    672: }
                    673: 
                    674: /* Div unit.  */
                    675: static void dec_div(DisasContext *dc)
                    676: {
                    677:     unsigned int u;
                    678: 
                    679:     u = dc->imm & 2; 
                    680:     LOG_DIS("div\n");
                    681: 
1.1.1.2   root      682:     if ((dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
                    683:           && !((dc->env->pvr.regs[0] & PVR0_USE_DIV_MASK))) {
                    684:         tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
                    685:         t_gen_raise_exception(dc, EXCP_HW_EXCP);
                    686:     }
                    687: 
1.1       root      688:     if (u)
                    689:         gen_helper_divu(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
                    690:     else
                    691:         gen_helper_divs(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
                    692:     if (!dc->rd)
                    693:         tcg_gen_movi_tl(cpu_R[dc->rd], 0);
                    694: }
                    695: 
                    696: static void dec_barrel(DisasContext *dc)
                    697: {
                    698:     TCGv t0;
                    699:     unsigned int s, t;
                    700: 
1.1.1.2   root      701:     if ((dc->tb_flags & MSR_EE_FLAG)
                    702:           && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
                    703:           && !(dc->env->pvr.regs[0] & PVR0_USE_BARREL_MASK)) {
                    704:         tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
                    705:         t_gen_raise_exception(dc, EXCP_HW_EXCP);
                    706:         return;
                    707:     }
                    708: 
1.1       root      709:     s = dc->imm & (1 << 10);
                    710:     t = dc->imm & (1 << 9);
                    711: 
                    712:     LOG_DIS("bs%s%s r%d r%d r%d\n",
                    713:             s ? "l" : "r", t ? "a" : "l", dc->rd, dc->ra, dc->rb);
                    714: 
                    715:     t0 = tcg_temp_new();
                    716: 
                    717:     tcg_gen_mov_tl(t0, *(dec_alu_op_b(dc)));
                    718:     tcg_gen_andi_tl(t0, t0, 31);
                    719: 
                    720:     if (s)
                    721:         tcg_gen_shl_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0);
                    722:     else {
                    723:         if (t)
                    724:             tcg_gen_sar_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0);
                    725:         else
                    726:             tcg_gen_shr_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0);
                    727:     }
                    728: }
                    729: 
                    730: static void dec_bit(DisasContext *dc)
                    731: {
                    732:     TCGv t0, t1;
                    733:     unsigned int op;
1.1.1.2   root      734:     int mem_index = cpu_mmu_index(dc->env);
1.1       root      735: 
                    736:     op = dc->ir & ((1 << 8) - 1);
                    737:     switch (op) {
                    738:         case 0x21:
                    739:             /* src.  */
                    740:             t0 = tcg_temp_new();
                    741: 
                    742:             LOG_DIS("src r%d r%d\n", dc->rd, dc->ra);
                    743:             tcg_gen_andi_tl(t0, cpu_R[dc->ra], 1);
                    744:             if (dc->rd) {
                    745:                 t1 = tcg_temp_new();
                    746:                 read_carry(dc, t1);
                    747:                 tcg_gen_shli_tl(t1, t1, 31);
                    748: 
                    749:                 tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
                    750:                 tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->rd], t1);
                    751:                 tcg_temp_free(t1);
                    752:             }
                    753: 
                    754:             /* Update carry.  */
                    755:             write_carry(dc, t0);
                    756:             tcg_temp_free(t0);
                    757:             break;
                    758: 
                    759:         case 0x1:
                    760:         case 0x41:
                    761:             /* srl.  */
                    762:             t0 = tcg_temp_new();
                    763:             LOG_DIS("srl r%d r%d\n", dc->rd, dc->ra);
                    764: 
                    765:             /* Update carry.  */
                    766:             tcg_gen_andi_tl(t0, cpu_R[dc->ra], 1);
                    767:             write_carry(dc, t0);
                    768:             tcg_temp_free(t0);
                    769:             if (dc->rd) {
                    770:                 if (op == 0x41)
                    771:                     tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
                    772:                 else
                    773:                     tcg_gen_sari_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
                    774:             }
                    775:             break;
                    776:         case 0x60:
                    777:             LOG_DIS("ext8s r%d r%d\n", dc->rd, dc->ra);
                    778:             tcg_gen_ext8s_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
                    779:             break;
                    780:         case 0x61:
                    781:             LOG_DIS("ext16s r%d r%d\n", dc->rd, dc->ra);
                    782:             tcg_gen_ext16s_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
                    783:             break;
                    784:         case 0x64:
1.1.1.3   root      785:         case 0x66:
                    786:         case 0x74:
                    787:         case 0x76:
1.1       root      788:             /* wdc.  */
                    789:             LOG_DIS("wdc r%d\n", dc->ra);
1.1.1.2   root      790:             if ((dc->tb_flags & MSR_EE_FLAG)
                    791:                  && mem_index == MMU_USER_IDX) {
                    792:                 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
                    793:                 t_gen_raise_exception(dc, EXCP_HW_EXCP);
                    794:                 return;
                    795:             }
1.1       root      796:             break;
                    797:         case 0x68:
                    798:             /* wic.  */
                    799:             LOG_DIS("wic r%d\n", dc->ra);
1.1.1.2   root      800:             if ((dc->tb_flags & MSR_EE_FLAG)
                    801:                  && mem_index == MMU_USER_IDX) {
                    802:                 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
                    803:                 t_gen_raise_exception(dc, EXCP_HW_EXCP);
                    804:                 return;
                    805:             }
1.1       root      806:             break;
                    807:         default:
                    808:             cpu_abort(dc->env, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
                    809:                      dc->pc, op, dc->rd, dc->ra, dc->rb);
                    810:             break;
                    811:     }
                    812: }
                    813: 
                    814: static inline void sync_jmpstate(DisasContext *dc)
                    815: {
1.1.1.4   root      816:     if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
                    817:         if (dc->jmp == JMP_DIRECT) {
1.1       root      818:             tcg_gen_movi_tl(env_btaken, 1);
1.1.1.4   root      819:         }
                    820:         dc->jmp = JMP_INDIRECT;
                    821:         tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
1.1       root      822:     }
                    823: }
                    824: 
                    825: static void dec_imm(DisasContext *dc)
                    826: {
                    827:     LOG_DIS("imm %x\n", dc->imm << 16);
                    828:     tcg_gen_movi_tl(env_imm, (dc->imm << 16));
                    829:     dc->tb_flags |= IMM_FLAG;
                    830:     dc->clear_imm = 0;
                    831: }
                    832: 
                    833: static inline void gen_load(DisasContext *dc, TCGv dst, TCGv addr,
                    834:                             unsigned int size)
                    835: {
                    836:     int mem_index = cpu_mmu_index(dc->env);
                    837: 
                    838:     if (size == 1) {
                    839:         tcg_gen_qemu_ld8u(dst, addr, mem_index);
                    840:     } else if (size == 2) {
                    841:         tcg_gen_qemu_ld16u(dst, addr, mem_index);
                    842:     } else if (size == 4) {
                    843:         tcg_gen_qemu_ld32u(dst, addr, mem_index);
                    844:     } else
                    845:         cpu_abort(dc->env, "Incorrect load size %d\n", size);
                    846: }
                    847: 
                    848: static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
                    849: {
                    850:     unsigned int extimm = dc->tb_flags & IMM_FLAG;
                    851: 
1.1.1.4   root      852:     /* Treat the common cases first.  */
1.1       root      853:     if (!dc->type_b) {
1.1.1.3   root      854:         /* If any of the regs is r0, return a ptr to the other.  */
                    855:         if (dc->ra == 0) {
                    856:             return &cpu_R[dc->rb];
                    857:         } else if (dc->rb == 0) {
                    858:             return &cpu_R[dc->ra];
                    859:         }
                    860: 
1.1       root      861:         *t = tcg_temp_new();
                    862:         tcg_gen_add_tl(*t, cpu_R[dc->ra], cpu_R[dc->rb]);
                    863:         return t;
                    864:     }
                    865:     /* Immediate.  */
                    866:     if (!extimm) {
                    867:         if (dc->imm == 0) {
                    868:             return &cpu_R[dc->ra];
                    869:         }
                    870:         *t = tcg_temp_new();
                    871:         tcg_gen_movi_tl(*t, (int32_t)((int16_t)dc->imm));
                    872:         tcg_gen_add_tl(*t, cpu_R[dc->ra], *t);
                    873:     } else {
                    874:         *t = tcg_temp_new();
                    875:         tcg_gen_add_tl(*t, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
                    876:     }
                    877: 
                    878:     return t;
                    879: }
                    880: 
1.1.1.4   root      881: static inline void dec_byteswap(DisasContext *dc, TCGv dst, TCGv src, int size)
                    882: {
                    883:     if (size == 4) {
                    884:         tcg_gen_bswap32_tl(dst, src);
                    885:     } else if (size == 2) {
                    886:         TCGv t = tcg_temp_new();
                    887: 
                    888:         /* bswap16 assumes the high bits are zero.  */
                    889:         tcg_gen_andi_tl(t, src, 0xffff);
                    890:         tcg_gen_bswap16_tl(dst, t);
                    891:         tcg_temp_free(t);
                    892:     } else {
                    893:         /* Ignore.
                    894:         cpu_abort(dc->env, "Invalid ldst byteswap size %d\n", size);
                    895:         */
                    896:     }
                    897: }
                    898: 
1.1       root      899: static void dec_load(DisasContext *dc)
                    900: {
                    901:     TCGv t, *addr;
1.1.1.4   root      902:     unsigned int size, rev = 0;
1.1       root      903: 
                    904:     size = 1 << (dc->opcode & 3);
1.1.1.4   root      905: 
                    906:     if (!dc->type_b) {
                    907:         rev = (dc->ir >> 9) & 1;
                    908:     }
                    909: 
1.1.1.2   root      910:     if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
                    911:           && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
                    912:         tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
                    913:         t_gen_raise_exception(dc, EXCP_HW_EXCP);
                    914:         return;
                    915:     }
1.1       root      916: 
1.1.1.4   root      917:     LOG_DIS("l%d%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "");
                    918: 
1.1       root      919:     t_sync_flags(dc);
                    920:     addr = compute_ldst_addr(dc, &t);
                    921: 
1.1.1.4   root      922:     /*
                    923:      * When doing reverse accesses we need to do two things.
                    924:      *
1.1.1.5 ! root      925:      * 1. Reverse the address wrt endianness.
1.1.1.4   root      926:      * 2. Byteswap the data lanes on the way back into the CPU core.
                    927:      */
                    928:     if (rev && size != 4) {
                    929:         /* Endian reverse the address. t is addr.  */
                    930:         switch (size) {
                    931:             case 1:
                    932:             {
                    933:                 /* 00 -> 11
                    934:                    01 -> 10
                    935:                    10 -> 10
                    936:                    11 -> 00 */
                    937:                 TCGv low = tcg_temp_new();
                    938: 
                    939:                 /* Force addr into the temp.  */
                    940:                 if (addr != &t) {
                    941:                     t = tcg_temp_new();
                    942:                     tcg_gen_mov_tl(t, *addr);
                    943:                     addr = &t;
                    944:                 }
                    945: 
                    946:                 tcg_gen_andi_tl(low, t, 3);
                    947:                 tcg_gen_sub_tl(low, tcg_const_tl(3), low);
                    948:                 tcg_gen_andi_tl(t, t, ~3);
                    949:                 tcg_gen_or_tl(t, t, low);
                    950:                 tcg_gen_mov_tl(env_imm, t);
                    951:                 tcg_temp_free(low);
                    952:                 break;
                    953:             }
                    954: 
                    955:             case 2:
                    956:                 /* 00 -> 10
                    957:                    10 -> 00.  */
                    958:                 /* Force addr into the temp.  */
                    959:                 if (addr != &t) {
                    960:                     t = tcg_temp_new();
                    961:                     tcg_gen_xori_tl(t, *addr, 2);
                    962:                     addr = &t;
                    963:                 } else {
                    964:                     tcg_gen_xori_tl(t, t, 2);
                    965:                 }
                    966:                 break;
                    967:             default:
                    968:                 cpu_abort(dc->env, "Invalid reverse size\n");
                    969:                 break;
                    970:         }
                    971:     }
                    972: 
1.1       root      973:     /* If we get a fault on a dslot, the jmpstate better be in sync.  */
                    974:     sync_jmpstate(dc);
1.1.1.2   root      975: 
                    976:     /* Verify alignment if needed.  */
                    977:     if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
                    978:         TCGv v = tcg_temp_new();
                    979: 
                    980:         /*
                    981:          * Microblaze gives MMU faults priority over faults due to
                    982:          * unaligned addresses. That's why we speculatively do the load
                    983:          * into v. If the load succeeds, we verify alignment of the
                    984:          * address and if that succeeds we write into the destination reg.
                    985:          */
                    986:         gen_load(dc, v, *addr, size);
                    987: 
                    988:         tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
                    989:         gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
                    990:                             tcg_const_tl(0), tcg_const_tl(size - 1));
1.1.1.4   root      991:         if (dc->rd) {
                    992:             if (rev) {
                    993:                 dec_byteswap(dc, cpu_R[dc->rd], v, size);
                    994:             } else {
                    995:                 tcg_gen_mov_tl(cpu_R[dc->rd], v);
                    996:             }
                    997:         }
1.1.1.2   root      998:         tcg_temp_free(v);
                    999:     } else {
                   1000:         if (dc->rd) {
                   1001:             gen_load(dc, cpu_R[dc->rd], *addr, size);
1.1.1.4   root     1002:             if (rev) {
                   1003:                 dec_byteswap(dc, cpu_R[dc->rd], cpu_R[dc->rd], size);
                   1004:             }
1.1.1.2   root     1005:         } else {
1.1.1.4   root     1006:             /* We are loading into r0, no need to reverse.  */
1.1.1.2   root     1007:             gen_load(dc, env_imm, *addr, size);
                   1008:         }
1.1       root     1009:     }
                   1010: 
                   1011:     if (addr == &t)
                   1012:         tcg_temp_free(t);
                   1013: }
                   1014: 
                   1015: static void gen_store(DisasContext *dc, TCGv addr, TCGv val,
                   1016:                       unsigned int size)
                   1017: {
                   1018:     int mem_index = cpu_mmu_index(dc->env);
                   1019: 
                   1020:     if (size == 1)
                   1021:         tcg_gen_qemu_st8(val, addr, mem_index);
                   1022:     else if (size == 2) {
                   1023:         tcg_gen_qemu_st16(val, addr, mem_index);
                   1024:     } else if (size == 4) {
                   1025:         tcg_gen_qemu_st32(val, addr, mem_index);
                   1026:     } else
                   1027:         cpu_abort(dc->env, "Incorrect store size %d\n", size);
                   1028: }
                   1029: 
                   1030: static void dec_store(DisasContext *dc)
                   1031: {
                   1032:     TCGv t, *addr;
1.1.1.4   root     1033:     unsigned int size, rev = 0;
1.1       root     1034: 
                   1035:     size = 1 << (dc->opcode & 3);
1.1.1.4   root     1036:     if (!dc->type_b) {
                   1037:         rev = (dc->ir >> 9) & 1;
                   1038:     }
1.1       root     1039: 
1.1.1.2   root     1040:     if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
                   1041:           && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
                   1042:         tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
                   1043:         t_gen_raise_exception(dc, EXCP_HW_EXCP);
                   1044:         return;
                   1045:     }
                   1046: 
1.1.1.4   root     1047:     LOG_DIS("s%d%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "");
1.1       root     1048:     t_sync_flags(dc);
                   1049:     /* If we get a fault on a dslot, the jmpstate better be in sync.  */
                   1050:     sync_jmpstate(dc);
                   1051:     addr = compute_ldst_addr(dc, &t);
1.1.1.2   root     1052: 
1.1.1.4   root     1053:     if (rev && size != 4) {
                   1054:         /* Endian reverse the address. t is addr.  */
                   1055:         switch (size) {
                   1056:             case 1:
                   1057:             {
                   1058:                 /* 00 -> 11
                   1059:                    01 -> 10
                   1060:                    10 -> 10
                   1061:                    11 -> 00 */
                   1062:                 TCGv low = tcg_temp_new();
                   1063: 
                   1064:                 /* Force addr into the temp.  */
                   1065:                 if (addr != &t) {
                   1066:                     t = tcg_temp_new();
                   1067:                     tcg_gen_mov_tl(t, *addr);
                   1068:                     addr = &t;
                   1069:                 }
                   1070: 
                   1071:                 tcg_gen_andi_tl(low, t, 3);
                   1072:                 tcg_gen_sub_tl(low, tcg_const_tl(3), low);
                   1073:                 tcg_gen_andi_tl(t, t, ~3);
                   1074:                 tcg_gen_or_tl(t, t, low);
                   1075:                 tcg_gen_mov_tl(env_imm, t);
                   1076:                 tcg_temp_free(low);
                   1077:                 break;
                   1078:             }
                   1079: 
                   1080:             case 2:
                   1081:                 /* 00 -> 10
                   1082:                    10 -> 00.  */
                   1083:                 /* Force addr into the temp.  */
                   1084:                 if (addr != &t) {
                   1085:                     t = tcg_temp_new();
                   1086:                     tcg_gen_xori_tl(t, *addr, 2);
                   1087:                     addr = &t;
                   1088:                 } else {
                   1089:                     tcg_gen_xori_tl(t, t, 2);
                   1090:                 }
                   1091:                 break;
                   1092:             default:
                   1093:                 cpu_abort(dc->env, "Invalid reverse size\n");
                   1094:                 break;
                   1095:         }
                   1096: 
                   1097:         if (size != 1) {
                   1098:             TCGv bs_data = tcg_temp_new();
                   1099:             dec_byteswap(dc, bs_data, cpu_R[dc->rd], size);
                   1100:             gen_store(dc, *addr, bs_data, size);
                   1101:             tcg_temp_free(bs_data);
                   1102:         } else {
                   1103:             gen_store(dc, *addr, cpu_R[dc->rd], size);
                   1104:         }
                   1105:     } else {
                   1106:         if (rev) {
                   1107:             TCGv bs_data = tcg_temp_new();
                   1108:             dec_byteswap(dc, bs_data, cpu_R[dc->rd], size);
                   1109:             gen_store(dc, *addr, bs_data, size);
                   1110:             tcg_temp_free(bs_data);
                   1111:         } else {
                   1112:             gen_store(dc, *addr, cpu_R[dc->rd], size);
                   1113:         }
                   1114:     }
1.1.1.2   root     1115: 
                   1116:     /* Verify alignment if needed.  */
                   1117:     if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
                   1118:         tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
                   1119:         /* FIXME: if the alignment is wrong, we should restore the value
1.1.1.4   root     1120:          *        in memory. One possible way to acheive this is to probe
                   1121:          *        the MMU prior to the memaccess, thay way we could put
                   1122:          *        the alignment checks in between the probe and the mem
                   1123:          *        access.
1.1.1.2   root     1124:          */
                   1125:         gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
                   1126:                             tcg_const_tl(1), tcg_const_tl(size - 1));
                   1127:     }
                   1128: 
1.1       root     1129:     if (addr == &t)
                   1130:         tcg_temp_free(t);
                   1131: }
                   1132: 
                   1133: static inline void eval_cc(DisasContext *dc, unsigned int cc,
                   1134:                            TCGv d, TCGv a, TCGv b)
                   1135: {
                   1136:     switch (cc) {
                   1137:         case CC_EQ:
1.1.1.3   root     1138:             tcg_gen_setcond_tl(TCG_COND_EQ, d, a, b);
1.1       root     1139:             break;
                   1140:         case CC_NE:
1.1.1.3   root     1141:             tcg_gen_setcond_tl(TCG_COND_NE, d, a, b);
1.1       root     1142:             break;
                   1143:         case CC_LT:
1.1.1.3   root     1144:             tcg_gen_setcond_tl(TCG_COND_LT, d, a, b);
1.1       root     1145:             break;
                   1146:         case CC_LE:
1.1.1.3   root     1147:             tcg_gen_setcond_tl(TCG_COND_LE, d, a, b);
1.1       root     1148:             break;
                   1149:         case CC_GE:
1.1.1.3   root     1150:             tcg_gen_setcond_tl(TCG_COND_GE, d, a, b);
1.1       root     1151:             break;
                   1152:         case CC_GT:
1.1.1.3   root     1153:             tcg_gen_setcond_tl(TCG_COND_GT, d, a, b);
1.1       root     1154:             break;
                   1155:         default:
                   1156:             cpu_abort(dc->env, "Unknown condition code %x.\n", cc);
                   1157:             break;
                   1158:     }
                   1159: }
                   1160: 
                   1161: static void eval_cond_jmp(DisasContext *dc, TCGv pc_true, TCGv pc_false)
                   1162: {
                   1163:     int l1;
                   1164: 
                   1165:     l1 = gen_new_label();
                   1166:     /* Conditional jmp.  */
                   1167:     tcg_gen_mov_tl(cpu_SR[SR_PC], pc_false);
                   1168:     tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1);
                   1169:     tcg_gen_mov_tl(cpu_SR[SR_PC], pc_true);
                   1170:     gen_set_label(l1);
                   1171: }
                   1172: 
                   1173: static void dec_bcc(DisasContext *dc)
                   1174: {
                   1175:     unsigned int cc;
                   1176:     unsigned int dslot;
                   1177: 
                   1178:     cc = EXTRACT_FIELD(dc->ir, 21, 23);
                   1179:     dslot = dc->ir & (1 << 25);
                   1180:     LOG_DIS("bcc%s r%d %x\n", dslot ? "d" : "", dc->ra, dc->imm);
                   1181: 
                   1182:     dc->delayed_branch = 1;
                   1183:     if (dslot) {
                   1184:         dc->delayed_branch = 2;
                   1185:         dc->tb_flags |= D_FLAG;
                   1186:         tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
                   1187:                       cpu_env, offsetof(CPUState, bimm));
                   1188:     }
                   1189: 
1.1.1.3   root     1190:     if (dec_alu_op_b_is_small_imm(dc)) {
                   1191:         int32_t offset = (int32_t)((int16_t)dc->imm); /* sign-extend.  */
                   1192: 
                   1193:         tcg_gen_movi_tl(env_btarget, dc->pc + offset);
1.1.1.4   root     1194:         dc->jmp = JMP_DIRECT_CC;
                   1195:         dc->jmp_pc = dc->pc + offset;
1.1.1.3   root     1196:     } else {
1.1.1.4   root     1197:         dc->jmp = JMP_INDIRECT;
1.1.1.3   root     1198:         tcg_gen_movi_tl(env_btarget, dc->pc);
                   1199:         tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc)));
                   1200:     }
                   1201:     eval_cc(dc, cc, env_btaken, cpu_R[dc->ra], tcg_const_tl(0));
1.1       root     1202: }
                   1203: 
                   1204: static void dec_br(DisasContext *dc)
                   1205: {
                   1206:     unsigned int dslot, link, abs;
1.1.1.3   root     1207:     int mem_index = cpu_mmu_index(dc->env);
1.1       root     1208: 
                   1209:     dslot = dc->ir & (1 << 20);
                   1210:     abs = dc->ir & (1 << 19);
                   1211:     link = dc->ir & (1 << 18);
                   1212:     LOG_DIS("br%s%s%s%s imm=%x\n",
                   1213:              abs ? "a" : "", link ? "l" : "",
                   1214:              dc->type_b ? "i" : "", dslot ? "d" : "",
                   1215:              dc->imm);
                   1216: 
                   1217:     dc->delayed_branch = 1;
                   1218:     if (dslot) {
                   1219:         dc->delayed_branch = 2;
                   1220:         dc->tb_flags |= D_FLAG;
                   1221:         tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
                   1222:                       cpu_env, offsetof(CPUState, bimm));
                   1223:     }
                   1224:     if (link && dc->rd)
                   1225:         tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc);
                   1226: 
                   1227:     dc->jmp = JMP_INDIRECT;
                   1228:     if (abs) {
                   1229:         tcg_gen_movi_tl(env_btaken, 1);
                   1230:         tcg_gen_mov_tl(env_btarget, *(dec_alu_op_b(dc)));
1.1.1.3   root     1231:         if (link && !dslot) {
                   1232:             if (!(dc->tb_flags & IMM_FLAG) && (dc->imm == 8 || dc->imm == 0x18))
                   1233:                 t_gen_raise_exception(dc, EXCP_BREAK);
                   1234:             if (dc->imm == 0) {
                   1235:                 if ((dc->tb_flags & MSR_EE_FLAG) && mem_index == MMU_USER_IDX) {
                   1236:                     tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
                   1237:                     t_gen_raise_exception(dc, EXCP_HW_EXCP);
                   1238:                     return;
                   1239:                 }
                   1240: 
                   1241:                 t_gen_raise_exception(dc, EXCP_DEBUG);
                   1242:             }
                   1243:         }
1.1       root     1244:     } else {
1.1.1.3   root     1245:         if (dec_alu_op_b_is_small_imm(dc)) {
                   1246:             dc->jmp = JMP_DIRECT;
                   1247:             dc->jmp_pc = dc->pc + (int32_t)((int16_t)dc->imm);
                   1248:         } else {
1.1       root     1249:             tcg_gen_movi_tl(env_btaken, 1);
                   1250:             tcg_gen_movi_tl(env_btarget, dc->pc);
                   1251:             tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc)));
                   1252:         }
                   1253:     }
                   1254: }
                   1255: 
                   1256: static inline void do_rti(DisasContext *dc)
                   1257: {
                   1258:     TCGv t0, t1;
                   1259:     t0 = tcg_temp_new();
                   1260:     t1 = tcg_temp_new();
                   1261:     tcg_gen_shri_tl(t0, cpu_SR[SR_MSR], 1);
                   1262:     tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_IE);
                   1263:     tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
                   1264: 
                   1265:     tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
                   1266:     tcg_gen_or_tl(t1, t1, t0);
                   1267:     msr_write(dc, t1);
                   1268:     tcg_temp_free(t1);
                   1269:     tcg_temp_free(t0);
                   1270:     dc->tb_flags &= ~DRTI_FLAG;
                   1271: }
                   1272: 
                   1273: static inline void do_rtb(DisasContext *dc)
                   1274: {
                   1275:     TCGv t0, t1;
                   1276:     t0 = tcg_temp_new();
                   1277:     t1 = tcg_temp_new();
                   1278:     tcg_gen_andi_tl(t1, cpu_SR[SR_MSR], ~MSR_BIP);
                   1279:     tcg_gen_shri_tl(t0, t1, 1);
                   1280:     tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
                   1281: 
                   1282:     tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
                   1283:     tcg_gen_or_tl(t1, t1, t0);
                   1284:     msr_write(dc, t1);
                   1285:     tcg_temp_free(t1);
                   1286:     tcg_temp_free(t0);
                   1287:     dc->tb_flags &= ~DRTB_FLAG;
                   1288: }
                   1289: 
                   1290: static inline void do_rte(DisasContext *dc)
                   1291: {
                   1292:     TCGv t0, t1;
                   1293:     t0 = tcg_temp_new();
                   1294:     t1 = tcg_temp_new();
                   1295: 
                   1296:     tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_EE);
                   1297:     tcg_gen_andi_tl(t1, t1, ~MSR_EIP);
                   1298:     tcg_gen_shri_tl(t0, t1, 1);
                   1299:     tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
                   1300: 
                   1301:     tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
                   1302:     tcg_gen_or_tl(t1, t1, t0);
                   1303:     msr_write(dc, t1);
                   1304:     tcg_temp_free(t1);
                   1305:     tcg_temp_free(t0);
                   1306:     dc->tb_flags &= ~DRTE_FLAG;
                   1307: }
                   1308: 
                   1309: static void dec_rts(DisasContext *dc)
                   1310: {
                   1311:     unsigned int b_bit, i_bit, e_bit;
1.1.1.2   root     1312:     int mem_index = cpu_mmu_index(dc->env);
1.1       root     1313: 
                   1314:     i_bit = dc->ir & (1 << 21);
                   1315:     b_bit = dc->ir & (1 << 22);
                   1316:     e_bit = dc->ir & (1 << 23);
                   1317: 
                   1318:     dc->delayed_branch = 2;
                   1319:     dc->tb_flags |= D_FLAG;
                   1320:     tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
                   1321:                   cpu_env, offsetof(CPUState, bimm));
                   1322: 
                   1323:     if (i_bit) {
                   1324:         LOG_DIS("rtid ir=%x\n", dc->ir);
1.1.1.2   root     1325:         if ((dc->tb_flags & MSR_EE_FLAG)
                   1326:              && mem_index == MMU_USER_IDX) {
                   1327:             tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
                   1328:             t_gen_raise_exception(dc, EXCP_HW_EXCP);
                   1329:         }
1.1       root     1330:         dc->tb_flags |= DRTI_FLAG;
                   1331:     } else if (b_bit) {
                   1332:         LOG_DIS("rtbd ir=%x\n", dc->ir);
1.1.1.2   root     1333:         if ((dc->tb_flags & MSR_EE_FLAG)
                   1334:              && mem_index == MMU_USER_IDX) {
                   1335:             tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
                   1336:             t_gen_raise_exception(dc, EXCP_HW_EXCP);
                   1337:         }
1.1       root     1338:         dc->tb_flags |= DRTB_FLAG;
                   1339:     } else if (e_bit) {
                   1340:         LOG_DIS("rted ir=%x\n", dc->ir);
1.1.1.2   root     1341:         if ((dc->tb_flags & MSR_EE_FLAG)
                   1342:              && mem_index == MMU_USER_IDX) {
                   1343:             tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
                   1344:             t_gen_raise_exception(dc, EXCP_HW_EXCP);
                   1345:         }
1.1       root     1346:         dc->tb_flags |= DRTE_FLAG;
                   1347:     } else
                   1348:         LOG_DIS("rts ir=%x\n", dc->ir);
                   1349: 
1.1.1.4   root     1350:     dc->jmp = JMP_INDIRECT;
1.1       root     1351:     tcg_gen_movi_tl(env_btaken, 1);
                   1352:     tcg_gen_add_tl(env_btarget, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
                   1353: }
                   1354: 
1.1.1.4   root     1355: static int dec_check_fpuv2(DisasContext *dc)
                   1356: {
                   1357:     int r;
                   1358: 
                   1359:     r = dc->env->pvr.regs[2] & PVR2_USE_FPU2_MASK;
                   1360: 
                   1361:     if (!r && (dc->tb_flags & MSR_EE_FLAG)) {
                   1362:         tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_FPU);
                   1363:         t_gen_raise_exception(dc, EXCP_HW_EXCP);
                   1364:     }
                   1365:     return r;
                   1366: }
                   1367: 
1.1.1.2   root     1368: static void dec_fpu(DisasContext *dc)
                   1369: {
1.1.1.4   root     1370:     unsigned int fpu_insn;
                   1371: 
1.1.1.2   root     1372:     if ((dc->tb_flags & MSR_EE_FLAG)
                   1373:           && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
                   1374:           && !((dc->env->pvr.regs[2] & PVR2_USE_FPU_MASK))) {
1.1.1.4   root     1375:         tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
1.1.1.2   root     1376:         t_gen_raise_exception(dc, EXCP_HW_EXCP);
                   1377:         return;
                   1378:     }
                   1379: 
1.1.1.4   root     1380:     fpu_insn = (dc->ir >> 7) & 7;
                   1381: 
                   1382:     switch (fpu_insn) {
                   1383:         case 0:
                   1384:             gen_helper_fadd(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                   1385:             break;
                   1386: 
                   1387:         case 1:
                   1388:             gen_helper_frsub(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                   1389:             break;
                   1390: 
                   1391:         case 2:
                   1392:             gen_helper_fmul(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                   1393:             break;
                   1394: 
                   1395:         case 3:
                   1396:             gen_helper_fdiv(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                   1397:             break;
                   1398: 
                   1399:         case 4:
                   1400:             switch ((dc->ir >> 4) & 7) {
                   1401:                 case 0:
                   1402:                     gen_helper_fcmp_un(cpu_R[dc->rd],
                   1403:                                        cpu_R[dc->ra], cpu_R[dc->rb]);
                   1404:                     break;
                   1405:                 case 1:
                   1406:                     gen_helper_fcmp_lt(cpu_R[dc->rd],
                   1407:                                        cpu_R[dc->ra], cpu_R[dc->rb]);
                   1408:                     break;
                   1409:                 case 2:
                   1410:                     gen_helper_fcmp_eq(cpu_R[dc->rd],
                   1411:                                        cpu_R[dc->ra], cpu_R[dc->rb]);
                   1412:                     break;
                   1413:                 case 3:
                   1414:                     gen_helper_fcmp_le(cpu_R[dc->rd],
                   1415:                                        cpu_R[dc->ra], cpu_R[dc->rb]);
                   1416:                     break;
                   1417:                 case 4:
                   1418:                     gen_helper_fcmp_gt(cpu_R[dc->rd],
                   1419:                                        cpu_R[dc->ra], cpu_R[dc->rb]);
                   1420:                     break;
                   1421:                 case 5:
                   1422:                     gen_helper_fcmp_ne(cpu_R[dc->rd],
                   1423:                                        cpu_R[dc->ra], cpu_R[dc->rb]);
                   1424:                     break;
                   1425:                 case 6:
                   1426:                     gen_helper_fcmp_ge(cpu_R[dc->rd],
                   1427:                                        cpu_R[dc->ra], cpu_R[dc->rb]);
                   1428:                     break;
                   1429:                 default:
                   1430:                     qemu_log ("unimplemented fcmp fpu_insn=%x pc=%x opc=%x\n",
                   1431:                               fpu_insn, dc->pc, dc->opcode);
                   1432:                     dc->abort_at_next_insn = 1;
                   1433:                     break;
                   1434:             }
                   1435:             break;
                   1436: 
                   1437:         case 5:
                   1438:             if (!dec_check_fpuv2(dc)) {
                   1439:                 return;
                   1440:             }
                   1441:             gen_helper_flt(cpu_R[dc->rd], cpu_R[dc->ra]);
                   1442:             break;
                   1443: 
                   1444:         case 6:
                   1445:             if (!dec_check_fpuv2(dc)) {
                   1446:                 return;
                   1447:             }
                   1448:             gen_helper_fint(cpu_R[dc->rd], cpu_R[dc->ra]);
                   1449:             break;
                   1450: 
                   1451:         case 7:
                   1452:             if (!dec_check_fpuv2(dc)) {
                   1453:                 return;
                   1454:             }
                   1455:             gen_helper_fsqrt(cpu_R[dc->rd], cpu_R[dc->ra]);
                   1456:             break;
                   1457: 
                   1458:         default:
                   1459:             qemu_log ("unimplemented FPU insn fpu_insn=%x pc=%x opc=%x\n",
                   1460:                       fpu_insn, dc->pc, dc->opcode);
                   1461:             dc->abort_at_next_insn = 1;
                   1462:             break;
                   1463:     }
1.1.1.2   root     1464: }
                   1465: 
1.1       root     1466: static void dec_null(DisasContext *dc)
                   1467: {
1.1.1.2   root     1468:     if ((dc->tb_flags & MSR_EE_FLAG)
                   1469:           && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
                   1470:         tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
                   1471:         t_gen_raise_exception(dc, EXCP_HW_EXCP);
                   1472:         return;
                   1473:     }
1.1       root     1474:     qemu_log ("unknown insn pc=%x opc=%x\n", dc->pc, dc->opcode);
                   1475:     dc->abort_at_next_insn = 1;
                   1476: }
                   1477: 
1.1.1.5 ! root     1478: /* Insns connected to FSL or AXI stream attached devices.  */
        !          1479: static void dec_stream(DisasContext *dc)
        !          1480: {
        !          1481:     int mem_index = cpu_mmu_index(dc->env);
        !          1482:     TCGv_i32 t_id, t_ctrl;
        !          1483:     int ctrl;
        !          1484: 
        !          1485:     LOG_DIS("%s%s imm=%x\n", dc->rd ? "get" : "put",
        !          1486:             dc->type_b ? "" : "d", dc->imm);
        !          1487: 
        !          1488:     if ((dc->tb_flags & MSR_EE_FLAG) && (mem_index == MMU_USER_IDX)) {
        !          1489:         tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
        !          1490:         t_gen_raise_exception(dc, EXCP_HW_EXCP);
        !          1491:         return;
        !          1492:     }
        !          1493: 
        !          1494:     t_id = tcg_temp_new();
        !          1495:     if (dc->type_b) {
        !          1496:         tcg_gen_movi_tl(t_id, dc->imm & 0xf);
        !          1497:         ctrl = dc->imm >> 10;
        !          1498:     } else {
        !          1499:         tcg_gen_andi_tl(t_id, cpu_R[dc->rb], 0xf);
        !          1500:         ctrl = dc->imm >> 5;
        !          1501:     }
        !          1502: 
        !          1503:     t_ctrl = tcg_const_tl(ctrl);
        !          1504: 
        !          1505:     if (dc->rd == 0) {
        !          1506:         gen_helper_put(t_id, t_ctrl, cpu_R[dc->ra]);
        !          1507:     } else {
        !          1508:         gen_helper_get(cpu_R[dc->rd], t_id, t_ctrl);
        !          1509:     }
        !          1510:     tcg_temp_free(t_id);
        !          1511:     tcg_temp_free(t_ctrl);
        !          1512: }
        !          1513: 
1.1       root     1514: static struct decoder_info {
                   1515:     struct {
                   1516:         uint32_t bits;
                   1517:         uint32_t mask;
                   1518:     };
                   1519:     void (*dec)(DisasContext *dc);
                   1520: } decinfo[] = {
                   1521:     {DEC_ADD, dec_add},
                   1522:     {DEC_SUB, dec_sub},
                   1523:     {DEC_AND, dec_and},
                   1524:     {DEC_XOR, dec_xor},
                   1525:     {DEC_OR, dec_or},
                   1526:     {DEC_BIT, dec_bit},
                   1527:     {DEC_BARREL, dec_barrel},
                   1528:     {DEC_LD, dec_load},
                   1529:     {DEC_ST, dec_store},
                   1530:     {DEC_IMM, dec_imm},
                   1531:     {DEC_BR, dec_br},
                   1532:     {DEC_BCC, dec_bcc},
                   1533:     {DEC_RTS, dec_rts},
1.1.1.2   root     1534:     {DEC_FPU, dec_fpu},
1.1       root     1535:     {DEC_MUL, dec_mul},
                   1536:     {DEC_DIV, dec_div},
                   1537:     {DEC_MSR, dec_msr},
1.1.1.5 ! root     1538:     {DEC_STREAM, dec_stream},
1.1       root     1539:     {{0, 0}, dec_null}
                   1540: };
                   1541: 
                   1542: static inline void decode(DisasContext *dc)
                   1543: {
                   1544:     uint32_t ir;
                   1545:     int i;
                   1546: 
                   1547:     if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
                   1548:         tcg_gen_debug_insn_start(dc->pc);
                   1549: 
                   1550:     dc->ir = ir = ldl_code(dc->pc);
                   1551:     LOG_DIS("%8.8x\t", dc->ir);
                   1552: 
                   1553:     if (dc->ir)
                   1554:         dc->nr_nops = 0;
                   1555:     else {
1.1.1.2   root     1556:         if ((dc->tb_flags & MSR_EE_FLAG)
                   1557:               && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
                   1558:               && (dc->env->pvr.regs[2] & PVR2_OPCODE_0x0_ILL_MASK)) {
                   1559:             tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
                   1560:             t_gen_raise_exception(dc, EXCP_HW_EXCP);
                   1561:             return;
                   1562:         }
                   1563: 
1.1       root     1564:         LOG_DIS("nr_nops=%d\t", dc->nr_nops);
                   1565:         dc->nr_nops++;
                   1566:         if (dc->nr_nops > 4)
                   1567:             cpu_abort(dc->env, "fetching nop sequence\n");
                   1568:     }
                   1569:     /* bit 2 seems to indicate insn type.  */
                   1570:     dc->type_b = ir & (1 << 29);
                   1571: 
                   1572:     dc->opcode = EXTRACT_FIELD(ir, 26, 31);
                   1573:     dc->rd = EXTRACT_FIELD(ir, 21, 25);
                   1574:     dc->ra = EXTRACT_FIELD(ir, 16, 20);
                   1575:     dc->rb = EXTRACT_FIELD(ir, 11, 15);
                   1576:     dc->imm = EXTRACT_FIELD(ir, 0, 15);
                   1577: 
                   1578:     /* Large switch for all insns.  */
                   1579:     for (i = 0; i < ARRAY_SIZE(decinfo); i++) {
                   1580:         if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) {
                   1581:             decinfo[i].dec(dc);
                   1582:             break;
                   1583:         }
                   1584:     }
                   1585: }
                   1586: 
                   1587: static void check_breakpoint(CPUState *env, DisasContext *dc)
                   1588: {
                   1589:     CPUBreakpoint *bp;
                   1590: 
1.1.1.2   root     1591:     if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
                   1592:         QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1.1       root     1593:             if (bp->pc == dc->pc) {
                   1594:                 t_gen_raise_exception(dc, EXCP_DEBUG);
                   1595:                 dc->is_jmp = DISAS_UPDATE;
                   1596:              }
                   1597:         }
                   1598:     }
                   1599: }
                   1600: 
                   1601: /* generate intermediate code for basic block 'tb'.  */
                   1602: static void
                   1603: gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
                   1604:                                int search_pc)
                   1605: {
                   1606:     uint16_t *gen_opc_end;
                   1607:     uint32_t pc_start;
                   1608:     int j, lj;
                   1609:     struct DisasContext ctx;
                   1610:     struct DisasContext *dc = &ctx;
                   1611:     uint32_t next_page_start, org_flags;
                   1612:     target_ulong npc;
                   1613:     int num_insns;
                   1614:     int max_insns;
                   1615: 
                   1616:     qemu_log_try_set_file(stderr);
                   1617: 
                   1618:     pc_start = tb->pc;
                   1619:     dc->env = env;
                   1620:     dc->tb = tb;
                   1621:     org_flags = dc->synced_flags = dc->tb_flags = tb->flags;
                   1622: 
                   1623:     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
                   1624: 
                   1625:     dc->is_jmp = DISAS_NEXT;
                   1626:     dc->jmp = 0;
                   1627:     dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
1.1.1.4   root     1628:     if (dc->delayed_branch) {
                   1629:         dc->jmp = JMP_INDIRECT;
                   1630:     }
1.1       root     1631:     dc->pc = pc_start;
                   1632:     dc->singlestep_enabled = env->singlestep_enabled;
                   1633:     dc->cpustate_changed = 0;
                   1634:     dc->abort_at_next_insn = 0;
                   1635:     dc->nr_nops = 0;
                   1636: 
                   1637:     if (pc_start & 3)
                   1638:         cpu_abort(env, "Microblaze: unaligned PC=%x\n", pc_start);
                   1639: 
                   1640:     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
                   1641: #if !SIM_COMPAT
                   1642:         qemu_log("--------------\n");
                   1643:         log_cpu_state(env, 0);
                   1644: #endif
                   1645:     }
                   1646: 
                   1647:     next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
                   1648:     lj = -1;
                   1649:     num_insns = 0;
                   1650:     max_insns = tb->cflags & CF_COUNT_MASK;
                   1651:     if (max_insns == 0)
                   1652:         max_insns = CF_COUNT_MASK;
                   1653: 
                   1654:     gen_icount_start();
                   1655:     do
                   1656:     {
                   1657: #if SIM_COMPAT
                   1658:         if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
                   1659:             tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
                   1660:             gen_helper_debug();
                   1661:         }
                   1662: #endif
                   1663:         check_breakpoint(env, dc);
                   1664: 
                   1665:         if (search_pc) {
                   1666:             j = gen_opc_ptr - gen_opc_buf;
                   1667:             if (lj < j) {
                   1668:                 lj++;
                   1669:                 while (lj < j)
                   1670:                     gen_opc_instr_start[lj++] = 0;
                   1671:             }
                   1672:             gen_opc_pc[lj] = dc->pc;
                   1673:             gen_opc_instr_start[lj] = 1;
                   1674:                         gen_opc_icount[lj] = num_insns;
                   1675:         }
                   1676: 
                   1677:         /* Pretty disas.  */
                   1678:         LOG_DIS("%8.8x:\t", dc->pc);
                   1679: 
                   1680:         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
                   1681:             gen_io_start();
                   1682: 
                   1683:         dc->clear_imm = 1;
                   1684:        decode(dc);
                   1685:         if (dc->clear_imm)
                   1686:             dc->tb_flags &= ~IMM_FLAG;
                   1687:         dc->pc += 4;
                   1688:         num_insns++;
                   1689: 
                   1690:         if (dc->delayed_branch) {
                   1691:             dc->delayed_branch--;
                   1692:             if (!dc->delayed_branch) {
                   1693:                 if (dc->tb_flags & DRTI_FLAG)
                   1694:                     do_rti(dc);
                   1695:                  if (dc->tb_flags & DRTB_FLAG)
                   1696:                     do_rtb(dc);
                   1697:                 if (dc->tb_flags & DRTE_FLAG)
                   1698:                     do_rte(dc);
                   1699:                 /* Clear the delay slot flag.  */
                   1700:                 dc->tb_flags &= ~D_FLAG;
                   1701:                 /* If it is a direct jump, try direct chaining.  */
1.1.1.4   root     1702:                 if (dc->jmp == JMP_INDIRECT) {
1.1       root     1703:                     eval_cond_jmp(dc, env_btarget, tcg_const_tl(dc->pc));
                   1704:                     dc->is_jmp = DISAS_JUMP;
1.1.1.4   root     1705:                 } else if (dc->jmp == JMP_DIRECT) {
                   1706:                     t_sync_flags(dc);
                   1707:                     gen_goto_tb(dc, 0, dc->jmp_pc);
                   1708:                     dc->is_jmp = DISAS_TB_JUMP;
                   1709:                 } else if (dc->jmp == JMP_DIRECT_CC) {
                   1710:                     int l1;
                   1711: 
                   1712:                     t_sync_flags(dc);
                   1713:                     l1 = gen_new_label();
                   1714:                     /* Conditional jmp.  */
                   1715:                     tcg_gen_brcondi_tl(TCG_COND_NE, env_btaken, 0, l1);
                   1716:                     gen_goto_tb(dc, 1, dc->pc);
                   1717:                     gen_set_label(l1);
                   1718:                     gen_goto_tb(dc, 0, dc->jmp_pc);
                   1719: 
                   1720:                     dc->is_jmp = DISAS_TB_JUMP;
1.1       root     1721:                 }
                   1722:                 break;
                   1723:             }
                   1724:         }
                   1725:         if (env->singlestep_enabled)
                   1726:             break;
                   1727:     } while (!dc->is_jmp && !dc->cpustate_changed
                   1728:          && gen_opc_ptr < gen_opc_end
                   1729:                  && !singlestep
                   1730:          && (dc->pc < next_page_start)
                   1731:                  && num_insns < max_insns);
                   1732: 
                   1733:     npc = dc->pc;
1.1.1.4   root     1734:     if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
1.1       root     1735:         if (dc->tb_flags & D_FLAG) {
                   1736:             dc->is_jmp = DISAS_UPDATE;
                   1737:             tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
                   1738:             sync_jmpstate(dc);
                   1739:         } else
                   1740:             npc = dc->jmp_pc;
                   1741:     }
                   1742: 
                   1743:     if (tb->cflags & CF_LAST_IO)
                   1744:         gen_io_end();
                   1745:     /* Force an update if the per-tb cpu state has changed.  */
                   1746:     if (dc->is_jmp == DISAS_NEXT
                   1747:         && (dc->cpustate_changed || org_flags != dc->tb_flags)) {
                   1748:         dc->is_jmp = DISAS_UPDATE;
                   1749:         tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
                   1750:     }
                   1751:     t_sync_flags(dc);
                   1752: 
                   1753:     if (unlikely(env->singlestep_enabled)) {
1.1.1.5 ! root     1754:         TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG);
        !          1755: 
        !          1756:         if (dc->is_jmp != DISAS_JUMP) {
1.1       root     1757:             tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
1.1.1.5 ! root     1758:         }
        !          1759:         gen_helper_raise_exception(tmp);
        !          1760:         tcg_temp_free_i32(tmp);
1.1       root     1761:     } else {
                   1762:         switch(dc->is_jmp) {
                   1763:             case DISAS_NEXT:
                   1764:                 gen_goto_tb(dc, 1, npc);
                   1765:                 break;
                   1766:             default:
                   1767:             case DISAS_JUMP:
                   1768:             case DISAS_UPDATE:
                   1769:                 /* indicate that the hash table must be used
                   1770:                    to find the next TB */
                   1771:                 tcg_gen_exit_tb(0);
                   1772:                 break;
                   1773:             case DISAS_TB_JUMP:
                   1774:                 /* nothing more to generate */
                   1775:                 break;
                   1776:         }
                   1777:     }
                   1778:     gen_icount_end(tb, num_insns);
                   1779:     *gen_opc_ptr = INDEX_op_end;
                   1780:     if (search_pc) {
                   1781:         j = gen_opc_ptr - gen_opc_buf;
                   1782:         lj++;
                   1783:         while (lj <= j)
                   1784:             gen_opc_instr_start[lj++] = 0;
                   1785:     } else {
                   1786:         tb->size = dc->pc - pc_start;
                   1787:                 tb->icount = num_insns;
                   1788:     }
                   1789: 
                   1790: #ifdef DEBUG_DISAS
                   1791: #if !SIM_COMPAT
                   1792:     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
                   1793:         qemu_log("\n");
                   1794: #if DISAS_GNU
                   1795:         log_target_disas(pc_start, dc->pc - pc_start, 0);
                   1796: #endif
1.1.1.4   root     1797:         qemu_log("\nisize=%d osize=%td\n",
1.1       root     1798:             dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
                   1799:     }
                   1800: #endif
                   1801: #endif
                   1802:     assert(!dc->abort_at_next_insn);
                   1803: }
                   1804: 
                   1805: void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
                   1806: {
                   1807:     gen_intermediate_code_internal(env, tb, 0);
                   1808: }
                   1809: 
                   1810: void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
                   1811: {
                   1812:     gen_intermediate_code_internal(env, tb, 1);
                   1813: }
                   1814: 
1.1.1.4   root     1815: void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
1.1       root     1816:                      int flags)
                   1817: {
                   1818:     int i;
                   1819: 
                   1820:     if (!env || !f)
                   1821:         return;
                   1822: 
                   1823:     cpu_fprintf(f, "IN: PC=%x %s\n",
                   1824:                 env->sregs[SR_PC], lookup_symbol(env->sregs[SR_PC]));
1.1.1.4   root     1825:     cpu_fprintf(f, "rmsr=%x resr=%x rear=%x debug=%x imm=%x iflags=%x fsr=%x\n",
1.1.1.3   root     1826:              env->sregs[SR_MSR], env->sregs[SR_ESR], env->sregs[SR_EAR],
1.1.1.4   root     1827:              env->debug, env->imm, env->iflags, env->sregs[SR_FSR]);
1.1.1.3   root     1828:     cpu_fprintf(f, "btaken=%d btarget=%x mode=%s(saved=%s) eip=%d ie=%d\n",
1.1       root     1829:              env->btaken, env->btarget,
                   1830:              (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel",
1.1.1.3   root     1831:              (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel",
                   1832:              (env->sregs[SR_MSR] & MSR_EIP),
                   1833:              (env->sregs[SR_MSR] & MSR_IE));
                   1834: 
1.1       root     1835:     for (i = 0; i < 32; i++) {
                   1836:         cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
                   1837:         if ((i + 1) % 4 == 0)
                   1838:             cpu_fprintf(f, "\n");
                   1839:         }
                   1840:     cpu_fprintf(f, "\n\n");
                   1841: }
                   1842: 
                   1843: CPUState *cpu_mb_init (const char *cpu_model)
                   1844: {
                   1845:     CPUState *env;
                   1846:     static int tcg_initialized = 0;
                   1847:     int i;
                   1848: 
                   1849:     env = qemu_mallocz(sizeof(CPUState));
                   1850: 
                   1851:     cpu_exec_init(env);
                   1852:     cpu_reset(env);
1.1.1.4   root     1853:     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1.1       root     1854: 
                   1855:     if (tcg_initialized)
                   1856:         return env;
                   1857: 
                   1858:     tcg_initialized = 1;
                   1859: 
                   1860:     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
                   1861: 
                   1862:     env_debug = tcg_global_mem_new(TCG_AREG0, 
                   1863:                     offsetof(CPUState, debug),
                   1864:                     "debug0");
                   1865:     env_iflags = tcg_global_mem_new(TCG_AREG0, 
                   1866:                     offsetof(CPUState, iflags),
                   1867:                     "iflags");
                   1868:     env_imm = tcg_global_mem_new(TCG_AREG0, 
                   1869:                     offsetof(CPUState, imm),
                   1870:                     "imm");
                   1871:     env_btarget = tcg_global_mem_new(TCG_AREG0,
                   1872:                      offsetof(CPUState, btarget),
                   1873:                      "btarget");
                   1874:     env_btaken = tcg_global_mem_new(TCG_AREG0,
                   1875:                      offsetof(CPUState, btaken),
                   1876:                      "btaken");
                   1877:     for (i = 0; i < ARRAY_SIZE(cpu_R); i++) {
                   1878:         cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
                   1879:                           offsetof(CPUState, regs[i]),
                   1880:                           regnames[i]);
                   1881:     }
                   1882:     for (i = 0; i < ARRAY_SIZE(cpu_SR); i++) {
                   1883:         cpu_SR[i] = tcg_global_mem_new(TCG_AREG0,
                   1884:                           offsetof(CPUState, sregs[i]),
                   1885:                           special_regnames[i]);
                   1886:     }
                   1887: #define GEN_HELPER 2
                   1888: #include "helper.h"
                   1889: 
                   1890:     return env;
                   1891: }
                   1892: 
                   1893: void cpu_reset (CPUState *env)
                   1894: {
                   1895:     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
                   1896:         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
                   1897:         log_cpu_state(env, 0);
                   1898:     }
                   1899: 
                   1900:     memset(env, 0, offsetof(CPUMBState, breakpoints));
                   1901:     tlb_flush(env, 1);
                   1902: 
1.1.1.2   root     1903:     env->pvr.regs[0] = PVR0_PVR_FULL_MASK \
                   1904:                        | PVR0_USE_BARREL_MASK \
                   1905:                        | PVR0_USE_DIV_MASK \
                   1906:                        | PVR0_USE_HW_MUL_MASK \
                   1907:                        | PVR0_USE_EXC_MASK \
                   1908:                        | PVR0_USE_ICACHE_MASK \
                   1909:                        | PVR0_USE_DCACHE_MASK \
                   1910:                        | PVR0_USE_MMU \
                   1911:                        | (0xb << 8);
                   1912:     env->pvr.regs[2] = PVR2_D_OPB_MASK \
                   1913:                         | PVR2_D_LMB_MASK \
                   1914:                         | PVR2_I_OPB_MASK \
                   1915:                         | PVR2_I_LMB_MASK \
                   1916:                         | PVR2_USE_MSR_INSTR \
                   1917:                         | PVR2_USE_PCMP_INSTR \
                   1918:                         | PVR2_USE_BARREL_MASK \
                   1919:                         | PVR2_USE_DIV_MASK \
                   1920:                         | PVR2_USE_HW_MUL_MASK \
                   1921:                         | PVR2_USE_MUL64_MASK \
1.1.1.4   root     1922:                         | PVR2_USE_FPU_MASK \
                   1923:                         | PVR2_USE_FPU2_MASK \
                   1924:                         | PVR2_FPU_EXC_MASK \
1.1.1.2   root     1925:                         | 0;
                   1926:     env->pvr.regs[10] = 0x0c000000; /* Default to spartan 3a dsp family.  */
                   1927:     env->pvr.regs[11] = PVR11_USE_MMU | (16 << 17);
                   1928: 
1.1       root     1929: #if defined(CONFIG_USER_ONLY)
                   1930:     /* start in user mode with interrupts enabled.  */
1.1.1.4   root     1931:     env->sregs[SR_MSR] = MSR_EE | MSR_IE | MSR_VM | MSR_UM;
1.1       root     1932:     env->pvr.regs[10] = 0x0c000000; /* Spartan 3a dsp.  */
                   1933: #else
1.1.1.4   root     1934:     env->sregs[SR_MSR] = 0;
1.1       root     1935:     mmu_init(&env->mmu);
1.1.1.2   root     1936:     env->mmu.c_mmu = 3;
                   1937:     env->mmu.c_mmu_tlb_access = 3;
                   1938:     env->mmu.c_mmu_zones = 16;
1.1       root     1939: #endif
                   1940: }
                   1941: 
1.1.1.5 ! root     1942: void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
1.1       root     1943: {
                   1944:     env->sregs[SR_PC] = gen_opc_pc[pc_pos];
                   1945: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.