1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "qemu/osdep.h"
22#include "cpu.h"
23#include "disas/disas.h"
24#include "exec/exec-all.h"
25#include "tcg-op.h"
26#include "exec/helper-proto.h"
27#include "microblaze-decode.h"
28#include "exec/cpu_ldst.h"
29#include "exec/helper-gen.h"
30#include "exec/translator.h"
31#include "qemu/qemu-print.h"
32
33#include "trace-tcg.h"
34#include "exec/log.h"
35
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
52#define DISAS_JUMP DISAS_TARGET_0
53#define DISAS_UPDATE DISAS_TARGET_1
54#define DISAS_TB_JUMP DISAS_TARGET_2
55
56static TCGv_i32 env_debug;
57static TCGv_i32 cpu_R[32];
58static TCGv_i64 cpu_SR[14];
59static TCGv_i32 env_imm;
60static TCGv_i32 env_btaken;
61static TCGv_i64 env_btarget;
62static TCGv_i32 env_iflags;
63static TCGv env_res_addr;
64static TCGv_i32 env_res_val;
65
66#include "exec/gen-icount.h"
67
68
69typedef struct DisasContext {
70 MicroBlazeCPU *cpu;
71 uint32_t pc;
72
73
74 int type_b;
75 uint32_t ir;
76 uint8_t opcode;
77 uint8_t rd, ra, rb;
78 uint16_t imm;
79
80 unsigned int cpustate_changed;
81 unsigned int delayed_branch;
82 unsigned int tb_flags, synced_flags;
83 unsigned int clear_imm;
84 int is_jmp;
85
86#define JMP_NOJMP 0
87#define JMP_DIRECT 1
88#define JMP_DIRECT_CC 2
89#define JMP_INDIRECT 3
90 unsigned int jmp;
91 uint32_t jmp_pc;
92
93 int abort_at_next_insn;
94 struct TranslationBlock *tb;
95 int singlestep_enabled;
96} DisasContext;
97
98static const char *regnames[] =
99{
100 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
101 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
102 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
103 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
104};
105
106static const char *special_regnames[] =
107{
108 "rpc", "rmsr", "sr2", "rear", "sr4", "resr", "sr6", "rfsr",
109 "sr8", "sr9", "sr10", "rbtr", "sr12", "redr"
110};
111
112static inline void t_sync_flags(DisasContext *dc)
113{
114
115 if (dc->tb_flags != dc->synced_flags) {
116 tcg_gen_movi_i32(env_iflags, dc->tb_flags);
117 dc->synced_flags = dc->tb_flags;
118 }
119}
120
121static inline void t_gen_raise_exception(DisasContext *dc, uint32_t index)
122{
123 TCGv_i32 tmp = tcg_const_i32(index);
124
125 t_sync_flags(dc);
126 tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc);
127 gen_helper_raise_exception(cpu_env, tmp);
128 tcg_temp_free_i32(tmp);
129 dc->is_jmp = DISAS_UPDATE;
130}
131
132static inline bool use_goto_tb(DisasContext *dc, target_ulong dest)
133{
134#ifndef CONFIG_USER_ONLY
135 return (dc->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
136#else
137 return true;
138#endif
139}
140
141static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
142{
143 if (use_goto_tb(dc, dest)) {
144 tcg_gen_goto_tb(n);
145 tcg_gen_movi_i64(cpu_SR[SR_PC], dest);
146 tcg_gen_exit_tb(dc->tb, n);
147 } else {
148 tcg_gen_movi_i64(cpu_SR[SR_PC], dest);
149 tcg_gen_exit_tb(NULL, 0);
150 }
151}
152
153static void read_carry(DisasContext *dc, TCGv_i32 d)
154{
155 tcg_gen_extrl_i64_i32(d, cpu_SR[SR_MSR]);
156 tcg_gen_shri_i32(d, d, 31);
157}
158
159
160
161
162
163static void write_carry(DisasContext *dc, TCGv_i32 v)
164{
165 TCGv_i64 t0 = tcg_temp_new_i64();
166 tcg_gen_extu_i32_i64(t0, v);
167
168 tcg_gen_deposit_i64(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t0, 2, 1);
169 tcg_gen_deposit_i64(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t0, 31, 1);
170 tcg_temp_free_i64(t0);
171}
172
173static void write_carryi(DisasContext *dc, bool carry)
174{
175 TCGv_i32 t0 = tcg_temp_new_i32();
176 tcg_gen_movi_i32(t0, carry);
177 write_carry(dc, t0);
178 tcg_temp_free_i32(t0);
179}
180
181
182
183
184
185static bool trap_illegal(DisasContext *dc, bool cond)
186{
187 if (cond && (dc->tb_flags & MSR_EE_FLAG)
188 && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
189 tcg_gen_movi_i64(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
190 t_gen_raise_exception(dc, EXCP_HW_EXCP);
191 }
192 return cond;
193}
194
195
196
197
198
199static bool trap_userspace(DisasContext *dc, bool cond)
200{
201 int mem_index = cpu_mmu_index(&dc->cpu->env, false);
202 bool cond_user = cond && mem_index == MMU_USER_IDX;
203
204 if (cond_user && (dc->tb_flags & MSR_EE_FLAG)) {
205 tcg_gen_movi_i64(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
206 t_gen_raise_exception(dc, EXCP_HW_EXCP);
207 }
208 return cond_user;
209}
210
211
212
213static inline int dec_alu_op_b_is_small_imm(DisasContext *dc)
214{
215
216 return dc->type_b && !(dc->tb_flags & IMM_FLAG);
217}
218
219static inline TCGv_i32 *dec_alu_op_b(DisasContext *dc)
220{
221 if (dc->type_b) {
222 if (dc->tb_flags & IMM_FLAG)
223 tcg_gen_ori_i32(env_imm, env_imm, dc->imm);
224 else
225 tcg_gen_movi_i32(env_imm, (int32_t)((int16_t)dc->imm));
226 return &env_imm;
227 } else
228 return &cpu_R[dc->rb];
229}
230
231static void dec_add(DisasContext *dc)
232{
233 unsigned int k, c;
234 TCGv_i32 cf;
235
236 k = dc->opcode & 4;
237 c = dc->opcode & 2;
238
239 LOG_DIS("add%s%s%s r%d r%d r%d\n",
240 dc->type_b ? "i" : "", k ? "k" : "", c ? "c" : "",
241 dc->rd, dc->ra, dc->rb);
242
243
244 if (k) {
245
246
247 if (dc->rd) {
248 tcg_gen_add_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
249
250 if (c) {
251
252 cf = tcg_temp_new_i32();
253
254 read_carry(dc, cf);
255 tcg_gen_add_i32(cpu_R[dc->rd], cpu_R[dc->rd], cf);
256 tcg_temp_free_i32(cf);
257 }
258 }
259 return;
260 }
261
262
263
264 cf = tcg_temp_new_i32();
265 if (c) {
266 read_carry(dc, cf);
267 } else {
268 tcg_gen_movi_i32(cf, 0);
269 }
270
271 if (dc->rd) {
272 TCGv_i32 ncf = tcg_temp_new_i32();
273 gen_helper_carry(ncf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf);
274 tcg_gen_add_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
275 tcg_gen_add_i32(cpu_R[dc->rd], cpu_R[dc->rd], cf);
276 write_carry(dc, ncf);
277 tcg_temp_free_i32(ncf);
278 } else {
279 gen_helper_carry(cf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf);
280 write_carry(dc, cf);
281 }
282 tcg_temp_free_i32(cf);
283}
284
285static void dec_sub(DisasContext *dc)
286{
287 unsigned int u, cmp, k, c;
288 TCGv_i32 cf, na;
289
290 u = dc->imm & 2;
291 k = dc->opcode & 4;
292 c = dc->opcode & 2;
293 cmp = (dc->imm & 1) && (!dc->type_b) && k;
294
295 if (cmp) {
296 LOG_DIS("cmp%s r%d, r%d ir=%x\n", u ? "u" : "", dc->rd, dc->ra, dc->ir);
297 if (dc->rd) {
298 if (u)
299 gen_helper_cmpu(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
300 else
301 gen_helper_cmp(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
302 }
303 return;
304 }
305
306 LOG_DIS("sub%s%s r%d, r%d r%d\n",
307 k ? "k" : "", c ? "c" : "", dc->rd, dc->ra, dc->rb);
308
309
310 if (k) {
311
312
313 if (dc->rd) {
314 tcg_gen_sub_i32(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
315
316 if (c) {
317
318 cf = tcg_temp_new_i32();
319
320 read_carry(dc, cf);
321 tcg_gen_add_i32(cpu_R[dc->rd], cpu_R[dc->rd], cf);
322 tcg_temp_free_i32(cf);
323 }
324 }
325 return;
326 }
327
328
329
330 cf = tcg_temp_new_i32();
331 na = tcg_temp_new_i32();
332 if (c) {
333 read_carry(dc, cf);
334 } else {
335 tcg_gen_movi_i32(cf, 1);
336 }
337
338
339 tcg_gen_not_i32(na, cpu_R[dc->ra]);
340
341 if (dc->rd) {
342 TCGv_i32 ncf = tcg_temp_new_i32();
343 gen_helper_carry(ncf, na, *(dec_alu_op_b(dc)), cf);
344 tcg_gen_add_i32(cpu_R[dc->rd], na, *(dec_alu_op_b(dc)));
345 tcg_gen_add_i32(cpu_R[dc->rd], cpu_R[dc->rd], cf);
346 write_carry(dc, ncf);
347 tcg_temp_free_i32(ncf);
348 } else {
349 gen_helper_carry(cf, na, *(dec_alu_op_b(dc)), cf);
350 write_carry(dc, cf);
351 }
352 tcg_temp_free_i32(cf);
353 tcg_temp_free_i32(na);
354}
355
356static void dec_pattern(DisasContext *dc)
357{
358 unsigned int mode;
359
360 if (trap_illegal(dc, !dc->cpu->cfg.use_pcmp_instr)) {
361 return;
362 }
363
364 mode = dc->opcode & 3;
365 switch (mode) {
366 case 0:
367
368 LOG_DIS("pcmpbf r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
369 if (dc->rd)
370 gen_helper_pcmpbf(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
371 break;
372 case 2:
373 LOG_DIS("pcmpeq r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
374 if (dc->rd) {
375 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_R[dc->rd],
376 cpu_R[dc->ra], cpu_R[dc->rb]);
377 }
378 break;
379 case 3:
380 LOG_DIS("pcmpne r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
381 if (dc->rd) {
382 tcg_gen_setcond_i32(TCG_COND_NE, cpu_R[dc->rd],
383 cpu_R[dc->ra], cpu_R[dc->rb]);
384 }
385 break;
386 default:
387 cpu_abort(CPU(dc->cpu),
388 "unsupported pattern insn opcode=%x\n", dc->opcode);
389 break;
390 }
391}
392
393static void dec_and(DisasContext *dc)
394{
395 unsigned int not;
396
397 if (!dc->type_b && (dc->imm & (1 << 10))) {
398 dec_pattern(dc);
399 return;
400 }
401
402 not = dc->opcode & (1 << 1);
403 LOG_DIS("and%s\n", not ? "n" : "");
404
405 if (!dc->rd)
406 return;
407
408 if (not) {
409 tcg_gen_andc_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
410 } else
411 tcg_gen_and_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
412}
413
414static void dec_or(DisasContext *dc)
415{
416 if (!dc->type_b && (dc->imm & (1 << 10))) {
417 dec_pattern(dc);
418 return;
419 }
420
421 LOG_DIS("or r%d r%d r%d imm=%x\n", dc->rd, dc->ra, dc->rb, dc->imm);
422 if (dc->rd)
423 tcg_gen_or_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
424}
425
426static void dec_xor(DisasContext *dc)
427{
428 if (!dc->type_b && (dc->imm & (1 << 10))) {
429 dec_pattern(dc);
430 return;
431 }
432
433 LOG_DIS("xor r%d\n", dc->rd);
434 if (dc->rd)
435 tcg_gen_xor_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
436}
437
438static inline void msr_read(DisasContext *dc, TCGv_i32 d)
439{
440 tcg_gen_extrl_i64_i32(d, cpu_SR[SR_MSR]);
441}
442
443static inline void msr_write(DisasContext *dc, TCGv_i32 v)
444{
445 TCGv_i64 t;
446
447 t = tcg_temp_new_i64();
448 dc->cpustate_changed = 1;
449
450 tcg_gen_extu_i32_i64(t, v);
451 tcg_gen_andi_i64(t, t, ~MSR_PVR);
452 tcg_gen_andi_i64(cpu_SR[SR_MSR], cpu_SR[SR_MSR], MSR_PVR);
453 tcg_gen_or_i64(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t);
454 tcg_temp_free_i64(t);
455}
456
457static void dec_msr(DisasContext *dc)
458{
459 CPUState *cs = CPU(dc->cpu);
460 TCGv_i32 t0, t1;
461 unsigned int sr, rn;
462 bool to, clrset, extended = false;
463
464 sr = extract32(dc->imm, 0, 14);
465 to = extract32(dc->imm, 14, 1);
466 clrset = extract32(dc->imm, 15, 1) == 0;
467 dc->type_b = 1;
468 if (to) {
469 dc->cpustate_changed = 1;
470 }
471
472
473 if (dc->cpu->cfg.addr_size > 32) {
474
475 static const unsigned int e_bit[] = { 19, 24 };
476
477 extended = extract32(dc->imm, e_bit[to], 1);
478 }
479
480
481 if (clrset) {
482 bool clr = extract32(dc->ir, 16, 1);
483
484 LOG_DIS("msr%s r%d imm=%x\n", clr ? "clr" : "set",
485 dc->rd, dc->imm);
486
487 if (!dc->cpu->cfg.use_msr_instr) {
488
489 return;
490 }
491
492 if (trap_userspace(dc, dc->imm != 4 && dc->imm != 0)) {
493 return;
494 }
495
496 if (dc->rd)
497 msr_read(dc, cpu_R[dc->rd]);
498
499 t0 = tcg_temp_new_i32();
500 t1 = tcg_temp_new_i32();
501 msr_read(dc, t0);
502 tcg_gen_mov_i32(t1, *(dec_alu_op_b(dc)));
503
504 if (clr) {
505 tcg_gen_not_i32(t1, t1);
506 tcg_gen_and_i32(t0, t0, t1);
507 } else
508 tcg_gen_or_i32(t0, t0, t1);
509 msr_write(dc, t0);
510 tcg_temp_free_i32(t0);
511 tcg_temp_free_i32(t1);
512 tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc + 4);
513 dc->is_jmp = DISAS_UPDATE;
514 return;
515 }
516
517 if (trap_userspace(dc, to)) {
518 return;
519 }
520
521#if !defined(CONFIG_USER_ONLY)
522
523 if ((sr & ~0xff) == 0x1000) {
524 TCGv_i32 tmp_ext = tcg_const_i32(extended);
525 TCGv_i32 tmp_sr;
526
527 sr &= 7;
528 tmp_sr = tcg_const_i32(sr);
529 LOG_DIS("m%ss sr%d r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm);
530 if (to) {
531 gen_helper_mmu_write(cpu_env, tmp_ext, tmp_sr, cpu_R[dc->ra]);
532 } else {
533 gen_helper_mmu_read(cpu_R[dc->rd], cpu_env, tmp_ext, tmp_sr);
534 }
535 tcg_temp_free_i32(tmp_sr);
536 tcg_temp_free_i32(tmp_ext);
537 return;
538 }
539#endif
540
541 if (to) {
542 LOG_DIS("m%ss sr%x r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm);
543 switch (sr) {
544 case 0:
545 break;
546 case 1:
547 msr_write(dc, cpu_R[dc->ra]);
548 break;
549 case SR_EAR:
550 case SR_ESR:
551 case SR_FSR:
552 tcg_gen_extu_i32_i64(cpu_SR[sr], cpu_R[dc->ra]);
553 break;
554 case 0x800:
555 tcg_gen_st_i32(cpu_R[dc->ra],
556 cpu_env, offsetof(CPUMBState, slr));
557 break;
558 case 0x802:
559 tcg_gen_st_i32(cpu_R[dc->ra],
560 cpu_env, offsetof(CPUMBState, shr));
561 break;
562 default:
563 cpu_abort(CPU(dc->cpu), "unknown mts reg %x\n", sr);
564 break;
565 }
566 } else {
567 LOG_DIS("m%ss r%d sr%x imm=%x\n", to ? "t" : "f", dc->rd, sr, dc->imm);
568
569 switch (sr) {
570 case 0:
571 tcg_gen_movi_i32(cpu_R[dc->rd], dc->pc);
572 break;
573 case 1:
574 msr_read(dc, cpu_R[dc->rd]);
575 break;
576 case SR_EAR:
577 if (extended) {
578 tcg_gen_extrh_i64_i32(cpu_R[dc->rd], cpu_SR[sr]);
579 break;
580 }
581 case SR_ESR:
582 case SR_FSR:
583 case SR_BTR:
584 tcg_gen_extrl_i64_i32(cpu_R[dc->rd], cpu_SR[sr]);
585 break;
586 case 0x800:
587 tcg_gen_ld_i32(cpu_R[dc->rd],
588 cpu_env, offsetof(CPUMBState, slr));
589 break;
590 case 0x802:
591 tcg_gen_ld_i32(cpu_R[dc->rd],
592 cpu_env, offsetof(CPUMBState, shr));
593 break;
594 case 0x2000 ... 0x200c:
595 rn = sr & 0xf;
596 tcg_gen_ld_i32(cpu_R[dc->rd],
597 cpu_env, offsetof(CPUMBState, pvr.regs[rn]));
598 break;
599 default:
600 cpu_abort(cs, "unknown mfs reg %x\n", sr);
601 break;
602 }
603 }
604
605 if (dc->rd == 0) {
606 tcg_gen_movi_i32(cpu_R[0], 0);
607 }
608}
609
610
611static void dec_mul(DisasContext *dc)
612{
613 TCGv_i32 tmp;
614 unsigned int subcode;
615
616 if (trap_illegal(dc, !dc->cpu->cfg.use_hw_mul)) {
617 return;
618 }
619
620 subcode = dc->imm & 3;
621
622 if (dc->type_b) {
623 LOG_DIS("muli r%d r%d %x\n", dc->rd, dc->ra, dc->imm);
624 tcg_gen_mul_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
625 return;
626 }
627
628
629 if (subcode >= 1 && subcode <= 3 && dc->cpu->cfg.use_hw_mul < 2) {
630
631 }
632
633 tmp = tcg_temp_new_i32();
634 switch (subcode) {
635 case 0:
636 LOG_DIS("mul r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
637 tcg_gen_mul_i32(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
638 break;
639 case 1:
640 LOG_DIS("mulh r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
641 tcg_gen_muls2_i32(tmp, cpu_R[dc->rd],
642 cpu_R[dc->ra], cpu_R[dc->rb]);
643 break;
644 case 2:
645 LOG_DIS("mulhsu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
646 tcg_gen_mulsu2_i32(tmp, cpu_R[dc->rd],
647 cpu_R[dc->ra], cpu_R[dc->rb]);
648 break;
649 case 3:
650 LOG_DIS("mulhu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
651 tcg_gen_mulu2_i32(tmp, cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
652 break;
653 default:
654 cpu_abort(CPU(dc->cpu), "unknown MUL insn %x\n", subcode);
655 break;
656 }
657 tcg_temp_free_i32(tmp);
658}
659
660
661static void dec_div(DisasContext *dc)
662{
663 unsigned int u;
664
665 u = dc->imm & 2;
666 LOG_DIS("div\n");
667
668 if (trap_illegal(dc, !dc->cpu->cfg.use_div)) {
669 return;
670 }
671
672 if (u)
673 gen_helper_divu(cpu_R[dc->rd], cpu_env, *(dec_alu_op_b(dc)),
674 cpu_R[dc->ra]);
675 else
676 gen_helper_divs(cpu_R[dc->rd], cpu_env, *(dec_alu_op_b(dc)),
677 cpu_R[dc->ra]);
678 if (!dc->rd)
679 tcg_gen_movi_i32(cpu_R[dc->rd], 0);
680}
681
682static void dec_barrel(DisasContext *dc)
683{
684 TCGv_i32 t0;
685 unsigned int imm_w, imm_s;
686 bool s, t, e = false, i = false;
687
688 if (trap_illegal(dc, !dc->cpu->cfg.use_barrel)) {
689 return;
690 }
691
692 if (dc->type_b) {
693
694 i = extract32(dc->imm, 15, 1);
695 e = extract32(dc->imm, 14, 1);
696 }
697 s = extract32(dc->imm, 10, 1);
698 t = extract32(dc->imm, 9, 1);
699 imm_w = extract32(dc->imm, 6, 5);
700 imm_s = extract32(dc->imm, 0, 5);
701
702 LOG_DIS("bs%s%s%s r%d r%d r%d\n",
703 e ? "e" : "",
704 s ? "l" : "r", t ? "a" : "l", dc->rd, dc->ra, dc->rb);
705
706 if (e) {
707 if (imm_w + imm_s > 32 || imm_w == 0) {
708
709 qemu_log_mask(LOG_GUEST_ERROR, "bsefi: Bad input w=%d s=%d\n",
710 imm_w, imm_s);
711 } else {
712 tcg_gen_extract_i32(cpu_R[dc->rd], cpu_R[dc->ra], imm_s, imm_w);
713 }
714 } else if (i) {
715 int width = imm_w - imm_s + 1;
716
717 if (imm_w < imm_s) {
718
719 qemu_log_mask(LOG_GUEST_ERROR, "bsifi: Bad input w=%d s=%d\n",
720 imm_w, imm_s);
721 } else {
722 tcg_gen_deposit_i32(cpu_R[dc->rd], cpu_R[dc->rd], cpu_R[dc->ra],
723 imm_s, width);
724 }
725 } else {
726 t0 = tcg_temp_new_i32();
727
728 tcg_gen_mov_i32(t0, *(dec_alu_op_b(dc)));
729 tcg_gen_andi_i32(t0, t0, 31);
730
731 if (s) {
732 tcg_gen_shl_i32(cpu_R[dc->rd], cpu_R[dc->ra], t0);
733 } else {
734 if (t) {
735 tcg_gen_sar_i32(cpu_R[dc->rd], cpu_R[dc->ra], t0);
736 } else {
737 tcg_gen_shr_i32(cpu_R[dc->rd], cpu_R[dc->ra], t0);
738 }
739 }
740 tcg_temp_free_i32(t0);
741 }
742}
743
744static void dec_bit(DisasContext *dc)
745{
746 CPUState *cs = CPU(dc->cpu);
747 TCGv_i32 t0;
748 unsigned int op;
749
750 op = dc->ir & ((1 << 9) - 1);
751 switch (op) {
752 case 0x21:
753
754 t0 = tcg_temp_new_i32();
755
756 LOG_DIS("src r%d r%d\n", dc->rd, dc->ra);
757 tcg_gen_extrl_i64_i32(t0, cpu_SR[SR_MSR]);
758 tcg_gen_andi_i32(t0, t0, MSR_CC);
759 write_carry(dc, cpu_R[dc->ra]);
760 if (dc->rd) {
761 tcg_gen_shri_i32(cpu_R[dc->rd], cpu_R[dc->ra], 1);
762 tcg_gen_or_i32(cpu_R[dc->rd], cpu_R[dc->rd], t0);
763 }
764 tcg_temp_free_i32(t0);
765 break;
766
767 case 0x1:
768 case 0x41:
769
770 LOG_DIS("srl r%d r%d\n", dc->rd, dc->ra);
771
772
773 write_carry(dc, cpu_R[dc->ra]);
774 if (dc->rd) {
775 if (op == 0x41)
776 tcg_gen_shri_i32(cpu_R[dc->rd], cpu_R[dc->ra], 1);
777 else
778 tcg_gen_sari_i32(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:
790 case 0x66:
791 case 0x74:
792 case 0x76:
793
794 LOG_DIS("wdc r%d\n", dc->ra);
795 trap_userspace(dc, true);
796 break;
797 case 0x68:
798
799 LOG_DIS("wic r%d\n", dc->ra);
800 trap_userspace(dc, true);
801 break;
802 case 0xe0:
803 if (trap_illegal(dc, !dc->cpu->cfg.use_pcmp_instr)) {
804 return;
805 }
806 if (dc->cpu->cfg.use_pcmp_instr) {
807 tcg_gen_clzi_i32(cpu_R[dc->rd], cpu_R[dc->ra], 32);
808 }
809 break;
810 case 0x1e0:
811
812 LOG_DIS("swapb r%d r%d\n", dc->rd, dc->ra);
813 tcg_gen_bswap32_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
814 break;
815 case 0x1e2:
816
817 LOG_DIS("swaph r%d r%d\n", dc->rd, dc->ra);
818 tcg_gen_rotri_i32(cpu_R[dc->rd], cpu_R[dc->ra], 16);
819 break;
820 default:
821 cpu_abort(cs, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
822 dc->pc, op, dc->rd, dc->ra, dc->rb);
823 break;
824 }
825}
826
827static inline void sync_jmpstate(DisasContext *dc)
828{
829 if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
830 if (dc->jmp == JMP_DIRECT) {
831 tcg_gen_movi_i32(env_btaken, 1);
832 }
833 dc->jmp = JMP_INDIRECT;
834 tcg_gen_movi_i64(env_btarget, dc->jmp_pc);
835 }
836}
837
838static void dec_imm(DisasContext *dc)
839{
840 LOG_DIS("imm %x\n", dc->imm << 16);
841 tcg_gen_movi_i32(env_imm, (dc->imm << 16));
842 dc->tb_flags |= IMM_FLAG;
843 dc->clear_imm = 0;
844}
845
846static inline void compute_ldst_addr(DisasContext *dc, bool ea, TCGv t)
847{
848 bool extimm = dc->tb_flags & IMM_FLAG;
849
850 bool stackprot = false;
851 TCGv_i32 t32;
852
853
854 if (dc->ra == 1 && dc->cpu->cfg.stackprot) {
855 stackprot = true;
856 }
857
858
859 if (!dc->type_b) {
860 if (ea) {
861 int addr_size = dc->cpu->cfg.addr_size;
862
863 if (addr_size == 32) {
864 tcg_gen_extu_i32_tl(t, cpu_R[dc->rb]);
865 return;
866 }
867
868 tcg_gen_concat_i32_i64(t, cpu_R[dc->rb], cpu_R[dc->ra]);
869 if (addr_size < 64) {
870
871 tcg_gen_andi_i64(t, t, MAKE_64BIT_MASK(0, addr_size));
872 }
873 return;
874 }
875
876
877 if (dc->ra == 0) {
878 tcg_gen_extu_i32_tl(t, cpu_R[dc->rb]);
879 return;
880 } else if (dc->rb == 0) {
881 tcg_gen_extu_i32_tl(t, cpu_R[dc->ra]);
882 return;
883 }
884
885 if (dc->rb == 1 && dc->cpu->cfg.stackprot) {
886 stackprot = true;
887 }
888
889 t32 = tcg_temp_new_i32();
890 tcg_gen_add_i32(t32, cpu_R[dc->ra], cpu_R[dc->rb]);
891 tcg_gen_extu_i32_tl(t, t32);
892 tcg_temp_free_i32(t32);
893
894 if (stackprot) {
895 gen_helper_stackprot(cpu_env, t);
896 }
897 return;
898 }
899
900 t32 = tcg_temp_new_i32();
901 if (!extimm) {
902 tcg_gen_addi_i32(t32, cpu_R[dc->ra], (int16_t)dc->imm);
903 } else {
904 tcg_gen_add_i32(t32, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
905 }
906 tcg_gen_extu_i32_tl(t, t32);
907 tcg_temp_free_i32(t32);
908
909 if (stackprot) {
910 gen_helper_stackprot(cpu_env, t);
911 }
912 return;
913}
914
915static void dec_load(DisasContext *dc)
916{
917 TCGv_i32 v;
918 TCGv addr;
919 unsigned int size;
920 bool rev = false, ex = false, ea = false;
921 int mem_index = cpu_mmu_index(&dc->cpu->env, false);
922 TCGMemOp mop;
923
924 mop = dc->opcode & 3;
925 size = 1 << mop;
926 if (!dc->type_b) {
927 ea = extract32(dc->ir, 7, 1);
928 rev = extract32(dc->ir, 9, 1);
929 ex = extract32(dc->ir, 10, 1);
930 }
931 mop |= MO_TE;
932 if (rev) {
933 mop ^= MO_BSWAP;
934 }
935
936 if (trap_illegal(dc, size > 4)) {
937 return;
938 }
939
940 if (trap_userspace(dc, ea)) {
941 return;
942 }
943
944 LOG_DIS("l%d%s%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "",
945 ex ? "x" : "",
946 ea ? "ea" : "");
947
948 t_sync_flags(dc);
949 addr = tcg_temp_new();
950 compute_ldst_addr(dc, ea, addr);
951
952 mem_index = ea ? MMU_NOMMU_IDX : mem_index;
953
954
955
956
957
958
959
960 if (rev && size != 4) {
961
962 switch (size) {
963 case 1:
964 {
965
966
967
968
969 TCGv low = tcg_temp_new();
970
971 tcg_gen_andi_tl(low, addr, 3);
972 tcg_gen_sub_tl(low, tcg_const_tl(3), low);
973 tcg_gen_andi_tl(addr, addr, ~3);
974 tcg_gen_or_tl(addr, addr, low);
975 tcg_temp_free(low);
976 break;
977 }
978
979 case 2:
980
981
982 tcg_gen_xori_tl(addr, addr, 2);
983 break;
984 default:
985 cpu_abort(CPU(dc->cpu), "Invalid reverse size\n");
986 break;
987 }
988 }
989
990
991 if (ex) {
992 tcg_gen_andi_tl(addr, addr, ~3);
993 }
994
995
996 sync_jmpstate(dc);
997
998
999
1000
1001
1002
1003
1004
1005 v = tcg_temp_new_i32();
1006 tcg_gen_qemu_ld_i32(v, addr, mem_index, mop);
1007
1008 if ((dc->cpu->env.pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
1009 tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc);
1010 gen_helper_memalign(cpu_env, addr, tcg_const_i32(dc->rd),
1011 tcg_const_i32(0), tcg_const_i32(size - 1));
1012 }
1013
1014 if (ex) {
1015 tcg_gen_mov_tl(env_res_addr, addr);
1016 tcg_gen_mov_i32(env_res_val, v);
1017 }
1018 if (dc->rd) {
1019 tcg_gen_mov_i32(cpu_R[dc->rd], v);
1020 }
1021 tcg_temp_free_i32(v);
1022
1023 if (ex) {
1024
1025 write_carryi(dc, 0);
1026 }
1027
1028 tcg_temp_free(addr);
1029}
1030
1031static void dec_store(DisasContext *dc)
1032{
1033 TCGv addr;
1034 TCGLabel *swx_skip = NULL;
1035 unsigned int size;
1036 bool rev = false, ex = false, ea = false;
1037 int mem_index = cpu_mmu_index(&dc->cpu->env, false);
1038 TCGMemOp mop;
1039
1040 mop = dc->opcode & 3;
1041 size = 1 << mop;
1042 if (!dc->type_b) {
1043 ea = extract32(dc->ir, 7, 1);
1044 rev = extract32(dc->ir, 9, 1);
1045 ex = extract32(dc->ir, 10, 1);
1046 }
1047 mop |= MO_TE;
1048 if (rev) {
1049 mop ^= MO_BSWAP;
1050 }
1051
1052 if (trap_illegal(dc, size > 4)) {
1053 return;
1054 }
1055
1056 trap_userspace(dc, ea);
1057
1058 LOG_DIS("s%d%s%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "",
1059 ex ? "x" : "",
1060 ea ? "ea" : "");
1061 t_sync_flags(dc);
1062
1063 sync_jmpstate(dc);
1064
1065 addr = ex ? tcg_temp_local_new() : tcg_temp_new();
1066 compute_ldst_addr(dc, ea, addr);
1067
1068 mem_index = ea ? MMU_NOMMU_IDX : mem_index;
1069
1070 if (ex) {
1071 TCGv_i32 tval;
1072
1073
1074 tcg_gen_andi_tl(addr, addr, ~3);
1075
1076 write_carryi(dc, 1);
1077 swx_skip = gen_new_label();
1078 tcg_gen_brcond_tl(TCG_COND_NE, env_res_addr, addr, swx_skip);
1079
1080
1081
1082
1083
1084
1085 tval = tcg_temp_new_i32();
1086 tcg_gen_qemu_ld_i32(tval, addr, cpu_mmu_index(&dc->cpu->env, false),
1087 MO_TEUL);
1088 tcg_gen_brcond_i32(TCG_COND_NE, env_res_val, tval, swx_skip);
1089 write_carryi(dc, 0);
1090 tcg_temp_free_i32(tval);
1091 }
1092
1093 if (rev && size != 4) {
1094
1095 switch (size) {
1096 case 1:
1097 {
1098
1099
1100
1101
1102 TCGv low = tcg_temp_new();
1103
1104 tcg_gen_andi_tl(low, addr, 3);
1105 tcg_gen_sub_tl(low, tcg_const_tl(3), low);
1106 tcg_gen_andi_tl(addr, addr, ~3);
1107 tcg_gen_or_tl(addr, addr, low);
1108 tcg_temp_free(low);
1109 break;
1110 }
1111
1112 case 2:
1113
1114
1115
1116 tcg_gen_xori_tl(addr, addr, 2);
1117 break;
1118 default:
1119 cpu_abort(CPU(dc->cpu), "Invalid reverse size\n");
1120 break;
1121 }
1122 }
1123 tcg_gen_qemu_st_i32(cpu_R[dc->rd], addr, mem_index, mop);
1124
1125
1126 if ((dc->cpu->env.pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
1127 tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc);
1128
1129
1130
1131
1132
1133
1134 gen_helper_memalign(cpu_env, addr, tcg_const_i32(dc->rd),
1135 tcg_const_i32(1), tcg_const_i32(size - 1));
1136 }
1137
1138 if (ex) {
1139 gen_set_label(swx_skip);
1140 }
1141
1142 tcg_temp_free(addr);
1143}
1144
1145static inline void eval_cc(DisasContext *dc, unsigned int cc,
1146 TCGv_i32 d, TCGv_i32 a)
1147{
1148 static const int mb_to_tcg_cc[] = {
1149 [CC_EQ] = TCG_COND_EQ,
1150 [CC_NE] = TCG_COND_NE,
1151 [CC_LT] = TCG_COND_LT,
1152 [CC_LE] = TCG_COND_LE,
1153 [CC_GE] = TCG_COND_GE,
1154 [CC_GT] = TCG_COND_GT,
1155 };
1156
1157 switch (cc) {
1158 case CC_EQ:
1159 case CC_NE:
1160 case CC_LT:
1161 case CC_LE:
1162 case CC_GE:
1163 case CC_GT:
1164 tcg_gen_setcondi_i32(mb_to_tcg_cc[cc], d, a, 0);
1165 break;
1166 default:
1167 cpu_abort(CPU(dc->cpu), "Unknown condition code %x.\n", cc);
1168 break;
1169 }
1170}
1171
1172static void eval_cond_jmp(DisasContext *dc, TCGv_i64 pc_true, TCGv_i64 pc_false)
1173{
1174 TCGv_i64 tmp_btaken = tcg_temp_new_i64();
1175 TCGv_i64 tmp_zero = tcg_const_i64(0);
1176
1177 tcg_gen_extu_i32_i64(tmp_btaken, env_btaken);
1178 tcg_gen_movcond_i64(TCG_COND_NE, cpu_SR[SR_PC],
1179 tmp_btaken, tmp_zero,
1180 pc_true, pc_false);
1181
1182 tcg_temp_free_i64(tmp_btaken);
1183 tcg_temp_free_i64(tmp_zero);
1184}
1185
1186static void dec_bcc(DisasContext *dc)
1187{
1188 unsigned int cc;
1189 unsigned int dslot;
1190
1191 cc = EXTRACT_FIELD(dc->ir, 21, 23);
1192 dslot = dc->ir & (1 << 25);
1193 LOG_DIS("bcc%s r%d %x\n", dslot ? "d" : "", dc->ra, dc->imm);
1194
1195 dc->delayed_branch = 1;
1196 if (dslot) {
1197 dc->delayed_branch = 2;
1198 dc->tb_flags |= D_FLAG;
1199 tcg_gen_st_i32(tcg_const_i32(dc->type_b && (dc->tb_flags & IMM_FLAG)),
1200 cpu_env, offsetof(CPUMBState, bimm));
1201 }
1202
1203 if (dec_alu_op_b_is_small_imm(dc)) {
1204 int32_t offset = (int32_t)((int16_t)dc->imm);
1205
1206 tcg_gen_movi_i64(env_btarget, dc->pc + offset);
1207 dc->jmp = JMP_DIRECT_CC;
1208 dc->jmp_pc = dc->pc + offset;
1209 } else {
1210 dc->jmp = JMP_INDIRECT;
1211 tcg_gen_extu_i32_i64(env_btarget, *(dec_alu_op_b(dc)));
1212 tcg_gen_addi_i64(env_btarget, env_btarget, dc->pc);
1213 tcg_gen_andi_i64(env_btarget, env_btarget, UINT32_MAX);
1214 }
1215 eval_cc(dc, cc, env_btaken, cpu_R[dc->ra]);
1216}
1217
1218static void dec_br(DisasContext *dc)
1219{
1220 unsigned int dslot, link, abs, mbar;
1221
1222 dslot = dc->ir & (1 << 20);
1223 abs = dc->ir & (1 << 19);
1224 link = dc->ir & (1 << 18);
1225
1226
1227 mbar = (dc->ir >> 16) & 31;
1228 if (mbar == 2 && dc->imm == 4) {
1229
1230 if (dc->rd & 16) {
1231 TCGv_i32 tmp_hlt = tcg_const_i32(EXCP_HLT);
1232 TCGv_i32 tmp_1 = tcg_const_i32(1);
1233
1234 LOG_DIS("sleep\n");
1235
1236 t_sync_flags(dc);
1237 tcg_gen_st_i32(tmp_1, cpu_env,
1238 -offsetof(MicroBlazeCPU, env)
1239 +offsetof(CPUState, halted));
1240 tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc + 4);
1241 gen_helper_raise_exception(cpu_env, tmp_hlt);
1242 tcg_temp_free_i32(tmp_hlt);
1243 tcg_temp_free_i32(tmp_1);
1244 return;
1245 }
1246 LOG_DIS("mbar %d\n", dc->rd);
1247
1248 dc->cpustate_changed = 1;
1249 return;
1250 }
1251
1252 LOG_DIS("br%s%s%s%s imm=%x\n",
1253 abs ? "a" : "", link ? "l" : "",
1254 dc->type_b ? "i" : "", dslot ? "d" : "",
1255 dc->imm);
1256
1257 dc->delayed_branch = 1;
1258 if (dslot) {
1259 dc->delayed_branch = 2;
1260 dc->tb_flags |= D_FLAG;
1261 tcg_gen_st_i32(tcg_const_i32(dc->type_b && (dc->tb_flags & IMM_FLAG)),
1262 cpu_env, offsetof(CPUMBState, bimm));
1263 }
1264 if (link && dc->rd)
1265 tcg_gen_movi_i32(cpu_R[dc->rd], dc->pc);
1266
1267 dc->jmp = JMP_INDIRECT;
1268 if (abs) {
1269 tcg_gen_movi_i32(env_btaken, 1);
1270 tcg_gen_extu_i32_i64(env_btarget, *(dec_alu_op_b(dc)));
1271 if (link && !dslot) {
1272 if (!(dc->tb_flags & IMM_FLAG) && (dc->imm == 8 || dc->imm == 0x18))
1273 t_gen_raise_exception(dc, EXCP_BREAK);
1274 if (dc->imm == 0) {
1275 if (trap_userspace(dc, true)) {
1276 return;
1277 }
1278
1279 t_gen_raise_exception(dc, EXCP_DEBUG);
1280 }
1281 }
1282 } else {
1283 if (dec_alu_op_b_is_small_imm(dc)) {
1284 dc->jmp = JMP_DIRECT;
1285 dc->jmp_pc = dc->pc + (int32_t)((int16_t)dc->imm);
1286 } else {
1287 tcg_gen_movi_i32(env_btaken, 1);
1288 tcg_gen_extu_i32_i64(env_btarget, *(dec_alu_op_b(dc)));
1289 tcg_gen_addi_i64(env_btarget, env_btarget, dc->pc);
1290 tcg_gen_andi_i64(env_btarget, env_btarget, UINT32_MAX);
1291 }
1292 }
1293}
1294
1295static inline void do_rti(DisasContext *dc)
1296{
1297 TCGv_i32 t0, t1;
1298 t0 = tcg_temp_new_i32();
1299 t1 = tcg_temp_new_i32();
1300 tcg_gen_extrl_i64_i32(t1, cpu_SR[SR_MSR]);
1301 tcg_gen_shri_i32(t0, t1, 1);
1302 tcg_gen_ori_i32(t1, t1, MSR_IE);
1303 tcg_gen_andi_i32(t0, t0, (MSR_VM | MSR_UM));
1304
1305 tcg_gen_andi_i32(t1, t1, ~(MSR_VM | MSR_UM));
1306 tcg_gen_or_i32(t1, t1, t0);
1307 msr_write(dc, t1);
1308 tcg_temp_free_i32(t1);
1309 tcg_temp_free_i32(t0);
1310 dc->tb_flags &= ~DRTI_FLAG;
1311}
1312
1313static inline void do_rtb(DisasContext *dc)
1314{
1315 TCGv_i32 t0, t1;
1316 t0 = tcg_temp_new_i32();
1317 t1 = tcg_temp_new_i32();
1318 tcg_gen_extrl_i64_i32(t1, cpu_SR[SR_MSR]);
1319 tcg_gen_andi_i32(t1, t1, ~MSR_BIP);
1320 tcg_gen_shri_i32(t0, t1, 1);
1321 tcg_gen_andi_i32(t0, t0, (MSR_VM | MSR_UM));
1322
1323 tcg_gen_andi_i32(t1, t1, ~(MSR_VM | MSR_UM));
1324 tcg_gen_or_i32(t1, t1, t0);
1325 msr_write(dc, t1);
1326 tcg_temp_free_i32(t1);
1327 tcg_temp_free_i32(t0);
1328 dc->tb_flags &= ~DRTB_FLAG;
1329}
1330
1331static inline void do_rte(DisasContext *dc)
1332{
1333 TCGv_i32 t0, t1;
1334 t0 = tcg_temp_new_i32();
1335 t1 = tcg_temp_new_i32();
1336
1337 tcg_gen_extrl_i64_i32(t1, cpu_SR[SR_MSR]);
1338 tcg_gen_ori_i32(t1, t1, MSR_EE);
1339 tcg_gen_andi_i32(t1, t1, ~MSR_EIP);
1340 tcg_gen_shri_i32(t0, t1, 1);
1341 tcg_gen_andi_i32(t0, t0, (MSR_VM | MSR_UM));
1342
1343 tcg_gen_andi_i32(t1, t1, ~(MSR_VM | MSR_UM));
1344 tcg_gen_or_i32(t1, t1, t0);
1345 msr_write(dc, t1);
1346 tcg_temp_free_i32(t1);
1347 tcg_temp_free_i32(t0);
1348 dc->tb_flags &= ~DRTE_FLAG;
1349}
1350
1351static void dec_rts(DisasContext *dc)
1352{
1353 unsigned int b_bit, i_bit, e_bit;
1354 TCGv_i64 tmp64;
1355
1356 i_bit = dc->ir & (1 << 21);
1357 b_bit = dc->ir & (1 << 22);
1358 e_bit = dc->ir & (1 << 23);
1359
1360 if (trap_userspace(dc, i_bit || b_bit || e_bit)) {
1361 return;
1362 }
1363
1364 dc->delayed_branch = 2;
1365 dc->tb_flags |= D_FLAG;
1366 tcg_gen_st_i32(tcg_const_i32(dc->type_b && (dc->tb_flags & IMM_FLAG)),
1367 cpu_env, offsetof(CPUMBState, bimm));
1368
1369 if (i_bit) {
1370 LOG_DIS("rtid ir=%x\n", dc->ir);
1371 dc->tb_flags |= DRTI_FLAG;
1372 } else if (b_bit) {
1373 LOG_DIS("rtbd ir=%x\n", dc->ir);
1374 dc->tb_flags |= DRTB_FLAG;
1375 } else if (e_bit) {
1376 LOG_DIS("rted ir=%x\n", dc->ir);
1377 dc->tb_flags |= DRTE_FLAG;
1378 } else
1379 LOG_DIS("rts ir=%x\n", dc->ir);
1380
1381 dc->jmp = JMP_INDIRECT;
1382 tcg_gen_movi_i32(env_btaken, 1);
1383
1384 tmp64 = tcg_temp_new_i64();
1385 tcg_gen_extu_i32_i64(env_btarget, *(dec_alu_op_b(dc)));
1386 tcg_gen_extu_i32_i64(tmp64, cpu_R[dc->ra]);
1387 tcg_gen_add_i64(env_btarget, env_btarget, tmp64);
1388 tcg_gen_andi_i64(env_btarget, env_btarget, UINT32_MAX);
1389 tcg_temp_free_i64(tmp64);
1390}
1391
1392static int dec_check_fpuv2(DisasContext *dc)
1393{
1394 if ((dc->cpu->cfg.use_fpu != 2) && (dc->tb_flags & MSR_EE_FLAG)) {
1395 tcg_gen_movi_i64(cpu_SR[SR_ESR], ESR_EC_FPU);
1396 t_gen_raise_exception(dc, EXCP_HW_EXCP);
1397 }
1398 return (dc->cpu->cfg.use_fpu == 2) ? 0 : PVR2_USE_FPU2_MASK;
1399}
1400
1401static void dec_fpu(DisasContext *dc)
1402{
1403 unsigned int fpu_insn;
1404
1405 if (trap_illegal(dc, !dc->cpu->cfg.use_fpu)) {
1406 return;
1407 }
1408
1409 fpu_insn = (dc->ir >> 7) & 7;
1410
1411 switch (fpu_insn) {
1412 case 0:
1413 gen_helper_fadd(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra],
1414 cpu_R[dc->rb]);
1415 break;
1416
1417 case 1:
1418 gen_helper_frsub(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra],
1419 cpu_R[dc->rb]);
1420 break;
1421
1422 case 2:
1423 gen_helper_fmul(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra],
1424 cpu_R[dc->rb]);
1425 break;
1426
1427 case 3:
1428 gen_helper_fdiv(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra],
1429 cpu_R[dc->rb]);
1430 break;
1431
1432 case 4:
1433 switch ((dc->ir >> 4) & 7) {
1434 case 0:
1435 gen_helper_fcmp_un(cpu_R[dc->rd], cpu_env,
1436 cpu_R[dc->ra], cpu_R[dc->rb]);
1437 break;
1438 case 1:
1439 gen_helper_fcmp_lt(cpu_R[dc->rd], cpu_env,
1440 cpu_R[dc->ra], cpu_R[dc->rb]);
1441 break;
1442 case 2:
1443 gen_helper_fcmp_eq(cpu_R[dc->rd], cpu_env,
1444 cpu_R[dc->ra], cpu_R[dc->rb]);
1445 break;
1446 case 3:
1447 gen_helper_fcmp_le(cpu_R[dc->rd], cpu_env,
1448 cpu_R[dc->ra], cpu_R[dc->rb]);
1449 break;
1450 case 4:
1451 gen_helper_fcmp_gt(cpu_R[dc->rd], cpu_env,
1452 cpu_R[dc->ra], cpu_R[dc->rb]);
1453 break;
1454 case 5:
1455 gen_helper_fcmp_ne(cpu_R[dc->rd], cpu_env,
1456 cpu_R[dc->ra], cpu_R[dc->rb]);
1457 break;
1458 case 6:
1459 gen_helper_fcmp_ge(cpu_R[dc->rd], cpu_env,
1460 cpu_R[dc->ra], cpu_R[dc->rb]);
1461 break;
1462 default:
1463 qemu_log_mask(LOG_UNIMP,
1464 "unimplemented fcmp fpu_insn=%x pc=%x"
1465 " opc=%x\n",
1466 fpu_insn, dc->pc, dc->opcode);
1467 dc->abort_at_next_insn = 1;
1468 break;
1469 }
1470 break;
1471
1472 case 5:
1473 if (!dec_check_fpuv2(dc)) {
1474 return;
1475 }
1476 gen_helper_flt(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]);
1477 break;
1478
1479 case 6:
1480 if (!dec_check_fpuv2(dc)) {
1481 return;
1482 }
1483 gen_helper_fint(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]);
1484 break;
1485
1486 case 7:
1487 if (!dec_check_fpuv2(dc)) {
1488 return;
1489 }
1490 gen_helper_fsqrt(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]);
1491 break;
1492
1493 default:
1494 qemu_log_mask(LOG_UNIMP, "unimplemented FPU insn fpu_insn=%x pc=%x"
1495 " opc=%x\n",
1496 fpu_insn, dc->pc, dc->opcode);
1497 dc->abort_at_next_insn = 1;
1498 break;
1499 }
1500}
1501
1502static void dec_null(DisasContext *dc)
1503{
1504 if (trap_illegal(dc, true)) {
1505 return;
1506 }
1507 qemu_log_mask(LOG_GUEST_ERROR, "unknown insn pc=%x opc=%x\n", dc->pc, dc->opcode);
1508 dc->abort_at_next_insn = 1;
1509}
1510
1511
1512static void dec_stream(DisasContext *dc)
1513{
1514 TCGv_i32 t_id, t_ctrl;
1515 int ctrl;
1516
1517 LOG_DIS("%s%s imm=%x\n", dc->rd ? "get" : "put",
1518 dc->type_b ? "" : "d", dc->imm);
1519
1520 if (trap_userspace(dc, true)) {
1521 return;
1522 }
1523
1524 t_id = tcg_temp_new_i32();
1525 if (dc->type_b) {
1526 tcg_gen_movi_i32(t_id, dc->imm & 0xf);
1527 ctrl = dc->imm >> 10;
1528 } else {
1529 tcg_gen_andi_i32(t_id, cpu_R[dc->rb], 0xf);
1530 ctrl = dc->imm >> 5;
1531 }
1532
1533 t_ctrl = tcg_const_i32(ctrl);
1534
1535 if (dc->rd == 0) {
1536 gen_helper_put(t_id, t_ctrl, cpu_R[dc->ra]);
1537 } else {
1538 gen_helper_get(cpu_R[dc->rd], t_id, t_ctrl);
1539 }
1540 tcg_temp_free_i32(t_id);
1541 tcg_temp_free_i32(t_ctrl);
1542}
1543
1544static struct decoder_info {
1545 struct {
1546 uint32_t bits;
1547 uint32_t mask;
1548 };
1549 void (*dec)(DisasContext *dc);
1550} decinfo[] = {
1551 {DEC_ADD, dec_add},
1552 {DEC_SUB, dec_sub},
1553 {DEC_AND, dec_and},
1554 {DEC_XOR, dec_xor},
1555 {DEC_OR, dec_or},
1556 {DEC_BIT, dec_bit},
1557 {DEC_BARREL, dec_barrel},
1558 {DEC_LD, dec_load},
1559 {DEC_ST, dec_store},
1560 {DEC_IMM, dec_imm},
1561 {DEC_BR, dec_br},
1562 {DEC_BCC, dec_bcc},
1563 {DEC_RTS, dec_rts},
1564 {DEC_FPU, dec_fpu},
1565 {DEC_MUL, dec_mul},
1566 {DEC_DIV, dec_div},
1567 {DEC_MSR, dec_msr},
1568 {DEC_STREAM, dec_stream},
1569 {{0, 0}, dec_null}
1570};
1571
1572static inline void decode(DisasContext *dc, uint32_t ir)
1573{
1574 int i;
1575
1576 dc->ir = ir;
1577 LOG_DIS("%8.8x\t", dc->ir);
1578
1579 if (ir == 0) {
1580 trap_illegal(dc, dc->cpu->env.pvr.regs[2] & PVR2_OPCODE_0x0_ILL_MASK);
1581
1582 return;
1583 }
1584
1585
1586 dc->type_b = ir & (1 << 29);
1587
1588 dc->opcode = EXTRACT_FIELD(ir, 26, 31);
1589 dc->rd = EXTRACT_FIELD(ir, 21, 25);
1590 dc->ra = EXTRACT_FIELD(ir, 16, 20);
1591 dc->rb = EXTRACT_FIELD(ir, 11, 15);
1592 dc->imm = EXTRACT_FIELD(ir, 0, 15);
1593
1594
1595 for (i = 0; i < ARRAY_SIZE(decinfo); i++) {
1596 if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) {
1597 decinfo[i].dec(dc);
1598 break;
1599 }
1600 }
1601}
1602
1603
1604void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
1605{
1606 CPUMBState *env = cs->env_ptr;
1607 MicroBlazeCPU *cpu = env_archcpu(env);
1608 uint32_t pc_start;
1609 struct DisasContext ctx;
1610 struct DisasContext *dc = &ctx;
1611 uint32_t page_start, org_flags;
1612 uint32_t npc;
1613 int num_insns;
1614
1615 pc_start = tb->pc;
1616 dc->cpu = cpu;
1617 dc->tb = tb;
1618 org_flags = dc->synced_flags = dc->tb_flags = tb->flags;
1619
1620 dc->is_jmp = DISAS_NEXT;
1621 dc->jmp = 0;
1622 dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
1623 if (dc->delayed_branch) {
1624 dc->jmp = JMP_INDIRECT;
1625 }
1626 dc->pc = pc_start;
1627 dc->singlestep_enabled = cs->singlestep_enabled;
1628 dc->cpustate_changed = 0;
1629 dc->abort_at_next_insn = 0;
1630
1631 if (pc_start & 3) {
1632 cpu_abort(cs, "Microblaze: unaligned PC=%x\n", pc_start);
1633 }
1634
1635 page_start = pc_start & TARGET_PAGE_MASK;
1636 num_insns = 0;
1637
1638 gen_tb_start(tb);
1639 do
1640 {
1641 tcg_gen_insn_start(dc->pc);
1642 num_insns++;
1643
1644#if SIM_COMPAT
1645 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1646 tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc);
1647 gen_helper_debug();
1648 }
1649#endif
1650
1651 if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
1652 t_gen_raise_exception(dc, EXCP_DEBUG);
1653 dc->is_jmp = DISAS_UPDATE;
1654
1655
1656
1657
1658 dc->pc += 4;
1659 break;
1660 }
1661
1662
1663 LOG_DIS("%8.8x:\t", dc->pc);
1664
1665 if (num_insns == max_insns && (tb_cflags(tb) & CF_LAST_IO)) {
1666 gen_io_start();
1667 }
1668
1669 dc->clear_imm = 1;
1670 decode(dc, cpu_ldl_code(env, dc->pc));
1671 if (dc->clear_imm)
1672 dc->tb_flags &= ~IMM_FLAG;
1673 dc->pc += 4;
1674
1675 if (dc->delayed_branch) {
1676 dc->delayed_branch--;
1677 if (!dc->delayed_branch) {
1678 if (dc->tb_flags & DRTI_FLAG)
1679 do_rti(dc);
1680 if (dc->tb_flags & DRTB_FLAG)
1681 do_rtb(dc);
1682 if (dc->tb_flags & DRTE_FLAG)
1683 do_rte(dc);
1684
1685 dc->tb_flags &= ~D_FLAG;
1686
1687 if (dc->jmp == JMP_INDIRECT) {
1688 eval_cond_jmp(dc, env_btarget, tcg_const_i64(dc->pc));
1689 dc->is_jmp = DISAS_JUMP;
1690 } else if (dc->jmp == JMP_DIRECT) {
1691 t_sync_flags(dc);
1692 gen_goto_tb(dc, 0, dc->jmp_pc);
1693 dc->is_jmp = DISAS_TB_JUMP;
1694 } else if (dc->jmp == JMP_DIRECT_CC) {
1695 TCGLabel *l1 = gen_new_label();
1696 t_sync_flags(dc);
1697
1698 tcg_gen_brcondi_i32(TCG_COND_NE, env_btaken, 0, l1);
1699 gen_goto_tb(dc, 1, dc->pc);
1700 gen_set_label(l1);
1701 gen_goto_tb(dc, 0, dc->jmp_pc);
1702
1703 dc->is_jmp = DISAS_TB_JUMP;
1704 }
1705 break;
1706 }
1707 }
1708 if (cs->singlestep_enabled) {
1709 break;
1710 }
1711 } while (!dc->is_jmp && !dc->cpustate_changed
1712 && !tcg_op_buf_full()
1713 && !singlestep
1714 && (dc->pc - page_start < TARGET_PAGE_SIZE)
1715 && num_insns < max_insns);
1716
1717 npc = dc->pc;
1718 if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
1719 if (dc->tb_flags & D_FLAG) {
1720 dc->is_jmp = DISAS_UPDATE;
1721 tcg_gen_movi_i64(cpu_SR[SR_PC], npc);
1722 sync_jmpstate(dc);
1723 } else
1724 npc = dc->jmp_pc;
1725 }
1726
1727 if (tb_cflags(tb) & CF_LAST_IO)
1728 gen_io_end();
1729
1730 if (dc->is_jmp == DISAS_NEXT
1731 && (dc->cpustate_changed || org_flags != dc->tb_flags)) {
1732 dc->is_jmp = DISAS_UPDATE;
1733 tcg_gen_movi_i64(cpu_SR[SR_PC], npc);
1734 }
1735 t_sync_flags(dc);
1736
1737 if (unlikely(cs->singlestep_enabled)) {
1738 TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG);
1739
1740 if (dc->is_jmp != DISAS_JUMP) {
1741 tcg_gen_movi_i64(cpu_SR[SR_PC], npc);
1742 }
1743 gen_helper_raise_exception(cpu_env, tmp);
1744 tcg_temp_free_i32(tmp);
1745 } else {
1746 switch(dc->is_jmp) {
1747 case DISAS_NEXT:
1748 gen_goto_tb(dc, 1, npc);
1749 break;
1750 default:
1751 case DISAS_JUMP:
1752 case DISAS_UPDATE:
1753
1754
1755 tcg_gen_exit_tb(NULL, 0);
1756 break;
1757 case DISAS_TB_JUMP:
1758
1759 break;
1760 }
1761 }
1762 gen_tb_end(tb, num_insns);
1763
1764 tb->size = dc->pc - pc_start;
1765 tb->icount = num_insns;
1766
1767#ifdef DEBUG_DISAS
1768#if !SIM_COMPAT
1769 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
1770 && qemu_log_in_addr_range(pc_start)) {
1771 qemu_log_lock();
1772 qemu_log("--------------\n");
1773 log_target_disas(cs, pc_start, dc->pc - pc_start);
1774 qemu_log_unlock();
1775 }
1776#endif
1777#endif
1778 assert(!dc->abort_at_next_insn);
1779}
1780
1781void mb_cpu_dump_state(CPUState *cs, FILE *f, int flags)
1782{
1783 MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
1784 CPUMBState *env = &cpu->env;
1785 int i;
1786
1787 if (!env) {
1788 return;
1789 }
1790
1791 qemu_fprintf(f, "IN: PC=%" PRIx64 " %s\n",
1792 env->sregs[SR_PC], lookup_symbol(env->sregs[SR_PC]));
1793 qemu_fprintf(f, "rmsr=%" PRIx64 " resr=%" PRIx64 " rear=%" PRIx64 " "
1794 "debug=%x imm=%x iflags=%x fsr=%" PRIx64 "\n",
1795 env->sregs[SR_MSR], env->sregs[SR_ESR], env->sregs[SR_EAR],
1796 env->debug, env->imm, env->iflags, env->sregs[SR_FSR]);
1797 qemu_fprintf(f, "btaken=%d btarget=%" PRIx64 " mode=%s(saved=%s) "
1798 "eip=%d ie=%d\n",
1799 env->btaken, env->btarget,
1800 (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel",
1801 (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel",
1802 (bool)(env->sregs[SR_MSR] & MSR_EIP),
1803 (bool)(env->sregs[SR_MSR] & MSR_IE));
1804
1805 for (i = 0; i < 32; i++) {
1806 qemu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
1807 if ((i + 1) % 4 == 0)
1808 qemu_fprintf(f, "\n");
1809 }
1810 qemu_fprintf(f, "\n\n");
1811}
1812
1813void mb_tcg_init(void)
1814{
1815 int i;
1816
1817 env_debug = tcg_global_mem_new_i32(cpu_env,
1818 offsetof(CPUMBState, debug),
1819 "debug0");
1820 env_iflags = tcg_global_mem_new_i32(cpu_env,
1821 offsetof(CPUMBState, iflags),
1822 "iflags");
1823 env_imm = tcg_global_mem_new_i32(cpu_env,
1824 offsetof(CPUMBState, imm),
1825 "imm");
1826 env_btarget = tcg_global_mem_new_i64(cpu_env,
1827 offsetof(CPUMBState, btarget),
1828 "btarget");
1829 env_btaken = tcg_global_mem_new_i32(cpu_env,
1830 offsetof(CPUMBState, btaken),
1831 "btaken");
1832 env_res_addr = tcg_global_mem_new(cpu_env,
1833 offsetof(CPUMBState, res_addr),
1834 "res_addr");
1835 env_res_val = tcg_global_mem_new_i32(cpu_env,
1836 offsetof(CPUMBState, res_val),
1837 "res_val");
1838 for (i = 0; i < ARRAY_SIZE(cpu_R); i++) {
1839 cpu_R[i] = tcg_global_mem_new_i32(cpu_env,
1840 offsetof(CPUMBState, regs[i]),
1841 regnames[i]);
1842 }
1843 for (i = 0; i < ARRAY_SIZE(cpu_SR); i++) {
1844 cpu_SR[i] = tcg_global_mem_new_i64(cpu_env,
1845 offsetof(CPUMBState, sregs[i]),
1846 special_regnames[i]);
1847 }
1848}
1849
1850void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb,
1851 target_ulong *data)
1852{
1853 env->sregs[SR_PC] = data[0];
1854}
1855