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

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: {
1.1.1.6 ! root      427:     TCGv t;
        !           428: 
        !           429:     t = tcg_temp_new();
1.1       root      430:     dc->cpustate_changed = 1;
1.1.1.6 ! root      431:     /* PVR bit is not writable.  */
        !           432:     tcg_gen_andi_tl(t, v, ~MSR_PVR);
        !           433:     tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], MSR_PVR);
        !           434:     tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], v);
        !           435:     tcg_temp_free(t);
1.1       root      436: }
                    437: 
                    438: static void dec_msr(DisasContext *dc)
                    439: {
                    440:     TCGv t0, t1;
                    441:     unsigned int sr, to, rn;
1.1.1.2   root      442:     int mem_index = cpu_mmu_index(dc->env);
1.1       root      443: 
                    444:     sr = dc->imm & ((1 << 14) - 1);
                    445:     to = dc->imm & (1 << 14);
                    446:     dc->type_b = 1;
                    447:     if (to)
                    448:         dc->cpustate_changed = 1;
                    449: 
                    450:     /* msrclr and msrset.  */
                    451:     if (!(dc->imm & (1 << 15))) {
                    452:         unsigned int clr = dc->ir & (1 << 16);
                    453: 
                    454:         LOG_DIS("msr%s r%d imm=%x\n", clr ? "clr" : "set",
                    455:                 dc->rd, dc->imm);
1.1.1.2   root      456: 
                    457:         if (!(dc->env->pvr.regs[2] & PVR2_USE_MSR_INSTR)) {
                    458:             /* nop??? */
                    459:             return;
                    460:         }
                    461: 
                    462:         if ((dc->tb_flags & MSR_EE_FLAG)
                    463:             && mem_index == MMU_USER_IDX && (dc->imm != 4 && dc->imm != 0)) {
                    464:             tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
                    465:             t_gen_raise_exception(dc, EXCP_HW_EXCP);
                    466:             return;
                    467:         }
                    468: 
1.1       root      469:         if (dc->rd)
                    470:             msr_read(dc, cpu_R[dc->rd]);
                    471: 
                    472:         t0 = tcg_temp_new();
                    473:         t1 = tcg_temp_new();
                    474:         msr_read(dc, t0);
                    475:         tcg_gen_mov_tl(t1, *(dec_alu_op_b(dc)));
                    476: 
                    477:         if (clr) {
                    478:             tcg_gen_not_tl(t1, t1);
                    479:             tcg_gen_and_tl(t0, t0, t1);
                    480:         } else
                    481:             tcg_gen_or_tl(t0, t0, t1);
                    482:         msr_write(dc, t0);
                    483:         tcg_temp_free(t0);
                    484:         tcg_temp_free(t1);
                    485:        tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc + 4);
                    486:         dc->is_jmp = DISAS_UPDATE;
                    487:         return;
                    488:     }
                    489: 
1.1.1.2   root      490:     if (to) {
                    491:         if ((dc->tb_flags & MSR_EE_FLAG)
                    492:              && mem_index == MMU_USER_IDX) {
                    493:             tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
                    494:             t_gen_raise_exception(dc, EXCP_HW_EXCP);
                    495:             return;
                    496:         }
                    497:     }
                    498: 
1.1       root      499: #if !defined(CONFIG_USER_ONLY)
                    500:     /* Catch read/writes to the mmu block.  */
                    501:     if ((sr & ~0xff) == 0x1000) {
                    502:         sr &= 7;
                    503:         LOG_DIS("m%ss sr%d r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm);
                    504:         if (to)
                    505:             gen_helper_mmu_write(tcg_const_tl(sr), cpu_R[dc->ra]);
                    506:         else
                    507:             gen_helper_mmu_read(cpu_R[dc->rd], tcg_const_tl(sr));
                    508:         return;
                    509:     }
                    510: #endif
                    511: 
                    512:     if (to) {
                    513:         LOG_DIS("m%ss sr%x r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm);
                    514:         switch (sr) {
                    515:             case 0:
                    516:                 break;
                    517:             case 1:
                    518:                 msr_write(dc, cpu_R[dc->ra]);
                    519:                 break;
                    520:             case 0x3:
                    521:                 tcg_gen_mov_tl(cpu_SR[SR_EAR], cpu_R[dc->ra]);
                    522:                 break;
                    523:             case 0x5:
                    524:                 tcg_gen_mov_tl(cpu_SR[SR_ESR], cpu_R[dc->ra]);
                    525:                 break;
                    526:             case 0x7:
1.1.1.4   root      527:                 tcg_gen_andi_tl(cpu_SR[SR_FSR], cpu_R[dc->ra], 31);
1.1       root      528:                 break;
                    529:             default:
                    530:                 cpu_abort(dc->env, "unknown mts reg %x\n", sr);
                    531:                 break;
                    532:         }
                    533:     } else {
                    534:         LOG_DIS("m%ss r%d sr%x imm=%x\n", to ? "t" : "f", dc->rd, sr, dc->imm);
                    535: 
                    536:         switch (sr) {
                    537:             case 0:
                    538:                 tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc);
                    539:                 break;
                    540:             case 1:
                    541:                 msr_read(dc, cpu_R[dc->rd]);
                    542:                 break;
                    543:             case 0x3:
                    544:                 tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_EAR]);
                    545:                 break;
                    546:             case 0x5:
                    547:                 tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_ESR]);
                    548:                 break;
                    549:              case 0x7:
1.1.1.4   root      550:                 tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_FSR]);
1.1       root      551:                 break;
                    552:             case 0xb:
                    553:                 tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_BTR]);
                    554:                 break;
                    555:             case 0x2000:
                    556:             case 0x2001:
                    557:             case 0x2002:
                    558:             case 0x2003:
                    559:             case 0x2004:
                    560:             case 0x2005:
                    561:             case 0x2006:
                    562:             case 0x2007:
                    563:             case 0x2008:
                    564:             case 0x2009:
                    565:             case 0x200a:
                    566:             case 0x200b:
                    567:             case 0x200c:
                    568:                 rn = sr & 0xf;
                    569:                 tcg_gen_ld_tl(cpu_R[dc->rd],
                    570:                               cpu_env, offsetof(CPUState, pvr.regs[rn]));
                    571:                 break;
                    572:             default:
                    573:                 cpu_abort(dc->env, "unknown mfs reg %x\n", sr);
                    574:                 break;
                    575:         }
                    576:     }
1.1.1.2   root      577: 
                    578:     if (dc->rd == 0) {
                    579:         tcg_gen_movi_tl(cpu_R[0], 0);
                    580:     }
