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

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

unix.superglobalmegacorp.com

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