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