1.1       root      581: }
                    582: 
                    583: /* 64-bit signed mul, lower result in d and upper in d2.  */
                    584: static void t_gen_muls(TCGv d, TCGv d2, TCGv a, TCGv b)
                    585: {
                    586:     TCGv_i64 t0, t1;
                    587: 
                    588:     t0 = tcg_temp_new_i64();
                    589:     t1 = tcg_temp_new_i64();
                    590: 
                    591:     tcg_gen_ext_i32_i64(t0, a);
                    592:     tcg_gen_ext_i32_i64(t1, b);
                    593:     tcg_gen_mul_i64(t0, t0, t1);
                    594: 
                    595:     tcg_gen_trunc_i64_i32(d, t0);
                    596:     tcg_gen_shri_i64(t0, t0, 32);
                    597:     tcg_gen_trunc_i64_i32(d2, t0);
                    598: 
                    599:     tcg_temp_free_i64(t0);
                    600:     tcg_temp_free_i64(t1);
                    601: }
                    602: 
                    603: /* 64-bit unsigned muls, lower result in d and upper in d2.  */
                    604: static void t_gen_mulu(TCGv d, TCGv d2, TCGv a, TCGv b)
                    605: {
                    606:     TCGv_i64 t0, t1;
                    607: 
                    608:     t0 = tcg_temp_new_i64();
                    609:     t1 = tcg_temp_new_i64();
                    610: 
                    611:     tcg_gen_extu_i32_i64(t0, a);
                    612:     tcg_gen_extu_i32_i64(t1, b);
                    613:     tcg_gen_mul_i64(t0, t0, t1);
                    614: 
                    615:     tcg_gen_trunc_i64_i32(d, t0);
                    616:     tcg_gen_shri_i64(t0, t0, 32);
                    617:     tcg_gen_trunc_i64_i32(d2, t0);
                    618: 
                    619:     tcg_temp_free_i64(t0);
                    620:     tcg_temp_free_i64(t1);
                    621: }
                    622: 
                    623: /* Multiplier unit.  */
                    624: static void dec_mul(DisasContext *dc)
                    625: {
                    626:     TCGv d[2];
                    627:     unsigned int subcode;
                    628: 
1.1.1.2   root      629:     if ((dc->tb_flags & MSR_EE_FLAG)
                    630:          && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
                    631:          && !(dc->env->pvr.regs[0] & PVR0_USE_HW_MUL_MASK)) {
                    632:         tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
                    633:         t_gen_raise_exception(dc, EXCP_HW_EXCP);
                    634:         return;
                    635:     }
                    636: 
1.1       root      637:     subcode = dc->imm & 3;
                    638:     d[0] = tcg_temp_new();
                    639:     d[1] = tcg_temp_new();
                    640: 
                    641:     if (dc->type_b) {
                    642:         LOG_DIS("muli r%d r%d %x\n", dc->rd, dc->ra, dc->imm);
                    643:         t_gen_mulu(cpu_R[dc->rd], d[1], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
                    644:         goto done;
                    645:     }
                    646: 
1.1.1.2   root      647:     /* mulh, mulhsu and mulhu are not available if C_USE_HW_MUL is < 2.  */
                    648:     if (subcode >= 1 && subcode <= 3
                    649:         && !((dc->env->pvr.regs[2] & PVR2_USE_MUL64_MASK))) {
                    650:         /* nop??? */
                    651:     }
                    652: 
1.1       root      653:     switch (subcode) {
                    654:         case 0:
                    655:             LOG_DIS("mul r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
                    656:             t_gen_mulu(cpu_R[dc->rd], d[1], cpu_R[dc->ra], cpu_R[dc->rb]);
                    657:             break;
                    658:         case 1:
                    659:             LOG_DIS("mulh r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
                    660:             t_gen_muls(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                    661:             break;
                    662:         case 2:
                    663:             LOG_DIS("mulhsu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
                    664:             t_gen_muls(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                    665:             break;
                    666:         case 3:
                    667:             LOG_DIS("mulhu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
                    668:             t_gen_mulu(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                    669:             break;
                    670:         default:
                    671:             cpu_abort(dc->env, "unknown MUL insn %x\n", subcode);
                    672:             break;
                    673:     }
                    674: done:
                    675:     tcg_temp_free(d[0]);
                    676:     tcg_temp_free(d[1]);
                    677: }
                    678: 
                    679: /* Div unit.  */
                    680: static void dec_div(DisasContext *dc)
                    681: {
                    682:     unsigned int u;
                    683: 
                    684:     u = dc->imm & 2; 
                    685:     LOG_DIS("div\n");
                    686: 
1.1.1.2   root      687:     if ((dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
                    688:           && !((dc->env->pvr.regs[0] & PVR0_USE_DIV_MASK))) {
                    689:         tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
                    690:         t_gen_raise_exception(dc, EXCP_HW_EXCP);
                    691:     }
                    692: 
1.1       root      693:     if (u)
                    694:         gen_helper_divu(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
                    695:     else
                    696:         gen_helper_divs(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
                    697:     if (!dc->rd)
                    698:         tcg_gen_movi_tl(cpu_R[dc->rd], 0);
                    699: }
                    700: 
                    701: static void dec_barrel(DisasContext *dc)
                    702: {
                    703:     TCGv t0;
                    704:     unsigned int s, t;
                    705: 
1.1.1.2   root      706:     if ((dc->tb_flags & MSR_EE_FLAG)
                    707:           && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
                    708:           && !(dc->env->pvr.regs[0] & PVR0_USE_BARREL_MASK)) {
                    709:         tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
                    710:         t_gen_raise_exception(dc, EXCP_HW_EXCP);
                    711:         return;
                    712:     }
                    713: 
1.1       root      714:     s = dc->imm & (1 << 10);
                    715:     t = dc->imm & (1 << 9);
                    716: 
                    717:     LOG_DIS("bs%s%s r%d r%d r%d\n",
                    718:             s ? "l" : "r", t ? "a" : "l", dc->rd, dc->ra, dc->rb);
                    719: 
                    720:     t0 = tcg_temp_new();
                    721: 
                    722:     tcg_gen_mov_tl(t0, *(dec_alu_op_b(dc)));
                    723:     tcg_gen_andi_tl(t0, t0, 31);
                    724: 
                    725:     if (s)
                    726:         tcg_gen_shl_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0);
                    727:     else {
                    728:         if (t)
                    729:             tcg_gen_sar_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0);
                    730:         else
                    731:             tcg_gen_shr_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0);
                    732:     }
                    733: }
                    734: 
                    735: static void dec_bit(DisasContext *dc)
                    736: {
                    737:     TCGv t0, t1;
                    738:     unsigned int op;
1.1.1.2   root      739:     int mem_index = cpu_mmu_index(dc->env);
1.1       root      740: 
                    741:     op = dc->ir & ((1 << 8) - 1);
                    742:     switch (op) {
                    743:         case 0x21:
                    744:             /* src.  */
                    745:             t0 = tcg_temp_new();
                    746: 
                    747:             LOG_DIS("src r%d r%d\n", dc->rd, dc->ra);
                    748:             tcg_gen_andi_tl(t0, cpu_R[dc->ra], 1);
                    749:             if (dc->rd) {
                    750:                 t1 = tcg_temp_new();
                    751:                 read_carry(dc, t1);
                    752:                 tcg_gen_shli_tl(t1, t1, 31);
                    753: 
                    754:                 tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
                    755:                 tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->rd], t1);
                    756:                 tcg_temp_free(t1);
                    757:             }
                    758: 
                    759:             /* Update carry.  */
                    760:             write_carry(dc, t0);
                    761:             tcg_temp_free(t0);
                    762:             break;
                    763: 
                    764:         case 0x1:
                    765:         case 0x41:
                    766:             /* srl.  */
                    767:             t0 = tcg_temp_new();
                    768:             LOG_DIS("srl r%d r%d\n", dc->rd, dc->ra);
                    769: 
                    770:             /* Update carry.  */
                    771:             tcg_gen_andi_tl(t0, cpu_R[dc->ra], 1);
                    772:             write_carry(dc, t0);
                    773:             tcg_temp_free(t0);
                    774:             if (dc->rd) {
                    775:                 if (op == 0x41)
                    776:                     tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
                    777:                 else
                    778:                     tcg_gen_sari_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
                    779:             }
                    780:             break;
                    781:         case 0x60:
                    782:             LOG_DIS("ext8s r%d r%d\n", dc->rd, dc->ra);
                    783:             tcg_gen_ext8s_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
                    784:             break;
                    785:         case 0x61:
                    786:             LOG_DIS("ext16s r%d r%d\n", dc->rd, dc->ra);
                    787:             tcg_gen_ext16s_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
                    788:             break;
                    789:         case 0x64:
1.1.1.3   root      790:         case 0x66:
                    791:         case 0x74:
                    792:         case 0x76:
1.1       root      793:             /* wdc.  */
                    794:             LOG_DIS("wdc r%d\n", dc->ra);
1.1.1.2   root      795:             if ((dc->tb_flags & MSR_EE_FLAG)
                    796:                  && mem_index == MMU_USER_IDX) {
                    797:                 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
                    798:                 t_gen_raise_exception(dc, EXCP_HW_EXCP);
                    799:                 return;
                    800:             }
1.1       root      801:             break;
                    802:         case 0x68:
                    803:             /* wic.  */
                    804:             LOG_DIS("wic r%d\n", dc->ra);
1.1.1.2   root      805:             if ((dc->tb_flags & MSR_EE_FLAG)
                    806:                  && mem_index == MMU_USER_IDX) {
                    807:                 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
                    808:                 t_gen_raise_exception(dc, EXCP_HW_EXCP);
                    809:                 return;
                    810:             }
1.1       root      811:             break;
                    812:         default:
                    813:             cpu_abort(dc->env, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
                    814:                      dc->pc, op, dc->rd, dc->ra, dc->rb);
                    815:             break;
                    816:     }
                    817: }
                    818: 
                    819: static inline void sync_jmpstate(DisasContext *dc)
                    820: {
1.1.1.4   root      821:     if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
                    822:         if (dc->jmp == JMP_DIRECT) {
1.1       root      823:             tcg_gen_movi_tl(env_btaken, 1);
1.1.1.4   root      824:         }
                    825:         dc->jmp = JMP_INDIRECT;
                    826:         tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
1.1       root      827:     }
                    828: }
                    829: 
                    830: static void dec_imm(DisasContext *dc)
                    831: {
                    832:     LOG_DIS("imm %x\n", dc->imm << 16);
                    833:     tcg_gen_movi_tl(env_imm, (dc->imm << 16));
                    834:     dc->tb_flags |= IMM_FLAG;
                    835:     dc->clear_imm = 0;
                    836: }
                    837: 
                    838: static inline void gen_load(DisasContext *dc, TCGv dst, TCGv addr,
                    839:                             unsigned int size)
                    840: {
                    841:     int mem_index = cpu_mmu_index(dc->env);
                    842: 
                    843:     if (size == 1) {
                    844:         tcg_gen_qemu_ld8u(dst, addr, mem_index);
                    845:     } else if (size == 2) {
                    846:         tcg_gen_qemu_ld16u(dst, addr, mem_index);
                    847:     } else if (size == 4) {
                    848:         tcg_gen_qemu_ld32u(dst, addr, mem_index);
                    849:     } else
                    850:         cpu_abort(dc->env, "Incorrect load size %d\n", size);
                    851: }
                    852: 
                    853: static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
                    854: {
                    855:     unsigned int extimm = dc->tb_flags & IMM_FLAG;
                    856: 
1.1.1.4   root      857:     /* Treat the common cases first.  */
1.1       root      858:     if (!dc->type_b) {
1.1.1.3   root      859:         /* If any of the regs is r0, return a ptr to the other.  */
                    860:         if (dc->ra == 0) {
                    861:             return &cpu_R[dc->rb];
                    862:         } else if (dc->rb == 0) {
                    863:             return &cpu_R[dc->ra];
                    864:         }
                    865: 
1.1       root      866:         *t = tcg_temp_new();
                    867:         tcg_gen_add_tl(*t, cpu_R[dc->ra], cpu_R[dc->rb]);
                    868:         return t;
                    869:     }
                    870:     /* Immediate.  */
                    871:     if (!extimm) {
                    872:         if (dc->imm == 0) {
                    873:             return &cpu_R[dc->ra];
                    874:         }
                    875:         *t = tcg_temp_new();
                    876:         tcg_gen_movi_tl(*t, (int32_t)((int16_t)dc->imm));
                    877:         tcg_gen_add_tl(*t, cpu_R[dc->ra], *t);
                    878:     } else {
                    879:         *t = tcg_temp_new();
                    880:         tcg_gen_add_tl(*t, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
                    881:     }
                    882: 
                    883:     return t;
                    884: }
                    885: 
1.1.1.4   root      886: static inline void dec_byteswap(DisasContext *dc, TCGv dst, TCGv src, int size)
                    887: {
                    888:     if (size == 4) {
                    889:         tcg_gen_bswap32_tl(dst, src);
                    890:     } else if (size == 2) {
                    891:         TCGv t = tcg_temp_new();
                    892: 
                    893:         /* bswap16 assumes the high bits are zero.  */
                    894:         tcg_gen_andi_tl(t, src, 0xffff);
                    895:         tcg_gen_bswap16_tl(dst, t);
                    896:         tcg_temp_free(t);
                    897:     } else {
                    898:         /* Ignore.
                    899:         cpu_abort(dc->env, "Invalid ldst byteswap size %d\n", size);
                    900:         */
                    901:     }
                    902: }
                    903: 
1.1       root      904: static void dec_load(DisasContext *dc)
                    905: {
                    906:     TCGv t, *addr;
1.1.1.4   root      907:     unsigned int size, rev = 0;
1.1       root      908: 
                    909:     size = 1 << (dc->opcode & 3);
1.1.1.4   root      910: 
                    911:     if (!dc->type_b) {
                    912:         rev = (dc->ir >> 9) & 1;
                    913:     }
                    914: 
1.1.1.2   root      915:     if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
                    916:           && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
                    917:         tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
                    918:         t_gen_raise_exception(dc, EXCP_HW_EXCP);
                    919:         return;
                    920:     }
1.1       root      921: 
1.1.1.4   root      922:     LOG_DIS("l%d%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "");
                    923: 
1.1       root      924:     t_sync_flags(dc);
                    925:     addr = compute_ldst_addr(dc, &t);
                    926: 
1.1.1.4   root      927:     /*
                    928:      * When doing reverse accesses we need to do two things.
                    929:      *
1.1.1.5   root      930:      * 1. Reverse the address wrt endianness.
1.1.1.4   root      931:      * 2. Byteswap the data lanes on the way back into the CPU core.
                    932:      */
                    933:     if (rev && size != 4) {
                    934:         /* Endian reverse the address. t is addr.  */
                    935:         switch (size) {
                    936:             case 1:
                    937:             {
                    938:                 /* 00 -> 11
                    939:                    01 -> 10
                    940:                    10 -> 10
                    941:                    11 -> 00 */
                    942:                 TCGv low = tcg_temp_new();
                    943: 
                    944:                 /* Force addr into the temp.  */
                    945:                 if (addr != &t) {
                    946:                     t = tcg_temp_new();
                    947:                     tcg_gen_mov_tl(t, *addr);
                    948:                     addr = &t;
                    949:                 }
                    950: 
                    951:                 tcg_gen_andi_tl(low, t, 3);
                    952:                 tcg_gen_sub_tl(low, tcg_const_tl(3), low);
                    953:                 tcg_gen_andi_tl(t, t, ~3);
                    954:                 tcg_gen_or_tl(t, t, low);
                    955:                 tcg_gen_mov_tl(env_imm, t);
                    956:                 tcg_temp_free(low);
                    957:                 break;
                    958:             }
                    959: 
                    960:             case 2:
                    961:                 /* 00 -> 10
                    962:                    10 -> 00.  */
                    963:                 /* Force addr into the temp.  */
                    964:                 if (addr != &t) {
                    965:                     t = tcg_temp_new();
                    966:                     tcg_gen_xori_tl(t, *addr, 2);
                    967:                     addr = &t;
                    968:                 } else {
                    969:                     tcg_gen_xori_tl(t, t, 2);
                    970:                 }
                    971:                 break;
                    972:             default:
                    973:                 cpu_abort(dc->env, "Invalid reverse size\n");
                    974:                 break;
                    975:         }
                    976:     }
                    977: 
1.1       root      978:     /* If we get a fault on a dslot, the jmpstate better be in sync.  */
                    979:     sync_jmpstate(dc);
1.1.1.2   root      980: 
                    981:     /* Verify alignment if needed.  */
                    982:     if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
                    983:         TCGv v = tcg_temp_new();
                    984: 
                    985:         /*
                    986:          * Microblaze gives MMU faults priority over faults due to
                    987:          * unaligned addresses. That's why we speculatively do the load
                    988:          * into v. If the load succeeds, we verify alignment of the
                    989:          * address and if that succeeds we write into the destination reg.
                    990:          */
                    991:         gen_load(dc, v, *addr, size);
                    992: 
                    993:         tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
                    994:         gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
                    995:                             tcg_const_tl(0), tcg_const_tl(size - 1));
1.1.1.4   root      996:         if (dc->rd) {
                    997:             if (rev) {
                    998:                 dec_byteswap(dc, cpu_R[dc->rd], v, size);
                    999:             } else {
                   1000:                 tcg_gen_mov_tl(cpu_R[dc->rd], v);
                   1001:             }
                   1002:         }
1.1.1.2   root     1003:         tcg_temp_free(v);
                   1004:     } else {
                   1005:         if (dc->rd) {
                   1006:             gen_load(dc, cpu_R[dc->rd], *addr, size);
1.1.1.4   root     1007:             if (rev) {
                   1008:                 dec_byteswap(dc, cpu_R[dc->rd], cpu_R[dc->rd], size);
                   1009:             }
1.1.1.2   root     1010:         } else {
1.1.1.4   root     1011:             /* We are loading into r0, no need to reverse.  */
1.1.1.2   root     1012:             gen_load(dc, env_imm, *addr, size);
                   1013:         }
1.1       root     1014:     }
                   1015: 
                   1016:     if (addr == &t)
                   1017:         tcg_temp_free(t);
                   1018: }
                   1019: 
                   1020: static void gen_store(DisasContext *dc, TCGv addr, TCGv val,
                   1021:                       unsigned int size)
                   1022: {
                   1023:     int mem_index = cpu_mmu_index(dc->env);
                   1024: 
                   1025:     if (size == 1)
                   1026:         tcg_gen_qemu_st8(val, addr, mem_index);
                   1027:     else if (size == 2) {
                   1028:         tcg_gen_qemu_st16(val, addr, mem_index);
                   1029:     } else if (size == 4) {
                   1030:         tcg_gen_qemu_st32(val, addr, mem_index);
                   1031:     } else
                   1032:         cpu_abort(dc->env, "Incorrect store size %d\n", size);
                   1033: }
                   1034: 
                   1035: static void dec_store(DisasContext *dc)
                   1036: {
                   1037:     TCGv t, *addr;
1.1.1.4   root     1038:     unsigned int size, rev = 0;
1.1       root     1039: 
                   1040:     size = 1 << (dc->opcode & 3);
1.1.1.4   root     1041:     if (!dc->type_b) {
                   1042:         rev = (dc->ir >> 9) & 1;
                   1043:     }
1.1       root     1044: 
1.1.1.2   root     1045:     if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
                   1046:           && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
                   1047:         tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
                   1048:         t_gen_raise_exception(dc, EXCP_HW_EXCP);
                   1049:         return;
                   1050:     }
                   1051: 
1.1.1.4   root     1052:     LOG_DIS("s%d%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "");
1.1       root     1053:     t_sync_flags(dc);
                   1054:     /* If we get a fault on a dslot, the jmpstate better be in sync.  */
                   1055:     sync_jmpstate(dc);
                   1056:     addr = compute_ldst_addr(dc, &t);
1.1.1.2   root     1057: 
1.1.1.4   root     1058:     if (rev && size != 4) {
                   1059:         /* Endian reverse the address. t is addr.  */
                   1060:         switch (size) {
                   1061:             case 1:
                   1062:             {
                   1063:                 /* 00 -> 11
                   1064:                    01 -> 10
                   1065:                    10 -> 10
                   1066:                    11 -> 00 */
                   1067:                 TCGv low = tcg_temp_new();
                   1068: 
                   1069:                 /* Force addr into the temp.  */
                   1070:                 if (addr != &t) {
                   1071:                     t = tcg_temp_new();
                   1072:                     tcg_gen_mov_tl(t, *addr);
                   1073:                     addr = &t;
                   1074:                 }
                   1075: 
                   1076:                 tcg_gen_andi_tl(low, t, 3);
                   1077:                 tcg_gen_sub_tl(low, tcg_const_tl(3), low);
                   1078:                 tcg_gen_andi_tl(t, t, ~3);
                   1079:                 tcg_gen_or_tl(t, t, low);
                   1080:                 tcg_gen_mov_tl(env_imm, t);
                   1081:                 tcg_temp_free(low);
                   1082:                 break;
                   1083:             }
                   1084: 
                   1085:             case 2:
                   1086:                 /* 00 -> 10
                   1087:                    10 -> 00.  */
                   1088:                 /* Force addr into the temp.  */
                   1089:                 if (addr != &t) {
                   1090:                     t = tcg_temp_new();
                   1091:                     tcg_gen_xori_tl(t, *addr, 2);
                   1092:                     addr = &t;
                   1093:                 } else {
                   1094:                     tcg_gen_xori_tl(t, t, 2);
                   1095:                 }
                   1096:                 break;
                   1097:             default:
                   1098:                 cpu_abort(dc->env, "Invalid reverse size\n");
                   1099:                 break;
                   1100:         }
                   1101: 
                   1102:         if (size != 1) {
                   1103:             TCGv bs_data = tcg_temp_new();
                   1104:             dec_byteswap(dc, bs_data, cpu_R[dc->rd], size);
                   1105:             gen_store(dc, *addr, bs_data, size);
                   1106:             tcg_temp_free(bs_data);
                   1107:         } else {
                   1108:             gen_store(dc, *addr, cpu_R[dc->rd], size);
                   1109:         }
                   1110:     } else {
                   1111:         if (rev) {
                   1112:             TCGv bs_data = tcg_temp_new();
                   1113:             dec_byteswap(dc, bs_data, cpu_R[dc->rd], size);
                   1114:             gen_store(dc, *addr, bs_data, size);
                   1115:             tcg_temp_free(bs_data);
                   1116:         } else {
                   1117:             gen_store(dc, *addr, cpu_R[dc->rd], size);
                   1118:         }
                   1119:     }
1.1.1.2   root     1120: 
                   1121:     /* Verify alignment if needed.  */
                   1122:     if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
                   1123:         tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
                   1124:         /* FIXME: if the alignment is wrong, we should restore the value
1.1.1.4   root     1125:          *        in memory. One possible way to acheive this is to probe
                   1126:          *        the MMU prior to the memaccess, thay way we could put
                   1127:          *        the alignment checks in between the probe and the mem
                   1128:          *        access.
1.1.1.2   root     1129:          */
                   1130:         gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
                   1131:                             tcg_const_tl(1), tcg_const_tl(size - 1));
                   1132:     }
                   1133: 
1.1       root     1134:     if (addr == &t)
                   1135:         tcg_temp_free(t);
                   1136: }
                   1137: 
                   1138: static inline void eval_cc(DisasContext *dc, unsigned int cc,
                   1139:                            TCGv d, TCGv a, TCGv b)
                   1140: {
                   1141:     switch (cc) {
                   1142:         case CC_EQ:
1.1.1.3   root     1143:             tcg_gen_setcond_tl(TCG_COND_EQ, d, a, b);
1.1       root     1144:             break;
                   1145:         case CC_NE:
1.1.1.3   root     1146:             tcg_gen_setcond_tl(TCG_COND_NE, d, a, b);
1.1       root     1147:             break;
                   1148:         case CC_LT:
1.1.1.3   root     1149:             tcg_gen_setcond_tl(TCG_COND_LT, d, a, b);
1.1       root     1150:             break;
                   1151:         case CC_LE:
1.1.1.3   root     1152:             tcg_gen_setcond_tl(TCG_COND_LE, d, a, b);
1.1       root     1153:             break;
                   1154:         case CC_GE:
1.1.1.3   root     1155:             tcg_gen_setcond_tl(TCG_COND_GE, d, a, b);
1.1       root     1156:             break;
                   1157:         case CC_GT:
1.1.1.3   root     1158:             tcg_gen_setcond_tl(TCG_COND_GT, d, a, b);
1.1       root     1159:             break;
                   1160:         default:
                   1161:             cpu_abort(dc->env, "Unknown condition code %x.\n", cc);
                   1162:             break;
                   1163:     }
                   1164: }
                   1165: 
                   1166: static void eval_cond_jmp(DisasContext *dc, TCGv pc_true, TCGv pc_false)
                   1167: {
                   1168:     int l1;
                   1169: 
                   1170:     l1 = gen_new_label();
                   1171:     /* Conditional jmp.  */
                   1172:     tcg_gen_mov_tl(cpu_SR[SR_PC], pc_false);
                   1173:     tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1);
                   1174:     tcg_gen_mov_tl(cpu_SR[SR_PC], pc_true);
                   1175:     gen_set_label(l1);
                   1176: }
                   1177: 
                   1178: static void dec_bcc(DisasContext *dc)
                   1179: {
                   1180:     unsigned int cc;
                   1181:     unsigned int dslot;
                   1182: 
                   1183:     cc = EXTRACT_FIELD(dc->ir, 21, 23);
                   1184:     dslot = dc->ir & (1 << 25);
                   1185:     LOG_DIS("bcc%s r%d %x\n", dslot ? "d" : "", dc->ra, dc->imm);
                   1186: 
                   1187:     dc->delayed_branch = 1;
                   1188:     if (dslot) {
                   1189:         dc->delayed_branch = 2;
                   1190:         dc->tb_flags |= D_FLAG;
                   1191:         tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
                   1192:                       cpu_env, offsetof(CPUState, bimm));
                   1193:     }
                   1194: 
1.1.1.3   root     1195:     if (dec_alu_op_b_is_small_imm(dc)) {
                   1196:         int32_t offset = (int32_t)((int16_t)dc->imm); /* sign-extend.  */
                   1197: 
                   1198:         tcg_gen_movi_tl(env_btarget, dc->pc + offset);
1.1.1.4   root     1199:         dc->jmp = JMP_DIRECT_CC;
                   1200:         dc->jmp_pc = dc->pc + offset;
1.1.1.3   root     1201:     } else {
1.1.1.4   root     1202:         dc->jmp = JMP_INDIRECT;
1.1.1.3   root     1203:         tcg_gen_movi_tl(env_btarget, dc->pc);
                   1204:         tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc)));
                   1205:     }
                   1206:     eval_cc(dc, cc, env_btaken, cpu_R[dc->ra], tcg_const_tl(0));
