spapr: Only report host/guest IOMMU page size mismatches on KVM
[qemu/ar7.git] / target / microblaze / translate.c
blobcb65d1e129c11670b18a979d11e2d6f334fc9689
1 /*
2 * Xilinx MicroBlaze emulation for qemu: main translation routines.
4 * Copyright (c) 2009 Edgar E. Iglesias.
5 * Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
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.
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.
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/>.
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"
31 #include "trace-tcg.h"
32 #include "exec/log.h"
35 #define SIM_COMPAT 0
36 #define DISAS_GNU 1
37 #define DISAS_MB 1
38 #if DISAS_MB && !SIM_COMPAT
39 # define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
40 #else
41 # define LOG_DIS(...) do { } while (0)
42 #endif
44 #define D(x)
46 #define EXTRACT_FIELD(src, start, end) \
47 (((src) >> start) & ((1 << (end - start + 1)) - 1))
49 static TCGv env_debug;
50 static TCGv_env cpu_env;
51 static TCGv cpu_R[32];
52 static TCGv cpu_SR[18];
53 static TCGv env_imm;
54 static TCGv env_btaken;
55 static TCGv env_btarget;
56 static TCGv env_iflags;
57 static TCGv env_res_addr;
58 static TCGv env_res_val;
60 #include "exec/gen-icount.h"
62 /* This is the state at translation time. */
63 typedef struct DisasContext {
64 MicroBlazeCPU *cpu;
65 target_ulong pc;
67 /* Decoder. */
68 int type_b;
69 uint32_t ir;
70 uint8_t opcode;
71 uint8_t rd, ra, rb;
72 uint16_t imm;
74 unsigned int cpustate_changed;
75 unsigned int delayed_branch;
76 unsigned int tb_flags, synced_flags; /* tb dependent flags. */
77 unsigned int clear_imm;
78 int is_jmp;
80 #define JMP_NOJMP 0
81 #define JMP_DIRECT 1
82 #define JMP_DIRECT_CC 2
83 #define JMP_INDIRECT 3
84 unsigned int jmp;
85 uint32_t jmp_pc;
87 int abort_at_next_insn;
88 int nr_nops;
89 struct TranslationBlock *tb;
90 int singlestep_enabled;
91 } DisasContext;
93 static const char *regnames[] =
95 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
96 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
97 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
98 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
101 static const char *special_regnames[] =
103 "rpc", "rmsr", "sr2", "sr3", "sr4", "sr5", "sr6", "sr7",
104 "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15",
105 "sr16", "sr17", "sr18"
108 static inline void t_sync_flags(DisasContext *dc)
110 /* Synch the tb dependent flags between translator and runtime. */
111 if (dc->tb_flags != dc->synced_flags) {
112 tcg_gen_movi_tl(env_iflags, dc->tb_flags);
113 dc->synced_flags = dc->tb_flags;
117 static inline void t_gen_raise_exception(DisasContext *dc, uint32_t index)
119 TCGv_i32 tmp = tcg_const_i32(index);
121 t_sync_flags(dc);
122 tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
123 gen_helper_raise_exception(cpu_env, tmp);
124 tcg_temp_free_i32(tmp);
125 dc->is_jmp = DISAS_UPDATE;
128 static inline bool use_goto_tb(DisasContext *dc, target_ulong dest)
130 #ifndef CONFIG_USER_ONLY
131 return (dc->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
132 #else
133 return true;
134 #endif
137 static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
139 if (use_goto_tb(dc, dest)) {
140 tcg_gen_goto_tb(n);
141 tcg_gen_movi_tl(cpu_SR[SR_PC], dest);
142 tcg_gen_exit_tb((uintptr_t)dc->tb + n);
143 } else {
144 tcg_gen_movi_tl(cpu_SR[SR_PC], dest);
145 tcg_gen_exit_tb(0);
149 static void read_carry(DisasContext *dc, TCGv d)
151 tcg_gen_shri_tl(d, cpu_SR[SR_MSR], 31);
155 * write_carry sets the carry bits in MSR based on bit 0 of v.
156 * v[31:1] are ignored.
158 static void write_carry(DisasContext *dc, TCGv v)
160 TCGv t0 = tcg_temp_new();
161 tcg_gen_shli_tl(t0, v, 31);
162 tcg_gen_sari_tl(t0, t0, 31);
163 tcg_gen_andi_tl(t0, t0, (MSR_C | MSR_CC));
164 tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR],
165 ~(MSR_C | MSR_CC));
166 tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t0);
167 tcg_temp_free(t0);
170 static void write_carryi(DisasContext *dc, bool carry)
172 TCGv t0 = tcg_temp_new();
173 tcg_gen_movi_tl(t0, carry);
174 write_carry(dc, t0);
175 tcg_temp_free(t0);
178 /* True if ALU operand b is a small immediate that may deserve
179 faster treatment. */
180 static inline int dec_alu_op_b_is_small_imm(DisasContext *dc)
182 /* Immediate insn without the imm prefix ? */
183 return dc->type_b && !(dc->tb_flags & IMM_FLAG);
186 static inline TCGv *dec_alu_op_b(DisasContext *dc)
188 if (dc->type_b) {
189 if (dc->tb_flags & IMM_FLAG)
190 tcg_gen_ori_tl(env_imm, env_imm, dc->imm);
191 else
192 tcg_gen_movi_tl(env_imm, (int32_t)((int16_t)dc->imm));
193 return &env_imm;
194 } else
195 return &cpu_R[dc->rb];
198 static void dec_add(DisasContext *dc)
200 unsigned int k, c;
201 TCGv cf;
203 k = dc->opcode & 4;
204 c = dc->opcode & 2;
206 LOG_DIS("add%s%s%s r%d r%d r%d\n",
207 dc->type_b ? "i" : "", k ? "k" : "", c ? "c" : "",
208 dc->rd, dc->ra, dc->rb);
210 /* Take care of the easy cases first. */
211 if (k) {
212 /* k - keep carry, no need to update MSR. */
213 /* If rd == r0, it's a nop. */
214 if (dc->rd) {
215 tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
217 if (c) {
218 /* c - Add carry into the result. */
219 cf = tcg_temp_new();
221 read_carry(dc, cf);
222 tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
223 tcg_temp_free(cf);
226 return;
229 /* From now on, we can assume k is zero. So we need to update MSR. */
230 /* Extract carry. */
231 cf = tcg_temp_new();
232 if (c) {
233 read_carry(dc, cf);
234 } else {
235 tcg_gen_movi_tl(cf, 0);
238 if (dc->rd) {
239 TCGv ncf = tcg_temp_new();
240 gen_helper_carry(ncf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf);
241 tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
242 tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
243 write_carry(dc, ncf);
244 tcg_temp_free(ncf);
245 } else {
246 gen_helper_carry(cf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf);
247 write_carry(dc, cf);
249 tcg_temp_free(cf);
252 static void dec_sub(DisasContext *dc)
254 unsigned int u, cmp, k, c;
255 TCGv cf, na;
257 u = dc->imm & 2;
258 k = dc->opcode & 4;
259 c = dc->opcode & 2;
260 cmp = (dc->imm & 1) && (!dc->type_b) && k;
262 if (cmp) {
263 LOG_DIS("cmp%s r%d, r%d ir=%x\n", u ? "u" : "", dc->rd, dc->ra, dc->ir);
264 if (dc->rd) {
265 if (u)
266 gen_helper_cmpu(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
267 else
268 gen_helper_cmp(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
270 return;
273 LOG_DIS("sub%s%s r%d, r%d r%d\n",
274 k ? "k" : "", c ? "c" : "", dc->rd, dc->ra, dc->rb);
276 /* Take care of the easy cases first. */
277 if (k) {
278 /* k - keep carry, no need to update MSR. */
279 /* If rd == r0, it's a nop. */
280 if (dc->rd) {
281 tcg_gen_sub_tl(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
283 if (c) {
284 /* c - Add carry into the result. */
285 cf = tcg_temp_new();
287 read_carry(dc, cf);
288 tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
289 tcg_temp_free(cf);
292 return;
295 /* From now on, we can assume k is zero. So we need to update MSR. */
296 /* Extract carry. And complement a into na. */
297 cf = tcg_temp_new();
298 na = tcg_temp_new();
299 if (c) {
300 read_carry(dc, cf);
301 } else {
302 tcg_gen_movi_tl(cf, 1);
305 /* d = b + ~a + c. carry defaults to 1. */
306 tcg_gen_not_tl(na, cpu_R[dc->ra]);
308 if (dc->rd) {
309 TCGv ncf = tcg_temp_new();
310 gen_helper_carry(ncf, na, *(dec_alu_op_b(dc)), cf);
311 tcg_gen_add_tl(cpu_R[dc->rd], na, *(dec_alu_op_b(dc)));
312 tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
313 write_carry(dc, ncf);
314 tcg_temp_free(ncf);
315 } else {
316 gen_helper_carry(cf, na, *(dec_alu_op_b(dc)), cf);
317 write_carry(dc, cf);
319 tcg_temp_free(cf);
320 tcg_temp_free(na);
323 static void dec_pattern(DisasContext *dc)
325 unsigned int mode;
327 if ((dc->tb_flags & MSR_EE_FLAG)
328 && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
329 && !dc->cpu->cfg.use_pcmp_instr) {
330 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
331 t_gen_raise_exception(dc, EXCP_HW_EXCP);
334 mode = dc->opcode & 3;
335 switch (mode) {
336 case 0:
337 /* pcmpbf. */
338 LOG_DIS("pcmpbf r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
339 if (dc->rd)
340 gen_helper_pcmpbf(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
341 break;
342 case 2:
343 LOG_DIS("pcmpeq r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
344 if (dc->rd) {
345 tcg_gen_setcond_tl(TCG_COND_EQ, cpu_R[dc->rd],
346 cpu_R[dc->ra], cpu_R[dc->rb]);
348 break;
349 case 3:
350 LOG_DIS("pcmpne r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
351 if (dc->rd) {
352 tcg_gen_setcond_tl(TCG_COND_NE, cpu_R[dc->rd],
353 cpu_R[dc->ra], cpu_R[dc->rb]);
355 break;
356 default:
357 cpu_abort(CPU(dc->cpu),
358 "unsupported pattern insn opcode=%x\n", dc->opcode);
359 break;
363 static void dec_and(DisasContext *dc)
365 unsigned int not;
367 if (!dc->type_b && (dc->imm & (1 << 10))) {
368 dec_pattern(dc);
369 return;
372 not = dc->opcode & (1 << 1);
373 LOG_DIS("and%s\n", not ? "n" : "");
375 if (!dc->rd)
376 return;
378 if (not) {
379 tcg_gen_andc_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
380 } else
381 tcg_gen_and_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
384 static void dec_or(DisasContext *dc)
386 if (!dc->type_b && (dc->imm & (1 << 10))) {
387 dec_pattern(dc);
388 return;
391 LOG_DIS("or r%d r%d r%d imm=%x\n", dc->rd, dc->ra, dc->rb, dc->imm);
392 if (dc->rd)
393 tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
396 static void dec_xor(DisasContext *dc)
398 if (!dc->type_b && (dc->imm & (1 << 10))) {
399 dec_pattern(dc);
400 return;
403 LOG_DIS("xor r%d\n", dc->rd);
404 if (dc->rd)
405 tcg_gen_xor_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
408 static inline void msr_read(DisasContext *dc, TCGv d)
410 tcg_gen_mov_tl(d, cpu_SR[SR_MSR]);
413 static inline void msr_write(DisasContext *dc, TCGv v)
415 TCGv t;
417 t = tcg_temp_new();
418 dc->cpustate_changed = 1;
419 /* PVR bit is not writable. */
420 tcg_gen_andi_tl(t, v, ~MSR_PVR);
421 tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], MSR_PVR);
422 tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], v);
423 tcg_temp_free(t);
426 static void dec_msr(DisasContext *dc)
428 CPUState *cs = CPU(dc->cpu);
429 TCGv t0, t1;
430 unsigned int sr, to, rn;
431 int mem_index = cpu_mmu_index(&dc->cpu->env, false);
433 sr = dc->imm & ((1 << 14) - 1);
434 to = dc->imm & (1 << 14);
435 dc->type_b = 1;
436 if (to)
437 dc->cpustate_changed = 1;
439 /* msrclr and msrset. */
440 if (!(dc->imm & (1 << 15))) {
441 unsigned int clr = dc->ir & (1 << 16);
443 LOG_DIS("msr%s r%d imm=%x\n", clr ? "clr" : "set",
444 dc->rd, dc->imm);
446 if (!dc->cpu->cfg.use_msr_instr) {
447 /* nop??? */
448 return;
451 if ((dc->tb_flags & MSR_EE_FLAG)
452 && mem_index == MMU_USER_IDX && (dc->imm != 4 && dc->imm != 0)) {
453 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
454 t_gen_raise_exception(dc, EXCP_HW_EXCP);
455 return;
458 if (dc->rd)
459 msr_read(dc, cpu_R[dc->rd]);
461 t0 = tcg_temp_new();
462 t1 = tcg_temp_new();
463 msr_read(dc, t0);
464 tcg_gen_mov_tl(t1, *(dec_alu_op_b(dc)));
466 if (clr) {
467 tcg_gen_not_tl(t1, t1);
468 tcg_gen_and_tl(t0, t0, t1);
469 } else
470 tcg_gen_or_tl(t0, t0, t1);
471 msr_write(dc, t0);
472 tcg_temp_free(t0);
473 tcg_temp_free(t1);
474 tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc + 4);
475 dc->is_jmp = DISAS_UPDATE;
476 return;
479 if (to) {
480 if ((dc->tb_flags & MSR_EE_FLAG)
481 && mem_index == MMU_USER_IDX) {
482 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
483 t_gen_raise_exception(dc, EXCP_HW_EXCP);
484 return;
488 #if !defined(CONFIG_USER_ONLY)
489 /* Catch read/writes to the mmu block. */
490 if ((sr & ~0xff) == 0x1000) {
491 sr &= 7;
492 LOG_DIS("m%ss sr%d r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm);
493 if (to)
494 gen_helper_mmu_write(cpu_env, tcg_const_tl(sr), cpu_R[dc->ra]);
495 else
496 gen_helper_mmu_read(cpu_R[dc->rd], cpu_env, tcg_const_tl(sr));
497 return;
499 #endif
501 if (to) {
502 LOG_DIS("m%ss sr%x r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm);
503 switch (sr) {
504 case 0:
505 break;
506 case 1:
507 msr_write(dc, cpu_R[dc->ra]);
508 break;
509 case 0x3:
510 tcg_gen_mov_tl(cpu_SR[SR_EAR], cpu_R[dc->ra]);
511 break;
512 case 0x5:
513 tcg_gen_mov_tl(cpu_SR[SR_ESR], cpu_R[dc->ra]);
514 break;
515 case 0x7:
516 tcg_gen_andi_tl(cpu_SR[SR_FSR], cpu_R[dc->ra], 31);
517 break;
518 case 0x800:
519 tcg_gen_st_tl(cpu_R[dc->ra], cpu_env, offsetof(CPUMBState, slr));
520 break;
521 case 0x802:
522 tcg_gen_st_tl(cpu_R[dc->ra], cpu_env, offsetof(CPUMBState, shr));
523 break;
524 default:
525 cpu_abort(CPU(dc->cpu), "unknown mts reg %x\n", sr);
526 break;
528 } else {
529 LOG_DIS("m%ss r%d sr%x imm=%x\n", to ? "t" : "f", dc->rd, sr, dc->imm);
531 switch (sr) {
532 case 0:
533 tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc);
534 break;
535 case 1:
536 msr_read(dc, cpu_R[dc->rd]);
537 break;
538 case 0x3:
539 tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_EAR]);
540 break;
541 case 0x5:
542 tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_ESR]);
543 break;
544 case 0x7:
545 tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_FSR]);
546 break;
547 case 0xb:
548 tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_BTR]);
549 break;
550 case 0x800:
551 tcg_gen_ld_tl(cpu_R[dc->rd], cpu_env, offsetof(CPUMBState, slr));
552 break;
553 case 0x802:
554 tcg_gen_ld_tl(cpu_R[dc->rd], cpu_env, offsetof(CPUMBState, shr));
555 break;
556 case 0x2000:
557 case 0x2001:
558 case 0x2002:
559 case 0x2003:
560 case 0x2004:
561 case 0x2005:
562 case 0x2006:
563 case 0x2007:
564 case 0x2008:
565 case 0x2009:
566 case 0x200a:
567 case 0x200b:
568 case 0x200c:
569 rn = sr & 0xf;
570 tcg_gen_ld_tl(cpu_R[dc->rd],
571 cpu_env, offsetof(CPUMBState, pvr.regs[rn]));
572 break;
573 default:
574 cpu_abort(cs, "unknown mfs reg %x\n", sr);
575 break;
579 if (dc->rd == 0) {
580 tcg_gen_movi_tl(cpu_R[0], 0);
584 /* Multiplier unit. */
585 static void dec_mul(DisasContext *dc)
587 TCGv tmp;
588 unsigned int subcode;
590 if ((dc->tb_flags & MSR_EE_FLAG)
591 && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
592 && !dc->cpu->cfg.use_hw_mul) {
593 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
594 t_gen_raise_exception(dc, EXCP_HW_EXCP);
595 return;
598 subcode = dc->imm & 3;
600 if (dc->type_b) {
601 LOG_DIS("muli r%d r%d %x\n", dc->rd, dc->ra, dc->imm);
602 tcg_gen_mul_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
603 return;
606 /* mulh, mulhsu and mulhu are not available if C_USE_HW_MUL is < 2. */
607 if (subcode >= 1 && subcode <= 3 && dc->cpu->cfg.use_hw_mul < 2) {
608 /* nop??? */
611 tmp = tcg_temp_new();
612 switch (subcode) {
613 case 0:
614 LOG_DIS("mul r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
615 tcg_gen_mul_tl(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
616 break;
617 case 1:
618 LOG_DIS("mulh r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
619 tcg_gen_muls2_tl(tmp, cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
620 break;
621 case 2:
622 LOG_DIS("mulhsu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
623 tcg_gen_mulsu2_tl(tmp, cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
624 break;
625 case 3:
626 LOG_DIS("mulhu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
627 tcg_gen_mulu2_tl(tmp, cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
628 break;
629 default:
630 cpu_abort(CPU(dc->cpu), "unknown MUL insn %x\n", subcode);
631 break;
633 tcg_temp_free(tmp);
636 /* Div unit. */
637 static void dec_div(DisasContext *dc)
639 unsigned int u;
641 u = dc->imm & 2;
642 LOG_DIS("div\n");
644 if ((dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
645 && !dc->cpu->cfg.use_div) {
646 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
647 t_gen_raise_exception(dc, EXCP_HW_EXCP);
650 if (u)
651 gen_helper_divu(cpu_R[dc->rd], cpu_env, *(dec_alu_op_b(dc)),
652 cpu_R[dc->ra]);
653 else
654 gen_helper_divs(cpu_R[dc->rd], cpu_env, *(dec_alu_op_b(dc)),
655 cpu_R[dc->ra]);
656 if (!dc->rd)
657 tcg_gen_movi_tl(cpu_R[dc->rd], 0);
660 static void dec_barrel(DisasContext *dc)
662 TCGv t0;
663 unsigned int imm_w, imm_s;
664 bool s, t, e = false, i = false;
666 if ((dc->tb_flags & MSR_EE_FLAG)
667 && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
668 && !dc->cpu->cfg.use_barrel) {
669 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
670 t_gen_raise_exception(dc, EXCP_HW_EXCP);
671 return;
674 if (dc->type_b) {
675 /* Insert and extract are only available in immediate mode. */
676 i = extract32(dc->imm, 15, 1);
677 e = extract32(dc->imm, 14, 1);
679 s = extract32(dc->imm, 10, 1);
680 t = extract32(dc->imm, 9, 1);
681 imm_w = extract32(dc->imm, 6, 5);
682 imm_s = extract32(dc->imm, 0, 5);
684 LOG_DIS("bs%s%s%s r%d r%d r%d\n",
685 e ? "e" : "",
686 s ? "l" : "r", t ? "a" : "l", dc->rd, dc->ra, dc->rb);
688 if (e) {
689 if (imm_w + imm_s > 32 || imm_w == 0) {
690 /* These inputs have an undefined behavior. */
691 qemu_log_mask(LOG_GUEST_ERROR, "bsefi: Bad input w=%d s=%d\n",
692 imm_w, imm_s);
693 } else {
694 tcg_gen_extract_i32(cpu_R[dc->rd], cpu_R[dc->ra], imm_s, imm_w);
696 } else if (i) {
697 int width = imm_w - imm_s + 1;
699 if (imm_w < imm_s) {
700 /* These inputs have an undefined behavior. */
701 qemu_log_mask(LOG_GUEST_ERROR, "bsifi: Bad input w=%d s=%d\n",
702 imm_w, imm_s);
703 } else {
704 tcg_gen_deposit_i32(cpu_R[dc->rd], cpu_R[dc->rd], cpu_R[dc->ra],
705 imm_s, width);
707 } else {
708 t0 = tcg_temp_new();
710 tcg_gen_mov_tl(t0, *(dec_alu_op_b(dc)));
711 tcg_gen_andi_tl(t0, t0, 31);
713 if (s) {
714 tcg_gen_shl_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0);
715 } else {
716 if (t) {
717 tcg_gen_sar_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0);
718 } else {
719 tcg_gen_shr_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0);
722 tcg_temp_free(t0);
726 static void dec_bit(DisasContext *dc)
728 CPUState *cs = CPU(dc->cpu);
729 TCGv t0;
730 unsigned int op;
731 int mem_index = cpu_mmu_index(&dc->cpu->env, false);
733 op = dc->ir & ((1 << 9) - 1);
734 switch (op) {
735 case 0x21:
736 /* src. */
737 t0 = tcg_temp_new();
739 LOG_DIS("src r%d r%d\n", dc->rd, dc->ra);
740 tcg_gen_andi_tl(t0, cpu_SR[SR_MSR], MSR_CC);
741 write_carry(dc, cpu_R[dc->ra]);
742 if (dc->rd) {
743 tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
744 tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->rd], t0);
746 tcg_temp_free(t0);
747 break;
749 case 0x1:
750 case 0x41:
751 /* srl. */
752 LOG_DIS("srl r%d r%d\n", dc->rd, dc->ra);
754 /* Update carry. Note that write carry only looks at the LSB. */
755 write_carry(dc, cpu_R[dc->ra]);
756 if (dc->rd) {
757 if (op == 0x41)
758 tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
759 else
760 tcg_gen_sari_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
762 break;
763 case 0x60:
764 LOG_DIS("ext8s r%d r%d\n", dc->rd, dc->ra);
765 tcg_gen_ext8s_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
766 break;
767 case 0x61:
768 LOG_DIS("ext16s r%d r%d\n", dc->rd, dc->ra);
769 tcg_gen_ext16s_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
770 break;
771 case 0x64:
772 case 0x66:
773 case 0x74:
774 case 0x76:
775 /* wdc. */
776 LOG_DIS("wdc r%d\n", dc->ra);
777 if ((dc->tb_flags & MSR_EE_FLAG)
778 && mem_index == MMU_USER_IDX) {
779 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
780 t_gen_raise_exception(dc, EXCP_HW_EXCP);
781 return;
783 break;
784 case 0x68:
785 /* wic. */
786 LOG_DIS("wic r%d\n", dc->ra);
787 if ((dc->tb_flags & MSR_EE_FLAG)
788 && mem_index == MMU_USER_IDX) {
789 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
790 t_gen_raise_exception(dc, EXCP_HW_EXCP);
791 return;
793 break;
794 case 0xe0:
795 if ((dc->tb_flags & MSR_EE_FLAG)
796 && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
797 && !dc->cpu->cfg.use_pcmp_instr) {
798 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
799 t_gen_raise_exception(dc, EXCP_HW_EXCP);
801 if (dc->cpu->cfg.use_pcmp_instr) {
802 tcg_gen_clzi_i32(cpu_R[dc->rd], cpu_R[dc->ra], 32);
804 break;
805 case 0x1e0:
806 /* swapb */
807 LOG_DIS("swapb r%d r%d\n", dc->rd, dc->ra);
808 tcg_gen_bswap32_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
809 break;
810 case 0x1e2:
811 /*swaph */
812 LOG_DIS("swaph r%d r%d\n", dc->rd, dc->ra);
813 tcg_gen_rotri_i32(cpu_R[dc->rd], cpu_R[dc->ra], 16);
814 break;
815 default:
816 cpu_abort(cs, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
817 dc->pc, op, dc->rd, dc->ra, dc->rb);
818 break;
822 static inline void sync_jmpstate(DisasContext *dc)
824 if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
825 if (dc->jmp == JMP_DIRECT) {
826 tcg_gen_movi_tl(env_btaken, 1);
828 dc->jmp = JMP_INDIRECT;
829 tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
833 static void dec_imm(DisasContext *dc)
835 LOG_DIS("imm %x\n", dc->imm << 16);
836 tcg_gen_movi_tl(env_imm, (dc->imm << 16));
837 dc->tb_flags |= IMM_FLAG;
838 dc->clear_imm = 0;
841 static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
843 unsigned int extimm = dc->tb_flags & IMM_FLAG;
844 /* Should be set to one if r1 is used by loadstores. */
845 int stackprot = 0;
847 /* All load/stores use ra. */
848 if (dc->ra == 1 && dc->cpu->cfg.stackprot) {
849 stackprot = 1;
852 /* Treat the common cases first. */
853 if (!dc->type_b) {
854 /* If any of the regs is r0, return a ptr to the other. */
855 if (dc->ra == 0) {
856 return &cpu_R[dc->rb];
857 } else if (dc->rb == 0) {
858 return &cpu_R[dc->ra];
861 if (dc->rb == 1 && dc->cpu->cfg.stackprot) {
862 stackprot = 1;
865 *t = tcg_temp_new();
866 tcg_gen_add_tl(*t, cpu_R[dc->ra], cpu_R[dc->rb]);
868 if (stackprot) {
869 gen_helper_stackprot(cpu_env, *t);
871 return t;
873 /* Immediate. */
874 if (!extimm) {
875 if (dc->imm == 0) {
876 return &cpu_R[dc->ra];
878 *t = tcg_temp_new();
879 tcg_gen_movi_tl(*t, (int32_t)((int16_t)dc->imm));
880 tcg_gen_add_tl(*t, cpu_R[dc->ra], *t);
881 } else {
882 *t = tcg_temp_new();
883 tcg_gen_add_tl(*t, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
886 if (stackprot) {
887 gen_helper_stackprot(cpu_env, *t);
889 return t;
892 static void dec_load(DisasContext *dc)
894 TCGv t, v, *addr;
895 unsigned int size, rev = 0, ex = 0;
896 TCGMemOp mop;
898 mop = dc->opcode & 3;
899 size = 1 << mop;
900 if (!dc->type_b) {
901 rev = (dc->ir >> 9) & 1;
902 ex = (dc->ir >> 10) & 1;
904 mop |= MO_TE;
905 if (rev) {
906 mop ^= MO_BSWAP;
909 if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
910 && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
911 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
912 t_gen_raise_exception(dc, EXCP_HW_EXCP);
913 return;
916 LOG_DIS("l%d%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "",
917 ex ? "x" : "");
919 t_sync_flags(dc);
920 addr = compute_ldst_addr(dc, &t);
923 * When doing reverse accesses we need to do two things.
925 * 1. Reverse the address wrt endianness.
926 * 2. Byteswap the data lanes on the way back into the CPU core.
928 if (rev && size != 4) {
929 /* Endian reverse the address. t is addr. */
930 switch (size) {
931 case 1:
933 /* 00 -> 11
934 01 -> 10
935 10 -> 10
936 11 -> 00 */
937 TCGv low = tcg_temp_new();
939 /* Force addr into the temp. */
940 if (addr != &t) {
941 t = tcg_temp_new();
942 tcg_gen_mov_tl(t, *addr);
943 addr = &t;
946 tcg_gen_andi_tl(low, t, 3);
947 tcg_gen_sub_tl(low, tcg_const_tl(3), low);
948 tcg_gen_andi_tl(t, t, ~3);
949 tcg_gen_or_tl(t, t, low);
950 tcg_gen_mov_tl(env_imm, t);
951 tcg_temp_free(low);
952 break;
955 case 2:
956 /* 00 -> 10
957 10 -> 00. */
958 /* Force addr into the temp. */
959 if (addr != &t) {
960 t = tcg_temp_new();
961 tcg_gen_xori_tl(t, *addr, 2);
962 addr = &t;
963 } else {
964 tcg_gen_xori_tl(t, t, 2);
966 break;
967 default:
968 cpu_abort(CPU(dc->cpu), "Invalid reverse size\n");
969 break;
973 /* lwx does not throw unaligned access errors, so force alignment */
974 if (ex) {
975 /* Force addr into the temp. */
976 if (addr != &t) {
977 t = tcg_temp_new();
978 tcg_gen_mov_tl(t, *addr);
979 addr = &t;
981 tcg_gen_andi_tl(t, t, ~3);
984 /* If we get a fault on a dslot, the jmpstate better be in sync. */
985 sync_jmpstate(dc);
987 /* Verify alignment if needed. */
989 * Microblaze gives MMU faults priority over faults due to
990 * unaligned addresses. That's why we speculatively do the load
991 * into v. If the load succeeds, we verify alignment of the
992 * address and if that succeeds we write into the destination reg.
994 v = tcg_temp_new();
995 tcg_gen_qemu_ld_tl(v, *addr, cpu_mmu_index(&dc->cpu->env, false), mop);
997 if ((dc->cpu->env.pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
998 tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
999 gen_helper_memalign(cpu_env, *addr, tcg_const_tl(dc->rd),
1000 tcg_const_tl(0), tcg_const_tl(size - 1));
1003 if (ex) {
1004 tcg_gen_mov_tl(env_res_addr, *addr);
1005 tcg_gen_mov_tl(env_res_val, v);
1007 if (dc->rd) {
1008 tcg_gen_mov_tl(cpu_R[dc->rd], v);
1010 tcg_temp_free(v);
1012 if (ex) { /* lwx */
1013 /* no support for AXI exclusive so always clear C */
1014 write_carryi(dc, 0);
1017 if (addr == &t)
1018 tcg_temp_free(t);
1021 static void dec_store(DisasContext *dc)
1023 TCGv t, *addr, swx_addr;
1024 TCGLabel *swx_skip = NULL;
1025 unsigned int size, rev = 0, ex = 0;
1026 TCGMemOp mop;
1028 mop = dc->opcode & 3;
1029 size = 1 << mop;
1030 if (!dc->type_b) {
1031 rev = (dc->ir >> 9) & 1;
1032 ex = (dc->ir >> 10) & 1;
1034 mop |= MO_TE;
1035 if (rev) {
1036 mop ^= MO_BSWAP;
1039 if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
1040 && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
1041 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
1042 t_gen_raise_exception(dc, EXCP_HW_EXCP);
1043 return;
1046 LOG_DIS("s%d%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "",
1047 ex ? "x" : "");
1048 t_sync_flags(dc);
1049 /* If we get a fault on a dslot, the jmpstate better be in sync. */
1050 sync_jmpstate(dc);
1051 addr = compute_ldst_addr(dc, &t);
1053 swx_addr = tcg_temp_local_new();
1054 if (ex) { /* swx */
1055 TCGv tval;
1057 /* Force addr into the swx_addr. */
1058 tcg_gen_mov_tl(swx_addr, *addr);
1059 addr = &swx_addr;
1060 /* swx does not throw unaligned access errors, so force alignment */
1061 tcg_gen_andi_tl(swx_addr, swx_addr, ~3);
1063 write_carryi(dc, 1);
1064 swx_skip = gen_new_label();
1065 tcg_gen_brcond_tl(TCG_COND_NE, env_res_addr, swx_addr, swx_skip);
1067 /* Compare the value loaded at lwx with current contents of
1068 the reserved location.
1069 FIXME: This only works for system emulation where we can expect
1070 this compare and the following write to be atomic. For user
1071 emulation we need to add atomicity between threads. */
1072 tval = tcg_temp_new();
1073 tcg_gen_qemu_ld_tl(tval, swx_addr, cpu_mmu_index(&dc->cpu->env, false),
1074 MO_TEUL);
1075 tcg_gen_brcond_tl(TCG_COND_NE, env_res_val, tval, swx_skip);
1076 write_carryi(dc, 0);
1077 tcg_temp_free(tval);
1080 if (rev && size != 4) {
1081 /* Endian reverse the address. t is addr. */
1082 switch (size) {
1083 case 1:
1085 /* 00 -> 11
1086 01 -> 10
1087 10 -> 10
1088 11 -> 00 */
1089 TCGv low = tcg_temp_new();
1091 /* Force addr into the temp. */
1092 if (addr != &t) {
1093 t = tcg_temp_new();
1094 tcg_gen_mov_tl(t, *addr);
1095 addr = &t;
1098 tcg_gen_andi_tl(low, t, 3);
1099 tcg_gen_sub_tl(low, tcg_const_tl(3), low);
1100 tcg_gen_andi_tl(t, t, ~3);
1101 tcg_gen_or_tl(t, t, low);
1102 tcg_gen_mov_tl(env_imm, t);
1103 tcg_temp_free(low);
1104 break;
1107 case 2:
1108 /* 00 -> 10
1109 10 -> 00. */
1110 /* Force addr into the temp. */
1111 if (addr != &t) {
1112 t = tcg_temp_new();
1113 tcg_gen_xori_tl(t, *addr, 2);
1114 addr = &t;
1115 } else {
1116 tcg_gen_xori_tl(t, t, 2);
1118 break;
1119 default:
1120 cpu_abort(CPU(dc->cpu), "Invalid reverse size\n");
1121 break;
1124 tcg_gen_qemu_st_tl(cpu_R[dc->rd], *addr, cpu_mmu_index(&dc->cpu->env, false), mop);
1126 /* Verify alignment if needed. */
1127 if ((dc->cpu->env.pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
1128 tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
1129 /* FIXME: if the alignment is wrong, we should restore the value
1130 * in memory. One possible way to achieve this is to probe
1131 * the MMU prior to the memaccess, thay way we could put
1132 * the alignment checks in between the probe and the mem
1133 * access.
1135 gen_helper_memalign(cpu_env, *addr, tcg_const_tl(dc->rd),
1136 tcg_const_tl(1), tcg_const_tl(size - 1));
1139 if (ex) {
1140 gen_set_label(swx_skip);
1142 tcg_temp_free(swx_addr);
1144 if (addr == &t)
1145 tcg_temp_free(t);
1148 static inline void eval_cc(DisasContext *dc, unsigned int cc,
1149 TCGv d, TCGv a, TCGv b)
1151 switch (cc) {
1152 case CC_EQ:
1153 tcg_gen_setcond_tl(TCG_COND_EQ, d, a, b);
1154 break;
1155 case CC_NE:
1156 tcg_gen_setcond_tl(TCG_COND_NE, d, a, b);
1157 break;
1158 case CC_LT:
1159 tcg_gen_setcond_tl(TCG_COND_LT, d, a, b);
1160 break;
1161 case CC_LE:
1162 tcg_gen_setcond_tl(TCG_COND_LE, d, a, b);
1163 break;
1164 case CC_GE:
1165 tcg_gen_setcond_tl(TCG_COND_GE, d, a, b);
1166 break;
1167 case CC_GT:
1168 tcg_gen_setcond_tl(TCG_COND_GT, d, a, b);
1169 break;
1170 default:
1171 cpu_abort(CPU(dc->cpu), "Unknown condition code %x.\n", cc);
1172 break;
1176 static void eval_cond_jmp(DisasContext *dc, TCGv pc_true, TCGv pc_false)
1178 TCGLabel *l1 = gen_new_label();
1179 /* Conditional jmp. */
1180 tcg_gen_mov_tl(cpu_SR[SR_PC], pc_false);
1181 tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1);
1182 tcg_gen_mov_tl(cpu_SR[SR_PC], pc_true);
1183 gen_set_label(l1);
1186 static void dec_bcc(DisasContext *dc)
1188 unsigned int cc;
1189 unsigned int dslot;
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);
1195 dc->delayed_branch = 1;
1196 if (dslot) {
1197 dc->delayed_branch = 2;
1198 dc->tb_flags |= D_FLAG;
1199 tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
1200 cpu_env, offsetof(CPUMBState, bimm));
1203 if (dec_alu_op_b_is_small_imm(dc)) {
1204 int32_t offset = (int32_t)((int16_t)dc->imm); /* sign-extend. */
1206 tcg_gen_movi_tl(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_movi_tl(env_btarget, dc->pc);
1212 tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc)));
1214 eval_cc(dc, cc, env_btaken, cpu_R[dc->ra], tcg_const_tl(0));
1217 static void dec_br(DisasContext *dc)
1219 unsigned int dslot, link, abs, mbar;
1220 int mem_index = cpu_mmu_index(&dc->cpu->env, false);
1222 dslot = dc->ir & (1 << 20);
1223 abs = dc->ir & (1 << 19);
1224 link = dc->ir & (1 << 18);
1226 /* Memory barrier. */
1227 mbar = (dc->ir >> 16) & 31;
1228 if (mbar == 2 && dc->imm == 4) {
1229 /* mbar IMM & 16 decodes to sleep. */
1230 if (dc->rd & 16) {
1231 TCGv_i32 tmp_hlt = tcg_const_i32(EXCP_HLT);
1232 TCGv_i32 tmp_1 = tcg_const_i32(1);
1234 LOG_DIS("sleep\n");
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_tl(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;
1246 LOG_DIS("mbar %d\n", dc->rd);
1247 /* Break the TB. */
1248 dc->cpustate_changed = 1;
1249 return;
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);
1257 dc->delayed_branch = 1;
1258 if (dslot) {
1259 dc->delayed_branch = 2;
1260 dc->tb_flags |= D_FLAG;
1261 tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
1262 cpu_env, offsetof(CPUMBState, bimm));
1264 if (link && dc->rd)
1265 tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc);
1267 dc->jmp = JMP_INDIRECT;
1268 if (abs) {
1269 tcg_gen_movi_tl(env_btaken, 1);
1270 tcg_gen_mov_tl(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 ((dc->tb_flags & MSR_EE_FLAG) && mem_index == MMU_USER_IDX) {
1276 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
1277 t_gen_raise_exception(dc, EXCP_HW_EXCP);
1278 return;
1281 t_gen_raise_exception(dc, EXCP_DEBUG);
1284 } else {
1285 if (dec_alu_op_b_is_small_imm(dc)) {
1286 dc->jmp = JMP_DIRECT;
1287 dc->jmp_pc = dc->pc + (int32_t)((int16_t)dc->imm);
1288 } else {
1289 tcg_gen_movi_tl(env_btaken, 1);
1290 tcg_gen_movi_tl(env_btarget, dc->pc);
1291 tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc)));
1296 static inline void do_rti(DisasContext *dc)
1298 TCGv t0, t1;
1299 t0 = tcg_temp_new();
1300 t1 = tcg_temp_new();
1301 tcg_gen_shri_tl(t0, cpu_SR[SR_MSR], 1);
1302 tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_IE);
1303 tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
1305 tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
1306 tcg_gen_or_tl(t1, t1, t0);
1307 msr_write(dc, t1);
1308 tcg_temp_free(t1);
1309 tcg_temp_free(t0);
1310 dc->tb_flags &= ~DRTI_FLAG;
1313 static inline void do_rtb(DisasContext *dc)
1315 TCGv t0, t1;
1316 t0 = tcg_temp_new();
1317 t1 = tcg_temp_new();
1318 tcg_gen_andi_tl(t1, cpu_SR[SR_MSR], ~MSR_BIP);
1319 tcg_gen_shri_tl(t0, t1, 1);
1320 tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
1322 tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
1323 tcg_gen_or_tl(t1, t1, t0);
1324 msr_write(dc, t1);
1325 tcg_temp_free(t1);
1326 tcg_temp_free(t0);
1327 dc->tb_flags &= ~DRTB_FLAG;
1330 static inline void do_rte(DisasContext *dc)
1332 TCGv t0, t1;
1333 t0 = tcg_temp_new();
1334 t1 = tcg_temp_new();
1336 tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_EE);
1337 tcg_gen_andi_tl(t1, t1, ~MSR_EIP);
1338 tcg_gen_shri_tl(t0, t1, 1);
1339 tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
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 &= ~DRTE_FLAG;
1349 static void dec_rts(DisasContext *dc)
1351 unsigned int b_bit, i_bit, e_bit;
1352 int mem_index = cpu_mmu_index(&dc->cpu->env, false);
1354 i_bit = dc->ir & (1 << 21);
1355 b_bit = dc->ir & (1 << 22);
1356 e_bit = dc->ir & (1 << 23);
1358 dc->delayed_branch = 2;
1359 dc->tb_flags |= D_FLAG;
1360 tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
1361 cpu_env, offsetof(CPUMBState, bimm));
1363 if (i_bit) {
1364 LOG_DIS("rtid ir=%x\n", dc->ir);
1365 if ((dc->tb_flags & MSR_EE_FLAG)
1366 && mem_index == MMU_USER_IDX) {
1367 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
1368 t_gen_raise_exception(dc, EXCP_HW_EXCP);
1370 dc->tb_flags |= DRTI_FLAG;
1371 } else if (b_bit) {
1372 LOG_DIS("rtbd ir=%x\n", dc->ir);
1373 if ((dc->tb_flags & MSR_EE_FLAG)
1374 && mem_index == MMU_USER_IDX) {
1375 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
1376 t_gen_raise_exception(dc, EXCP_HW_EXCP);
1378 dc->tb_flags |= DRTB_FLAG;
1379 } else if (e_bit) {
1380 LOG_DIS("rted ir=%x\n", dc->ir);
1381 if ((dc->tb_flags & MSR_EE_FLAG)
1382 && mem_index == MMU_USER_IDX) {
1383 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
1384 t_gen_raise_exception(dc, EXCP_HW_EXCP);
1386 dc->tb_flags |= DRTE_FLAG;
1387 } else
1388 LOG_DIS("rts ir=%x\n", dc->ir);
1390 dc->jmp = JMP_INDIRECT;
1391 tcg_gen_movi_tl(env_btaken, 1);
1392 tcg_gen_add_tl(env_btarget, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
1395 static int dec_check_fpuv2(DisasContext *dc)
1397 if ((dc->cpu->cfg.use_fpu != 2) && (dc->tb_flags & MSR_EE_FLAG)) {
1398 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_FPU);
1399 t_gen_raise_exception(dc, EXCP_HW_EXCP);
1401 return (dc->cpu->cfg.use_fpu == 2) ? 0 : PVR2_USE_FPU2_MASK;
1404 static void dec_fpu(DisasContext *dc)
1406 unsigned int fpu_insn;
1408 if ((dc->tb_flags & MSR_EE_FLAG)
1409 && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
1410 && (dc->cpu->cfg.use_fpu != 1)) {
1411 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
1412 t_gen_raise_exception(dc, EXCP_HW_EXCP);
1413 return;
1416 fpu_insn = (dc->ir >> 7) & 7;
1418 switch (fpu_insn) {
1419 case 0:
1420 gen_helper_fadd(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra],
1421 cpu_R[dc->rb]);
1422 break;
1424 case 1:
1425 gen_helper_frsub(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra],
1426 cpu_R[dc->rb]);
1427 break;
1429 case 2:
1430 gen_helper_fmul(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra],
1431 cpu_R[dc->rb]);
1432 break;
1434 case 3:
1435 gen_helper_fdiv(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra],
1436 cpu_R[dc->rb]);
1437 break;
1439 case 4:
1440 switch ((dc->ir >> 4) & 7) {
1441 case 0:
1442 gen_helper_fcmp_un(cpu_R[dc->rd], cpu_env,
1443 cpu_R[dc->ra], cpu_R[dc->rb]);
1444 break;
1445 case 1:
1446 gen_helper_fcmp_lt(cpu_R[dc->rd], cpu_env,
1447 cpu_R[dc->ra], cpu_R[dc->rb]);
1448 break;
1449 case 2:
1450 gen_helper_fcmp_eq(cpu_R[dc->rd], cpu_env,
1451 cpu_R[dc->ra], cpu_R[dc->rb]);
1452 break;
1453 case 3:
1454 gen_helper_fcmp_le(cpu_R[dc->rd], cpu_env,
1455 cpu_R[dc->ra], cpu_R[dc->rb]);
1456 break;
1457 case 4:
1458 gen_helper_fcmp_gt(cpu_R[dc->rd], cpu_env,
1459 cpu_R[dc->ra], cpu_R[dc->rb]);
1460 break;
1461 case 5:
1462 gen_helper_fcmp_ne(cpu_R[dc->rd], cpu_env,
1463 cpu_R[dc->ra], cpu_R[dc->rb]);
1464 break;
1465 case 6:
1466 gen_helper_fcmp_ge(cpu_R[dc->rd], cpu_env,
1467 cpu_R[dc->ra], cpu_R[dc->rb]);
1468 break;
1469 default:
1470 qemu_log_mask(LOG_UNIMP,
1471 "unimplemented fcmp fpu_insn=%x pc=%x"
1472 " opc=%x\n",
1473 fpu_insn, dc->pc, dc->opcode);
1474 dc->abort_at_next_insn = 1;
1475 break;
1477 break;
1479 case 5:
1480 if (!dec_check_fpuv2(dc)) {
1481 return;
1483 gen_helper_flt(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]);
1484 break;
1486 case 6:
1487 if (!dec_check_fpuv2(dc)) {
1488 return;
1490 gen_helper_fint(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]);
1491 break;
1493 case 7:
1494 if (!dec_check_fpuv2(dc)) {
1495 return;
1497 gen_helper_fsqrt(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]);
1498 break;
1500 default:
1501 qemu_log_mask(LOG_UNIMP, "unimplemented FPU insn fpu_insn=%x pc=%x"
1502 " opc=%x\n",
1503 fpu_insn, dc->pc, dc->opcode);
1504 dc->abort_at_next_insn = 1;
1505 break;
1509 static void dec_null(DisasContext *dc)
1511 if ((dc->tb_flags & MSR_EE_FLAG)
1512 && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
1513 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
1514 t_gen_raise_exception(dc, EXCP_HW_EXCP);
1515 return;
1517 qemu_log_mask(LOG_GUEST_ERROR, "unknown insn pc=%x opc=%x\n", dc->pc, dc->opcode);
1518 dc->abort_at_next_insn = 1;
1521 /* Insns connected to FSL or AXI stream attached devices. */
1522 static void dec_stream(DisasContext *dc)
1524 int mem_index = cpu_mmu_index(&dc->cpu->env, false);
1525 TCGv_i32 t_id, t_ctrl;
1526 int ctrl;
1528 LOG_DIS("%s%s imm=%x\n", dc->rd ? "get" : "put",
1529 dc->type_b ? "" : "d", dc->imm);
1531 if ((dc->tb_flags & MSR_EE_FLAG) && (mem_index == MMU_USER_IDX)) {
1532 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
1533 t_gen_raise_exception(dc, EXCP_HW_EXCP);
1534 return;
1537 t_id = tcg_temp_new();
1538 if (dc->type_b) {
1539 tcg_gen_movi_tl(t_id, dc->imm & 0xf);
1540 ctrl = dc->imm >> 10;
1541 } else {
1542 tcg_gen_andi_tl(t_id, cpu_R[dc->rb], 0xf);
1543 ctrl = dc->imm >> 5;
1546 t_ctrl = tcg_const_tl(ctrl);
1548 if (dc->rd == 0) {
1549 gen_helper_put(t_id, t_ctrl, cpu_R[dc->ra]);
1550 } else {
1551 gen_helper_get(cpu_R[dc->rd], t_id, t_ctrl);
1553 tcg_temp_free(t_id);
1554 tcg_temp_free(t_ctrl);
1557 static struct decoder_info {
1558 struct {
1559 uint32_t bits;
1560 uint32_t mask;
1562 void (*dec)(DisasContext *dc);
1563 } decinfo[] = {
1564 {DEC_ADD, dec_add},
1565 {DEC_SUB, dec_sub},
1566 {DEC_AND, dec_and},
1567 {DEC_XOR, dec_xor},
1568 {DEC_OR, dec_or},
1569 {DEC_BIT, dec_bit},
1570 {DEC_BARREL, dec_barrel},
1571 {DEC_LD, dec_load},
1572 {DEC_ST, dec_store},
1573 {DEC_IMM, dec_imm},
1574 {DEC_BR, dec_br},
1575 {DEC_BCC, dec_bcc},
1576 {DEC_RTS, dec_rts},
1577 {DEC_FPU, dec_fpu},
1578 {DEC_MUL, dec_mul},
1579 {DEC_DIV, dec_div},
1580 {DEC_MSR, dec_msr},
1581 {DEC_STREAM, dec_stream},
1582 {{0, 0}, dec_null}
1585 static inline void decode(DisasContext *dc, uint32_t ir)
1587 int i;
1589 dc->ir = ir;
1590 LOG_DIS("%8.8x\t", dc->ir);
1592 if (dc->ir)
1593 dc->nr_nops = 0;
1594 else {
1595 if ((dc->tb_flags & MSR_EE_FLAG)
1596 && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
1597 && (dc->cpu->env.pvr.regs[2] & PVR2_OPCODE_0x0_ILL_MASK)) {
1598 tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
1599 t_gen_raise_exception(dc, EXCP_HW_EXCP);
1600 return;
1603 LOG_DIS("nr_nops=%d\t", dc->nr_nops);
1604 dc->nr_nops++;
1605 if (dc->nr_nops > 4) {
1606 cpu_abort(CPU(dc->cpu), "fetching nop sequence\n");
1609 /* bit 2 seems to indicate insn type. */
1610 dc->type_b = ir & (1 << 29);
1612 dc->opcode = EXTRACT_FIELD(ir, 26, 31);
1613 dc->rd = EXTRACT_FIELD(ir, 21, 25);
1614 dc->ra = EXTRACT_FIELD(ir, 16, 20);
1615 dc->rb = EXTRACT_FIELD(ir, 11, 15);
1616 dc->imm = EXTRACT_FIELD(ir, 0, 15);
1618 /* Large switch for all insns. */
1619 for (i = 0; i < ARRAY_SIZE(decinfo); i++) {
1620 if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) {
1621 decinfo[i].dec(dc);
1622 break;
1627 /* generate intermediate code for basic block 'tb'. */
1628 void gen_intermediate_code(CPUMBState *env, struct TranslationBlock *tb)
1630 MicroBlazeCPU *cpu = mb_env_get_cpu(env);
1631 CPUState *cs = CPU(cpu);
1632 uint32_t pc_start;
1633 struct DisasContext ctx;
1634 struct DisasContext *dc = &ctx;
1635 uint32_t next_page_start, org_flags;
1636 target_ulong npc;
1637 int num_insns;
1638 int max_insns;
1640 pc_start = tb->pc;
1641 dc->cpu = cpu;
1642 dc->tb = tb;
1643 org_flags = dc->synced_flags = dc->tb_flags = tb->flags;
1645 dc->is_jmp = DISAS_NEXT;
1646 dc->jmp = 0;
1647 dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
1648 if (dc->delayed_branch) {
1649 dc->jmp = JMP_INDIRECT;
1651 dc->pc = pc_start;
1652 dc->singlestep_enabled = cs->singlestep_enabled;
1653 dc->cpustate_changed = 0;
1654 dc->abort_at_next_insn = 0;
1655 dc->nr_nops = 0;
1657 if (pc_start & 3) {
1658 cpu_abort(cs, "Microblaze: unaligned PC=%x\n", pc_start);
1661 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
1662 num_insns = 0;
1663 max_insns = tb->cflags & CF_COUNT_MASK;
1664 if (max_insns == 0) {
1665 max_insns = CF_COUNT_MASK;
1667 if (max_insns > TCG_MAX_INSNS) {
1668 max_insns = TCG_MAX_INSNS;
1671 gen_tb_start(tb);
1674 tcg_gen_insn_start(dc->pc);
1675 num_insns++;
1677 #if SIM_COMPAT
1678 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1679 tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
1680 gen_helper_debug();
1682 #endif
1684 if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
1685 t_gen_raise_exception(dc, EXCP_DEBUG);
1686 dc->is_jmp = DISAS_UPDATE;
1687 /* The address covered by the breakpoint must be included in
1688 [tb->pc, tb->pc + tb->size) in order to for it to be
1689 properly cleared -- thus we increment the PC here so that
1690 the logic setting tb->size below does the right thing. */
1691 dc->pc += 4;
1692 break;
1695 /* Pretty disas. */
1696 LOG_DIS("%8.8x:\t", dc->pc);
1698 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
1699 gen_io_start();
1702 dc->clear_imm = 1;
1703 decode(dc, cpu_ldl_code(env, dc->pc));
1704 if (dc->clear_imm)
1705 dc->tb_flags &= ~IMM_FLAG;
1706 dc->pc += 4;
1708 if (dc->delayed_branch) {
1709 dc->delayed_branch--;
1710 if (!dc->delayed_branch) {
1711 if (dc->tb_flags & DRTI_FLAG)
1712 do_rti(dc);
1713 if (dc->tb_flags & DRTB_FLAG)
1714 do_rtb(dc);
1715 if (dc->tb_flags & DRTE_FLAG)
1716 do_rte(dc);
1717 /* Clear the delay slot flag. */
1718 dc->tb_flags &= ~D_FLAG;
1719 /* If it is a direct jump, try direct chaining. */
1720 if (dc->jmp == JMP_INDIRECT) {
1721 eval_cond_jmp(dc, env_btarget, tcg_const_tl(dc->pc));
1722 dc->is_jmp = DISAS_JUMP;
1723 } else if (dc->jmp == JMP_DIRECT) {
1724 t_sync_flags(dc);
1725 gen_goto_tb(dc, 0, dc->jmp_pc);
1726 dc->is_jmp = DISAS_TB_JUMP;
1727 } else if (dc->jmp == JMP_DIRECT_CC) {
1728 TCGLabel *l1 = gen_new_label();
1729 t_sync_flags(dc);
1730 /* Conditional jmp. */
1731 tcg_gen_brcondi_tl(TCG_COND_NE, env_btaken, 0, l1);
1732 gen_goto_tb(dc, 1, dc->pc);
1733 gen_set_label(l1);
1734 gen_goto_tb(dc, 0, dc->jmp_pc);
1736 dc->is_jmp = DISAS_TB_JUMP;
1738 break;
1741 if (cs->singlestep_enabled) {
1742 break;
1744 } while (!dc->is_jmp && !dc->cpustate_changed
1745 && !tcg_op_buf_full()
1746 && !singlestep
1747 && (dc->pc < next_page_start)
1748 && num_insns < max_insns);
1750 npc = dc->pc;
1751 if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
1752 if (dc->tb_flags & D_FLAG) {
1753 dc->is_jmp = DISAS_UPDATE;
1754 tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
1755 sync_jmpstate(dc);
1756 } else
1757 npc = dc->jmp_pc;
1760 if (tb->cflags & CF_LAST_IO)
1761 gen_io_end();
1762 /* Force an update if the per-tb cpu state has changed. */
1763 if (dc->is_jmp == DISAS_NEXT
1764 && (dc->cpustate_changed || org_flags != dc->tb_flags)) {
1765 dc->is_jmp = DISAS_UPDATE;
1766 tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
1768 t_sync_flags(dc);
1770 if (unlikely(cs->singlestep_enabled)) {
1771 TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG);
1773 if (dc->is_jmp != DISAS_JUMP) {
1774 tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
1776 gen_helper_raise_exception(cpu_env, tmp);
1777 tcg_temp_free_i32(tmp);
1778 } else {
1779 switch(dc->is_jmp) {
1780 case DISAS_NEXT:
1781 gen_goto_tb(dc, 1, npc);
1782 break;
1783 default:
1784 case DISAS_JUMP:
1785 case DISAS_UPDATE:
1786 /* indicate that the hash table must be used
1787 to find the next TB */
1788 tcg_gen_exit_tb(0);
1789 break;
1790 case DISAS_TB_JUMP:
1791 /* nothing more to generate */
1792 break;
1795 gen_tb_end(tb, num_insns);
1797 tb->size = dc->pc - pc_start;
1798 tb->icount = num_insns;
1800 #ifdef DEBUG_DISAS
1801 #if !SIM_COMPAT
1802 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
1803 && qemu_log_in_addr_range(pc_start)) {
1804 qemu_log_lock();
1805 qemu_log("--------------\n");
1806 #if DISAS_GNU
1807 log_target_disas(cs, pc_start, dc->pc - pc_start, 0);
1808 #endif
1809 qemu_log("\nisize=%d osize=%d\n",
1810 dc->pc - pc_start, tcg_op_buf_count());
1811 qemu_log_unlock();
1813 #endif
1814 #endif
1815 assert(!dc->abort_at_next_insn);
1818 void mb_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
1819 int flags)
1821 MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
1822 CPUMBState *env = &cpu->env;
1823 int i;
1825 if (!env || !f)
1826 return;
1828 cpu_fprintf(f, "IN: PC=%x %s\n",
1829 env->sregs[SR_PC], lookup_symbol(env->sregs[SR_PC]));
1830 cpu_fprintf(f, "rmsr=%x resr=%x rear=%x debug=%x imm=%x iflags=%x fsr=%x\n",
1831 env->sregs[SR_MSR], env->sregs[SR_ESR], env->sregs[SR_EAR],
1832 env->debug, env->imm, env->iflags, env->sregs[SR_FSR]);
1833 cpu_fprintf(f, "btaken=%d btarget=%x mode=%s(saved=%s) eip=%d ie=%d\n",
1834 env->btaken, env->btarget,
1835 (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel",
1836 (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel",
1837 (env->sregs[SR_MSR] & MSR_EIP),
1838 (env->sregs[SR_MSR] & MSR_IE));
1840 for (i = 0; i < 32; i++) {
1841 cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
1842 if ((i + 1) % 4 == 0)
1843 cpu_fprintf(f, "\n");
1845 cpu_fprintf(f, "\n\n");
1848 MicroBlazeCPU *cpu_mb_init(const char *cpu_model)
1850 MicroBlazeCPU *cpu;
1852 cpu = MICROBLAZE_CPU(object_new(TYPE_MICROBLAZE_CPU));
1854 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
1856 return cpu;
1859 void mb_tcg_init(void)
1861 int i;
1863 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
1864 tcg_ctx.tcg_env = cpu_env;
1866 env_debug = tcg_global_mem_new(cpu_env,
1867 offsetof(CPUMBState, debug),
1868 "debug0");
1869 env_iflags = tcg_global_mem_new(cpu_env,
1870 offsetof(CPUMBState, iflags),
1871 "iflags");
1872 env_imm = tcg_global_mem_new(cpu_env,
1873 offsetof(CPUMBState, imm),
1874 "imm");
1875 env_btarget = tcg_global_mem_new(cpu_env,
1876 offsetof(CPUMBState, btarget),
1877 "btarget");
1878 env_btaken = tcg_global_mem_new(cpu_env,
1879 offsetof(CPUMBState, btaken),
1880 "btaken");
1881 env_res_addr = tcg_global_mem_new(cpu_env,
1882 offsetof(CPUMBState, res_addr),
1883 "res_addr");
1884 env_res_val = tcg_global_mem_new(cpu_env,
1885 offsetof(CPUMBState, res_val),
1886 "res_val");
1887 for (i = 0; i < ARRAY_SIZE(cpu_R); i++) {
1888 cpu_R[i] = tcg_global_mem_new(cpu_env,
1889 offsetof(CPUMBState, regs[i]),
1890 regnames[i]);
1892 for (i = 0; i < ARRAY_SIZE(cpu_SR); i++) {
1893 cpu_SR[i] = tcg_global_mem_new(cpu_env,
1894 offsetof(CPUMBState, sregs[i]),
1895 special_regnames[i]);
1899 void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb,
1900 target_ulong *data)
1902 env->sregs[SR_PC] = data[0];