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