1.1       root     1207: }
                   1208: 
                   1209: static void dec_br(DisasContext *dc)
                   1210: {
                   1211:     unsigned int dslot, link, abs;
1.1.1.3   root     1212:     int mem_index = cpu_mmu_index(dc->env);
1.1       root     1213: 
                   1214:     dslot = dc->ir & (1 << 20);
                   1215:     abs = dc->ir & (1 << 19);
                   1216:     link = dc->ir & (1 << 18);
                   1217:     LOG_DIS("br%s%s%s%s imm=%x\n",
                   1218:              abs ? "a" : "", link ? "l" : "",
                   1219:              dc->type_b ? "i" : "", dslot ? "d" : "",
                   1220:              dc->imm);
                   1221: 
                   1222:     dc->delayed_branch = 1;
                   1223:     if (dslot) {
                   1224:         dc->delayed_branch = 2;
                   1225:         dc->tb_flags |= D_FLAG;
                   1226:         tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
                   1227:                       cpu_env, offsetof(CPUState, bimm));
                   1228:     }
                   1229:     if (link && dc->rd)
                   1230:         tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc);
                   1231: 
                   1232:     dc->jmp = JMP_INDIRECT;
                   1233:     if (abs) {
                   1234:         tcg_gen_movi_tl(env_btaken, 1);
                   1235:         tcg_gen_mov_tl(env_btarget, *(dec_alu_op_b(dc)));
1.1.1.3   root     1236:         if (link && !dslot) {
                   1237:             if (!(dc->tb_flags & IMM_FLAG) && (dc->imm == 8 || dc->imm == 0x18))
                   1238:                 t_gen_raise_exception(dc, EXCP_BREAK);
                   1239:             if (dc->imm == 0) {
                   1240:                 if ((dc->tb_flags & MSR_EE_FLAG) && mem_index == MMU_USER_IDX) {
                   1241:                     tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
                   1242:                     t_gen_raise_exception(dc, EXCP_HW_EXCP);
                   1243:                     return;
                   1244:                 }
                   1245: 
                   1246:                 t_gen_raise_exception(dc, EXCP_DEBUG);
                   1247:             }
                   1248:         }
1.1       root     1249:     } else {
1.1.1.3   root     1250:         if (dec_alu_op_b_is_small_imm(dc)) {
                   1251:             dc->jmp = JMP_DIRECT;
                   1252:             dc->jmp_pc = dc->pc + (int32_t)((int16_t)dc->imm);
                   1253:         } else {
1.1       root     1254:             tcg_gen_movi_tl(env_btaken, 1);
                   1255:             tcg_gen_movi_tl(env_btarget, dc->pc);
                   1256:             tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc)));
                   1257:         }
                   1258:     }
                   1259: }
                   1260: 
                   1261: static inline void do_rti(DisasContext *dc)
                   1262: {
                   1263:     TCGv t0, t1;
                   1264:     t0 = tcg_temp_new();
                   1265:     t1 = tcg_temp_new();
                   1266:     tcg_gen_shri_tl(t0, cpu_SR[SR_MSR], 1);
                   1267:     tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_IE);
                   1268:     tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
                   1269: 
                   1270:     tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
                   1271:     tcg_gen_or_tl(t1, t1, t0);
                   1272:     msr_write(dc, t1);
                   1273:     tcg_temp_free(t1);
                   1274:     tcg_temp_free(t0);
                   1275:     dc->tb_flags &= ~DRTI_FLAG;
                   1276: }
                   1277: 
                   1278: static inline void do_rtb(DisasContext *dc)
                   1279: {
                   1280:     TCGv t0, t1;
                   1281:     t0 = tcg_temp_new();
                   1282:     t1 = tcg_temp_new();
                   1283:     tcg_gen_andi_tl(t1, cpu_SR[SR_MSR], ~MSR_BIP);
                   1284:     tcg_gen_shri_tl(t0, t1, 1);
                   1285:     tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
                   1286: 
                   1287:     tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
                   1288:     tcg_gen_or_tl(t1, t1, t0);
                   1289:     msr_write(dc, t1);
                   1290:     tcg_temp_free(t1);
                   1291:     tcg_temp_free(t0);
                   1292:     dc->tb_flags &= ~DRTB_FLAG;
                   1293: }
                   1294: 
                   1295: static inline void do_rte(DisasContext *dc)
                   1296: {
                   1297:     TCGv t0, t1;
                   1298:     t0 = tcg_temp_new();
                   1299:     t1 = tcg_temp_new();
                   1300: 
                   1301:     tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_EE);
                   1302:     tcg_gen_andi_tl(t1, t1, ~MSR_EIP);
                   1303:     tcg_gen_shri_tl(t0, t1, 1);
                   1304:     tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
                   1305: 
                   1306:     tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
                   1307:     tcg_gen_or_tl(t1, t1, t0);
                   1308:     msr_write(dc, t1);
                   1309:     tcg_temp_free(t1);
                   1310:     tcg_temp_free(t0);
                   1311:     dc->tb_flags &= ~DRTE_FLAG;
                   1312: }
                   1313: 
                   1314: static void dec_rts(DisasContext *dc)
                   1315: {
                   1316:     unsigned int b_bit, i_bit, e_bit;
1.1.1.2   root     1317:     int mem_index = cpu_mmu_index(dc->env);
1.1       root     1318: 
                   1319:     i_bit = dc->ir & (1 << 21);
                   1320:     b_bit = dc->ir & (1 << 22);
                   1321:     e_bit = dc->ir & (1 << 23);
                   1322: 
                   1323:     dc->delayed_branch = 2;
                   1324:     dc->tb_flags |= D_FLAG;
                   1325:     tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
                   1326:                   cpu_env, offsetof(CPUState, bimm));
                   1327: 
                   1328:     if (i_bit) {
                   1329:         LOG_DIS("rtid ir=%x\n", dc->ir);
1.1.1.2   root     1330:         if ((dc->tb_flags & MSR_EE_FLAG)
                   1331:              && mem_index == MMU_USER_IDX) {
                   1332:             tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
                   1333:             t_gen_raise_exception(dc, EXCP_HW_EXCP);
                   1334:         }
1.1       root     1335:         dc->tb_flags |= DRTI_FLAG;
                   1336:     } else if (b_bit) {
                   1337:         LOG_DIS("rtbd ir=%x\n", dc->ir);
1.1.1.2   root     1338:         if ((dc->tb_flags & MSR_EE_FLAG)
                   1339:              && mem_index == MMU_USER_IDX) {
                   1340:             tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
                   1341:             t_gen_raise_exception(dc, EXCP_HW_EXCP);
                   1342:         }
1.1       root     1343:         dc->tb_flags |= DRTB_FLAG;
                   1344:     } else if (e_bit) {
                   1345:         LOG_DIS("rted ir=%x\n", dc->ir);
1.1.1.2   root     1346:         if ((dc->tb_flags & MSR_EE_FLAG)
                   1347:              && mem_index == MMU_USER_IDX) {
                   1348:             tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
                   1349:             t_gen_raise_exception(dc, EXCP_HW_EXCP);
                   1350:         }
1.1       root     1351:         dc->tb_flags |= DRTE_FLAG;
                   1352:     } else
                   1353:         LOG_DIS("rts ir=%x\n", dc->ir);
                   1354: 
