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