xref: /openbmc/qemu/target/microblaze/translate.c (revision 30b6852c)
1 /*
2  *  Xilinx MicroBlaze emulation for qemu: main translation routines.
3  *
4  *  Copyright (c) 2009 Edgar E. Iglesias.
5  *  Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include "qemu/osdep.h"
22 #include "cpu.h"
23 #include "disas/disas.h"
24 #include "exec/exec-all.h"
25 #include "tcg/tcg-op.h"
26 #include "exec/helper-proto.h"
27 #include "exec/cpu_ldst.h"
28 #include "exec/helper-gen.h"
29 #include "exec/translator.h"
30 #include "qemu/qemu-print.h"
31 
32 #include "exec/log.h"
33 
34 #define EXTRACT_FIELD(src, start, end) \
35             (((src) >> start) & ((1 << (end - start + 1)) - 1))
36 
37 /* is_jmp field values */
38 #define DISAS_JUMP    DISAS_TARGET_0 /* only pc was modified dynamically */
39 #define DISAS_EXIT    DISAS_TARGET_1 /* all cpu state modified dynamically */
40 
41 /* cpu state besides pc was modified dynamically; update pc to next */
42 #define DISAS_EXIT_NEXT DISAS_TARGET_2
43 /* cpu state besides pc was modified dynamically; update pc to btarget */
44 #define DISAS_EXIT_JUMP DISAS_TARGET_3
45 
46 static TCGv_i32 cpu_R[32];
47 static TCGv_i32 cpu_pc;
48 static TCGv_i32 cpu_msr;
49 static TCGv_i32 cpu_msr_c;
50 static TCGv_i32 cpu_imm;
51 static TCGv_i32 cpu_bvalue;
52 static TCGv_i32 cpu_btarget;
53 static TCGv_i32 cpu_iflags;
54 static TCGv cpu_res_addr;
55 static TCGv_i32 cpu_res_val;
56 
57 #include "exec/gen-icount.h"
58 
59 /* This is the state at translation time.  */
60 typedef struct DisasContext {
61     DisasContextBase base;
62     const MicroBlazeCPUConfig *cfg;
63 
64     /* TCG op of the current insn_start.  */
65     TCGOp *insn_start;
66 
67     TCGv_i32 r0;
68     bool r0_set;
69 
70     /* Decoder.  */
71     uint32_t ext_imm;
72     unsigned int tb_flags;
73     unsigned int tb_flags_to_set;
74     int mem_index;
75 
76     /* Condition under which to jump, including NEVER and ALWAYS. */
77     TCGCond jmp_cond;
78 
79     /* Immediate branch-taken destination, or -1 for indirect. */
80     uint32_t jmp_dest;
81 } DisasContext;
82 
83 static int typeb_imm(DisasContext *dc, int x)
84 {
85     if (dc->tb_flags & IMM_FLAG) {
86         return deposit32(dc->ext_imm, 0, 16, x);
87     }
88     return x;
89 }
90 
91 /* Include the auto-generated decoder.  */
92 #include "decode-insns.c.inc"
93 
94 static void t_sync_flags(DisasContext *dc)
95 {
96     /* Synch the tb dependent flags between translator and runtime.  */
97     if ((dc->tb_flags ^ dc->base.tb->flags) & IFLAGS_TB_MASK) {
98         tcg_gen_movi_i32(cpu_iflags, dc->tb_flags & IFLAGS_TB_MASK);
99     }
100 }
101 
102 static void gen_raise_exception(DisasContext *dc, uint32_t index)
103 {
104     TCGv_i32 tmp = tcg_const_i32(index);
105 
106     gen_helper_raise_exception(cpu_env, tmp);
107     tcg_temp_free_i32(tmp);
108     dc->base.is_jmp = DISAS_NORETURN;
109 }
110 
111 static void gen_raise_exception_sync(DisasContext *dc, uint32_t index)
112 {
113     t_sync_flags(dc);
114     tcg_gen_movi_i32(cpu_pc, dc->base.pc_next);
115     gen_raise_exception(dc, index);
116 }
117 
118 static void gen_raise_hw_excp(DisasContext *dc, uint32_t esr_ec)
119 {
120     TCGv_i32 tmp = tcg_const_i32(esr_ec);
121     tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUMBState, esr));
122     tcg_temp_free_i32(tmp);
123 
124     gen_raise_exception_sync(dc, EXCP_HW_EXCP);
125 }
126 
127 static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
128 {
129     if (dc->base.singlestep_enabled) {
130         TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG);
131         tcg_gen_movi_i32(cpu_pc, dest);
132         gen_helper_raise_exception(cpu_env, tmp);
133         tcg_temp_free_i32(tmp);
134     } else if (translator_use_goto_tb(&dc->base, dest)) {
135         tcg_gen_goto_tb(n);
136         tcg_gen_movi_i32(cpu_pc, dest);
137         tcg_gen_exit_tb(dc->base.tb, n);
138     } else {
139         tcg_gen_movi_i32(cpu_pc, dest);
140         tcg_gen_lookup_and_goto_ptr();
141     }
142     dc->base.is_jmp = DISAS_NORETURN;
143 }
144 
145 /*
146  * Returns true if the insn an illegal operation.
147  * If exceptions are enabled, an exception is raised.
148  */
149 static bool trap_illegal(DisasContext *dc, bool cond)
150 {
151     if (cond && (dc->tb_flags & MSR_EE)
152         && dc->cfg->illegal_opcode_exception) {
153         gen_raise_hw_excp(dc, ESR_EC_ILLEGAL_OP);
154     }
155     return cond;
156 }
157 
158 /*
159  * Returns true if the insn is illegal in userspace.
160  * If exceptions are enabled, an exception is raised.
161  */
162 static bool trap_userspace(DisasContext *dc, bool cond)
163 {
164     bool cond_user = cond && dc->mem_index == MMU_USER_IDX;
165 
166     if (cond_user && (dc->tb_flags & MSR_EE)) {
167         gen_raise_hw_excp(dc, ESR_EC_PRIVINSN);
168     }
169     return cond_user;
170 }
171 
172 /*
173  * Return true, and log an error, if the current insn is
174  * within a delay slot.
175  */
176 static bool invalid_delay_slot(DisasContext *dc, const char *insn_type)
177 {
178     if (dc->tb_flags & D_FLAG) {
179         qemu_log_mask(LOG_GUEST_ERROR,
180                       "Invalid insn in delay slot: %s at %08x\n",
181                       insn_type, (uint32_t)dc->base.pc_next);
182         return true;
183     }
184     return false;
185 }
186 
187 static TCGv_i32 reg_for_read(DisasContext *dc, int reg)
188 {
189     if (likely(reg != 0)) {
190         return cpu_R[reg];
191     }
192     if (!dc->r0_set) {
193         if (dc->r0 == NULL) {
194             dc->r0 = tcg_temp_new_i32();
195         }
196         tcg_gen_movi_i32(dc->r0, 0);
197         dc->r0_set = true;
198     }
199     return dc->r0;
200 }
201 
202 static TCGv_i32 reg_for_write(DisasContext *dc, int reg)
203 {
204     if (likely(reg != 0)) {
205         return cpu_R[reg];
206     }
207     if (dc->r0 == NULL) {
208         dc->r0 = tcg_temp_new_i32();
209     }
210     return dc->r0;
211 }
212 
213 static bool do_typea(DisasContext *dc, arg_typea *arg, bool side_effects,
214                      void (*fn)(TCGv_i32, TCGv_i32, TCGv_i32))
215 {
216     TCGv_i32 rd, ra, rb;
217 
218     if (arg->rd == 0 && !side_effects) {
219         return true;
220     }
221 
222     rd = reg_for_write(dc, arg->rd);
223     ra = reg_for_read(dc, arg->ra);
224     rb = reg_for_read(dc, arg->rb);
225     fn(rd, ra, rb);
226     return true;
227 }
228 
229 static bool do_typea0(DisasContext *dc, arg_typea0 *arg, bool side_effects,
230                       void (*fn)(TCGv_i32, TCGv_i32))
231 {
232     TCGv_i32 rd, ra;
233 
234     if (arg->rd == 0 && !side_effects) {
235         return true;
236     }
237 
238     rd = reg_for_write(dc, arg->rd);
239     ra = reg_for_read(dc, arg->ra);
240     fn(rd, ra);
241     return true;
242 }
243 
244 static bool do_typeb_imm(DisasContext *dc, arg_typeb *arg, bool side_effects,
245                          void (*fni)(TCGv_i32, TCGv_i32, int32_t))
246 {
247     TCGv_i32 rd, ra;
248 
249     if (arg->rd == 0 && !side_effects) {
250         return true;
251     }
252 
253     rd = reg_for_write(dc, arg->rd);
254     ra = reg_for_read(dc, arg->ra);
255     fni(rd, ra, arg->imm);
256     return true;
257 }
258 
259 static bool do_typeb_val(DisasContext *dc, arg_typeb *arg, bool side_effects,
260                          void (*fn)(TCGv_i32, TCGv_i32, TCGv_i32))
261 {
262     TCGv_i32 rd, ra, imm;
263 
264     if (arg->rd == 0 && !side_effects) {
265         return true;
266     }
267 
268     rd = reg_for_write(dc, arg->rd);
269     ra = reg_for_read(dc, arg->ra);
270     imm = tcg_const_i32(arg->imm);
271 
272     fn(rd, ra, imm);
273 
274     tcg_temp_free_i32(imm);
275     return true;
276 }
277 
278 #define DO_TYPEA(NAME, SE, FN) \
279     static bool trans_##NAME(DisasContext *dc, arg_typea *a) \
280     { return do_typea(dc, a, SE, FN); }
281 
282 #define DO_TYPEA_CFG(NAME, CFG, SE, FN) \
283     static bool trans_##NAME(DisasContext *dc, arg_typea *a) \
284     { return dc->cfg->CFG && do_typea(dc, a, SE, FN); }
285 
286 #define DO_TYPEA0(NAME, SE, FN) \
287     static bool trans_##NAME(DisasContext *dc, arg_typea0 *a) \
288     { return do_typea0(dc, a, SE, FN); }
289 
290 #define DO_TYPEA0_CFG(NAME, CFG, SE, FN) \
291     static bool trans_##NAME(DisasContext *dc, arg_typea0 *a) \
292     { return dc->cfg->CFG && do_typea0(dc, a, SE, FN); }
293 
294 #define DO_TYPEBI(NAME, SE, FNI) \
295     static bool trans_##NAME(DisasContext *dc, arg_typeb *a) \
296     { return do_typeb_imm(dc, a, SE, FNI); }
297 
298 #define DO_TYPEBI_CFG(NAME, CFG, SE, FNI) \
299     static bool trans_##NAME(DisasContext *dc, arg_typeb *a) \
300     { return dc->cfg->CFG && do_typeb_imm(dc, a, SE, FNI); }
301 
302 #define DO_TYPEBV(NAME, SE, FN) \
303     static bool trans_##NAME(DisasContext *dc, arg_typeb *a) \
304     { return do_typeb_val(dc, a, SE, FN); }
305 
306 #define ENV_WRAPPER2(NAME, HELPER) \
307     static void NAME(TCGv_i32 out, TCGv_i32 ina) \
308     { HELPER(out, cpu_env, ina); }
309 
310 #define ENV_WRAPPER3(NAME, HELPER) \
311     static void NAME(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) \
312     { HELPER(out, cpu_env, ina, inb); }
313 
314 /* No input carry, but output carry. */
315 static void gen_add(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
316 {
317     TCGv_i32 zero = tcg_const_i32(0);
318 
319     tcg_gen_add2_i32(out, cpu_msr_c, ina, zero, inb, zero);
320 
321     tcg_temp_free_i32(zero);
322 }
323 
324 /* Input and output carry. */
325 static void gen_addc(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
326 {
327     TCGv_i32 zero = tcg_const_i32(0);
328     TCGv_i32 tmp = tcg_temp_new_i32();
329 
330     tcg_gen_add2_i32(tmp, cpu_msr_c, ina, zero, cpu_msr_c, zero);
331     tcg_gen_add2_i32(out, cpu_msr_c, tmp, cpu_msr_c, inb, zero);
332 
333     tcg_temp_free_i32(tmp);
334     tcg_temp_free_i32(zero);
335 }
336 
337 /* Input carry, but no output carry. */
338 static void gen_addkc(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
339 {
340     tcg_gen_add_i32(out, ina, inb);
341     tcg_gen_add_i32(out, out, cpu_msr_c);
342 }
343 
344 DO_TYPEA(add, true, gen_add)
345 DO_TYPEA(addc, true, gen_addc)
346 DO_TYPEA(addk, false, tcg_gen_add_i32)
347 DO_TYPEA(addkc, true, gen_addkc)
348 
349 DO_TYPEBV(addi, true, gen_add)
350 DO_TYPEBV(addic, true, gen_addc)
351 DO_TYPEBI(addik, false, tcg_gen_addi_i32)
352 DO_TYPEBV(addikc, true, gen_addkc)
353 
354 static void gen_andni(TCGv_i32 out, TCGv_i32 ina, int32_t imm)
355 {
356     tcg_gen_andi_i32(out, ina, ~imm);
357 }
358 
359 DO_TYPEA(and, false, tcg_gen_and_i32)
360 DO_TYPEBI(andi, false, tcg_gen_andi_i32)
361 DO_TYPEA(andn, false, tcg_gen_andc_i32)
362 DO_TYPEBI(andni, false, gen_andni)
363 
364 static void gen_bsra(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
365 {
366     TCGv_i32 tmp = tcg_temp_new_i32();
367     tcg_gen_andi_i32(tmp, inb, 31);
368     tcg_gen_sar_i32(out, ina, tmp);
369     tcg_temp_free_i32(tmp);
370 }
371 
372 static void gen_bsrl(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
373 {
374     TCGv_i32 tmp = tcg_temp_new_i32();
375     tcg_gen_andi_i32(tmp, inb, 31);
376     tcg_gen_shr_i32(out, ina, tmp);
377     tcg_temp_free_i32(tmp);
378 }
379 
380 static void gen_bsll(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
381 {
382     TCGv_i32 tmp = tcg_temp_new_i32();
383     tcg_gen_andi_i32(tmp, inb, 31);
384     tcg_gen_shl_i32(out, ina, tmp);
385     tcg_temp_free_i32(tmp);
386 }
387 
388 static void gen_bsefi(TCGv_i32 out, TCGv_i32 ina, int32_t imm)
389 {
390     /* Note that decodetree has extracted and reassembled imm_w/imm_s. */
391     int imm_w = extract32(imm, 5, 5);
392     int imm_s = extract32(imm, 0, 5);
393 
394     if (imm_w + imm_s > 32 || imm_w == 0) {
395         /* These inputs have an undefined behavior.  */
396         qemu_log_mask(LOG_GUEST_ERROR, "bsefi: Bad input w=%d s=%d\n",
397                       imm_w, imm_s);
398     } else {
399         tcg_gen_extract_i32(out, ina, imm_s, imm_w);
400     }
401 }
402 
403 static void gen_bsifi(TCGv_i32 out, TCGv_i32 ina, int32_t imm)
404 {
405     /* Note that decodetree has extracted and reassembled imm_w/imm_s. */
406     int imm_w = extract32(imm, 5, 5);
407     int imm_s = extract32(imm, 0, 5);
408     int width = imm_w - imm_s + 1;
409 
410     if (imm_w < imm_s) {
411         /* These inputs have an undefined behavior.  */
412         qemu_log_mask(LOG_GUEST_ERROR, "bsifi: Bad input w=%d s=%d\n",
413                       imm_w, imm_s);
414     } else {
415         tcg_gen_deposit_i32(out, out, ina, imm_s, width);
416     }
417 }
418 
419 DO_TYPEA_CFG(bsra, use_barrel, false, gen_bsra)
420 DO_TYPEA_CFG(bsrl, use_barrel, false, gen_bsrl)
421 DO_TYPEA_CFG(bsll, use_barrel, false, gen_bsll)
422 
423 DO_TYPEBI_CFG(bsrai, use_barrel, false, tcg_gen_sari_i32)
424 DO_TYPEBI_CFG(bsrli, use_barrel, false, tcg_gen_shri_i32)
425 DO_TYPEBI_CFG(bslli, use_barrel, false, tcg_gen_shli_i32)
426 
427 DO_TYPEBI_CFG(bsefi, use_barrel, false, gen_bsefi)
428 DO_TYPEBI_CFG(bsifi, use_barrel, false, gen_bsifi)
429 
430 static void gen_clz(TCGv_i32 out, TCGv_i32 ina)
431 {
432     tcg_gen_clzi_i32(out, ina, 32);
433 }
434 
435 DO_TYPEA0_CFG(clz, use_pcmp_instr, false, gen_clz)
436 
437 static void gen_cmp(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
438 {
439     TCGv_i32 lt = tcg_temp_new_i32();
440 
441     tcg_gen_setcond_i32(TCG_COND_LT, lt, inb, ina);
442     tcg_gen_sub_i32(out, inb, ina);
443     tcg_gen_deposit_i32(out, out, lt, 31, 1);
444     tcg_temp_free_i32(lt);
445 }
446 
447 static void gen_cmpu(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
448 {
449     TCGv_i32 lt = tcg_temp_new_i32();
450 
451     tcg_gen_setcond_i32(TCG_COND_LTU, lt, inb, ina);
452     tcg_gen_sub_i32(out, inb, ina);
453     tcg_gen_deposit_i32(out, out, lt, 31, 1);
454     tcg_temp_free_i32(lt);
455 }
456 
457 DO_TYPEA(cmp, false, gen_cmp)
458 DO_TYPEA(cmpu, false, gen_cmpu)
459 
460 ENV_WRAPPER3(gen_fadd, gen_helper_fadd)
461 ENV_WRAPPER3(gen_frsub, gen_helper_frsub)
462 ENV_WRAPPER3(gen_fmul, gen_helper_fmul)
463 ENV_WRAPPER3(gen_fdiv, gen_helper_fdiv)
464 ENV_WRAPPER3(gen_fcmp_un, gen_helper_fcmp_un)
465 ENV_WRAPPER3(gen_fcmp_lt, gen_helper_fcmp_lt)
466 ENV_WRAPPER3(gen_fcmp_eq, gen_helper_fcmp_eq)
467 ENV_WRAPPER3(gen_fcmp_le, gen_helper_fcmp_le)
468 ENV_WRAPPER3(gen_fcmp_gt, gen_helper_fcmp_gt)
469 ENV_WRAPPER3(gen_fcmp_ne, gen_helper_fcmp_ne)
470 ENV_WRAPPER3(gen_fcmp_ge, gen_helper_fcmp_ge)
471 
472 DO_TYPEA_CFG(fadd, use_fpu, true, gen_fadd)
473 DO_TYPEA_CFG(frsub, use_fpu, true, gen_frsub)
474 DO_TYPEA_CFG(fmul, use_fpu, true, gen_fmul)
475 DO_TYPEA_CFG(fdiv, use_fpu, true, gen_fdiv)
476 DO_TYPEA_CFG(fcmp_un, use_fpu, true, gen_fcmp_un)
477 DO_TYPEA_CFG(fcmp_lt, use_fpu, true, gen_fcmp_lt)
478 DO_TYPEA_CFG(fcmp_eq, use_fpu, true, gen_fcmp_eq)
479 DO_TYPEA_CFG(fcmp_le, use_fpu, true, gen_fcmp_le)
480 DO_TYPEA_CFG(fcmp_gt, use_fpu, true, gen_fcmp_gt)
481 DO_TYPEA_CFG(fcmp_ne, use_fpu, true, gen_fcmp_ne)
482 DO_TYPEA_CFG(fcmp_ge, use_fpu, true, gen_fcmp_ge)
483 
484 ENV_WRAPPER2(gen_flt, gen_helper_flt)
485 ENV_WRAPPER2(gen_fint, gen_helper_fint)
486 ENV_WRAPPER2(gen_fsqrt, gen_helper_fsqrt)
487 
488 DO_TYPEA0_CFG(flt, use_fpu >= 2, true, gen_flt)
489 DO_TYPEA0_CFG(fint, use_fpu >= 2, true, gen_fint)
490 DO_TYPEA0_CFG(fsqrt, use_fpu >= 2, true, gen_fsqrt)
491 
492 /* Does not use ENV_WRAPPER3, because arguments are swapped as well. */
493 static void gen_idiv(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
494 {
495     gen_helper_divs(out, cpu_env, inb, ina);
496 }
497 
498 static void gen_idivu(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
499 {
500     gen_helper_divu(out, cpu_env, inb, ina);
501 }
502 
503 DO_TYPEA_CFG(idiv, use_div, true, gen_idiv)
504 DO_TYPEA_CFG(idivu, use_div, true, gen_idivu)
505 
506 static bool trans_imm(DisasContext *dc, arg_imm *arg)
507 {
508     if (invalid_delay_slot(dc, "imm")) {
509         return true;
510     }
511     dc->ext_imm = arg->imm << 16;
512     tcg_gen_movi_i32(cpu_imm, dc->ext_imm);
513     dc->tb_flags_to_set = IMM_FLAG;
514     return true;
515 }
516 
517 static void gen_mulh(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
518 {
519     TCGv_i32 tmp = tcg_temp_new_i32();
520     tcg_gen_muls2_i32(tmp, out, ina, inb);
521     tcg_temp_free_i32(tmp);
522 }
523 
524 static void gen_mulhu(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
525 {
526     TCGv_i32 tmp = tcg_temp_new_i32();
527     tcg_gen_mulu2_i32(tmp, out, ina, inb);
528     tcg_temp_free_i32(tmp);
529 }
530 
531 static void gen_mulhsu(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
532 {
533     TCGv_i32 tmp = tcg_temp_new_i32();
534     tcg_gen_mulsu2_i32(tmp, out, ina, inb);
535     tcg_temp_free_i32(tmp);
536 }
537 
538 DO_TYPEA_CFG(mul, use_hw_mul, false, tcg_gen_mul_i32)
539 DO_TYPEA_CFG(mulh, use_hw_mul >= 2, false, gen_mulh)
540 DO_TYPEA_CFG(mulhu, use_hw_mul >= 2, false, gen_mulhu)
541 DO_TYPEA_CFG(mulhsu, use_hw_mul >= 2, false, gen_mulhsu)
542 DO_TYPEBI_CFG(muli, use_hw_mul, false, tcg_gen_muli_i32)
543 
544 DO_TYPEA(or, false, tcg_gen_or_i32)
545 DO_TYPEBI(ori, false, tcg_gen_ori_i32)
546 
547 static void gen_pcmpeq(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
548 {
549     tcg_gen_setcond_i32(TCG_COND_EQ, out, ina, inb);
550 }
551 
552 static void gen_pcmpne(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
553 {
554     tcg_gen_setcond_i32(TCG_COND_NE, out, ina, inb);
555 }
556 
557 DO_TYPEA_CFG(pcmpbf, use_pcmp_instr, false, gen_helper_pcmpbf)
558 DO_TYPEA_CFG(pcmpeq, use_pcmp_instr, false, gen_pcmpeq)
559 DO_TYPEA_CFG(pcmpne, use_pcmp_instr, false, gen_pcmpne)
560 
561 /* No input carry, but output carry. */
562 static void gen_rsub(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
563 {
564     tcg_gen_setcond_i32(TCG_COND_GEU, cpu_msr_c, inb, ina);
565     tcg_gen_sub_i32(out, inb, ina);
566 }
567 
568 /* Input and output carry. */
569 static void gen_rsubc(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
570 {
571     TCGv_i32 zero = tcg_const_i32(0);
572     TCGv_i32 tmp = tcg_temp_new_i32();
573 
574     tcg_gen_not_i32(tmp, ina);
575     tcg_gen_add2_i32(tmp, cpu_msr_c, tmp, zero, cpu_msr_c, zero);
576     tcg_gen_add2_i32(out, cpu_msr_c, tmp, cpu_msr_c, inb, zero);
577 
578     tcg_temp_free_i32(zero);
579     tcg_temp_free_i32(tmp);
580 }
581 
582 /* No input or output carry. */
583 static void gen_rsubk(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
584 {
585     tcg_gen_sub_i32(out, inb, ina);
586 }
587 
588 /* Input carry, no output carry. */
589 static void gen_rsubkc(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
590 {
591     TCGv_i32 nota = tcg_temp_new_i32();
592 
593     tcg_gen_not_i32(nota, ina);
594     tcg_gen_add_i32(out, inb, nota);
595     tcg_gen_add_i32(out, out, cpu_msr_c);
596 
597     tcg_temp_free_i32(nota);
598 }
599 
600 DO_TYPEA(rsub, true, gen_rsub)
601 DO_TYPEA(rsubc, true, gen_rsubc)
602 DO_TYPEA(rsubk, false, gen_rsubk)
603 DO_TYPEA(rsubkc, true, gen_rsubkc)
604 
605 DO_TYPEBV(rsubi, true, gen_rsub)
606 DO_TYPEBV(rsubic, true, gen_rsubc)
607 DO_TYPEBV(rsubik, false, gen_rsubk)
608 DO_TYPEBV(rsubikc, true, gen_rsubkc)
609 
610 DO_TYPEA0(sext8, false, tcg_gen_ext8s_i32)
611 DO_TYPEA0(sext16, false, tcg_gen_ext16s_i32)
612 
613 static void gen_sra(TCGv_i32 out, TCGv_i32 ina)
614 {
615     tcg_gen_andi_i32(cpu_msr_c, ina, 1);
616     tcg_gen_sari_i32(out, ina, 1);
617 }
618 
619 static void gen_src(TCGv_i32 out, TCGv_i32 ina)
620 {
621     TCGv_i32 tmp = tcg_temp_new_i32();
622 
623     tcg_gen_mov_i32(tmp, cpu_msr_c);
624     tcg_gen_andi_i32(cpu_msr_c, ina, 1);
625     tcg_gen_extract2_i32(out, ina, tmp, 1);
626 
627     tcg_temp_free_i32(tmp);
628 }
629 
630 static void gen_srl(TCGv_i32 out, TCGv_i32 ina)
631 {
632     tcg_gen_andi_i32(cpu_msr_c, ina, 1);
633     tcg_gen_shri_i32(out, ina, 1);
634 }
635 
636 DO_TYPEA0(sra, false, gen_sra)
637 DO_TYPEA0(src, false, gen_src)
638 DO_TYPEA0(srl, false, gen_srl)
639 
640 static void gen_swaph(TCGv_i32 out, TCGv_i32 ina)
641 {
642     tcg_gen_rotri_i32(out, ina, 16);
643 }
644 
645 DO_TYPEA0(swapb, false, tcg_gen_bswap32_i32)
646 DO_TYPEA0(swaph, false, gen_swaph)
647 
648 static bool trans_wdic(DisasContext *dc, arg_wdic *a)
649 {
650     /* Cache operations are nops: only check for supervisor mode.  */
651     trap_userspace(dc, true);
652     return true;
653 }
654 
655 DO_TYPEA(xor, false, tcg_gen_xor_i32)
656 DO_TYPEBI(xori, false, tcg_gen_xori_i32)
657 
658 static TCGv compute_ldst_addr_typea(DisasContext *dc, int ra, int rb)
659 {
660     TCGv ret = tcg_temp_new();
661 
662     /* If any of the regs is r0, set t to the value of the other reg.  */
663     if (ra && rb) {
664         TCGv_i32 tmp = tcg_temp_new_i32();
665         tcg_gen_add_i32(tmp, cpu_R[ra], cpu_R[rb]);
666         tcg_gen_extu_i32_tl(ret, tmp);
667         tcg_temp_free_i32(tmp);
668     } else if (ra) {
669         tcg_gen_extu_i32_tl(ret, cpu_R[ra]);
670     } else if (rb) {
671         tcg_gen_extu_i32_tl(ret, cpu_R[rb]);
672     } else {
673         tcg_gen_movi_tl(ret, 0);
674     }
675 
676     if ((ra == 1 || rb == 1) && dc->cfg->stackprot) {
677         gen_helper_stackprot(cpu_env, ret);
678     }
679     return ret;
680 }
681 
682 static TCGv compute_ldst_addr_typeb(DisasContext *dc, int ra, int imm)
683 {
684     TCGv ret = tcg_temp_new();
685 
686     /* If any of the regs is r0, set t to the value of the other reg.  */
687     if (ra) {
688         TCGv_i32 tmp = tcg_temp_new_i32();
689         tcg_gen_addi_i32(tmp, cpu_R[ra], imm);
690         tcg_gen_extu_i32_tl(ret, tmp);
691         tcg_temp_free_i32(tmp);
692     } else {
693         tcg_gen_movi_tl(ret, (uint32_t)imm);
694     }
695 
696     if (ra == 1 && dc->cfg->stackprot) {
697         gen_helper_stackprot(cpu_env, ret);
698     }
699     return ret;
700 }
701 
702 #ifndef CONFIG_USER_ONLY
703 static TCGv compute_ldst_addr_ea(DisasContext *dc, int ra, int rb)
704 {
705     int addr_size = dc->cfg->addr_size;
706     TCGv ret = tcg_temp_new();
707 
708     if (addr_size == 32 || ra == 0) {
709         if (rb) {
710             tcg_gen_extu_i32_tl(ret, cpu_R[rb]);
711         } else {
712             tcg_gen_movi_tl(ret, 0);
713         }
714     } else {
715         if (rb) {
716             tcg_gen_concat_i32_i64(ret, cpu_R[rb], cpu_R[ra]);
717         } else {
718             tcg_gen_extu_i32_tl(ret, cpu_R[ra]);
719             tcg_gen_shli_tl(ret, ret, 32);
720         }
721         if (addr_size < 64) {
722             /* Mask off out of range bits.  */
723             tcg_gen_andi_i64(ret, ret, MAKE_64BIT_MASK(0, addr_size));
724         }
725     }
726     return ret;
727 }
728 #endif
729 
730 static void record_unaligned_ess(DisasContext *dc, int rd,
731                                  MemOp size, bool store)
732 {
733     uint32_t iflags = tcg_get_insn_start_param(dc->insn_start, 1);
734 
735     iflags |= ESR_ESS_FLAG;
736     iflags |= rd << 5;
737     iflags |= store * ESR_S;
738     iflags |= (size == MO_32) * ESR_W;
739 
740     tcg_set_insn_start_param(dc->insn_start, 1, iflags);
741 }
742 
743 static bool do_load(DisasContext *dc, int rd, TCGv addr, MemOp mop,
744                     int mem_index, bool rev)
745 {
746     MemOp size = mop & MO_SIZE;
747 
748     /*
749      * When doing reverse accesses we need to do two things.
750      *
751      * 1. Reverse the address wrt endianness.
752      * 2. Byteswap the data lanes on the way back into the CPU core.
753      */
754     if (rev) {
755         if (size > MO_8) {
756             mop ^= MO_BSWAP;
757         }
758         if (size < MO_32) {
759             tcg_gen_xori_tl(addr, addr, 3 - size);
760         }
761     }
762 
763     if (size > MO_8 &&
764         (dc->tb_flags & MSR_EE) &&
765         dc->cfg->unaligned_exceptions) {
766         record_unaligned_ess(dc, rd, size, false);
767         mop |= MO_ALIGN;
768     }
769 
770     tcg_gen_qemu_ld_i32(reg_for_write(dc, rd), addr, mem_index, mop);
771 
772     tcg_temp_free(addr);
773     return true;
774 }
775 
776 static bool trans_lbu(DisasContext *dc, arg_typea *arg)
777 {
778     TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
779     return do_load(dc, arg->rd, addr, MO_UB, dc->mem_index, false);
780 }
781 
782 static bool trans_lbur(DisasContext *dc, arg_typea *arg)
783 {
784     TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
785     return do_load(dc, arg->rd, addr, MO_UB, dc->mem_index, true);
786 }
787 
788 static bool trans_lbuea(DisasContext *dc, arg_typea *arg)
789 {
790     if (trap_userspace(dc, true)) {
791         return true;
792     }
793 #ifdef CONFIG_USER_ONLY
794     return true;
795 #else
796     TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb);
797     return do_load(dc, arg->rd, addr, MO_UB, MMU_NOMMU_IDX, false);
798 #endif
799 }
800 
801 static bool trans_lbui(DisasContext *dc, arg_typeb *arg)
802 {
803     TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm);
804     return do_load(dc, arg->rd, addr, MO_UB, dc->mem_index, false);
805 }
806 
807 static bool trans_lhu(DisasContext *dc, arg_typea *arg)
808 {
809     TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
810     return do_load(dc, arg->rd, addr, MO_TEUW, dc->mem_index, false);
811 }
812 
813 static bool trans_lhur(DisasContext *dc, arg_typea *arg)
814 {
815     TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
816     return do_load(dc, arg->rd, addr, MO_TEUW, dc->mem_index, true);
817 }
818 
819 static bool trans_lhuea(DisasContext *dc, arg_typea *arg)
820 {
821     if (trap_userspace(dc, true)) {
822         return true;
823     }
824 #ifdef CONFIG_USER_ONLY
825     return true;
826 #else
827     TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb);
828     return do_load(dc, arg->rd, addr, MO_TEUW, MMU_NOMMU_IDX, false);
829 #endif
830 }
831 
832 static bool trans_lhui(DisasContext *dc, arg_typeb *arg)
833 {
834     TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm);
835     return do_load(dc, arg->rd, addr, MO_TEUW, dc->mem_index, false);
836 }
837 
838 static bool trans_lw(DisasContext *dc, arg_typea *arg)
839 {
840     TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
841     return do_load(dc, arg->rd, addr, MO_TEUL, dc->mem_index, false);
842 }
843 
844 static bool trans_lwr(DisasContext *dc, arg_typea *arg)
845 {
846     TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
847     return do_load(dc, arg->rd, addr, MO_TEUL, dc->mem_index, true);
848 }
849 
850 static bool trans_lwea(DisasContext *dc, arg_typea *arg)
851 {
852     if (trap_userspace(dc, true)) {
853         return true;
854     }
855 #ifdef CONFIG_USER_ONLY
856     return true;
857 #else
858     TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb);
859     return do_load(dc, arg->rd, addr, MO_TEUL, MMU_NOMMU_IDX, false);
860 #endif
861 }
862 
863 static bool trans_lwi(DisasContext *dc, arg_typeb *arg)
864 {
865     TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm);
866     return do_load(dc, arg->rd, addr, MO_TEUL, dc->mem_index, false);
867 }
868 
869 static bool trans_lwx(DisasContext *dc, arg_typea *arg)
870 {
871     TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
872 
873     /* lwx does not throw unaligned access errors, so force alignment */
874     tcg_gen_andi_tl(addr, addr, ~3);
875 
876     tcg_gen_qemu_ld_i32(cpu_res_val, addr, dc->mem_index, MO_TEUL);
877     tcg_gen_mov_tl(cpu_res_addr, addr);
878     tcg_temp_free(addr);
879 
880     if (arg->rd) {
881         tcg_gen_mov_i32(cpu_R[arg->rd], cpu_res_val);
882     }
883 
884     /* No support for AXI exclusive so always clear C */
885     tcg_gen_movi_i32(cpu_msr_c, 0);
886     return true;
887 }
888 
889 static bool do_store(DisasContext *dc, int rd, TCGv addr, MemOp mop,
890                      int mem_index, bool rev)
891 {
892     MemOp size = mop & MO_SIZE;
893 
894     /*
895      * When doing reverse accesses we need to do two things.
896      *
897      * 1. Reverse the address wrt endianness.
898      * 2. Byteswap the data lanes on the way back into the CPU core.
899      */
900     if (rev) {
901         if (size > MO_8) {
902             mop ^= MO_BSWAP;
903         }
904         if (size < MO_32) {
905             tcg_gen_xori_tl(addr, addr, 3 - size);
906         }
907     }
908 
909     if (size > MO_8 &&
910         (dc->tb_flags & MSR_EE) &&
911         dc->cfg->unaligned_exceptions) {
912         record_unaligned_ess(dc, rd, size, true);
913         mop |= MO_ALIGN;
914     }
915 
916     tcg_gen_qemu_st_i32(reg_for_read(dc, rd), addr, mem_index, mop);
917 
918     tcg_temp_free(addr);
919     return true;
920 }
921 
922 static bool trans_sb(DisasContext *dc, arg_typea *arg)
923 {
924     TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
925     return do_store(dc, arg->rd, addr, MO_UB, dc->mem_index, false);
926 }
927 
928 static bool trans_sbr(DisasContext *dc, arg_typea *arg)
929 {
930     TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
931     return do_store(dc, arg->rd, addr, MO_UB, dc->mem_index, true);
932 }
933 
934 static bool trans_sbea(DisasContext *dc, arg_typea *arg)
935 {
936     if (trap_userspace(dc, true)) {
937         return true;
938     }
939 #ifdef CONFIG_USER_ONLY
940     return true;
941 #else
942     TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb);
943     return do_store(dc, arg->rd, addr, MO_UB, MMU_NOMMU_IDX, false);
944 #endif
945 }
946 
947 static bool trans_sbi(DisasContext *dc, arg_typeb *arg)
948 {
949     TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm);
950     return do_store(dc, arg->rd, addr, MO_UB, dc->mem_index, false);
951 }
952 
953 static bool trans_sh(DisasContext *dc, arg_typea *arg)
954 {
955     TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
956     return do_store(dc, arg->rd, addr, MO_TEUW, dc->mem_index, false);
957 }
958 
959 static bool trans_shr(DisasContext *dc, arg_typea *arg)
960 {
961     TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
962     return do_store(dc, arg->rd, addr, MO_TEUW, dc->mem_index, true);
963 }
964 
965 static bool trans_shea(DisasContext *dc, arg_typea *arg)
966 {
967     if (trap_userspace(dc, true)) {
968         return true;
969     }
970 #ifdef CONFIG_USER_ONLY
971     return true;
972 #else
973     TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb);
974     return do_store(dc, arg->rd, addr, MO_TEUW, MMU_NOMMU_IDX, false);
975 #endif
976 }
977 
978 static bool trans_shi(DisasContext *dc, arg_typeb *arg)
979 {
980     TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm);
981     return do_store(dc, arg->rd, addr, MO_TEUW, dc->mem_index, false);
982 }
983 
984 static bool trans_sw(DisasContext *dc, arg_typea *arg)
985 {
986     TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
987     return do_store(dc, arg->rd, addr, MO_TEUL, dc->mem_index, false);
988 }
989 
990 static bool trans_swr(DisasContext *dc, arg_typea *arg)
991 {
992     TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
993     return do_store(dc, arg->rd, addr, MO_TEUL, dc->mem_index, true);
994 }
995 
996 static bool trans_swea(DisasContext *dc, arg_typea *arg)
997 {
998     if (trap_userspace(dc, true)) {
999         return true;
1000     }
1001 #ifdef CONFIG_USER_ONLY
1002     return true;
1003 #else
1004     TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb);
1005     return do_store(dc, arg->rd, addr, MO_TEUL, MMU_NOMMU_IDX, false);
1006 #endif
1007 }
1008 
1009 static bool trans_swi(DisasContext *dc, arg_typeb *arg)
1010 {
1011     TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm);
1012     return do_store(dc, arg->rd, addr, MO_TEUL, dc->mem_index, false);
1013 }
1014 
1015 static bool trans_swx(DisasContext *dc, arg_typea *arg)
1016 {
1017     TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
1018     TCGLabel *swx_done = gen_new_label();
1019     TCGLabel *swx_fail = gen_new_label();
1020     TCGv_i32 tval;
1021 
1022     /* swx does not throw unaligned access errors, so force alignment */
1023     tcg_gen_andi_tl(addr, addr, ~3);
1024 
1025     /*
1026      * Compare the address vs the one we used during lwx.
1027      * On mismatch, the operation fails.  On match, addr dies at the
1028      * branch, but we know we can use the equal version in the global.
1029      * In either case, addr is no longer needed.
1030      */
1031     tcg_gen_brcond_tl(TCG_COND_NE, cpu_res_addr, addr, swx_fail);
1032     tcg_temp_free(addr);
1033 
1034     /*
1035      * Compare the value loaded during lwx with current contents of
1036      * the reserved location.
1037      */
1038     tval = tcg_temp_new_i32();
1039 
1040     tcg_gen_atomic_cmpxchg_i32(tval, cpu_res_addr, cpu_res_val,
1041                                reg_for_write(dc, arg->rd),
1042                                dc->mem_index, MO_TEUL);
1043 
1044     tcg_gen_brcond_i32(TCG_COND_NE, cpu_res_val, tval, swx_fail);
1045     tcg_temp_free_i32(tval);
1046 
1047     /* Success */
1048     tcg_gen_movi_i32(cpu_msr_c, 0);
1049     tcg_gen_br(swx_done);
1050 
1051     /* Failure */
1052     gen_set_label(swx_fail);
1053     tcg_gen_movi_i32(cpu_msr_c, 1);
1054 
1055     gen_set_label(swx_done);
1056 
1057     /*
1058      * Prevent the saved address from working again without another ldx.
1059      * Akin to the pseudocode setting reservation = 0.
1060      */
1061     tcg_gen_movi_tl(cpu_res_addr, -1);
1062     return true;
1063 }
1064 
1065 static void setup_dslot(DisasContext *dc, bool type_b)
1066 {
1067     dc->tb_flags_to_set |= D_FLAG;
1068     if (type_b && (dc->tb_flags & IMM_FLAG)) {
1069         dc->tb_flags_to_set |= BIMM_FLAG;
1070     }
1071 }
1072 
1073 static bool do_branch(DisasContext *dc, int dest_rb, int dest_imm,
1074                       bool delay, bool abs, int link)
1075 {
1076     uint32_t add_pc;
1077 
1078     if (invalid_delay_slot(dc, "branch")) {
1079         return true;
1080     }
1081     if (delay) {
1082         setup_dslot(dc, dest_rb < 0);
1083     }
1084 
1085     if (link) {
1086         tcg_gen_movi_i32(cpu_R[link], dc->base.pc_next);
1087     }
1088 
1089     /* Store the branch taken destination into btarget.  */
1090     add_pc = abs ? 0 : dc->base.pc_next;
1091     if (dest_rb > 0) {
1092         dc->jmp_dest = -1;
1093         tcg_gen_addi_i32(cpu_btarget, cpu_R[dest_rb], add_pc);
1094     } else {
1095         dc->jmp_dest = add_pc + dest_imm;
1096         tcg_gen_movi_i32(cpu_btarget, dc->jmp_dest);
1097     }
1098     dc->jmp_cond = TCG_COND_ALWAYS;
1099     return true;
1100 }
1101 
1102 #define DO_BR(NAME, NAMEI, DELAY, ABS, LINK)                               \
1103     static bool trans_##NAME(DisasContext *dc, arg_typea_br *arg)          \
1104     { return do_branch(dc, arg->rb, 0, DELAY, ABS, LINK ? arg->rd : 0); }  \
1105     static bool trans_##NAMEI(DisasContext *dc, arg_typeb_br *arg)         \
1106     { return do_branch(dc, -1, arg->imm, DELAY, ABS, LINK ? arg->rd : 0); }
1107 
1108 DO_BR(br, bri, false, false, false)
1109 DO_BR(bra, brai, false, true, false)
1110 DO_BR(brd, brid, true, false, false)
1111 DO_BR(brad, braid, true, true, false)
1112 DO_BR(brld, brlid, true, false, true)
1113 DO_BR(brald, bralid, true, true, true)
1114 
1115 static bool do_bcc(DisasContext *dc, int dest_rb, int dest_imm,
1116                    TCGCond cond, int ra, bool delay)
1117 {
1118     TCGv_i32 zero, next;
1119 
1120     if (invalid_delay_slot(dc, "bcc")) {
1121         return true;
1122     }
1123     if (delay) {
1124         setup_dslot(dc, dest_rb < 0);
1125     }
1126 
1127     dc->jmp_cond = cond;
1128 
1129     /* Cache the condition register in cpu_bvalue across any delay slot.  */
1130     tcg_gen_mov_i32(cpu_bvalue, reg_for_read(dc, ra));
1131 
1132     /* Store the branch taken destination into btarget.  */
1133     if (dest_rb > 0) {
1134         dc->jmp_dest = -1;
1135         tcg_gen_addi_i32(cpu_btarget, cpu_R[dest_rb], dc->base.pc_next);
1136     } else {
1137         dc->jmp_dest = dc->base.pc_next + dest_imm;
1138         tcg_gen_movi_i32(cpu_btarget, dc->jmp_dest);
1139     }
1140 
1141     /* Compute the final destination into btarget.  */
1142     zero = tcg_const_i32(0);
1143     next = tcg_const_i32(dc->base.pc_next + (delay + 1) * 4);
1144     tcg_gen_movcond_i32(dc->jmp_cond, cpu_btarget,
1145                         reg_for_read(dc, ra), zero,
1146                         cpu_btarget, next);
1147     tcg_temp_free_i32(zero);
1148     tcg_temp_free_i32(next);
1149 
1150     return true;
1151 }
1152 
1153 #define DO_BCC(NAME, COND)                                              \
1154     static bool trans_##NAME(DisasContext *dc, arg_typea_bc *arg)       \
1155     { return do_bcc(dc, arg->rb, 0, COND, arg->ra, false); }            \
1156     static bool trans_##NAME##d(DisasContext *dc, arg_typea_bc *arg)    \
1157     { return do_bcc(dc, arg->rb, 0, COND, arg->ra, true); }             \
1158     static bool trans_##NAME##i(DisasContext *dc, arg_typeb_bc *arg)    \
1159     { return do_bcc(dc, -1, arg->imm, COND, arg->ra, false); }          \
1160     static bool trans_##NAME##id(DisasContext *dc, arg_typeb_bc *arg)   \
1161     { return do_bcc(dc, -1, arg->imm, COND, arg->ra, true); }
1162 
1163 DO_BCC(beq, TCG_COND_EQ)
1164 DO_BCC(bge, TCG_COND_GE)
1165 DO_BCC(bgt, TCG_COND_GT)
1166 DO_BCC(ble, TCG_COND_LE)
1167 DO_BCC(blt, TCG_COND_LT)
1168 DO_BCC(bne, TCG_COND_NE)
1169 
1170 static bool trans_brk(DisasContext *dc, arg_typea_br *arg)
1171 {
1172     if (trap_userspace(dc, true)) {
1173         return true;
1174     }
1175     if (invalid_delay_slot(dc, "brk")) {
1176         return true;
1177     }
1178 
1179     tcg_gen_mov_i32(cpu_pc, reg_for_read(dc, arg->rb));
1180     if (arg->rd) {
1181         tcg_gen_movi_i32(cpu_R[arg->rd], dc->base.pc_next);
1182     }
1183     tcg_gen_ori_i32(cpu_msr, cpu_msr, MSR_BIP);
1184     tcg_gen_movi_tl(cpu_res_addr, -1);
1185 
1186     dc->base.is_jmp = DISAS_EXIT;
1187     return true;
1188 }
1189 
1190 static bool trans_brki(DisasContext *dc, arg_typeb_br *arg)
1191 {
1192     uint32_t imm = arg->imm;
1193 
1194     if (trap_userspace(dc, imm != 0x8 && imm != 0x18)) {
1195         return true;
1196     }
1197     if (invalid_delay_slot(dc, "brki")) {
1198         return true;
1199     }
1200 
1201     tcg_gen_movi_i32(cpu_pc, imm);
1202     if (arg->rd) {
1203         tcg_gen_movi_i32(cpu_R[arg->rd], dc->base.pc_next);
1204     }
1205     tcg_gen_movi_tl(cpu_res_addr, -1);
1206 
1207 #ifdef CONFIG_USER_ONLY
1208     switch (imm) {
1209     case 0x8:  /* syscall trap */
1210         gen_raise_exception_sync(dc, EXCP_SYSCALL);
1211         break;
1212     case 0x18: /* debug trap */
1213         gen_raise_exception_sync(dc, EXCP_DEBUG);
1214         break;
1215     default:   /* eliminated with trap_userspace check */
1216         g_assert_not_reached();
1217     }
1218 #else
1219     uint32_t msr_to_set = 0;
1220 
1221     if (imm != 0x18) {
1222         msr_to_set |= MSR_BIP;
1223     }
1224     if (imm == 0x8 || imm == 0x18) {
1225         /* MSR_UM and MSR_VM are in tb_flags, so we know their value. */
1226         msr_to_set |= (dc->tb_flags & (MSR_UM | MSR_VM)) << 1;
1227         tcg_gen_andi_i32(cpu_msr, cpu_msr,
1228                          ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM));
1229     }
1230     tcg_gen_ori_i32(cpu_msr, cpu_msr, msr_to_set);
1231     dc->base.is_jmp = DISAS_EXIT;
1232 #endif
1233 
1234     return true;
1235 }
1236 
1237 static bool trans_mbar(DisasContext *dc, arg_mbar *arg)
1238 {
1239     int mbar_imm = arg->imm;
1240 
1241     /* Note that mbar is a specialized branch instruction. */
1242     if (invalid_delay_slot(dc, "mbar")) {
1243         return true;
1244     }
1245 
1246     /* Data access memory barrier.  */
1247     if ((mbar_imm & 2) == 0) {
1248         tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL);
1249     }
1250 
1251     /* Sleep. */
1252     if (mbar_imm & 16) {
1253         TCGv_i32 tmp_1;
1254 
1255         if (trap_userspace(dc, true)) {
1256             /* Sleep is a privileged instruction.  */
1257             return true;
1258         }
1259 
1260         t_sync_flags(dc);
1261 
1262         tmp_1 = tcg_const_i32(1);
1263         tcg_gen_st_i32(tmp_1, cpu_env,
1264                        -offsetof(MicroBlazeCPU, env)
1265                        +offsetof(CPUState, halted));
1266         tcg_temp_free_i32(tmp_1);
1267 
1268         tcg_gen_movi_i32(cpu_pc, dc->base.pc_next + 4);
1269 
1270         gen_raise_exception(dc, EXCP_HLT);
1271     }
1272 
1273     /*
1274      * If !(mbar_imm & 1), this is an instruction access memory barrier
1275      * and we need to end the TB so that we recognize self-modified
1276      * code immediately.
1277      *
1278      * However, there are some data mbars that need the TB break
1279      * (and return to main loop) to recognize interrupts right away.
1280      * E.g. recognizing a change to an interrupt controller register.
1281      *
1282      * Therefore, choose to end the TB always.
1283      */
1284     dc->base.is_jmp = DISAS_EXIT_NEXT;
1285     return true;
1286 }
1287 
1288 static bool do_rts(DisasContext *dc, arg_typeb_bc *arg, int to_set)
1289 {
1290     if (trap_userspace(dc, to_set)) {
1291         return true;
1292     }
1293     if (invalid_delay_slot(dc, "rts")) {
1294         return true;
1295     }
1296 
1297     dc->tb_flags_to_set |= to_set;
1298     setup_dslot(dc, true);
1299 
1300     dc->jmp_cond = TCG_COND_ALWAYS;
1301     dc->jmp_dest = -1;
1302     tcg_gen_addi_i32(cpu_btarget, reg_for_read(dc, arg->ra), arg->imm);
1303     return true;
1304 }
1305 
1306 #define DO_RTS(NAME, IFLAG) \
1307     static bool trans_##NAME(DisasContext *dc, arg_typeb_bc *arg) \
1308     { return do_rts(dc, arg, IFLAG); }
1309 
1310 DO_RTS(rtbd, DRTB_FLAG)
1311 DO_RTS(rtid, DRTI_FLAG)
1312 DO_RTS(rted, DRTE_FLAG)
1313 DO_RTS(rtsd, 0)
1314 
1315 static bool trans_zero(DisasContext *dc, arg_zero *arg)
1316 {
1317     /* If opcode_0_illegal, trap.  */
1318     if (dc->cfg->opcode_0_illegal) {
1319         trap_illegal(dc, true);
1320         return true;
1321     }
1322     /*
1323      * Otherwise, this is "add r0, r0, r0".
1324      * Continue to trans_add so that MSR[C] gets cleared.
1325      */
1326     return false;
1327 }
1328 
1329 static void msr_read(DisasContext *dc, TCGv_i32 d)
1330 {
1331     TCGv_i32 t;
1332 
1333     /* Replicate the cpu_msr_c boolean into the proper bit and the copy. */
1334     t = tcg_temp_new_i32();
1335     tcg_gen_muli_i32(t, cpu_msr_c, MSR_C | MSR_CC);
1336     tcg_gen_or_i32(d, cpu_msr, t);
1337     tcg_temp_free_i32(t);
1338 }
1339 
1340 static bool do_msrclrset(DisasContext *dc, arg_type_msr *arg, bool set)
1341 {
1342     uint32_t imm = arg->imm;
1343 
1344     if (trap_userspace(dc, imm != MSR_C)) {
1345         return true;
1346     }
1347 
1348     if (arg->rd) {
1349         msr_read(dc, cpu_R[arg->rd]);
1350     }
1351 
1352     /*
1353      * Handle the carry bit separately.
1354      * This is the only bit that userspace can modify.
1355      */
1356     if (imm & MSR_C) {
1357         tcg_gen_movi_i32(cpu_msr_c, set);
1358     }
1359 
1360     /*
1361      * MSR_C and MSR_CC set above.
1362      * MSR_PVR is not writable, and is always clear.
1363      */
1364     imm &= ~(MSR_C | MSR_CC | MSR_PVR);
1365 
1366     if (imm != 0) {
1367         if (set) {
1368             tcg_gen_ori_i32(cpu_msr, cpu_msr, imm);
1369         } else {
1370             tcg_gen_andi_i32(cpu_msr, cpu_msr, ~imm);
1371         }
1372         dc->base.is_jmp = DISAS_EXIT_NEXT;
1373     }
1374     return true;
1375 }
1376 
1377 static bool trans_msrclr(DisasContext *dc, arg_type_msr *arg)
1378 {
1379     return do_msrclrset(dc, arg, false);
1380 }
1381 
1382 static bool trans_msrset(DisasContext *dc, arg_type_msr *arg)
1383 {
1384     return do_msrclrset(dc, arg, true);
1385 }
1386 
1387 static bool trans_mts(DisasContext *dc, arg_mts *arg)
1388 {
1389     if (trap_userspace(dc, true)) {
1390         return true;
1391     }
1392 
1393 #ifdef CONFIG_USER_ONLY
1394     g_assert_not_reached();
1395 #else
1396     if (arg->e && arg->rs != 0x1003) {
1397         qemu_log_mask(LOG_GUEST_ERROR,
1398                       "Invalid extended mts reg 0x%x\n", arg->rs);
1399         return true;
1400     }
1401 
1402     TCGv_i32 src = reg_for_read(dc, arg->ra);
1403     switch (arg->rs) {
1404     case SR_MSR:
1405         /* Install MSR_C.  */
1406         tcg_gen_extract_i32(cpu_msr_c, src, 2, 1);
1407         /*
1408          * Clear MSR_C and MSR_CC;
1409          * MSR_PVR is not writable, and is always clear.
1410          */
1411         tcg_gen_andi_i32(cpu_msr, src, ~(MSR_C | MSR_CC | MSR_PVR));
1412         break;
1413     case SR_FSR:
1414         tcg_gen_st_i32(src, cpu_env, offsetof(CPUMBState, fsr));
1415         break;
1416     case 0x800:
1417         tcg_gen_st_i32(src, cpu_env, offsetof(CPUMBState, slr));
1418         break;
1419     case 0x802:
1420         tcg_gen_st_i32(src, cpu_env, offsetof(CPUMBState, shr));
1421         break;
1422 
1423     case 0x1000: /* PID */
1424     case 0x1001: /* ZPR */
1425     case 0x1002: /* TLBX */
1426     case 0x1003: /* TLBLO */
1427     case 0x1004: /* TLBHI */
1428     case 0x1005: /* TLBSX */
1429         {
1430             TCGv_i32 tmp_ext = tcg_const_i32(arg->e);
1431             TCGv_i32 tmp_reg = tcg_const_i32(arg->rs & 7);
1432 
1433             gen_helper_mmu_write(cpu_env, tmp_ext, tmp_reg, src);
1434             tcg_temp_free_i32(tmp_reg);
1435             tcg_temp_free_i32(tmp_ext);
1436         }
1437         break;
1438 
1439     default:
1440         qemu_log_mask(LOG_GUEST_ERROR, "Invalid mts reg 0x%x\n", arg->rs);
1441         return true;
1442     }
1443     dc->base.is_jmp = DISAS_EXIT_NEXT;
1444     return true;
1445 #endif
1446 }
1447 
1448 static bool trans_mfs(DisasContext *dc, arg_mfs *arg)
1449 {
1450     TCGv_i32 dest = reg_for_write(dc, arg->rd);
1451 
1452     if (arg->e) {
1453         switch (arg->rs) {
1454         case SR_EAR:
1455             {
1456                 TCGv_i64 t64 = tcg_temp_new_i64();
1457                 tcg_gen_ld_i64(t64, cpu_env, offsetof(CPUMBState, ear));
1458                 tcg_gen_extrh_i64_i32(dest, t64);
1459                 tcg_temp_free_i64(t64);
1460             }
1461             return true;
1462 #ifndef CONFIG_USER_ONLY
1463         case 0x1003: /* TLBLO */
1464             /* Handled below. */
1465             break;
1466 #endif
1467         case 0x2006 ... 0x2009:
1468             /* High bits of PVR6-9 not implemented. */
1469             tcg_gen_movi_i32(dest, 0);
1470             return true;
1471         default:
1472             qemu_log_mask(LOG_GUEST_ERROR,
1473                           "Invalid extended mfs reg 0x%x\n", arg->rs);
1474             return true;
1475         }
1476     }
1477 
1478     switch (arg->rs) {
1479     case SR_PC:
1480         tcg_gen_movi_i32(dest, dc->base.pc_next);
1481         break;
1482     case SR_MSR:
1483         msr_read(dc, dest);
1484         break;
1485     case SR_EAR:
1486         {
1487             TCGv_i64 t64 = tcg_temp_new_i64();
1488             tcg_gen_ld_i64(t64, cpu_env, offsetof(CPUMBState, ear));
1489             tcg_gen_extrl_i64_i32(dest, t64);
1490             tcg_temp_free_i64(t64);
1491         }
1492         break;
1493     case SR_ESR:
1494         tcg_gen_ld_i32(dest, cpu_env, offsetof(CPUMBState, esr));
1495         break;
1496     case SR_FSR:
1497         tcg_gen_ld_i32(dest, cpu_env, offsetof(CPUMBState, fsr));
1498         break;
1499     case SR_BTR:
1500         tcg_gen_ld_i32(dest, cpu_env, offsetof(CPUMBState, btr));
1501         break;
1502     case SR_EDR:
1503         tcg_gen_ld_i32(dest, cpu_env, offsetof(CPUMBState, edr));
1504         break;
1505     case 0x800:
1506         tcg_gen_ld_i32(dest, cpu_env, offsetof(CPUMBState, slr));
1507         break;
1508     case 0x802:
1509         tcg_gen_ld_i32(dest, cpu_env, offsetof(CPUMBState, shr));
1510         break;
1511 
1512 #ifndef CONFIG_USER_ONLY
1513     case 0x1000: /* PID */
1514     case 0x1001: /* ZPR */
1515     case 0x1002: /* TLBX */
1516     case 0x1003: /* TLBLO */
1517     case 0x1004: /* TLBHI */
1518     case 0x1005: /* TLBSX */
1519         {
1520             TCGv_i32 tmp_ext = tcg_const_i32(arg->e);
1521             TCGv_i32 tmp_reg = tcg_const_i32(arg->rs & 7);
1522 
1523             gen_helper_mmu_read(dest, cpu_env, tmp_ext, tmp_reg);
1524             tcg_temp_free_i32(tmp_reg);
1525             tcg_temp_free_i32(tmp_ext);
1526         }
1527         break;
1528 #endif
1529 
1530     case 0x2000 ... 0x200c:
1531         tcg_gen_ld_i32(dest, cpu_env,
1532                        offsetof(MicroBlazeCPU, cfg.pvr_regs[arg->rs - 0x2000])
1533                        - offsetof(MicroBlazeCPU, env));
1534         break;
1535     default:
1536         qemu_log_mask(LOG_GUEST_ERROR, "Invalid mfs reg 0x%x\n", arg->rs);
1537         break;
1538     }
1539     return true;
1540 }
1541 
1542 static void do_rti(DisasContext *dc)
1543 {
1544     TCGv_i32 tmp = tcg_temp_new_i32();
1545 
1546     tcg_gen_shri_i32(tmp, cpu_msr, 1);
1547     tcg_gen_ori_i32(cpu_msr, cpu_msr, MSR_IE);
1548     tcg_gen_andi_i32(tmp, tmp, MSR_VM | MSR_UM);
1549     tcg_gen_andi_i32(cpu_msr, cpu_msr, ~(MSR_VM | MSR_UM));
1550     tcg_gen_or_i32(cpu_msr, cpu_msr, tmp);
1551 
1552     tcg_temp_free_i32(tmp);
1553 }
1554 
1555 static void do_rtb(DisasContext *dc)
1556 {
1557     TCGv_i32 tmp = tcg_temp_new_i32();
1558 
1559     tcg_gen_shri_i32(tmp, cpu_msr, 1);
1560     tcg_gen_andi_i32(cpu_msr, cpu_msr, ~(MSR_VM | MSR_UM | MSR_BIP));
1561     tcg_gen_andi_i32(tmp, tmp, (MSR_VM | MSR_UM));
1562     tcg_gen_or_i32(cpu_msr, cpu_msr, tmp);
1563 
1564     tcg_temp_free_i32(tmp);
1565 }
1566 
1567 static void do_rte(DisasContext *dc)
1568 {
1569     TCGv_i32 tmp = tcg_temp_new_i32();
1570 
1571     tcg_gen_shri_i32(tmp, cpu_msr, 1);
1572     tcg_gen_ori_i32(cpu_msr, cpu_msr, MSR_EE);
1573     tcg_gen_andi_i32(tmp, tmp, (MSR_VM | MSR_UM));
1574     tcg_gen_andi_i32(cpu_msr, cpu_msr, ~(MSR_VM | MSR_UM | MSR_EIP));
1575     tcg_gen_or_i32(cpu_msr, cpu_msr, tmp);
1576 
1577     tcg_temp_free_i32(tmp);
1578 }
1579 
1580 /* Insns connected to FSL or AXI stream attached devices.  */
1581 static bool do_get(DisasContext *dc, int rd, int rb, int imm, int ctrl)
1582 {
1583     TCGv_i32 t_id, t_ctrl;
1584 
1585     if (trap_userspace(dc, true)) {
1586         return true;
1587     }
1588 
1589     t_id = tcg_temp_new_i32();
1590     if (rb) {
1591         tcg_gen_andi_i32(t_id, cpu_R[rb], 0xf);
1592     } else {
1593         tcg_gen_movi_i32(t_id, imm);
1594     }
1595 
1596     t_ctrl = tcg_const_i32(ctrl);
1597     gen_helper_get(reg_for_write(dc, rd), t_id, t_ctrl);
1598     tcg_temp_free_i32(t_id);
1599     tcg_temp_free_i32(t_ctrl);
1600     return true;
1601 }
1602 
1603 static bool trans_get(DisasContext *dc, arg_get *arg)
1604 {
1605     return do_get(dc, arg->rd, 0, arg->imm, arg->ctrl);
1606 }
1607 
1608 static bool trans_getd(DisasContext *dc, arg_getd *arg)
1609 {
1610     return do_get(dc, arg->rd, arg->rb, 0, arg->ctrl);
1611 }
1612 
1613 static bool do_put(DisasContext *dc, int ra, int rb, int imm, int ctrl)
1614 {
1615     TCGv_i32 t_id, t_ctrl;
1616 
1617     if (trap_userspace(dc, true)) {
1618         return true;
1619     }
1620 
1621     t_id = tcg_temp_new_i32();
1622     if (rb) {
1623         tcg_gen_andi_i32(t_id, cpu_R[rb], 0xf);
1624     } else {
1625         tcg_gen_movi_i32(t_id, imm);
1626     }
1627 
1628     t_ctrl = tcg_const_i32(ctrl);
1629     gen_helper_put(t_id, t_ctrl, reg_for_read(dc, ra));
1630     tcg_temp_free_i32(t_id);
1631     tcg_temp_free_i32(t_ctrl);
1632     return true;
1633 }
1634 
1635 static bool trans_put(DisasContext *dc, arg_put *arg)
1636 {
1637     return do_put(dc, arg->ra, 0, arg->imm, arg->ctrl);
1638 }
1639 
1640 static bool trans_putd(DisasContext *dc, arg_putd *arg)
1641 {
1642     return do_put(dc, arg->ra, arg->rb, 0, arg->ctrl);
1643 }
1644 
1645 static void mb_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs)
1646 {
1647     DisasContext *dc = container_of(dcb, DisasContext, base);
1648     MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
1649     int bound;
1650 
1651     dc->cfg = &cpu->cfg;
1652     dc->tb_flags = dc->base.tb->flags;
1653     dc->ext_imm = dc->base.tb->cs_base;
1654     dc->r0 = NULL;
1655     dc->r0_set = false;
1656     dc->mem_index = cpu_mmu_index(&cpu->env, false);
1657     dc->jmp_cond = dc->tb_flags & D_FLAG ? TCG_COND_ALWAYS : TCG_COND_NEVER;
1658     dc->jmp_dest = -1;
1659 
1660     bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
1661     dc->base.max_insns = MIN(dc->base.max_insns, bound);
1662 }
1663 
1664 static void mb_tr_tb_start(DisasContextBase *dcb, CPUState *cs)
1665 {
1666 }
1667 
1668 static void mb_tr_insn_start(DisasContextBase *dcb, CPUState *cs)
1669 {
1670     DisasContext *dc = container_of(dcb, DisasContext, base);
1671 
1672     tcg_gen_insn_start(dc->base.pc_next, dc->tb_flags & ~MSR_TB_MASK);
1673     dc->insn_start = tcg_last_op();
1674 }
1675 
1676 static void mb_tr_translate_insn(DisasContextBase *dcb, CPUState *cs)
1677 {
1678     DisasContext *dc = container_of(dcb, DisasContext, base);
1679     CPUMBState *env = cs->env_ptr;
1680     uint32_t ir;
1681 
1682     /* TODO: This should raise an exception, not terminate qemu. */
1683     if (dc->base.pc_next & 3) {
1684         cpu_abort(cs, "Microblaze: unaligned PC=%x\n",
1685                   (uint32_t)dc->base.pc_next);
1686     }
1687 
1688     dc->tb_flags_to_set = 0;
1689 
1690     ir = cpu_ldl_code(env, dc->base.pc_next);
1691     if (!decode(dc, ir)) {
1692         trap_illegal(dc, true);
1693     }
1694 
1695     if (dc->r0) {
1696         tcg_temp_free_i32(dc->r0);
1697         dc->r0 = NULL;
1698         dc->r0_set = false;
1699     }
1700 
1701     /* Discard the imm global when its contents cannot be used. */
1702     if ((dc->tb_flags & ~dc->tb_flags_to_set) & IMM_FLAG) {
1703         tcg_gen_discard_i32(cpu_imm);
1704     }
1705 
1706     dc->tb_flags &= ~(IMM_FLAG | BIMM_FLAG | D_FLAG);
1707     dc->tb_flags |= dc->tb_flags_to_set;
1708     dc->base.pc_next += 4;
1709 
1710     if (dc->jmp_cond != TCG_COND_NEVER && !(dc->tb_flags & D_FLAG)) {
1711         /*
1712          * Finish any return-from branch.
1713          */
1714         uint32_t rt_ibe = dc->tb_flags & (DRTI_FLAG | DRTB_FLAG | DRTE_FLAG);
1715         if (unlikely(rt_ibe != 0)) {
1716             dc->tb_flags &= ~(DRTI_FLAG | DRTB_FLAG | DRTE_FLAG);
1717             if (rt_ibe & DRTI_FLAG) {
1718                 do_rti(dc);
1719             } else if (rt_ibe & DRTB_FLAG) {
1720                 do_rtb(dc);
1721             } else {
1722                 do_rte(dc);
1723             }
1724         }
1725 
1726         /* Complete the branch, ending the TB. */
1727         switch (dc->base.is_jmp) {
1728         case DISAS_NORETURN:
1729             /*
1730              * E.g. illegal insn in a delay slot.  We've already exited
1731              * and will handle D_FLAG in mb_cpu_do_interrupt.
1732              */
1733             break;
1734         case DISAS_NEXT:
1735             /*
1736              * Normal insn a delay slot.
1737              * However, the return-from-exception type insns should
1738              * return to the main loop, as they have adjusted MSR.
1739              */
1740             dc->base.is_jmp = (rt_ibe ? DISAS_EXIT_JUMP : DISAS_JUMP);
1741             break;
1742         case DISAS_EXIT_NEXT:
1743             /*
1744              * E.g. mts insn in a delay slot.  Continue with btarget,
1745              * but still return to the main loop.
1746              */
1747             dc->base.is_jmp = DISAS_EXIT_JUMP;
1748             break;
1749         default:
1750             g_assert_not_reached();
1751         }
1752     }
1753 }
1754 
1755 static void mb_tr_tb_stop(DisasContextBase *dcb, CPUState *cs)
1756 {
1757     DisasContext *dc = container_of(dcb, DisasContext, base);
1758 
1759     if (dc->base.is_jmp == DISAS_NORETURN) {
1760         /* We have already exited the TB. */
1761         return;
1762     }
1763 
1764     t_sync_flags(dc);
1765 
1766     switch (dc->base.is_jmp) {
1767     case DISAS_TOO_MANY:
1768         gen_goto_tb(dc, 0, dc->base.pc_next);
1769         return;
1770 
1771     case DISAS_EXIT:
1772         break;
1773     case DISAS_EXIT_NEXT:
1774         tcg_gen_movi_i32(cpu_pc, dc->base.pc_next);
1775         break;
1776     case DISAS_EXIT_JUMP:
1777         tcg_gen_mov_i32(cpu_pc, cpu_btarget);
1778         tcg_gen_discard_i32(cpu_btarget);
1779         break;
1780 
1781     case DISAS_JUMP:
1782         if (dc->jmp_dest != -1 && !cs->singlestep_enabled) {
1783             /* Direct jump. */
1784             tcg_gen_discard_i32(cpu_btarget);
1785 
1786             if (dc->jmp_cond != TCG_COND_ALWAYS) {
1787                 /* Conditional direct jump. */
1788                 TCGLabel *taken = gen_new_label();
1789                 TCGv_i32 tmp = tcg_temp_new_i32();
1790 
1791                 /*
1792                  * Copy bvalue to a temp now, so we can discard bvalue.
1793                  * This can avoid writing bvalue to memory when the
1794                  * delay slot cannot raise an exception.
1795                  */
1796                 tcg_gen_mov_i32(tmp, cpu_bvalue);
1797                 tcg_gen_discard_i32(cpu_bvalue);
1798 
1799                 tcg_gen_brcondi_i32(dc->jmp_cond, tmp, 0, taken);
1800                 gen_goto_tb(dc, 1, dc->base.pc_next);
1801                 gen_set_label(taken);
1802             }
1803             gen_goto_tb(dc, 0, dc->jmp_dest);
1804             return;
1805         }
1806 
1807         /* Indirect jump (or direct jump w/ singlestep) */
1808         tcg_gen_mov_i32(cpu_pc, cpu_btarget);
1809         tcg_gen_discard_i32(cpu_btarget);
1810 
1811         if (unlikely(cs->singlestep_enabled)) {
1812             gen_raise_exception(dc, EXCP_DEBUG);
1813         } else {
1814             tcg_gen_lookup_and_goto_ptr();
1815         }
1816         return;
1817 
1818     default:
1819         g_assert_not_reached();
1820     }
1821 
1822     /* Finish DISAS_EXIT_* */
1823     if (unlikely(cs->singlestep_enabled)) {
1824         gen_raise_exception(dc, EXCP_DEBUG);
1825     } else {
1826         tcg_gen_exit_tb(NULL, 0);
1827     }
1828 }
1829 
1830 static void mb_tr_disas_log(const DisasContextBase *dcb, CPUState *cs)
1831 {
1832     qemu_log("IN: %s\n", lookup_symbol(dcb->pc_first));
1833     log_target_disas(cs, dcb->pc_first, dcb->tb->size);
1834 }
1835 
1836 static const TranslatorOps mb_tr_ops = {
1837     .init_disas_context = mb_tr_init_disas_context,
1838     .tb_start           = mb_tr_tb_start,
1839     .insn_start         = mb_tr_insn_start,
1840     .translate_insn     = mb_tr_translate_insn,
1841     .tb_stop            = mb_tr_tb_stop,
1842     .disas_log          = mb_tr_disas_log,
1843 };
1844 
1845 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
1846 {
1847     DisasContext dc;
1848     translator_loop(&mb_tr_ops, &dc.base, cpu, tb, max_insns);
1849 }
1850 
1851 void mb_cpu_dump_state(CPUState *cs, FILE *f, int flags)
1852 {
1853     MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
1854     CPUMBState *env = &cpu->env;
1855     uint32_t iflags;
1856     int i;
1857 
1858     qemu_fprintf(f, "pc=0x%08x msr=0x%05x mode=%s(saved=%s) eip=%d ie=%d\n",
1859                  env->pc, env->msr,
1860                  (env->msr & MSR_UM) ? "user" : "kernel",
1861                  (env->msr & MSR_UMS) ? "user" : "kernel",
1862                  (bool)(env->msr & MSR_EIP),
1863                  (bool)(env->msr & MSR_IE));
1864 
1865     iflags = env->iflags;
1866     qemu_fprintf(f, "iflags: 0x%08x", iflags);
1867     if (iflags & IMM_FLAG) {
1868         qemu_fprintf(f, " IMM(0x%08x)", env->imm);
1869     }
1870     if (iflags & BIMM_FLAG) {
1871         qemu_fprintf(f, " BIMM");
1872     }
1873     if (iflags & D_FLAG) {
1874         qemu_fprintf(f, " D(btarget=0x%08x)", env->btarget);
1875     }
1876     if (iflags & DRTI_FLAG) {
1877         qemu_fprintf(f, " DRTI");
1878     }
1879     if (iflags & DRTE_FLAG) {
1880         qemu_fprintf(f, " DRTE");
1881     }
1882     if (iflags & DRTB_FLAG) {
1883         qemu_fprintf(f, " DRTB");
1884     }
1885     if (iflags & ESR_ESS_FLAG) {
1886         qemu_fprintf(f, " ESR_ESS(0x%04x)", iflags & ESR_ESS_MASK);
1887     }
1888 
1889     qemu_fprintf(f, "\nesr=0x%04x fsr=0x%02x btr=0x%08x edr=0x%x\n"
1890                  "ear=0x" TARGET_FMT_lx " slr=0x%x shr=0x%x\n",
1891                  env->esr, env->fsr, env->btr, env->edr,
1892                  env->ear, env->slr, env->shr);
1893 
1894     for (i = 0; i < 32; i++) {
1895         qemu_fprintf(f, "r%2.2d=%08x%c",
1896                      i, env->regs[i], i % 4 == 3 ? '\n' : ' ');
1897     }
1898     qemu_fprintf(f, "\n");
1899 }
1900 
1901 void mb_tcg_init(void)
1902 {
1903 #define R(X)  { &cpu_R[X], offsetof(CPUMBState, regs[X]), "r" #X }
1904 #define SP(X) { &cpu_##X, offsetof(CPUMBState, X), #X }
1905 
1906     static const struct {
1907         TCGv_i32 *var; int ofs; char name[8];
1908     } i32s[] = {
1909         /*
1910          * Note that r0 is handled specially in reg_for_read
1911          * and reg_for_write.  Nothing should touch cpu_R[0].
1912          * Leave that element NULL, which will assert quickly
1913          * inside the tcg generator functions.
1914          */
1915                R(1),  R(2),  R(3),  R(4),  R(5),  R(6),  R(7),
1916         R(8),  R(9),  R(10), R(11), R(12), R(13), R(14), R(15),
1917         R(16), R(17), R(18), R(19), R(20), R(21), R(22), R(23),
1918         R(24), R(25), R(26), R(27), R(28), R(29), R(30), R(31),
1919 
1920         SP(pc),
1921         SP(msr),
1922         SP(msr_c),
1923         SP(imm),
1924         SP(iflags),
1925         SP(bvalue),
1926         SP(btarget),
1927         SP(res_val),
1928     };
1929 
1930 #undef R
1931 #undef SP
1932 
1933     for (int i = 0; i < ARRAY_SIZE(i32s); ++i) {
1934         *i32s[i].var =
1935           tcg_global_mem_new_i32(cpu_env, i32s[i].ofs, i32s[i].name);
1936     }
1937 
1938     cpu_res_addr =
1939         tcg_global_mem_new(cpu_env, offsetof(CPUMBState, res_addr), "res_addr");
1940 }
1941 
1942 void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb,
1943                           target_ulong *data)
1944 {
1945     env->pc = data[0];
1946     env->iflags = data[1];
1947 }
1948