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

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 "exec-all.h"
                     29: #include "disas.h"
                     30: #include "tcg-op.h"
                     31: #include "helper.h"
                     32: #include "microblaze-decode.h"
                     33: #include "qemu-common.h"
                     34: 
                     35: #define GEN_HELPER 1
                     36: #include "helper.h"
                     37: 
                     38: #define SIM_COMPAT 0
                     39: #define DISAS_GNU 1
                     40: #define DISAS_MB 1
                     41: #if DISAS_MB && !SIM_COMPAT
                     42: #  define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
                     43: #else
                     44: #  define LOG_DIS(...) do { } while (0)
                     45: #endif
                     46: 
                     47: #define D(x)
                     48: 
                     49: #define EXTRACT_FIELD(src, start, end) \
                     50:             (((src) >> start) & ((1 << (end - start + 1)) - 1))
                     51: 
                     52: static TCGv env_debug;
                     53: static TCGv_ptr cpu_env;
                     54: static TCGv cpu_R[32];
                     55: static TCGv cpu_SR[18];
                     56: static TCGv env_imm;
                     57: static TCGv env_btaken;
                     58: static TCGv env_btarget;
                     59: static TCGv env_iflags;
                     60: 
                     61: #include "gen-icount.h"
                     62: 
                     63: /* This is the state at translation time.  */
                     64: typedef struct DisasContext {
                     65:     CPUState *env;
                     66:     target_ulong pc, ppc;
                     67:     target_ulong cache_pc;
                     68: 
                     69:     /* Decoder.  */
                     70:     int type_b;
                     71:     uint32_t ir;
                     72:     uint8_t opcode;
                     73:     uint8_t rd, ra, rb;
                     74:     uint16_t imm;
                     75: 
                     76:     unsigned int cpustate_changed;
                     77:     unsigned int delayed_branch;
                     78:     unsigned int tb_flags, synced_flags; /* tb dependent flags.  */
                     79:     unsigned int clear_imm;
                     80:     int is_jmp;
                     81: 
                     82: #define JMP_NOJMP    0
                     83: #define JMP_DIRECT   1
                     84: #define JMP_INDIRECT 2
                     85:     unsigned int jmp;
                     86:     uint32_t jmp_pc;
                     87: 
                     88:     int abort_at_next_insn;
                     89:     int nr_nops;
                     90:     struct TranslationBlock *tb;
                     91:     int singlestep_enabled;
                     92: } DisasContext;
                     93: 
                     94: const static char *regnames[] =
                     95: {
                     96:     "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
                     97:     "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
                     98:     "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
                     99:     "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
                    100: };
                    101: 
                    102: const static char *special_regnames[] =
                    103: {
                    104:     "rpc", "rmsr", "sr2", "sr3", "sr4", "sr5", "sr6", "sr7",
                    105:     "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15",
                    106:     "sr16", "sr17", "sr18"
                    107: };
                    108: 
                    109: /* Sign extend at translation time.  */
                    110: static inline int sign_extend(unsigned int val, unsigned int width)
                    111: {
                    112:         int sval;
                    113: 
                    114:         /* LSL.  */
                    115:         val <<= 31 - width;
                    116:         sval = val;
                    117:         /* ASR.  */
                    118:         sval >>= 31 - width;
                    119:         return sval;
                    120: }
                    121: 
                    122: static inline void t_sync_flags(DisasContext *dc)
                    123: {
                    124:     /* Synch the tb dependant flags between translator and runtime.  */
                    125:     if (dc->tb_flags != dc->synced_flags) {
                    126:         tcg_gen_movi_tl(env_iflags, dc->tb_flags);
                    127:         dc->synced_flags = dc->tb_flags;
                    128:     }
                    129: }
                    130: 
                    131: static inline void t_gen_raise_exception(DisasContext *dc, uint32_t index)
                    132: {
                    133:     TCGv_i32 tmp = tcg_const_i32(index);
                    134: 
                    135:     t_sync_flags(dc);
                    136:     tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
                    137:     gen_helper_raise_exception(tmp);
                    138:     tcg_temp_free_i32(tmp);
                    139:     dc->is_jmp = DISAS_UPDATE;
                    140: }
                    141: 
                    142: static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
                    143: {
                    144:     TranslationBlock *tb;
                    145:     tb = dc->tb;
                    146:     if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
                    147:         tcg_gen_goto_tb(n);
                    148:         tcg_gen_movi_tl(cpu_SR[SR_PC], dest);
                    149:         tcg_gen_exit_tb((long)tb + n);
                    150:     } else {
                    151:         tcg_gen_movi_tl(cpu_SR[SR_PC], dest);
                    152:         tcg_gen_exit_tb(0);
                    153:     }
                    154: }
                    155: 
                    156: static inline TCGv *dec_alu_op_b(DisasContext *dc)
                    157: {
                    158:     if (dc->type_b) {
                    159:         if (dc->tb_flags & IMM_FLAG)
                    160:             tcg_gen_ori_tl(env_imm, env_imm, dc->imm);
                    161:         else
                    162:             tcg_gen_movi_tl(env_imm, (int32_t)((int16_t)dc->imm));
                    163:         return &env_imm;
                    164:     } else
                    165:         return &cpu_R[dc->rb];
                    166: }
                    167: 
                    168: static void dec_add(DisasContext *dc)
                    169: {
                    170:     unsigned int k, c;
                    171: 
                    172:     k = dc->opcode & 4;
                    173:     c = dc->opcode & 2;
                    174: 
                    175:     LOG_DIS("add%s%s%s r%d r%d r%d\n",
                    176:             dc->type_b ? "i" : "", k ? "k" : "", c ? "c" : "",
                    177:             dc->rd, dc->ra, dc->rb);
                    178: 
                    179:     if (k && !c && dc->rd)
                    180:         tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
                    181:     else if (dc->rd)
                    182:         gen_helper_addkc(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)),
                    183:                          tcg_const_tl(k), tcg_const_tl(c));
                    184:     else {
                    185:         TCGv d = tcg_temp_new();
                    186:         gen_helper_addkc(d, cpu_R[dc->ra], *(dec_alu_op_b(dc)),
                    187:                          tcg_const_tl(k), tcg_const_tl(c));
                    188:         tcg_temp_free(d);
                    189:     }
                    190: }
                    191: 
                    192: static void dec_sub(DisasContext *dc)
                    193: {
                    194:     unsigned int u, cmp, k, c;
                    195: 
                    196:     u = dc->imm & 2;
                    197:     k = dc->opcode & 4;
                    198:     c = dc->opcode & 2;
                    199:     cmp = (dc->imm & 1) && (!dc->type_b) && k;
                    200: 
                    201:     if (cmp) {
                    202:         LOG_DIS("cmp%s r%d, r%d ir=%x\n", u ? "u" : "", dc->rd, dc->ra, dc->ir);
                    203:         if (dc->rd) {
                    204:             if (u)
                    205:                 gen_helper_cmpu(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                    206:             else
                    207:                 gen_helper_cmp(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                    208:         }
                    209:     } else {
                    210:         LOG_DIS("sub%s%s r%d, r%d r%d\n",
                    211:                  k ? "k" : "",  c ? "c" : "", dc->rd, dc->ra, dc->rb);
                    212: 
                    213:         if (!k || c) {
                    214:             TCGv t;
                    215:             t = tcg_temp_new();
                    216:             if (dc->rd)
                    217:                 gen_helper_subkc(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)),
                    218:                                  tcg_const_tl(k), tcg_const_tl(c));
                    219:             else
                    220:                 gen_helper_subkc(t, cpu_R[dc->ra], *(dec_alu_op_b(dc)),
                    221:                                  tcg_const_tl(k), tcg_const_tl(c));
                    222:             tcg_temp_free(t);
                    223:         }
                    224:         else if (dc->rd)
                    225:             tcg_gen_sub_tl(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
                    226:     }
                    227: }
                    228: 
                    229: static void dec_pattern(DisasContext *dc)
                    230: {
                    231:     unsigned int mode;
                    232:     int l1;
                    233: 
                    234:     mode = dc->opcode & 3;
                    235:     switch (mode) {
                    236:         case 0:
                    237:             /* pcmpbf.  */
                    238:             LOG_DIS("pcmpbf r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
                    239:             if (dc->rd)
                    240:                 gen_helper_pcmpbf(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                    241:             break;
                    242:         case 2:
                    243:             LOG_DIS("pcmpeq r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
                    244:             if (dc->rd) {
                    245:                 TCGv t0 = tcg_temp_local_new();
                    246:                 l1 = gen_new_label();
                    247:                 tcg_gen_movi_tl(t0, 1);
                    248:                 tcg_gen_brcond_tl(TCG_COND_EQ,
                    249:                                   cpu_R[dc->ra], cpu_R[dc->rb], l1);
                    250:                 tcg_gen_movi_tl(t0, 0);
                    251:                 gen_set_label(l1);
                    252:                 tcg_gen_mov_tl(cpu_R[dc->rd], t0);
                    253:                 tcg_temp_free(t0);
                    254:             }
                    255:             break;
                    256:         case 3:
                    257:             LOG_DIS("pcmpne r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
                    258:             l1 = gen_new_label();
                    259:             if (dc->rd) {
                    260:                 TCGv t0 = tcg_temp_local_new();
                    261:                 tcg_gen_movi_tl(t0, 1);
                    262:                 tcg_gen_brcond_tl(TCG_COND_NE,
                    263:                                   cpu_R[dc->ra], cpu_R[dc->rb], l1);
                    264:                 tcg_gen_movi_tl(t0, 0);
                    265:                 gen_set_label(l1);
                    266:                 tcg_gen_mov_tl(cpu_R[dc->rd], t0);
                    267:                 tcg_temp_free(t0);
                    268:             }
                    269:             break;
                    270:         default:
                    271:             cpu_abort(dc->env,
                    272:                       "unsupported pattern insn opcode=%x\n", dc->opcode);
                    273:             break;
                    274:     }
                    275: }
                    276: 
                    277: static void dec_and(DisasContext *dc)
                    278: {
                    279:     unsigned int not;
                    280: 
                    281:     if (!dc->type_b && (dc->imm & (1 << 10))) {
                    282:         dec_pattern(dc);
                    283:         return;
                    284:     }
                    285: 
                    286:     not = dc->opcode & (1 << 1);
                    287:     LOG_DIS("and%s\n", not ? "n" : "");
                    288: 
                    289:     if (!dc->rd)
                    290:         return;
                    291: 
                    292:     if (not) {
                    293:         TCGv t = tcg_temp_new();
                    294:         tcg_gen_not_tl(t, *(dec_alu_op_b(dc)));
                    295:         tcg_gen_and_tl(cpu_R[dc->rd], cpu_R[dc->ra], t);
                    296:         tcg_temp_free(t);
                    297:     } else
                    298:         tcg_gen_and_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
                    299: }
                    300: 
                    301: static void dec_or(DisasContext *dc)
                    302: {
                    303:     if (!dc->type_b && (dc->imm & (1 << 10))) {
                    304:         dec_pattern(dc);
                    305:         return;
                    306:     }
                    307: 
                    308:     LOG_DIS("or r%d r%d r%d imm=%x\n", dc->rd, dc->ra, dc->rb, dc->imm);
                    309:     if (dc->rd)
                    310:         tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
                    311: }
                    312: 
                    313: static void dec_xor(DisasContext *dc)
                    314: {
                    315:     if (!dc->type_b && (dc->imm & (1 << 10))) {
                    316:         dec_pattern(dc);
                    317:         return;
                    318:     }
                    319: 
                    320:     LOG_DIS("xor r%d\n", dc->rd);
                    321:     if (dc->rd)
                    322:         tcg_gen_xor_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
                    323: }
                    324: 
                    325: static void read_carry(DisasContext *dc, TCGv d)
                    326: {
                    327:     tcg_gen_shri_tl(d, cpu_SR[SR_MSR], 31);
                    328: }
                    329: 
                    330: static void write_carry(DisasContext *dc, TCGv v)
                    331: {
                    332:     TCGv t0 = tcg_temp_new();
                    333:     tcg_gen_shli_tl(t0, v, 31);
                    334:     tcg_gen_sari_tl(t0, t0, 31);
                    335:     tcg_gen_mov_tl(env_debug, t0);
                    336:     tcg_gen_andi_tl(t0, t0, (MSR_C | MSR_CC));
                    337:     tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR],
                    338:                     ~(MSR_C | MSR_CC));
                    339:     tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t0);
                    340:     tcg_temp_free(t0);
                    341: }
                    342: 
                    343: 
                    344: static inline void msr_read(DisasContext *dc, TCGv d)
                    345: {
                    346:     tcg_gen_mov_tl(d, cpu_SR[SR_MSR]);
                    347: }
                    348: 
                    349: static inline void msr_write(DisasContext *dc, TCGv v)
                    350: {
                    351:     dc->cpustate_changed = 1;
                    352:     tcg_gen_mov_tl(cpu_SR[SR_MSR], v);
                    353:     /* PVR, we have a processor version register.  */
                    354:     tcg_gen_ori_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], (1 << 10));
                    355: }
                    356: 
                    357: static void dec_msr(DisasContext *dc)
                    358: {
                    359:     TCGv t0, t1;
                    360:     unsigned int sr, to, rn;
                    361: 
                    362:     sr = dc->imm & ((1 << 14) - 1);
                    363:     to = dc->imm & (1 << 14);
                    364:     dc->type_b = 1;
                    365:     if (to)
                    366:         dc->cpustate_changed = 1;
                    367: 
                    368:     /* msrclr and msrset.  */
                    369:     if (!(dc->imm & (1 << 15))) {
                    370:         unsigned int clr = dc->ir & (1 << 16);
                    371: 
                    372:         LOG_DIS("msr%s r%d imm=%x\n", clr ? "clr" : "set",
                    373:                 dc->rd, dc->imm);
                    374:         if (dc->rd)
                    375:             msr_read(dc, cpu_R[dc->rd]);
                    376: 
                    377:         t0 = tcg_temp_new();
                    378:         t1 = tcg_temp_new();
                    379:         msr_read(dc, t0);
                    380:         tcg_gen_mov_tl(t1, *(dec_alu_op_b(dc)));
                    381: 
                    382:         if (clr) {
                    383:             tcg_gen_not_tl(t1, t1);
                    384:             tcg_gen_and_tl(t0, t0, t1);
                    385:         } else
                    386:             tcg_gen_or_tl(t0, t0, t1);
                    387:         msr_write(dc, t0);
                    388:         tcg_temp_free(t0);
                    389:         tcg_temp_free(t1);
                    390:        tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc + 4);
                    391:         dc->is_jmp = DISAS_UPDATE;
                    392:         return;
                    393:     }
                    394: 
                    395: #if !defined(CONFIG_USER_ONLY)
                    396:     /* Catch read/writes to the mmu block.  */
                    397:     if ((sr & ~0xff) == 0x1000) {
                    398:         sr &= 7;
                    399:         LOG_DIS("m%ss sr%d r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm);
                    400:         if (to)
                    401:             gen_helper_mmu_write(tcg_const_tl(sr), cpu_R[dc->ra]);
                    402:         else
                    403:             gen_helper_mmu_read(cpu_R[dc->rd], tcg_const_tl(sr));
                    404:         return;
                    405:     }
                    406: #endif
                    407: 
                    408:     if (to) {
                    409:         LOG_DIS("m%ss sr%x r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm);
                    410:         switch (sr) {
                    411:             case 0:
                    412:                 break;
                    413:             case 1:
                    414:                 msr_write(dc, cpu_R[dc->ra]);
                    415:                 break;
                    416:             case 0x3:
                    417:                 tcg_gen_mov_tl(cpu_SR[SR_EAR], cpu_R[dc->ra]);
                    418:                 break;
                    419:             case 0x5:
                    420:                 tcg_gen_mov_tl(cpu_SR[SR_ESR], cpu_R[dc->ra]);
                    421:                 break;
                    422:             case 0x7:
                    423:                 /* Ignored at the moment.  */
                    424:                 break;
                    425:             default:
                    426:                 cpu_abort(dc->env, "unknown mts reg %x\n", sr);
                    427:                 break;
                    428:         }
                    429:     } else {
                    430:         LOG_DIS("m%ss r%d sr%x imm=%x\n", to ? "t" : "f", dc->rd, sr, dc->imm);
                    431: 
                    432:         switch (sr) {
                    433:             case 0:
                    434:                 tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc);
                    435:                 break;
                    436:             case 1:
                    437:                 msr_read(dc, cpu_R[dc->rd]);
                    438:                 break;
                    439:             case 0x3:
                    440:                 tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_EAR]);
                    441:                 break;
                    442:             case 0x5:
                    443:                 tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_ESR]);
                    444:                 break;
                    445:              case 0x7:
                    446:                 tcg_gen_movi_tl(cpu_R[dc->rd], 0);
                    447:                 break;
                    448:             case 0xb:
                    449:                 tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_BTR]);
                    450:                 break;
                    451:             case 0x2000:
                    452:             case 0x2001:
                    453:             case 0x2002:
                    454:             case 0x2003:
                    455:             case 0x2004:
                    456:             case 0x2005:
                    457:             case 0x2006:
                    458:             case 0x2007:
                    459:             case 0x2008:
                    460:             case 0x2009:
                    461:             case 0x200a:
                    462:             case 0x200b:
                    463:             case 0x200c:
                    464:                 rn = sr & 0xf;
                    465:                 tcg_gen_ld_tl(cpu_R[dc->rd],
                    466:                               cpu_env, offsetof(CPUState, pvr.regs[rn]));
                    467:                 break;
                    468:             default:
                    469:                 cpu_abort(dc->env, "unknown mfs reg %x\n", sr);
                    470:                 break;
                    471:         }
                    472:     }
                    473: }
                    474: 
                    475: /* 64-bit signed mul, lower result in d and upper in d2.  */
                    476: static void t_gen_muls(TCGv d, TCGv d2, TCGv a, TCGv b)
                    477: {
                    478:     TCGv_i64 t0, t1;
                    479: 
                    480:     t0 = tcg_temp_new_i64();
                    481:     t1 = tcg_temp_new_i64();
                    482: 
                    483:     tcg_gen_ext_i32_i64(t0, a);
                    484:     tcg_gen_ext_i32_i64(t1, b);
                    485:     tcg_gen_mul_i64(t0, t0, t1);
                    486: 
                    487:     tcg_gen_trunc_i64_i32(d, t0);
                    488:     tcg_gen_shri_i64(t0, t0, 32);
                    489:     tcg_gen_trunc_i64_i32(d2, t0);
                    490: 
                    491:     tcg_temp_free_i64(t0);
                    492:     tcg_temp_free_i64(t1);
                    493: }
                    494: 
                    495: /* 64-bit unsigned muls, lower result in d and upper in d2.  */
                    496: static void t_gen_mulu(TCGv d, TCGv d2, TCGv a, TCGv b)
                    497: {
                    498:     TCGv_i64 t0, t1;
                    499: 
                    500:     t0 = tcg_temp_new_i64();
                    501:     t1 = tcg_temp_new_i64();
                    502: 
                    503:     tcg_gen_extu_i32_i64(t0, a);
                    504:     tcg_gen_extu_i32_i64(t1, b);
                    505:     tcg_gen_mul_i64(t0, t0, t1);
                    506: 
                    507:     tcg_gen_trunc_i64_i32(d, t0);
                    508:     tcg_gen_shri_i64(t0, t0, 32);
                    509:     tcg_gen_trunc_i64_i32(d2, t0);
                    510: 
                    511:     tcg_temp_free_i64(t0);
                    512:     tcg_temp_free_i64(t1);
                    513: }
                    514: 
                    515: /* Multiplier unit.  */
                    516: static void dec_mul(DisasContext *dc)
                    517: {
                    518:     TCGv d[2];
                    519:     unsigned int subcode;
                    520: 
                    521:     subcode = dc->imm & 3;
                    522:     d[0] = tcg_temp_new();
                    523:     d[1] = tcg_temp_new();
                    524: 
                    525:     if (dc->type_b) {
                    526:         LOG_DIS("muli r%d r%d %x\n", dc->rd, dc->ra, dc->imm);
                    527:         t_gen_mulu(cpu_R[dc->rd], d[1], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
                    528:         goto done;
                    529:     }
                    530: 
                    531:     switch (subcode) {
                    532:         case 0:
                    533:             LOG_DIS("mul r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
                    534:             t_gen_mulu(cpu_R[dc->rd], d[1], cpu_R[dc->ra], cpu_R[dc->rb]);
                    535:             break;
                    536:         case 1:
                    537:             LOG_DIS("mulh r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
                    538:             t_gen_muls(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                    539:             break;
                    540:         case 2:
                    541:             LOG_DIS("mulhsu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
                    542:             t_gen_muls(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                    543:             break;
                    544:         case 3:
                    545:             LOG_DIS("mulhu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
                    546:             t_gen_mulu(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
                    547:             break;
                    548:         default:
                    549:             cpu_abort(dc->env, "unknown MUL insn %x\n", subcode);
                    550:             break;
                    551:     }
                    552: done:
                    553:     tcg_temp_free(d[0]);
                    554:     tcg_temp_free(d[1]);
                    555: }
                    556: 
                    557: /* Div unit.  */
                    558: static void dec_div(DisasContext *dc)
                    559: {
                    560:     unsigned int u;
                    561: 
                    562:     u = dc->imm & 2; 
                    563:     LOG_DIS("div\n");
                    564: 
                    565:     /* FIXME: support div by zero exceptions.  */
                    566:     if (u)
                    567:         gen_helper_divu(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
                    568:     else
                    569:         gen_helper_divs(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
                    570:     if (!dc->rd)
                    571:         tcg_gen_movi_tl(cpu_R[dc->rd], 0);
                    572: }
                    573: 
                    574: static void dec_barrel(DisasContext *dc)
                    575: {
                    576:     TCGv t0;
                    577:     unsigned int s, t;
                    578: 
                    579:     s = dc->imm & (1 << 10);
                    580:     t = dc->imm & (1 << 9);
                    581: 
                    582:     LOG_DIS("bs%s%s r%d r%d r%d\n",
                    583:             s ? "l" : "r", t ? "a" : "l", dc->rd, dc->ra, dc->rb);
                    584: 
                    585:     t0 = tcg_temp_new();
                    586: 
                    587:     tcg_gen_mov_tl(t0, *(dec_alu_op_b(dc)));
                    588:     tcg_gen_andi_tl(t0, t0, 31);
                    589: 
                    590:     if (s)
                    591:         tcg_gen_shl_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0);
                    592:     else {
                    593:         if (t)
                    594:             tcg_gen_sar_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0);
                    595:         else
                    596:             tcg_gen_shr_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0);
                    597:     }
                    598: }
                    599: 
                    600: static void dec_bit(DisasContext *dc)
                    601: {
                    602:     TCGv t0, t1;
                    603:     unsigned int op;
                    604: 
                    605:     op = dc->ir & ((1 << 8) - 1);
                    606:     switch (op) {
                    607:         case 0x21:
                    608:             /* src.  */
                    609:             t0 = tcg_temp_new();
                    610: 
                    611:             LOG_DIS("src r%d r%d\n", dc->rd, dc->ra);
                    612:             tcg_gen_andi_tl(t0, cpu_R[dc->ra], 1);
                    613:             if (dc->rd) {
                    614:                 t1 = tcg_temp_new();
                    615:                 read_carry(dc, t1);
                    616:                 tcg_gen_shli_tl(t1, t1, 31);
                    617: 
                    618:                 tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
                    619:                 tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->rd], t1);
                    620:                 tcg_temp_free(t1);
                    621:             }
                    622: 
                    623:             /* Update carry.  */
                    624:             write_carry(dc, t0);
                    625:             tcg_temp_free(t0);
                    626:             break;
                    627: 
                    628:         case 0x1:
                    629:         case 0x41:
                    630:             /* srl.  */
                    631:             t0 = tcg_temp_new();
                    632:             LOG_DIS("srl r%d r%d\n", dc->rd, dc->ra);
                    633: 
                    634:             /* Update carry.  */
                    635:             tcg_gen_andi_tl(t0, cpu_R[dc->ra], 1);
                    636:             write_carry(dc, t0);
                    637:             tcg_temp_free(t0);
                    638:             if (dc->rd) {
                    639:                 if (op == 0x41)
                    640:                     tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
                    641:                 else
                    642:                     tcg_gen_sari_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
                    643:             }
                    644:             break;
                    645:         case 0x60:
                    646:             LOG_DIS("ext8s r%d r%d\n", dc->rd, dc->ra);
                    647:             tcg_gen_ext8s_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
                    648:             break;
                    649:         case 0x61:
                    650:             LOG_DIS("ext16s r%d r%d\n", dc->rd, dc->ra);
                    651:             tcg_gen_ext16s_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
                    652:             break;
                    653:         case 0x64:
                    654:             /* wdc.  */
                    655:             LOG_DIS("wdc r%d\n", dc->ra);
                    656:             break;
                    657:         case 0x68:
                    658:             /* wic.  */
                    659:             LOG_DIS("wic r%d\n", dc->ra);
                    660:             break;
                    661:         default:
                    662:             cpu_abort(dc->env, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
                    663:                      dc->pc, op, dc->rd, dc->ra, dc->rb);
                    664:             break;
                    665:     }
                    666: }
                    667: 
                    668: static inline void sync_jmpstate(DisasContext *dc)
                    669: {
                    670:     if (dc->jmp == JMP_DIRECT) {
                    671:             dc->jmp = JMP_INDIRECT;
                    672:             tcg_gen_movi_tl(env_btaken, 1);
                    673:             tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
                    674:     }
                    675: }
                    676: 
                    677: static void dec_imm(DisasContext *dc)
                    678: {
                    679:     LOG_DIS("imm %x\n", dc->imm << 16);
                    680:     tcg_gen_movi_tl(env_imm, (dc->imm << 16));
                    681:     dc->tb_flags |= IMM_FLAG;
                    682:     dc->clear_imm = 0;
                    683: }
                    684: 
                    685: static inline void gen_load(DisasContext *dc, TCGv dst, TCGv addr,
                    686:                             unsigned int size)
                    687: {
                    688:     int mem_index = cpu_mmu_index(dc->env);
                    689: 
                    690:     if (size == 1) {
                    691:         tcg_gen_qemu_ld8u(dst, addr, mem_index);
                    692:     } else if (size == 2) {
                    693:         tcg_gen_qemu_ld16u(dst, addr, mem_index);
                    694:     } else if (size == 4) {
                    695:         tcg_gen_qemu_ld32u(dst, addr, mem_index);
                    696:     } else
                    697:         cpu_abort(dc->env, "Incorrect load size %d\n", size);
                    698: }
                    699: 
                    700: static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
                    701: {
                    702:     unsigned int extimm = dc->tb_flags & IMM_FLAG;
                    703: 
                    704:     /* Treat the fast cases first.  */
                    705:     if (!dc->type_b) {
                    706:         *t = tcg_temp_new();
                    707:         tcg_gen_add_tl(*t, cpu_R[dc->ra], cpu_R[dc->rb]);
                    708:         return t;
                    709:     }
                    710:     /* Immediate.  */
                    711:     if (!extimm) {
                    712:         if (dc->imm == 0) {
                    713:             return &cpu_R[dc->ra];
                    714:         }
                    715:         *t = tcg_temp_new();
                    716:         tcg_gen_movi_tl(*t, (int32_t)((int16_t)dc->imm));
                    717:         tcg_gen_add_tl(*t, cpu_R[dc->ra], *t);
                    718:     } else {
                    719:         *t = tcg_temp_new();
                    720:         tcg_gen_add_tl(*t, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
                    721:     }
                    722: 
                    723:     return t;
                    724: }
                    725: 
                    726: static void dec_load(DisasContext *dc)
                    727: {
                    728:     TCGv t, *addr;
                    729:     unsigned int size;
                    730: 
                    731:     size = 1 << (dc->opcode & 3);
                    732: 
                    733:     LOG_DIS("l %x %d\n", dc->opcode, size);
                    734:     t_sync_flags(dc);
                    735:     addr = compute_ldst_addr(dc, &t);
                    736: 
                    737:     /* If we get a fault on a dslot, the jmpstate better be in sync.  */
                    738:     sync_jmpstate(dc);
                    739:     if (dc->rd)
                    740:         gen_load(dc, cpu_R[dc->rd], *addr, size);
                    741:     else {
                    742:         gen_load(dc, env_imm, *addr, size);
                    743:     }
                    744: 
                    745:     if (addr == &t)
                    746:         tcg_temp_free(t);
                    747: }
                    748: 
                    749: static void gen_store(DisasContext *dc, TCGv addr, TCGv val,
                    750:                       unsigned int size)
                    751: {
                    752:     int mem_index = cpu_mmu_index(dc->env);
                    753: 
                    754:     if (size == 1)
                    755:         tcg_gen_qemu_st8(val, addr, mem_index);
                    756:     else if (size == 2) {
                    757:         tcg_gen_qemu_st16(val, addr, mem_index);
                    758:     } else if (size == 4) {
                    759:         tcg_gen_qemu_st32(val, addr, mem_index);
                    760:     } else
                    761:         cpu_abort(dc->env, "Incorrect store size %d\n", size);
                    762: }
                    763: 
                    764: static void dec_store(DisasContext *dc)
                    765: {
                    766:     TCGv t, *addr;
                    767:     unsigned int size;
                    768: 
                    769:     size = 1 << (dc->opcode & 3);
                    770: 
                    771:     LOG_DIS("s%d%s\n", size, dc->type_b ? "i" : "");
                    772:     t_sync_flags(dc);
                    773:     /* If we get a fault on a dslot, the jmpstate better be in sync.  */
                    774:     sync_jmpstate(dc);
                    775:     addr = compute_ldst_addr(dc, &t);
                    776:     gen_store(dc, *addr, cpu_R[dc->rd], size);
                    777:     if (addr == &t)
                    778:         tcg_temp_free(t);
                    779: }
                    780: 
                    781: static inline void eval_cc(DisasContext *dc, unsigned int cc,
                    782:                            TCGv d, TCGv a, TCGv b)
                    783: {
                    784:     int l1;
                    785: 
                    786:     switch (cc) {
                    787:         case CC_EQ:
                    788:             l1 = gen_new_label();
                    789:             tcg_gen_movi_tl(env_btaken, 1);
                    790:             tcg_gen_brcond_tl(TCG_COND_EQ, a, b, l1);
                    791:             tcg_gen_movi_tl(env_btaken, 0);
                    792:             gen_set_label(l1);
                    793:             break;
                    794:         case CC_NE:
                    795:             l1 = gen_new_label();
                    796:             tcg_gen_movi_tl(env_btaken, 1);
                    797:             tcg_gen_brcond_tl(TCG_COND_NE, a, b, l1);
                    798:             tcg_gen_movi_tl(env_btaken, 0);
                    799:             gen_set_label(l1);
                    800:             break;
                    801:         case CC_LT:
                    802:             l1 = gen_new_label();
                    803:             tcg_gen_movi_tl(env_btaken, 1);
                    804:             tcg_gen_brcond_tl(TCG_COND_LT, a, b, l1);
                    805:             tcg_gen_movi_tl(env_btaken, 0);
                    806:             gen_set_label(l1);
                    807:             break;
                    808:         case CC_LE:
                    809:             l1 = gen_new_label();
                    810:             tcg_gen_movi_tl(env_btaken, 1);
                    811:             tcg_gen_brcond_tl(TCG_COND_LE, a, b, l1);
                    812:             tcg_gen_movi_tl(env_btaken, 0);
                    813:             gen_set_label(l1);
                    814:             break;
                    815:         case CC_GE:
                    816:             l1 = gen_new_label();
                    817:             tcg_gen_movi_tl(env_btaken, 1);
                    818:             tcg_gen_brcond_tl(TCG_COND_GE, a, b, l1);
                    819:             tcg_gen_movi_tl(env_btaken, 0);
                    820:             gen_set_label(l1);
                    821:             break;
                    822:         case CC_GT:
                    823:             l1 = gen_new_label();
                    824:             tcg_gen_movi_tl(env_btaken, 1);
                    825:             tcg_gen_brcond_tl(TCG_COND_GT, a, b, l1);
                    826:             tcg_gen_movi_tl(env_btaken, 0);
                    827:             gen_set_label(l1);
                    828:             break;
                    829:         default:
                    830:             cpu_abort(dc->env, "Unknown condition code %x.\n", cc);
                    831:             break;
                    832:     }
                    833: }
                    834: 
                    835: static void eval_cond_jmp(DisasContext *dc, TCGv pc_true, TCGv pc_false)
                    836: {
                    837:     int l1;
                    838: 
                    839:     l1 = gen_new_label();
                    840:     /* Conditional jmp.  */
                    841:     tcg_gen_mov_tl(cpu_SR[SR_PC], pc_false);
                    842:     tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1);
                    843:     tcg_gen_mov_tl(cpu_SR[SR_PC], pc_true);
                    844:     gen_set_label(l1);
                    845: }
                    846: 
                    847: static void dec_bcc(DisasContext *dc)
                    848: {
                    849:     unsigned int cc;
                    850:     unsigned int dslot;
                    851: 
                    852:     cc = EXTRACT_FIELD(dc->ir, 21, 23);
                    853:     dslot = dc->ir & (1 << 25);
                    854:     LOG_DIS("bcc%s r%d %x\n", dslot ? "d" : "", dc->ra, dc->imm);
                    855: 
                    856:     dc->delayed_branch = 1;
                    857:     if (dslot) {
                    858:         dc->delayed_branch = 2;
                    859:         dc->tb_flags |= D_FLAG;
                    860:         tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
                    861:                       cpu_env, offsetof(CPUState, bimm));
                    862:     }
                    863: 
                    864:     tcg_gen_movi_tl(env_btarget, dc->pc);
                    865:     tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc)));
                    866:     eval_cc(dc, cc, env_btaken, cpu_R[dc->ra], tcg_const_tl(0));
                    867:     dc->jmp = JMP_INDIRECT;
                    868: }
                    869: 
                    870: static void dec_br(DisasContext *dc)
                    871: {
                    872:     unsigned int dslot, link, abs;
                    873: 
                    874:     dslot = dc->ir & (1 << 20);
                    875:     abs = dc->ir & (1 << 19);
                    876:     link = dc->ir & (1 << 18);
                    877:     LOG_DIS("br%s%s%s%s imm=%x\n",
                    878:              abs ? "a" : "", link ? "l" : "",
                    879:              dc->type_b ? "i" : "", dslot ? "d" : "",
                    880:              dc->imm);
                    881: 
                    882:     dc->delayed_branch = 1;
                    883:     if (dslot) {
                    884:         dc->delayed_branch = 2;
                    885:         dc->tb_flags |= D_FLAG;
                    886:         tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
                    887:                       cpu_env, offsetof(CPUState, bimm));
                    888:     }
                    889:     if (link && dc->rd)
                    890:         tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc);
                    891: 
                    892:     dc->jmp = JMP_INDIRECT;
                    893:     if (abs) {
                    894:         tcg_gen_movi_tl(env_btaken, 1);
                    895:         tcg_gen_mov_tl(env_btarget, *(dec_alu_op_b(dc)));
                    896:         if (link && !(dc->tb_flags & IMM_FLAG)
                    897:             && (dc->imm == 8 || dc->imm == 0x18))
                    898:             t_gen_raise_exception(dc, EXCP_BREAK);
                    899:         if (dc->imm == 0)
                    900:             t_gen_raise_exception(dc, EXCP_DEBUG);
                    901:     } else {
                    902:         if (dc->tb_flags & IMM_FLAG) {
                    903:             tcg_gen_movi_tl(env_btaken, 1);
                    904:             tcg_gen_movi_tl(env_btarget, dc->pc);
                    905:             tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc)));
                    906:         } else {
                    907:             dc->jmp = JMP_DIRECT;
                    908:             dc->jmp_pc = dc->pc + (int32_t)((int16_t)dc->imm);
                    909:         }
                    910:     }
                    911: }
                    912: 
                    913: static inline void do_rti(DisasContext *dc)
                    914: {
                    915:     TCGv t0, t1;
                    916:     t0 = tcg_temp_new();
                    917:     t1 = tcg_temp_new();
                    918:     tcg_gen_shri_tl(t0, cpu_SR[SR_MSR], 1);
                    919:     tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_IE);
                    920:     tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
                    921: 
                    922:     tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
                    923:     tcg_gen_or_tl(t1, t1, t0);
                    924:     msr_write(dc, t1);
                    925:     tcg_temp_free(t1);
                    926:     tcg_temp_free(t0);
                    927:     dc->tb_flags &= ~DRTI_FLAG;
                    928: }
                    929: 
                    930: static inline void do_rtb(DisasContext *dc)
                    931: {
                    932:     TCGv t0, t1;
                    933:     t0 = tcg_temp_new();
                    934:     t1 = tcg_temp_new();
                    935:     tcg_gen_andi_tl(t1, cpu_SR[SR_MSR], ~MSR_BIP);
                    936:     tcg_gen_shri_tl(t0, t1, 1);
                    937:     tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
                    938: 
                    939:     tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
                    940:     tcg_gen_or_tl(t1, t1, t0);
                    941:     msr_write(dc, t1);
                    942:     tcg_temp_free(t1);
                    943:     tcg_temp_free(t0);
                    944:     dc->tb_flags &= ~DRTB_FLAG;
                    945: }
                    946: 
                    947: static inline void do_rte(DisasContext *dc)
                    948: {
                    949:     TCGv t0, t1;
                    950:     t0 = tcg_temp_new();
                    951:     t1 = tcg_temp_new();
                    952: 
                    953:     tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_EE);
                    954:     tcg_gen_andi_tl(t1, t1, ~MSR_EIP);
                    955:     tcg_gen_shri_tl(t0, t1, 1);
                    956:     tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
                    957: 
                    958:     tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
                    959:     tcg_gen_or_tl(t1, t1, t0);
                    960:     msr_write(dc, t1);
                    961:     tcg_temp_free(t1);
                    962:     tcg_temp_free(t0);
                    963:     dc->tb_flags &= ~DRTE_FLAG;
                    964: }
                    965: 
                    966: static void dec_rts(DisasContext *dc)
                    967: {
                    968:     unsigned int b_bit, i_bit, e_bit;
                    969: 
                    970:     i_bit = dc->ir & (1 << 21);
                    971:     b_bit = dc->ir & (1 << 22);
                    972:     e_bit = dc->ir & (1 << 23);
                    973: 
                    974:     dc->delayed_branch = 2;
                    975:     dc->tb_flags |= D_FLAG;
                    976:     tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
                    977:                   cpu_env, offsetof(CPUState, bimm));
                    978: 
                    979:     if (i_bit) {
                    980:         LOG_DIS("rtid ir=%x\n", dc->ir);
                    981:         dc->tb_flags |= DRTI_FLAG;
                    982:     } else if (b_bit) {
                    983:         LOG_DIS("rtbd ir=%x\n", dc->ir);
                    984:         dc->tb_flags |= DRTB_FLAG;
                    985:     } else if (e_bit) {
                    986:         LOG_DIS("rted ir=%x\n", dc->ir);
                    987:         dc->tb_flags |= DRTE_FLAG;
                    988:     } else
                    989:         LOG_DIS("rts ir=%x\n", dc->ir);
                    990: 
                    991:     tcg_gen_movi_tl(env_btaken, 1);
                    992:     tcg_gen_add_tl(env_btarget, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
                    993: }
                    994: 
                    995: static void dec_null(DisasContext *dc)
                    996: {
                    997:     qemu_log ("unknown insn pc=%x opc=%x\n", dc->pc, dc->opcode);
                    998:     dc->abort_at_next_insn = 1;
                    999: }
                   1000: 
                   1001: static struct decoder_info {
                   1002:     struct {
                   1003:         uint32_t bits;
                   1004:         uint32_t mask;
                   1005:     };
                   1006:     void (*dec)(DisasContext *dc);
                   1007: } decinfo[] = {
                   1008:     {DEC_ADD, dec_add},
                   1009:     {DEC_SUB, dec_sub},
                   1010:     {DEC_AND, dec_and},
                   1011:     {DEC_XOR, dec_xor},
                   1012:     {DEC_OR, dec_or},
                   1013:     {DEC_BIT, dec_bit},
                   1014:     {DEC_BARREL, dec_barrel},
                   1015:     {DEC_LD, dec_load},
                   1016:     {DEC_ST, dec_store},
                   1017:     {DEC_IMM, dec_imm},
                   1018:     {DEC_BR, dec_br},
                   1019:     {DEC_BCC, dec_bcc},
                   1020:     {DEC_RTS, dec_rts},
                   1021:     {DEC_MUL, dec_mul},
                   1022:     {DEC_DIV, dec_div},
                   1023:     {DEC_MSR, dec_msr},
                   1024:     {{0, 0}, dec_null}
                   1025: };
                   1026: 
                   1027: static inline void decode(DisasContext *dc)
                   1028: {
                   1029:     uint32_t ir;
                   1030:     int i;
                   1031: 
                   1032:     if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
                   1033:         tcg_gen_debug_insn_start(dc->pc);
                   1034: 
                   1035:     dc->ir = ir = ldl_code(dc->pc);
                   1036:     LOG_DIS("%8.8x\t", dc->ir);
                   1037: 
                   1038:     if (dc->ir)
                   1039:         dc->nr_nops = 0;
                   1040:     else {
                   1041:         LOG_DIS("nr_nops=%d\t", dc->nr_nops);
                   1042:         dc->nr_nops++;
                   1043:         if (dc->nr_nops > 4)
                   1044:             cpu_abort(dc->env, "fetching nop sequence\n");
                   1045:     }
                   1046:     /* bit 2 seems to indicate insn type.  */
                   1047:     dc->type_b = ir & (1 << 29);
                   1048: 
                   1049:     dc->opcode = EXTRACT_FIELD(ir, 26, 31);
                   1050:     dc->rd = EXTRACT_FIELD(ir, 21, 25);
                   1051:     dc->ra = EXTRACT_FIELD(ir, 16, 20);
                   1052:     dc->rb = EXTRACT_FIELD(ir, 11, 15);
                   1053:     dc->imm = EXTRACT_FIELD(ir, 0, 15);
                   1054: 
                   1055:     /* Large switch for all insns.  */
                   1056:     for (i = 0; i < ARRAY_SIZE(decinfo); i++) {
                   1057:         if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) {
                   1058:             decinfo[i].dec(dc);
                   1059:             break;
                   1060:         }
                   1061:     }
                   1062: }
                   1063: 
                   1064: 
                   1065: static void check_breakpoint(CPUState *env, DisasContext *dc)
                   1066: {
                   1067:     CPUBreakpoint *bp;
                   1068: 
                   1069:     if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
                   1070:         TAILQ_FOREACH(bp, &env->breakpoints, entry) {
                   1071:             if (bp->pc == dc->pc) {
                   1072:                 t_gen_raise_exception(dc, EXCP_DEBUG);
                   1073:                 dc->is_jmp = DISAS_UPDATE;
                   1074:              }
                   1075:         }
                   1076:     }
                   1077: }
                   1078: 
                   1079: /* generate intermediate code for basic block 'tb'.  */
                   1080: static void
                   1081: gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
                   1082:                                int search_pc)
                   1083: {
                   1084:     uint16_t *gen_opc_end;
                   1085:     uint32_t pc_start;
                   1086:     int j, lj;
                   1087:     struct DisasContext ctx;
                   1088:     struct DisasContext *dc = &ctx;
                   1089:     uint32_t next_page_start, org_flags;
                   1090:     target_ulong npc;
                   1091:     int num_insns;
                   1092:     int max_insns;
                   1093: 
                   1094:     qemu_log_try_set_file(stderr);
                   1095: 
                   1096:     pc_start = tb->pc;
                   1097:     dc->env = env;
                   1098:     dc->tb = tb;
                   1099:     org_flags = dc->synced_flags = dc->tb_flags = tb->flags;
                   1100: 
                   1101:     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
                   1102: 
                   1103:     dc->is_jmp = DISAS_NEXT;
                   1104:     dc->jmp = 0;
                   1105:     dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
                   1106:     dc->ppc = pc_start;
                   1107:     dc->pc = pc_start;
                   1108:     dc->cache_pc = -1;
                   1109:     dc->singlestep_enabled = env->singlestep_enabled;
                   1110:     dc->cpustate_changed = 0;
                   1111:     dc->abort_at_next_insn = 0;
                   1112:     dc->nr_nops = 0;
                   1113: 
                   1114:     if (pc_start & 3)
                   1115:         cpu_abort(env, "Microblaze: unaligned PC=%x\n", pc_start);
                   1116: 
                   1117:     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
                   1118: #if !SIM_COMPAT
                   1119:         qemu_log("--------------\n");
                   1120:         log_cpu_state(env, 0);
                   1121: #endif
                   1122:     }
                   1123: 
                   1124:     next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
                   1125:     lj = -1;
                   1126:     num_insns = 0;
                   1127:     max_insns = tb->cflags & CF_COUNT_MASK;
                   1128:     if (max_insns == 0)
                   1129:         max_insns = CF_COUNT_MASK;
                   1130: 
                   1131:     gen_icount_start();
                   1132:     do
                   1133:     {
                   1134: #if SIM_COMPAT
                   1135:         if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
                   1136:             tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
                   1137:             gen_helper_debug();
                   1138:         }
                   1139: #endif
                   1140:         check_breakpoint(env, dc);
                   1141: 
                   1142:         if (search_pc) {
                   1143:             j = gen_opc_ptr - gen_opc_buf;
                   1144:             if (lj < j) {
                   1145:                 lj++;
                   1146:                 while (lj < j)
                   1147:                     gen_opc_instr_start[lj++] = 0;
                   1148:             }
                   1149:             gen_opc_pc[lj] = dc->pc;
                   1150:             gen_opc_instr_start[lj] = 1;
                   1151:                         gen_opc_icount[lj] = num_insns;
                   1152:         }
                   1153: 
                   1154:         /* Pretty disas.  */
                   1155:         LOG_DIS("%8.8x:\t", dc->pc);
                   1156: 
                   1157:         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
                   1158:             gen_io_start();
                   1159: 
                   1160:         dc->clear_imm = 1;
                   1161:        decode(dc);
                   1162:         if (dc->clear_imm)
                   1163:             dc->tb_flags &= ~IMM_FLAG;
                   1164:         dc->ppc = dc->pc;
                   1165:         dc->pc += 4;
                   1166:         num_insns++;
                   1167: 
                   1168:         if (dc->delayed_branch) {
                   1169:             dc->delayed_branch--;
                   1170:             if (!dc->delayed_branch) {
                   1171:                 if (dc->tb_flags & DRTI_FLAG)
                   1172:                     do_rti(dc);
                   1173:                  if (dc->tb_flags & DRTB_FLAG)
                   1174:                     do_rtb(dc);
                   1175:                 if (dc->tb_flags & DRTE_FLAG)
                   1176:                     do_rte(dc);
                   1177:                 /* Clear the delay slot flag.  */
                   1178:                 dc->tb_flags &= ~D_FLAG;
                   1179:                 /* If it is a direct jump, try direct chaining.  */
                   1180:                 if (dc->jmp != JMP_DIRECT) {
                   1181:                     eval_cond_jmp(dc, env_btarget, tcg_const_tl(dc->pc));
                   1182:                     dc->is_jmp = DISAS_JUMP;
                   1183:                 }
                   1184:                 break;
                   1185:             }
                   1186:         }
                   1187:         if (env->singlestep_enabled)
                   1188:             break;
                   1189:     } while (!dc->is_jmp && !dc->cpustate_changed
                   1190:          && gen_opc_ptr < gen_opc_end
                   1191:                  && !singlestep
                   1192:          && (dc->pc < next_page_start)
                   1193:                  && num_insns < max_insns);
                   1194: 
                   1195:     npc = dc->pc;
                   1196:     if (dc->jmp == JMP_DIRECT) {
                   1197:         if (dc->tb_flags & D_FLAG) {
                   1198:             dc->is_jmp = DISAS_UPDATE;
                   1199:             tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
                   1200:             sync_jmpstate(dc);
                   1201:         } else
                   1202:             npc = dc->jmp_pc;
                   1203:     }
                   1204: 
                   1205:     if (tb->cflags & CF_LAST_IO)
                   1206:         gen_io_end();
                   1207:     /* Force an update if the per-tb cpu state has changed.  */
                   1208:     if (dc->is_jmp == DISAS_NEXT
                   1209:         && (dc->cpustate_changed || org_flags != dc->tb_flags)) {
                   1210:         dc->is_jmp = DISAS_UPDATE;
                   1211:         tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
                   1212:     }
                   1213:     t_sync_flags(dc);
                   1214: 
                   1215:     if (unlikely(env->singlestep_enabled)) {
                   1216:         t_gen_raise_exception(dc, EXCP_DEBUG);
                   1217:         if (dc->is_jmp == DISAS_NEXT)
                   1218:             tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
                   1219:     } else {
                   1220:         switch(dc->is_jmp) {
                   1221:             case DISAS_NEXT:
                   1222:                 gen_goto_tb(dc, 1, npc);
                   1223:                 break;
                   1224:             default:
                   1225:             case DISAS_JUMP:
                   1226:             case DISAS_UPDATE:
                   1227:                 /* indicate that the hash table must be used
                   1228:                    to find the next TB */
                   1229:                 tcg_gen_exit_tb(0);
                   1230:                 break;
                   1231:             case DISAS_TB_JUMP:
                   1232:                 /* nothing more to generate */
                   1233:                 break;
                   1234:         }
                   1235:     }
                   1236:     gen_icount_end(tb, num_insns);
                   1237:     *gen_opc_ptr = INDEX_op_end;
                   1238:     if (search_pc) {
                   1239:         j = gen_opc_ptr - gen_opc_buf;
                   1240:         lj++;
                   1241:         while (lj <= j)
                   1242:             gen_opc_instr_start[lj++] = 0;
                   1243:     } else {
                   1244:         tb->size = dc->pc - pc_start;
                   1245:                 tb->icount = num_insns;
                   1246:     }
                   1247: 
                   1248: #ifdef DEBUG_DISAS
                   1249: #if !SIM_COMPAT
                   1250:     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
                   1251:         qemu_log("\n");
                   1252: #if DISAS_GNU
                   1253:         log_target_disas(pc_start, dc->pc - pc_start, 0);
                   1254: #endif
                   1255:         qemu_log("\nisize=%d osize=%zd\n",
                   1256:             dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
                   1257:     }
                   1258: #endif
                   1259: #endif
                   1260:     assert(!dc->abort_at_next_insn);
                   1261: }
                   1262: 
                   1263: void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
                   1264: {
                   1265:     gen_intermediate_code_internal(env, tb, 0);
                   1266: }
                   1267: 
                   1268: void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
                   1269: {
                   1270:     gen_intermediate_code_internal(env, tb, 1);
                   1271: }
                   1272: 
                   1273: void cpu_dump_state (CPUState *env, FILE *f,
                   1274:                      int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                   1275:                      int flags)
                   1276: {
                   1277:     int i;
                   1278: 
                   1279:     if (!env || !f)
                   1280:         return;
                   1281: 
                   1282:     cpu_fprintf(f, "IN: PC=%x %s\n",
                   1283:                 env->sregs[SR_PC], lookup_symbol(env->sregs[SR_PC]));
                   1284:     cpu_fprintf(f, "rmsr=%x resr=%x debug[%x] imm=%x iflags=%x\n",
                   1285:              env->sregs[SR_MSR], env->sregs[SR_ESR],
                   1286:              env->debug, env->imm, env->iflags);
                   1287:     cpu_fprintf(f, "btaken=%d btarget=%x mode=%s(saved=%s)\n",
                   1288:              env->btaken, env->btarget,
                   1289:              (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel",
                   1290:              (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel");
                   1291:     for (i = 0; i < 32; i++) {
                   1292:         cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
                   1293:         if ((i + 1) % 4 == 0)
                   1294:             cpu_fprintf(f, "\n");
                   1295:         }
                   1296:     cpu_fprintf(f, "\n\n");
                   1297: }
                   1298: 
                   1299: CPUState *cpu_mb_init (const char *cpu_model)
                   1300: {
                   1301:     CPUState *env;
                   1302:     static int tcg_initialized = 0;
                   1303:     int i;
                   1304: 
                   1305:     env = qemu_mallocz(sizeof(CPUState));
                   1306: 
                   1307:     cpu_exec_init(env);
                   1308:     cpu_reset(env);
                   1309: 
                   1310:     env->pvr.regs[0] = PVR0_PVR_FULL_MASK \
                   1311:                        | PVR0_USE_BARREL_MASK \
                   1312:                        | PVR0_USE_DIV_MASK \
                   1313:                        | PVR0_USE_HW_MUL_MASK \
                   1314:                        | PVR0_USE_EXC_MASK \
                   1315:                        | PVR0_USE_ICACHE_MASK \
                   1316:                        | PVR0_USE_DCACHE_MASK \
                   1317:                        | PVR0_USE_MMU \
                   1318:                        | (0xb << 8);
                   1319:      env->pvr.regs[2] = PVR2_D_OPB_MASK \
                   1320:                         | PVR2_D_LMB_MASK \
                   1321:                         | PVR2_I_OPB_MASK \
                   1322:                         | PVR2_I_LMB_MASK \
                   1323:                         | PVR2_USE_MSR_INSTR \
                   1324:                         | PVR2_USE_PCMP_INSTR \
                   1325:                         | PVR2_USE_BARREL_MASK \
                   1326:                         | PVR2_USE_DIV_MASK \
                   1327:                         | PVR2_USE_HW_MUL_MASK \
                   1328:                         | PVR2_USE_MUL64_MASK \
                   1329:                         | 0;
                   1330:      env->pvr.regs[10] = 0x0c000000; /* Default to spartan 3a dsp family.  */
                   1331:      env->pvr.regs[11] = PVR11_USE_MMU;
                   1332: 
                   1333:     if (tcg_initialized)
                   1334:         return env;
                   1335: 
                   1336:     tcg_initialized = 1;
                   1337: 
                   1338:     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
                   1339: 
                   1340:     env_debug = tcg_global_mem_new(TCG_AREG0, 
                   1341:                     offsetof(CPUState, debug),
                   1342:                     "debug0");
                   1343:     env_iflags = tcg_global_mem_new(TCG_AREG0, 
                   1344:                     offsetof(CPUState, iflags),
                   1345:                     "iflags");
                   1346:     env_imm = tcg_global_mem_new(TCG_AREG0, 
                   1347:                     offsetof(CPUState, imm),
                   1348:                     "imm");
                   1349:     env_btarget = tcg_global_mem_new(TCG_AREG0,
                   1350:                      offsetof(CPUState, btarget),
                   1351:                      "btarget");
                   1352:     env_btaken = tcg_global_mem_new(TCG_AREG0,
                   1353:                      offsetof(CPUState, btaken),
                   1354:                      "btaken");
                   1355:     for (i = 0; i < ARRAY_SIZE(cpu_R); i++) {
                   1356:         cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
                   1357:                           offsetof(CPUState, regs[i]),
                   1358:                           regnames[i]);
                   1359:     }
                   1360:     for (i = 0; i < ARRAY_SIZE(cpu_SR); i++) {
                   1361:         cpu_SR[i] = tcg_global_mem_new(TCG_AREG0,
                   1362:                           offsetof(CPUState, sregs[i]),
                   1363:                           special_regnames[i]);
                   1364:     }
                   1365: #define GEN_HELPER 2
                   1366: #include "helper.h"
                   1367: 
                   1368:     return env;
                   1369: }
                   1370: 
                   1371: void cpu_reset (CPUState *env)
                   1372: {
                   1373:     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
                   1374:         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
                   1375:         log_cpu_state(env, 0);
                   1376:     }
                   1377: 
                   1378:     memset(env, 0, offsetof(CPUMBState, breakpoints));
                   1379:     tlb_flush(env, 1);
                   1380: 
                   1381:     env->sregs[SR_MSR] = 0;
                   1382: #if defined(CONFIG_USER_ONLY)
                   1383:     /* start in user mode with interrupts enabled.  */
                   1384:     env->pvr.regs[10] = 0x0c000000; /* Spartan 3a dsp.  */
                   1385: #else
                   1386:     mmu_init(&env->mmu);
                   1387: #endif
                   1388: }
                   1389: 
                   1390: void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
                   1391:                  unsigned long searched_pc, int pc_pos, void *puc)
                   1392: {
                   1393:     env->sregs[SR_PC] = gen_opc_pc[pc_pos];
                   1394: }

unix.superglobalmegacorp.com

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