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