1.1.1.4   root     1355:     dc->jmp = JMP_INDIRECT;
1.1       root     1356:     tcg_gen_movi_tl(env_btaken, 1);
                   1357:     tcg_gen_add_tl(env_btarget, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
                   1358: }
                   1359: 
1.1.1.4   root     1360: static int dec_check_fpuv2(DisasContext *dc)
                   1361: {
                   1362:     int r;
                   1363: 
                   1364:     r = dc->env->pvr.regs[2] & PVR2_USE_FPU2_MASK;
                   1365: 
                   1366:     if (!r && (dc->tb_flags & MSR_EE_FLAG)) {
                   1367:         tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_FPU);
                   1368:         t_gen_raise_exception(dc, EXCP_HW_EXCP);
                   1369:     }
                   1370:     return r;
                   1371: }
                   1372: 
1.1.1.2   root     1373: static void dec_fpu(DisasContext *dc)
                   1374: {
1.1.1.4   root     1375:     unsigned int fpu_insn;
                   1376: 
1.1.1.2   root     1377:     if ((dc->tb_flags & MSR_EE_FLAG)
                   1378:           && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
                   1379:           && !((dc->env->pvr.regs[2] & PVR2_USE_FPU_MASK))) {
1.1.1.4   root     1380:         tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
1.1.1.2   root     1381:         t_gen_raise_exception(dc, EXCP_HW_EXCP);
                   1382:         return;
                   1383:     }
                   1384: 
1.1.1.4   root     1385:     fpu_insn = (dc->ir >> 7) & 7;
                   1386: 
                   1387:     switch (fpu_insn) {
                   1388:         case 0:
                   1389:             gen_helper_fadd(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                   1390:             break;
                   1391: 
                   1392:         case 1:
                   1393:             gen_helper_frsub(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                   1394:             break;
                   1395: 
                   1396:         case 2:
                   1397:             gen_helper_fmul(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                   1398:             break;
                   1399: 
                   1400:         case 3:
                   1401:             gen_helper_fdiv(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                   1402:             break;
                   1403: 
                   1404:         case 4:
                   1405:             switch ((dc->ir >> 4) & 7) {
                   1406:                 case 0:
                   1407:                     gen_helper_fcmp_un(cpu_R[dc->rd],
                   1408:                                        cpu_R[dc->ra], cpu_R[dc->rb]);
                   1409:                     break;
                   1410:                 case 1:
                   1411:                     gen_helper_fcmp_lt(cpu_R[dc->rd],
                   1412:                                        cpu_R[dc->ra], cpu_R[dc->rb]);
                   1413:                     break;
                   1414:                 case 2:
                   1415:                     gen_helper_fcmp_eq(cpu_R[dc->rd],
                   1416:                                        cpu_R[dc->ra], cpu_R[dc->rb]);
                   1417:                     break;
                   1418:                 case 3:
                   1419:                     gen_helper_fcmp_le(cpu_R[dc->rd],
                   1420:                                        cpu_R[dc->ra], cpu_R[dc->rb]);
                   1421:                     break;
                   1422:                 case 4:
                   1423:                     gen_helper_fcmp_gt(cpu_R[dc->rd],
                   1424:                                        cpu_R[dc->ra], cpu_R[dc->rb]);
                   1425:                     break;
                   1426:                 case 5:
                   1427:                     gen_helper_fcmp_ne(cpu_R[dc->rd],
                   1428:                                        cpu_R[dc->ra], cpu_R[dc->rb]);
                   1429:                     break;
                   1430:                 case 6:
                   1431:                     gen_helper_fcmp_ge(cpu_R[dc->rd],
                   1432:                                        cpu_R[dc->ra], cpu_R[dc->rb]);
                   1433:                     break;
                   1434:                 default:
                   1435:                     qemu_log ("unimplemented fcmp fpu_insn=%x pc=%x opc=%x\n",
                   1436:                               fpu_insn, dc->pc, dc->opcode);
                   1437:                     dc->abort_at_next_insn = 1;
                   1438:                     break;
                   1439:             }
                   1440:             break;
                   1441: 
                   1442:         case 5:
                   1443:             if (!dec_check_fpuv2(dc)) {
                   1444:                 return;
                   1445:             }
                   1446:             gen_helper_flt(cpu_R[dc->rd], cpu_R[dc->ra]);
                   1447:             break;
                   1448: 
                   1449:         case 6:
                   1450:             if (!dec_check_fpuv2(dc)) {
                   1451:                 return;
                   1452:             }
                   1453:             gen_helper_fint(cpu_R[dc->rd], cpu_R[dc->ra]);
                   1454:             break;
                   1455: 
                   1456:         case 7:
                   1457:             if (!dec_check_fpuv2(dc)) {
                   1458:                 return;
                   1459:             }
                   1460:             gen_helper_fsqrt(cpu_R[dc->rd], cpu_R[dc->ra]);
                   1461:             break;
                   1462: 
                   1463:         default:
                   1464:             qemu_log ("unimplemented FPU insn fpu_insn=%x pc=%x opc=%x\n",
                   1465:                       fpu_insn, dc->pc, dc->opcode);
                   1466:             dc->abort_at_next_insn = 1;
                   1467:             break;
                   1468:     }
1.1.1.2   root     1469: }
                   1470: 
1.1       root     1471: static void dec_null(DisasContext *dc)
                   1472: {
1.1.1.2   root     1473:     if ((dc->tb_flags & MSR_EE_FLAG)
                   1474:           && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
                   1475:         tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
                   1476:         t_gen_raise_exception(dc, EXCP_HW_EXCP);
                   1477:         return;
                   1478:     }
1.1       root     1479:     qemu_log ("unknown insn pc=%x opc=%x\n", dc->pc, dc->opcode);
                   1480:     dc->abort_at_next_insn = 1;
                   1481: }
                   1482: 
1.1.1.5   root     1483: /* Insns connected to FSL or AXI stream attached devices.  */
                   1484: static void dec_stream(DisasContext *dc)
                   1485: {
                   1486:     int mem_index = cpu_mmu_index(dc->env);
                   1487:     TCGv_i32 t_id, t_ctrl;
                   1488:     int ctrl;
                   1489: 
                   1490:     LOG_DIS("%s%s imm=%x\n", dc->rd ? "get" : "put",
                   1491:             dc->type_b ? "" : "d", dc->imm);
                   1492: 
                   1493:     if ((dc->tb_flags & MSR_EE_FLAG) && (mem_index == MMU_USER_IDX)) {
                   1494:         tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
                   1495:         t_gen_raise_exception(dc, EXCP_HW_EXCP);
                   1496:         return;
                   1497:     }
                   1498: 
                   1499:     t_id = tcg_temp_new();
                   1500:     if (dc->type_b) {
                   1501:         tcg_gen_movi_tl(t_id, dc->imm & 0xf);
                   1502:         ctrl = dc->imm >> 10;
                   1503:     } else {
                   1504:         tcg_gen_andi_tl(t_id, cpu_R[dc->rb], 0xf);
                   1505:         ctrl = dc->imm >> 5;
                   1506:     }
                   1507: 
                   1508:     t_ctrl = tcg_const_tl(ctrl);
                   1509: 
                   1510:     if (dc->rd == 0) {
                   1511:         gen_helper_put(t_id, t_ctrl, cpu_R[dc->ra]);
                   1512:     } else {
                   1513:         gen_helper_get(cpu_R[dc->rd], t_id, t_ctrl);
                   1514:     }
                   1515:     tcg_temp_free(t_id);
                   1516:     tcg_temp_free(t_ctrl);
                   1517: }
                   1518: 
1.1       root     1519: static struct decoder_info {
                   1520:     struct {
                   1521:         uint32_t bits;
                   1522:         uint32_t mask;
                   1523:     };
                   1524:     void (*dec)(DisasContext *dc);
                   1525: } decinfo[] = {
                   1526:     {DEC_ADD, dec_add},
                   1527:     {DEC_SUB, dec_sub},
                   1528:     {DEC_AND, dec_and},
                   1529:     {DEC_XOR, dec_xor},
                   1530:     {DEC_OR, dec_or},
                   1531:     {DEC_BIT, dec_bit},
                   1532:     {DEC_BARREL, dec_barrel},
                   1533:     {DEC_LD, dec_load},
                   1534:     {DEC_ST, dec_store},
                   1535:     {DEC_IMM, dec_imm},
                   1536:     {DEC_BR, dec_br},
                   1537:     {DEC_BCC, dec_bcc},
                   1538:     {DEC_RTS, dec_rts},
1.1.1.2   root     1539:     {DEC_FPU, dec_fpu},
1.1       root     1540:     {DEC_MUL, dec_mul},
                   1541:     {DEC_DIV, dec_div},
                   1542:     {DEC_MSR, dec_msr},
1.1.1.5   root     1543:     {DEC_STREAM, dec_stream},
1.1       root     1544:     {{0, 0}, dec_null}
                   1545: };
                   1546: 
                   1547: static inline void decode(DisasContext *dc)
                   1548: {
                   1549:     uint32_t ir;
                   1550:     int i;
                   1551: 
                   1552:     if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
                   1553:         tcg_gen_debug_insn_start(dc->pc);
                   1554: 
                   1555:     dc->ir = ir = ldl_code(dc->pc);
                   1556:     LOG_DIS("%8.8x\t", dc->ir);
                   1557: 
                   1558:     if (dc->ir)
                   1559:         dc->nr_nops = 0;
                   1560:     else {
1.1.1.2   root     1561:         if ((dc->tb_flags & MSR_EE_FLAG)
                   1562:               && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
                   1563:               && (dc->env->pvr.regs[2] & PVR2_OPCODE_0x0_ILL_MASK)) {
                   1564:             tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
                   1565:             t_gen_raise_exception(dc, EXCP_HW_EXCP);
                   1566:             return;
                   1567:         }
                   1568: 
1.1       root     1569:         LOG_DIS("nr_nops=%d\t", dc->nr_nops);
                   1570:         dc->nr_nops++;
                   1571:         if (dc->nr_nops > 4)
                   1572:             cpu_abort(dc->env, "fetching nop sequence\n");
                   1573:     }
                   1574:     /* bit 2 seems to indicate insn type.  */
                   1575:     dc->type_b = ir & (1 << 29);
                   1576: 
                   1577:     dc->opcode = EXTRACT_FIELD(ir, 26, 31);
                   1578:     dc->rd = EXTRACT_FIELD(ir, 21, 25);
                   1579:     dc->ra = EXTRACT_FIELD(ir, 16, 20);
                   1580:     dc->rb = EXTRACT_FIELD(ir, 11, 15);
                   1581:     dc->imm = EXTRACT_FIELD(ir, 0, 15);
                   1582: 
                   1583:     /* Large switch for all insns.  */
                   1584:     for (i = 0; i < ARRAY_SIZE(decinfo); i++) {
                   1585:         if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) {
                   1586:             decinfo[i].dec(dc);
                   1587:             break;
                   1588:         }
                   1589:     }
                   1590: }
                   1591: 
                   1592: static void check_breakpoint(CPUState *env, DisasContext *dc)
                   1593: {
                   1594:     CPUBreakpoint *bp;
                   1595: 
1.1.1.2   root     1596:     if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
                   1597:         QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1.1       root     1598:             if (bp->pc == dc->pc) {
                   1599:                 t_gen_raise_exception(dc, EXCP_DEBUG);
                   1600:                 dc->is_jmp = DISAS_UPDATE;
                   1601:              }
                   1602:         }
                   1603:     }
                   1604: }
                   1605: 
                   1606: /* generate intermediate code for basic block 'tb'.  */
                   1607: static void
                   1608: gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
                   1609:                                int search_pc)
                   1610: {
                   1611:     uint16_t *gen_opc_end;
                   1612:     uint32_t pc_start;
                   1613:     int j, lj;
                   1614:     struct DisasContext ctx;
                   1615:     struct DisasContext *dc = &ctx;
                   1616:     uint32_t next_page_start, org_flags;
                   1617:     target_ulong npc;
                   1618:     int num_insns;
                   1619:     int max_insns;
                   1620: 
                   1621:     qemu_log_try_set_file(stderr);
                   1622: 
                   1623:     pc_start = tb->pc;
                   1624:     dc->env = env;
                   1625:     dc->tb = tb;
                   1626:     org_flags = dc->synced_flags = dc->tb_flags = tb->flags;
                   1627: 
                   1628:     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
                   1629: 
                   1630:     dc->is_jmp = DISAS_NEXT;
                   1631:     dc->jmp = 0;
                   1632:     dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
1.1.1.4   root     1633:     if (dc->delayed_branch) {
                   1634:         dc->jmp = JMP_INDIRECT;
                   1635:     }
1.1       root     1636:     dc->pc = pc_start;
                   1637:     dc->singlestep_enabled = env->singlestep_enabled;
                   1638:     dc->cpustate_changed = 0;
                   1639:     dc->abort_at_next_insn = 0;
                   1640:     dc->nr_nops = 0;
                   1641: 
                   1642:     if (pc_start & 3)
                   1643:         cpu_abort(env, "Microblaze: unaligned PC=%x\n", pc_start);
                   1644: 
                   1645:     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
                   1646: #if !SIM_COMPAT
                   1647:         qemu_log("--------------\n");
                   1648:         log_cpu_state(env, 0);
                   1649: #endif
                   1650:     }
                   1651: 
                   1652:     next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
                   1653:     lj = -1;
                   1654:     num_insns = 0;
                   1655:     max_insns = tb->cflags & CF_COUNT_MASK;
                   1656:     if (max_insns == 0)
                   1657:         max_insns = CF_COUNT_MASK;
                   1658: 
                   1659:     gen_icount_start();
                   1660:     do
                   1661:     {
                   1662: #if SIM_COMPAT
                   1663:         if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
                   1664:             tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
                   1665:             gen_helper_debug();
                   1666:         }
                   1667: #endif
                   1668:         check_breakpoint(env, dc);
                   1669: 
                   1670:         if (search_pc) {
                   1671:             j = gen_opc_ptr - gen_opc_buf;
                   1672:             if (lj < j) {
                   1673:                 lj++;
                   1674:                 while (lj < j)
                   1675:                     gen_opc_instr_start[lj++] = 0;
                   1676:             }
                   1677:             gen_opc_pc[lj] = dc->pc;
                   1678:             gen_opc_instr_start[lj] = 1;
                   1679:                         gen_opc_icount[lj] = num_insns;
                   1680:         }
                   1681: 
                   1682:         /* Pretty disas.  */
                   1683:         LOG_DIS("%8.8x:\t", dc->pc);
                   1684: 
                   1685:         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
                   1686:             gen_io_start();
                   1687: 
                   1688:         dc->clear_imm = 1;
                   1689:        decode(dc);
                   1690:         if (dc->clear_imm)
                   1691:             dc->tb_flags &= ~IMM_FLAG;
                   1692:         dc->pc += 4;
                   1693:         num_insns++;
                   1694: 
                   1695:         if (dc->delayed_branch) {
                   1696:             dc->delayed_branch--;
                   1697:             if (!dc->delayed_branch) {
                   1698:                 if (dc->tb_flags & DRTI_FLAG)
                   1699:                     do_rti(dc);
                   1700:                  if (dc->tb_flags & DRTB_FLAG)
                   1701:                     do_rtb(dc);
                   1702:                 if (dc->tb_flags & DRTE_FLAG)
                   1703:                     do_rte(dc);
                   1704:                 /* Clear the delay slot flag.  */
                   1705:                 dc->tb_flags &= ~D_FLAG;
                   1706:                 /* If it is a direct jump, try direct chaining.  */
1.1.1.4   root     1707:                 if (dc->jmp == JMP_INDIRECT) {
1.1       root     1708:                     eval_cond_jmp(dc, env_btarget, tcg_const_tl(dc->pc));
                   1709:                     dc->is_jmp = DISAS_JUMP;
1.1.1.4   root     1710:                 } else if (dc->jmp == JMP_DIRECT) {
                   1711:                     t_sync_flags(dc);
                   1712:                     gen_goto_tb(dc, 0, dc->jmp_pc);
                   1713:                     dc->is_jmp = DISAS_TB_JUMP;
                   1714:                 } else if (dc->jmp == JMP_DIRECT_CC) {
                   1715:                     int l1;
                   1716: 
                   1717:                     t_sync_flags(dc);
                   1718:                     l1 = gen_new_label();
                   1719:                     /* Conditional jmp.  */
                   1720:                     tcg_gen_brcondi_tl(TCG_COND_NE, env_btaken, 0, l1);
                   1721:                     gen_goto_tb(dc, 1, dc->pc);
                   1722:                     gen_set_label(l1);
                   1723:                     gen_goto_tb(dc, 0, dc->jmp_pc);
                   1724: 
                   1725:                     dc->is_jmp = DISAS_TB_JUMP;
1.1       root     1726:                 }
                   1727:                 break;
                   1728:             }
                   1729:         }
                   1730:         if (env->singlestep_enabled)
                   1731:             break;
                   1732:     } while (!dc->is_jmp && !dc->cpustate_changed
                   1733:          && gen_opc_ptr < gen_opc_end
                   1734:                  && !singlestep
                   1735:          && (dc->pc < next_page_start)
                   1736:                  && num_insns < max_insns);
                   1737: 
                   1738:     npc = dc->pc;
