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

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

unix.superglobalmegacorp.com

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