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