1.1.1.4   root     1739:     if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
1.1       root     1740:         if (dc->tb_flags & D_FLAG) {
                   1741:             dc->is_jmp = DISAS_UPDATE;
                   1742:             tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
                   1743:             sync_jmpstate(dc);
                   1744:         } else
                   1745:             npc = dc->jmp_pc;
                   1746:     }
                   1747: 
                   1748:     if (tb->cflags & CF_LAST_IO)
                   1749:         gen_io_end();
                   1750:     /* Force an update if the per-tb cpu state has changed.  */
                   1751:     if (dc->is_jmp == DISAS_NEXT
                   1752:         && (dc->cpustate_changed || org_flags != dc->tb_flags)) {
                   1753:         dc->is_jmp = DISAS_UPDATE;
                   1754:         tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
                   1755:     }
                   1756:     t_sync_flags(dc);
                   1757: 
                   1758:     if (unlikely(env->singlestep_enabled)) {
1.1.1.5   root     1759:         TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG);
                   1760: 
                   1761:         if (dc->is_jmp != DISAS_JUMP) {
1.1       root     1762:             tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
1.1.1.5   root     1763:         }
                   1764:         gen_helper_raise_exception(tmp);
                   1765:         tcg_temp_free_i32(tmp);
1.1       root     1766:     } else {
                   1767:         switch(dc->is_jmp) {
                   1768:             case DISAS_NEXT:
                   1769:                 gen_goto_tb(dc, 1, npc);
                   1770:                 break;
                   1771:             default:
                   1772:             case DISAS_JUMP:
                   1773:             case DISAS_UPDATE:
                   1774:                 /* indicate that the hash table must be used
                   1775:                    to find the next TB */
                   1776:                 tcg_gen_exit_tb(0);
                   1777:                 break;
                   1778:             case DISAS_TB_JUMP:
                   1779:                 /* nothing more to generate */
                   1780:                 break;
                   1781:         }
                   1782:     }
                   1783:     gen_icount_end(tb, num_insns);
                   1784:     *gen_opc_ptr = INDEX_op_end;
                   1785:     if (search_pc) {
                   1786:         j = gen_opc_ptr - gen_opc_buf;
                   1787:         lj++;
                   1788:         while (lj <= j)
                   1789:             gen_opc_instr_start[lj++] = 0;
                   1790:     } else {
                   1791:         tb->size = dc->pc - pc_start;
                   1792:                 tb->icount = num_insns;
                   1793:     }
                   1794: 
                   1795: #ifdef DEBUG_DISAS
                   1796: #if !SIM_COMPAT
                   1797:     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
                   1798:         qemu_log("\n");
                   1799: #if DISAS_GNU
                   1800:         log_target_disas(pc_start, dc->pc - pc_start, 0);
                   1801: #endif
