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