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