1.1.1.4   root     1802:         qemu_log("\nisize=%d osize=%td\n",
1.1       root     1803:             dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
                   1804:     }
                   1805: #endif
                   1806: #endif
                   1807:     assert(!dc->abort_at_next_insn);
                   1808: }
                   1809: 
                   1810: void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
                   1811: {
                   1812:     gen_intermediate_code_internal(env, tb, 0);
                   1813: }
                   1814: 
                   1815: void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
                   1816: {
                   1817:     gen_intermediate_code_internal(env, tb, 1);
                   1818: }
                   1819: 
1.1.1.4   root     1820: void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
1.1       root     1821:                      int flags)
                   1822: {
                   1823:     int i;
                   1824: 
                   1825:     if (!env || !f)
                   1826:         return;
                   1827: 
                   1828:     cpu_fprintf(f, "IN: PC=%x %s\n",
                   1829:                 env->sregs[SR_PC], lookup_symbol(env->sregs[SR_PC]));
1.1.1.4   root     1830:     cpu_fprintf(f, "rmsr=%x resr=%x rear=%x debug=%x imm=%x iflags=%x fsr=%x\n",
1.1.1.3   root     1831:              env->sregs[SR_MSR], env->sregs[SR_ESR], env->sregs[SR_EAR],
1.1.1.4   root     1832:              env->debug, env->imm, env->iflags, env->sregs[SR_FSR]);
1.1.1.3   root     1833:     cpu_fprintf(f, "btaken=%d btarget=%x mode=%s(saved=%s) eip=%d ie=%d\n",
1.1       root     1834:              env->btaken, env->btarget,
                   1835:              (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel",
1.1.1.3   root     1836:              (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel",
                   1837:              (env->sregs[SR_MSR] & MSR_EIP),
                   1838:              (env->sregs[SR_MSR] & MSR_IE));
                   1839: 
1.1       root     1840:     for (i = 0; i < 32; i++) {
                   1841:         cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
                   1842:         if ((i + 1) % 4 == 0)
                   1843:             cpu_fprintf(f, "\n");
                   1844:         }
                   1845:     cpu_fprintf(f, "\n\n");
                   1846: }
                   1847: 
                   1848: CPUState *cpu_mb_init (const char *cpu_model)
                   1849: {
                   1850:     CPUState *env;
                   1851:     static int tcg_initialized = 0;
                   1852:     int i;
                   1853: 
1.1.1.6 ! root     1854:     env = g_malloc0(sizeof(CPUState));
1.1       root     1855: 
                   1856:     cpu_exec_init(env);
                   1857:     cpu_reset(env);
1.1.1.6 ! root     1858:     qemu_init_vcpu(env);
1.1.1.4   root     1859:     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1.1       root     1860: 
                   1861:     if (tcg_initialized)
                   1862:         return env;
                   1863: 
                   1864:     tcg_initialized = 1;
                   1865: 
                   1866:     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
                   1867: 
                   1868:     env_debug = tcg_global_mem_new(TCG_AREG0, 
                   1869:                     offsetof(CPUState, debug),
                   1870:                     "debug0");
                   1871:     env_iflags = tcg_global_mem_new(TCG_AREG0, 
                   1872:                     offsetof(CPUState, iflags),
                   1873:                     "iflags");
                   1874:     env_imm = tcg_global_mem_new(TCG_AREG0, 
                   1875:                     offsetof(CPUState, imm),
                   1876:                     "imm");
                   1877:     env_btarget = tcg_global_mem_new(TCG_AREG0,
                   1878:                      offsetof(CPUState, btarget),
                   1879:                      "btarget");
                   1880:     env_btaken = tcg_global_mem_new(TCG_AREG0,
                   1881:                      offsetof(CPUState, btaken),
                   1882:                      "btaken");
                   1883:     for (i = 0; i < ARRAY_SIZE(cpu_R); i++) {
                   1884:         cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
                   1885:                           offsetof(CPUState, regs[i]),
                   1886:                           regnames[i]);
                   1887:     }
                   1888:     for (i = 0; i < ARRAY_SIZE(cpu_SR); i++) {
                   1889:         cpu_SR[i] = tcg_global_mem_new(TCG_AREG0,
                   1890:                           offsetof(CPUState, sregs[i]),
                   1891:                           special_regnames[i]);
                   1892:     }
                   1893: #define GEN_HELPER 2
                   1894: #include "helper.h"
                   1895: 
                   1896:     return env;
                   1897: }
                   1898: 
                   1899: void cpu_reset (CPUState *env)
                   1900: {
                   1901:     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
                   1902:         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
                   1903:         log_cpu_state(env, 0);
                   1904:     }
                   1905: 
                   1906:     memset(env, 0, offsetof(CPUMBState, breakpoints));
                   1907:     tlb_flush(env, 1);
                   1908: 
1.1.1.2   root     1909:     env->pvr.regs[0] = PVR0_PVR_FULL_MASK \
                   1910:                        | PVR0_USE_BARREL_MASK \
                   1911:                        | PVR0_USE_DIV_MASK \
                   1912:                        | PVR0_USE_HW_MUL_MASK \
                   1913:                        | PVR0_USE_EXC_MASK \
                   1914:                        | PVR0_USE_ICACHE_MASK \
                   1915:                        | PVR0_USE_DCACHE_MASK \
                   1916:                        | PVR0_USE_MMU \
                   1917:                        | (0xb << 8);
                   1918:     env->pvr.regs[2] = PVR2_D_OPB_MASK \
                   1919:                         | PVR2_D_LMB_MASK \
                   1920:                         | PVR2_I_OPB_MASK \
                   1921:                         | PVR2_I_LMB_MASK \
                   1922:                         | PVR2_USE_MSR_INSTR \
                   1923:                         | PVR2_USE_PCMP_INSTR \
                   1924:                         | PVR2_USE_BARREL_MASK \
                   1925:                         | PVR2_USE_DIV_MASK \
                   1926:                         | PVR2_USE_HW_MUL_MASK \
                   1927:                         | PVR2_USE_MUL64_MASK \
1.1.1.4   root     1928:                         | PVR2_USE_FPU_MASK \
                   1929:                         | PVR2_USE_FPU2_MASK \
                   1930:                         | PVR2_FPU_EXC_MASK \
1.1.1.2   root     1931:                         | 0;
                   1932:     env->pvr.regs[10] = 0x0c000000; /* Default to spartan 3a dsp family.  */
                   1933:     env->pvr.regs[11] = PVR11_USE_MMU | (16 << 17);
                   1934: 
1.1       root     1935: #if defined(CONFIG_USER_ONLY)
                   1936:     /* start in user mode with interrupts enabled.  */
1.1.1.4   root     1937:     env->sregs[SR_MSR] = MSR_EE | MSR_IE | MSR_VM | MSR_UM;
1.1       root     1938:     env->pvr.regs[10] = 0x0c000000; /* Spartan 3a dsp.  */
                   1939: #else
1.1.1.4   root     1940:     env->sregs[SR_MSR] = 0;
1.1       root     1941:     mmu_init(&env->mmu);
1.1.1.2   root     1942:     env->mmu.c_mmu = 3;
                   1943:     env->mmu.c_mmu_tlb_access = 3;
                   1944:     env->mmu.c_mmu_zones = 16;
1.1       root     1945: #endif
                   1946: }
                   1947: 
1.1.1.5   root     1948: void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
1.1       root     1949: {
                   1950:     env->sregs[SR_PC] = gen_opc_pc[pc_pos];
                   1951: }

unix.superglobalmegacorp.com

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