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