]>
git.proxmox.com Git - mirror_qemu.git/blob - target/microblaze/translate.c
2 * Xilinx MicroBlaze emulation for qemu: main translation routines.
4 * Copyright (c) 2009 Edgar E. Iglesias.
5 * Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include "qemu/osdep.h"
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 "microblaze-decode.h"
28 #include "exec/cpu_ldst.h"
29 #include "exec/helper-gen.h"
30 #include "exec/translator.h"
31 #include "qemu/qemu-print.h"
33 #include "trace-tcg.h"
40 #if DISAS_MB && !SIM_COMPAT
41 # define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
43 # define LOG_DIS(...) do { } while (0)
48 #define EXTRACT_FIELD(src, start, end) \
49 (((src) >> start) & ((1 << (end - start + 1)) - 1))
51 /* is_jmp field values */
52 #define DISAS_JUMP DISAS_TARGET_0 /* only pc was modified dynamically */
53 #define DISAS_UPDATE DISAS_TARGET_1 /* cpu state was modified dynamically */
54 #define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */
56 static TCGv_i32 env_debug
;
57 static TCGv_i32 cpu_R
[32];
58 static TCGv_i32 cpu_pc
;
59 static TCGv_i32 cpu_msr
;
60 static TCGv_i32 cpu_esr
;
61 static TCGv_i32 env_imm
;
62 static TCGv_i32 env_btaken
;
63 static TCGv_i32 cpu_btarget
;
64 static TCGv_i32 env_iflags
;
65 static TCGv env_res_addr
;
66 static TCGv_i32 env_res_val
;
68 #include "exec/gen-icount.h"
70 /* This is the state at translation time. */
71 typedef struct DisasContext
{
82 unsigned int cpustate_changed
;
83 unsigned int delayed_branch
;
84 unsigned int tb_flags
, synced_flags
; /* tb dependent flags. */
85 unsigned int clear_imm
;
90 #define JMP_DIRECT_CC 2
91 #define JMP_INDIRECT 3
95 int abort_at_next_insn
;
96 struct TranslationBlock
*tb
;
97 int singlestep_enabled
;
100 static const char *regnames
[] =
102 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
103 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
104 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
105 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
108 static inline void t_sync_flags(DisasContext
*dc
)
110 /* Synch the tb dependent flags between translator and runtime. */
111 if (dc
->tb_flags
!= dc
->synced_flags
) {
112 tcg_gen_movi_i32(env_iflags
, dc
->tb_flags
);
113 dc
->synced_flags
= dc
->tb_flags
;
117 static inline void t_gen_raise_exception(DisasContext
*dc
, uint32_t index
)
119 TCGv_i32 tmp
= tcg_const_i32(index
);
122 tcg_gen_movi_i32(cpu_pc
, dc
->pc
);
123 gen_helper_raise_exception(cpu_env
, tmp
);
124 tcg_temp_free_i32(tmp
);
125 dc
->is_jmp
= DISAS_UPDATE
;
128 static inline bool use_goto_tb(DisasContext
*dc
, target_ulong dest
)
130 #ifndef CONFIG_USER_ONLY
131 return (dc
->tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
);
137 static void gen_goto_tb(DisasContext
*dc
, int n
, target_ulong dest
)
139 if (use_goto_tb(dc
, dest
)) {
141 tcg_gen_movi_i32(cpu_pc
, dest
);
142 tcg_gen_exit_tb(dc
->tb
, n
);
144 tcg_gen_movi_i32(cpu_pc
, dest
);
145 tcg_gen_exit_tb(NULL
, 0);
149 static void read_carry(DisasContext
*dc
, TCGv_i32 d
)
151 tcg_gen_shri_i32(d
, cpu_msr
, 31);
155 * write_carry sets the carry bits in MSR based on bit 0 of v.
156 * v[31:1] are ignored.
158 static void write_carry(DisasContext
*dc
, TCGv_i32 v
)
160 /* Deposit bit 0 into MSR_C and the alias MSR_CC. */
161 tcg_gen_deposit_i32(cpu_msr
, cpu_msr
, v
, 2, 1);
162 tcg_gen_deposit_i32(cpu_msr
, cpu_msr
, v
, 31, 1);
165 static void write_carryi(DisasContext
*dc
, bool carry
)
167 TCGv_i32 t0
= tcg_temp_new_i32();
168 tcg_gen_movi_i32(t0
, carry
);
170 tcg_temp_free_i32(t0
);
174 * Returns true if the insn an illegal operation.
175 * If exceptions are enabled, an exception is raised.
177 static bool trap_illegal(DisasContext
*dc
, bool cond
)
179 if (cond
&& (dc
->tb_flags
& MSR_EE_FLAG
)
180 && dc
->cpu
->cfg
.illegal_opcode_exception
) {
181 tcg_gen_movi_i32(cpu_esr
, ESR_EC_ILLEGAL_OP
);
182 t_gen_raise_exception(dc
, EXCP_HW_EXCP
);
188 * Returns true if the insn is illegal in userspace.
189 * If exceptions are enabled, an exception is raised.
191 static bool trap_userspace(DisasContext
*dc
, bool cond
)
193 int mem_index
= cpu_mmu_index(&dc
->cpu
->env
, false);
194 bool cond_user
= cond
&& mem_index
== MMU_USER_IDX
;
196 if (cond_user
&& (dc
->tb_flags
& MSR_EE_FLAG
)) {
197 tcg_gen_movi_i32(cpu_esr
, ESR_EC_PRIVINSN
);
198 t_gen_raise_exception(dc
, EXCP_HW_EXCP
);
203 /* True if ALU operand b is a small immediate that may deserve
205 static inline int dec_alu_op_b_is_small_imm(DisasContext
*dc
)
207 /* Immediate insn without the imm prefix ? */
208 return dc
->type_b
&& !(dc
->tb_flags
& IMM_FLAG
);
211 static inline TCGv_i32
*dec_alu_op_b(DisasContext
*dc
)
214 if (dc
->tb_flags
& IMM_FLAG
)
215 tcg_gen_ori_i32(env_imm
, env_imm
, dc
->imm
);
217 tcg_gen_movi_i32(env_imm
, (int32_t)((int16_t)dc
->imm
));
220 return &cpu_R
[dc
->rb
];
223 static void dec_add(DisasContext
*dc
)
231 LOG_DIS("add%s%s%s r%d r%d r%d\n",
232 dc
->type_b
? "i" : "", k
? "k" : "", c
? "c" : "",
233 dc
->rd
, dc
->ra
, dc
->rb
);
235 /* Take care of the easy cases first. */
237 /* k - keep carry, no need to update MSR. */
238 /* If rd == r0, it's a nop. */
240 tcg_gen_add_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], *(dec_alu_op_b(dc
)));
243 /* c - Add carry into the result. */
244 cf
= tcg_temp_new_i32();
247 tcg_gen_add_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->rd
], cf
);
248 tcg_temp_free_i32(cf
);
254 /* From now on, we can assume k is zero. So we need to update MSR. */
256 cf
= tcg_temp_new_i32();
260 tcg_gen_movi_i32(cf
, 0);
264 TCGv_i32 ncf
= tcg_temp_new_i32();
265 gen_helper_carry(ncf
, cpu_R
[dc
->ra
], *(dec_alu_op_b(dc
)), cf
);
266 tcg_gen_add_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], *(dec_alu_op_b(dc
)));
267 tcg_gen_add_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->rd
], cf
);
268 write_carry(dc
, ncf
);
269 tcg_temp_free_i32(ncf
);
271 gen_helper_carry(cf
, cpu_R
[dc
->ra
], *(dec_alu_op_b(dc
)), cf
);
274 tcg_temp_free_i32(cf
);
277 static void dec_sub(DisasContext
*dc
)
279 unsigned int u
, cmp
, k
, c
;
285 cmp
= (dc
->imm
& 1) && (!dc
->type_b
) && k
;
288 LOG_DIS("cmp%s r%d, r%d ir=%x\n", u
? "u" : "", dc
->rd
, dc
->ra
, dc
->ir
);
291 gen_helper_cmpu(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
293 gen_helper_cmp(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
298 LOG_DIS("sub%s%s r%d, r%d r%d\n",
299 k
? "k" : "", c
? "c" : "", dc
->rd
, dc
->ra
, dc
->rb
);
301 /* Take care of the easy cases first. */
303 /* k - keep carry, no need to update MSR. */
304 /* If rd == r0, it's a nop. */
306 tcg_gen_sub_i32(cpu_R
[dc
->rd
], *(dec_alu_op_b(dc
)), cpu_R
[dc
->ra
]);
309 /* c - Add carry into the result. */
310 cf
= tcg_temp_new_i32();
313 tcg_gen_add_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->rd
], cf
);
314 tcg_temp_free_i32(cf
);
320 /* From now on, we can assume k is zero. So we need to update MSR. */
321 /* Extract carry. And complement a into na. */
322 cf
= tcg_temp_new_i32();
323 na
= tcg_temp_new_i32();
327 tcg_gen_movi_i32(cf
, 1);
330 /* d = b + ~a + c. carry defaults to 1. */
331 tcg_gen_not_i32(na
, cpu_R
[dc
->ra
]);
334 TCGv_i32 ncf
= tcg_temp_new_i32();
335 gen_helper_carry(ncf
, na
, *(dec_alu_op_b(dc
)), cf
);
336 tcg_gen_add_i32(cpu_R
[dc
->rd
], na
, *(dec_alu_op_b(dc
)));
337 tcg_gen_add_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->rd
], cf
);
338 write_carry(dc
, ncf
);
339 tcg_temp_free_i32(ncf
);
341 gen_helper_carry(cf
, na
, *(dec_alu_op_b(dc
)), cf
);
344 tcg_temp_free_i32(cf
);
345 tcg_temp_free_i32(na
);
348 static void dec_pattern(DisasContext
*dc
)
352 if (trap_illegal(dc
, !dc
->cpu
->cfg
.use_pcmp_instr
)) {
356 mode
= dc
->opcode
& 3;
360 LOG_DIS("pcmpbf r%d r%d r%d\n", dc
->rd
, dc
->ra
, dc
->rb
);
362 gen_helper_pcmpbf(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
365 LOG_DIS("pcmpeq r%d r%d r%d\n", dc
->rd
, dc
->ra
, dc
->rb
);
367 tcg_gen_setcond_i32(TCG_COND_EQ
, cpu_R
[dc
->rd
],
368 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
372 LOG_DIS("pcmpne r%d r%d r%d\n", dc
->rd
, dc
->ra
, dc
->rb
);
374 tcg_gen_setcond_i32(TCG_COND_NE
, cpu_R
[dc
->rd
],
375 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
379 cpu_abort(CPU(dc
->cpu
),
380 "unsupported pattern insn opcode=%x\n", dc
->opcode
);
385 static void dec_and(DisasContext
*dc
)
389 if (!dc
->type_b
&& (dc
->imm
& (1 << 10))) {
394 not = dc
->opcode
& (1 << 1);
395 LOG_DIS("and%s\n", not ? "n" : "");
401 tcg_gen_andc_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], *(dec_alu_op_b(dc
)));
403 tcg_gen_and_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], *(dec_alu_op_b(dc
)));
406 static void dec_or(DisasContext
*dc
)
408 if (!dc
->type_b
&& (dc
->imm
& (1 << 10))) {
413 LOG_DIS("or r%d r%d r%d imm=%x\n", dc
->rd
, dc
->ra
, dc
->rb
, dc
->imm
);
415 tcg_gen_or_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], *(dec_alu_op_b(dc
)));
418 static void dec_xor(DisasContext
*dc
)
420 if (!dc
->type_b
&& (dc
->imm
& (1 << 10))) {
425 LOG_DIS("xor r%d\n", dc
->rd
);
427 tcg_gen_xor_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], *(dec_alu_op_b(dc
)));
430 static inline void msr_read(DisasContext
*dc
, TCGv_i32 d
)
432 tcg_gen_mov_i32(d
, cpu_msr
);
435 static inline void msr_write(DisasContext
*dc
, TCGv_i32 v
)
437 dc
->cpustate_changed
= 1;
438 /* PVR bit is not writable, and is never set. */
439 tcg_gen_andi_i32(cpu_msr
, v
, ~MSR_PVR
);
442 static void dec_msr(DisasContext
*dc
)
444 CPUState
*cs
= CPU(dc
->cpu
);
447 bool to
, clrset
, extended
= false;
449 sr
= extract32(dc
->imm
, 0, 14);
450 to
= extract32(dc
->imm
, 14, 1);
451 clrset
= extract32(dc
->imm
, 15, 1) == 0;
454 dc
->cpustate_changed
= 1;
457 /* Extended MSRs are only available if addr_size > 32. */
458 if (dc
->cpu
->cfg
.addr_size
> 32) {
459 /* The E-bit is encoded differently for To/From MSR. */
460 static const unsigned int e_bit
[] = { 19, 24 };
462 extended
= extract32(dc
->imm
, e_bit
[to
], 1);
465 /* msrclr and msrset. */
467 bool clr
= extract32(dc
->ir
, 16, 1);
469 LOG_DIS("msr%s r%d imm=%x\n", clr
? "clr" : "set",
472 if (!dc
->cpu
->cfg
.use_msr_instr
) {
477 if (trap_userspace(dc
, dc
->imm
!= 4 && dc
->imm
!= 0)) {
482 msr_read(dc
, cpu_R
[dc
->rd
]);
484 t0
= tcg_temp_new_i32();
485 t1
= tcg_temp_new_i32();
487 tcg_gen_mov_i32(t1
, *(dec_alu_op_b(dc
)));
490 tcg_gen_not_i32(t1
, t1
);
491 tcg_gen_and_i32(t0
, t0
, t1
);
493 tcg_gen_or_i32(t0
, t0
, t1
);
495 tcg_temp_free_i32(t0
);
496 tcg_temp_free_i32(t1
);
497 tcg_gen_movi_i32(cpu_pc
, dc
->pc
+ 4);
498 dc
->is_jmp
= DISAS_UPDATE
;
502 if (trap_userspace(dc
, to
)) {
506 #if !defined(CONFIG_USER_ONLY)
507 /* Catch read/writes to the mmu block. */
508 if ((sr
& ~0xff) == 0x1000) {
509 TCGv_i32 tmp_ext
= tcg_const_i32(extended
);
513 tmp_sr
= tcg_const_i32(sr
);
514 LOG_DIS("m%ss sr%d r%d imm=%x\n", to
? "t" : "f", sr
, dc
->ra
, dc
->imm
);
516 gen_helper_mmu_write(cpu_env
, tmp_ext
, tmp_sr
, cpu_R
[dc
->ra
]);
518 gen_helper_mmu_read(cpu_R
[dc
->rd
], cpu_env
, tmp_ext
, tmp_sr
);
520 tcg_temp_free_i32(tmp_sr
);
521 tcg_temp_free_i32(tmp_ext
);
527 LOG_DIS("m%ss sr%x r%d imm=%x\n", to
? "t" : "f", sr
, dc
->ra
, dc
->imm
);
532 msr_write(dc
, cpu_R
[dc
->ra
]);
536 TCGv_i64 t64
= tcg_temp_new_i64();
537 tcg_gen_extu_i32_i64(t64
, cpu_R
[dc
->ra
]);
538 tcg_gen_st_i64(t64
, cpu_env
, offsetof(CPUMBState
, ear
));
539 tcg_temp_free_i64(t64
);
543 tcg_gen_mov_i32(cpu_esr
, cpu_R
[dc
->ra
]);
546 tcg_gen_st_i32(cpu_R
[dc
->ra
],
547 cpu_env
, offsetof(CPUMBState
, fsr
));
550 tcg_gen_st_i32(cpu_R
[dc
->ra
],
551 cpu_env
, offsetof(CPUMBState
, btr
));
554 tcg_gen_st_i32(cpu_R
[dc
->ra
],
555 cpu_env
, offsetof(CPUMBState
, edr
));
558 tcg_gen_st_i32(cpu_R
[dc
->ra
],
559 cpu_env
, offsetof(CPUMBState
, slr
));
562 tcg_gen_st_i32(cpu_R
[dc
->ra
],
563 cpu_env
, offsetof(CPUMBState
, shr
));
566 cpu_abort(CPU(dc
->cpu
), "unknown mts reg %x\n", sr
);
570 LOG_DIS("m%ss r%d sr%x imm=%x\n", to
? "t" : "f", dc
->rd
, sr
, dc
->imm
);
574 tcg_gen_movi_i32(cpu_R
[dc
->rd
], dc
->pc
);
577 msr_read(dc
, cpu_R
[dc
->rd
]);
581 TCGv_i64 t64
= tcg_temp_new_i64();
582 tcg_gen_ld_i64(t64
, cpu_env
, offsetof(CPUMBState
, ear
));
584 tcg_gen_extrh_i64_i32(cpu_R
[dc
->rd
], t64
);
586 tcg_gen_extrl_i64_i32(cpu_R
[dc
->rd
], t64
);
588 tcg_temp_free_i64(t64
);
592 tcg_gen_mov_i32(cpu_R
[dc
->rd
], cpu_esr
);
595 tcg_gen_ld_i32(cpu_R
[dc
->rd
],
596 cpu_env
, offsetof(CPUMBState
, fsr
));
599 tcg_gen_ld_i32(cpu_R
[dc
->rd
],
600 cpu_env
, offsetof(CPUMBState
, btr
));
603 tcg_gen_ld_i32(cpu_R
[dc
->rd
],
604 cpu_env
, offsetof(CPUMBState
, edr
));
607 tcg_gen_ld_i32(cpu_R
[dc
->rd
],
608 cpu_env
, offsetof(CPUMBState
, slr
));
611 tcg_gen_ld_i32(cpu_R
[dc
->rd
],
612 cpu_env
, offsetof(CPUMBState
, shr
));
614 case 0x2000 ... 0x200c:
616 tcg_gen_ld_i32(cpu_R
[dc
->rd
],
617 cpu_env
, offsetof(CPUMBState
, pvr
.regs
[rn
]));
620 cpu_abort(cs
, "unknown mfs reg %x\n", sr
);
626 tcg_gen_movi_i32(cpu_R
[0], 0);
630 /* Multiplier unit. */
631 static void dec_mul(DisasContext
*dc
)
634 unsigned int subcode
;
636 if (trap_illegal(dc
, !dc
->cpu
->cfg
.use_hw_mul
)) {
640 subcode
= dc
->imm
& 3;
643 LOG_DIS("muli r%d r%d %x\n", dc
->rd
, dc
->ra
, dc
->imm
);
644 tcg_gen_mul_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], *(dec_alu_op_b(dc
)));
648 /* mulh, mulhsu and mulhu are not available if C_USE_HW_MUL is < 2. */
649 if (subcode
>= 1 && subcode
<= 3 && dc
->cpu
->cfg
.use_hw_mul
< 2) {
653 tmp
= tcg_temp_new_i32();
656 LOG_DIS("mul r%d r%d r%d\n", dc
->rd
, dc
->ra
, dc
->rb
);
657 tcg_gen_mul_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
660 LOG_DIS("mulh r%d r%d r%d\n", dc
->rd
, dc
->ra
, dc
->rb
);
661 tcg_gen_muls2_i32(tmp
, cpu_R
[dc
->rd
],
662 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
665 LOG_DIS("mulhsu r%d r%d r%d\n", dc
->rd
, dc
->ra
, dc
->rb
);
666 tcg_gen_mulsu2_i32(tmp
, cpu_R
[dc
->rd
],
667 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
670 LOG_DIS("mulhu r%d r%d r%d\n", dc
->rd
, dc
->ra
, dc
->rb
);
671 tcg_gen_mulu2_i32(tmp
, cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
674 cpu_abort(CPU(dc
->cpu
), "unknown MUL insn %x\n", subcode
);
677 tcg_temp_free_i32(tmp
);
681 static void dec_div(DisasContext
*dc
)
688 if (trap_illegal(dc
, !dc
->cpu
->cfg
.use_div
)) {
693 gen_helper_divu(cpu_R
[dc
->rd
], cpu_env
, *(dec_alu_op_b(dc
)),
696 gen_helper_divs(cpu_R
[dc
->rd
], cpu_env
, *(dec_alu_op_b(dc
)),
699 tcg_gen_movi_i32(cpu_R
[dc
->rd
], 0);
702 static void dec_barrel(DisasContext
*dc
)
705 unsigned int imm_w
, imm_s
;
706 bool s
, t
, e
= false, i
= false;
708 if (trap_illegal(dc
, !dc
->cpu
->cfg
.use_barrel
)) {
713 /* Insert and extract are only available in immediate mode. */
714 i
= extract32(dc
->imm
, 15, 1);
715 e
= extract32(dc
->imm
, 14, 1);
717 s
= extract32(dc
->imm
, 10, 1);
718 t
= extract32(dc
->imm
, 9, 1);
719 imm_w
= extract32(dc
->imm
, 6, 5);
720 imm_s
= extract32(dc
->imm
, 0, 5);
722 LOG_DIS("bs%s%s%s r%d r%d r%d\n",
724 s
? "l" : "r", t
? "a" : "l", dc
->rd
, dc
->ra
, dc
->rb
);
727 if (imm_w
+ imm_s
> 32 || imm_w
== 0) {
728 /* These inputs have an undefined behavior. */
729 qemu_log_mask(LOG_GUEST_ERROR
, "bsefi: Bad input w=%d s=%d\n",
732 tcg_gen_extract_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], imm_s
, imm_w
);
735 int width
= imm_w
- imm_s
+ 1;
738 /* These inputs have an undefined behavior. */
739 qemu_log_mask(LOG_GUEST_ERROR
, "bsifi: Bad input w=%d s=%d\n",
742 tcg_gen_deposit_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->rd
], cpu_R
[dc
->ra
],
746 t0
= tcg_temp_new_i32();
748 tcg_gen_mov_i32(t0
, *(dec_alu_op_b(dc
)));
749 tcg_gen_andi_i32(t0
, t0
, 31);
752 tcg_gen_shl_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], t0
);
755 tcg_gen_sar_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], t0
);
757 tcg_gen_shr_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], t0
);
760 tcg_temp_free_i32(t0
);
764 static void dec_bit(DisasContext
*dc
)
766 CPUState
*cs
= CPU(dc
->cpu
);
770 op
= dc
->ir
& ((1 << 9) - 1);
774 t0
= tcg_temp_new_i32();
776 LOG_DIS("src r%d r%d\n", dc
->rd
, dc
->ra
);
777 tcg_gen_andi_i32(t0
, cpu_msr
, MSR_CC
);
778 write_carry(dc
, cpu_R
[dc
->ra
]);
780 tcg_gen_shri_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], 1);
781 tcg_gen_or_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->rd
], t0
);
783 tcg_temp_free_i32(t0
);
789 LOG_DIS("srl r%d r%d\n", dc
->rd
, dc
->ra
);
791 /* Update carry. Note that write carry only looks at the LSB. */
792 write_carry(dc
, cpu_R
[dc
->ra
]);
795 tcg_gen_shri_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], 1);
797 tcg_gen_sari_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], 1);
801 LOG_DIS("ext8s r%d r%d\n", dc
->rd
, dc
->ra
);
802 tcg_gen_ext8s_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
]);
805 LOG_DIS("ext16s r%d r%d\n", dc
->rd
, dc
->ra
);
806 tcg_gen_ext16s_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
]);
813 LOG_DIS("wdc r%d\n", dc
->ra
);
814 trap_userspace(dc
, true);
818 LOG_DIS("wic r%d\n", dc
->ra
);
819 trap_userspace(dc
, true);
822 if (trap_illegal(dc
, !dc
->cpu
->cfg
.use_pcmp_instr
)) {
825 if (dc
->cpu
->cfg
.use_pcmp_instr
) {
826 tcg_gen_clzi_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], 32);
831 LOG_DIS("swapb r%d r%d\n", dc
->rd
, dc
->ra
);
832 tcg_gen_bswap32_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
]);
836 LOG_DIS("swaph r%d r%d\n", dc
->rd
, dc
->ra
);
837 tcg_gen_rotri_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], 16);
840 cpu_abort(cs
, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
841 dc
->pc
, op
, dc
->rd
, dc
->ra
, dc
->rb
);
846 static inline void sync_jmpstate(DisasContext
*dc
)
848 if (dc
->jmp
== JMP_DIRECT
|| dc
->jmp
== JMP_DIRECT_CC
) {
849 if (dc
->jmp
== JMP_DIRECT
) {
850 tcg_gen_movi_i32(env_btaken
, 1);
852 dc
->jmp
= JMP_INDIRECT
;
853 tcg_gen_movi_i32(cpu_btarget
, dc
->jmp_pc
);
857 static void dec_imm(DisasContext
*dc
)
859 LOG_DIS("imm %x\n", dc
->imm
<< 16);
860 tcg_gen_movi_i32(env_imm
, (dc
->imm
<< 16));
861 dc
->tb_flags
|= IMM_FLAG
;
865 static inline void compute_ldst_addr(DisasContext
*dc
, bool ea
, TCGv t
)
867 bool extimm
= dc
->tb_flags
& IMM_FLAG
;
868 /* Should be set to true if r1 is used by loadstores. */
869 bool stackprot
= false;
872 /* All load/stores use ra. */
873 if (dc
->ra
== 1 && dc
->cpu
->cfg
.stackprot
) {
877 /* Treat the common cases first. */
880 int addr_size
= dc
->cpu
->cfg
.addr_size
;
882 if (addr_size
== 32) {
883 tcg_gen_extu_i32_tl(t
, cpu_R
[dc
->rb
]);
887 tcg_gen_concat_i32_i64(t
, cpu_R
[dc
->rb
], cpu_R
[dc
->ra
]);
888 if (addr_size
< 64) {
889 /* Mask off out of range bits. */
890 tcg_gen_andi_i64(t
, t
, MAKE_64BIT_MASK(0, addr_size
));
895 /* If any of the regs is r0, set t to the value of the other reg. */
897 tcg_gen_extu_i32_tl(t
, cpu_R
[dc
->rb
]);
899 } else if (dc
->rb
== 0) {
900 tcg_gen_extu_i32_tl(t
, cpu_R
[dc
->ra
]);
904 if (dc
->rb
== 1 && dc
->cpu
->cfg
.stackprot
) {
908 t32
= tcg_temp_new_i32();
909 tcg_gen_add_i32(t32
, cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
910 tcg_gen_extu_i32_tl(t
, t32
);
911 tcg_temp_free_i32(t32
);
914 gen_helper_stackprot(cpu_env
, t
);
919 t32
= tcg_temp_new_i32();
921 tcg_gen_addi_i32(t32
, cpu_R
[dc
->ra
], (int16_t)dc
->imm
);
923 tcg_gen_add_i32(t32
, cpu_R
[dc
->ra
], *(dec_alu_op_b(dc
)));
925 tcg_gen_extu_i32_tl(t
, t32
);
926 tcg_temp_free_i32(t32
);
929 gen_helper_stackprot(cpu_env
, t
);
934 static void dec_load(DisasContext
*dc
)
939 bool rev
= false, ex
= false, ea
= false;
940 int mem_index
= cpu_mmu_index(&dc
->cpu
->env
, false);
943 mop
= dc
->opcode
& 3;
946 ea
= extract32(dc
->ir
, 7, 1);
947 rev
= extract32(dc
->ir
, 9, 1);
948 ex
= extract32(dc
->ir
, 10, 1);
955 if (trap_illegal(dc
, size
> 4)) {
959 if (trap_userspace(dc
, ea
)) {
963 LOG_DIS("l%d%s%s%s%s\n", size
, dc
->type_b
? "i" : "", rev
? "r" : "",
968 addr
= tcg_temp_new();
969 compute_ldst_addr(dc
, ea
, addr
);
970 /* Extended addressing bypasses the MMU. */
971 mem_index
= ea
? MMU_NOMMU_IDX
: mem_index
;
974 * When doing reverse accesses we need to do two things.
976 * 1. Reverse the address wrt endianness.
977 * 2. Byteswap the data lanes on the way back into the CPU core.
979 if (rev
&& size
!= 4) {
980 /* Endian reverse the address. t is addr. */
984 tcg_gen_xori_tl(addr
, addr
, 3);
991 tcg_gen_xori_tl(addr
, addr
, 2);
994 cpu_abort(CPU(dc
->cpu
), "Invalid reverse size\n");
999 /* lwx does not throw unaligned access errors, so force alignment */
1001 tcg_gen_andi_tl(addr
, addr
, ~3);
1004 /* If we get a fault on a dslot, the jmpstate better be in sync. */
1007 /* Verify alignment if needed. */
1009 * Microblaze gives MMU faults priority over faults due to
1010 * unaligned addresses. That's why we speculatively do the load
1011 * into v. If the load succeeds, we verify alignment of the
1012 * address and if that succeeds we write into the destination reg.
1014 v
= tcg_temp_new_i32();
1015 tcg_gen_qemu_ld_i32(v
, addr
, mem_index
, mop
);
1017 if (dc
->cpu
->cfg
.unaligned_exceptions
&& size
> 1) {
1018 TCGv_i32 t0
= tcg_const_i32(0);
1019 TCGv_i32 treg
= tcg_const_i32(dc
->rd
);
1020 TCGv_i32 tsize
= tcg_const_i32(size
- 1);
1022 tcg_gen_movi_i32(cpu_pc
, dc
->pc
);
1023 gen_helper_memalign(cpu_env
, addr
, treg
, t0
, tsize
);
1025 tcg_temp_free_i32(t0
);
1026 tcg_temp_free_i32(treg
);
1027 tcg_temp_free_i32(tsize
);
1031 tcg_gen_mov_tl(env_res_addr
, addr
);
1032 tcg_gen_mov_i32(env_res_val
, v
);
1035 tcg_gen_mov_i32(cpu_R
[dc
->rd
], v
);
1037 tcg_temp_free_i32(v
);
1040 /* no support for AXI exclusive so always clear C */
1041 write_carryi(dc
, 0);
1044 tcg_temp_free(addr
);
1047 static void dec_store(DisasContext
*dc
)
1050 TCGLabel
*swx_skip
= NULL
;
1052 bool rev
= false, ex
= false, ea
= false;
1053 int mem_index
= cpu_mmu_index(&dc
->cpu
->env
, false);
1056 mop
= dc
->opcode
& 3;
1059 ea
= extract32(dc
->ir
, 7, 1);
1060 rev
= extract32(dc
->ir
, 9, 1);
1061 ex
= extract32(dc
->ir
, 10, 1);
1068 if (trap_illegal(dc
, size
> 4)) {
1072 trap_userspace(dc
, ea
);
1074 LOG_DIS("s%d%s%s%s%s\n", size
, dc
->type_b
? "i" : "", rev
? "r" : "",
1078 /* If we get a fault on a dslot, the jmpstate better be in sync. */
1080 /* SWX needs a temp_local. */
1081 addr
= ex
? tcg_temp_local_new() : tcg_temp_new();
1082 compute_ldst_addr(dc
, ea
, addr
);
1083 /* Extended addressing bypasses the MMU. */
1084 mem_index
= ea
? MMU_NOMMU_IDX
: mem_index
;
1089 /* swx does not throw unaligned access errors, so force alignment */
1090 tcg_gen_andi_tl(addr
, addr
, ~3);
1092 write_carryi(dc
, 1);
1093 swx_skip
= gen_new_label();
1094 tcg_gen_brcond_tl(TCG_COND_NE
, env_res_addr
, addr
, swx_skip
);
1097 * Compare the value loaded at lwx with current contents of
1098 * the reserved location.
1100 tval
= tcg_temp_new_i32();
1102 tcg_gen_atomic_cmpxchg_i32(tval
, addr
, env_res_val
,
1103 cpu_R
[dc
->rd
], mem_index
,
1106 tcg_gen_brcond_i32(TCG_COND_NE
, env_res_val
, tval
, swx_skip
);
1107 write_carryi(dc
, 0);
1108 tcg_temp_free_i32(tval
);
1111 if (rev
&& size
!= 4) {
1112 /* Endian reverse the address. t is addr. */
1116 tcg_gen_xori_tl(addr
, addr
, 3);
1123 /* Force addr into the temp. */
1124 tcg_gen_xori_tl(addr
, addr
, 2);
1127 cpu_abort(CPU(dc
->cpu
), "Invalid reverse size\n");
1133 tcg_gen_qemu_st_i32(cpu_R
[dc
->rd
], addr
, mem_index
, mop
);
1136 /* Verify alignment if needed. */
1137 if (dc
->cpu
->cfg
.unaligned_exceptions
&& size
> 1) {
1138 TCGv_i32 t1
= tcg_const_i32(1);
1139 TCGv_i32 treg
= tcg_const_i32(dc
->rd
);
1140 TCGv_i32 tsize
= tcg_const_i32(size
- 1);
1142 tcg_gen_movi_i32(cpu_pc
, dc
->pc
);
1143 /* FIXME: if the alignment is wrong, we should restore the value
1144 * in memory. One possible way to achieve this is to probe
1145 * the MMU prior to the memaccess, thay way we could put
1146 * the alignment checks in between the probe and the mem
1149 gen_helper_memalign(cpu_env
, addr
, treg
, t1
, tsize
);
1151 tcg_temp_free_i32(t1
);
1152 tcg_temp_free_i32(treg
);
1153 tcg_temp_free_i32(tsize
);
1157 gen_set_label(swx_skip
);
1160 tcg_temp_free(addr
);
1163 static inline void eval_cc(DisasContext
*dc
, unsigned int cc
,
1164 TCGv_i32 d
, TCGv_i32 a
)
1166 static const int mb_to_tcg_cc
[] = {
1167 [CC_EQ
] = TCG_COND_EQ
,
1168 [CC_NE
] = TCG_COND_NE
,
1169 [CC_LT
] = TCG_COND_LT
,
1170 [CC_LE
] = TCG_COND_LE
,
1171 [CC_GE
] = TCG_COND_GE
,
1172 [CC_GT
] = TCG_COND_GT
,
1182 tcg_gen_setcondi_i32(mb_to_tcg_cc
[cc
], d
, a
, 0);
1185 cpu_abort(CPU(dc
->cpu
), "Unknown condition code %x.\n", cc
);
1190 static void eval_cond_jmp(DisasContext
*dc
, TCGv_i32 pc_true
, TCGv_i32 pc_false
)
1192 TCGv_i32 zero
= tcg_const_i32(0);
1194 tcg_gen_movcond_i32(TCG_COND_NE
, cpu_pc
,
1198 tcg_temp_free_i32(zero
);
1201 static void dec_setup_dslot(DisasContext
*dc
)
1203 TCGv_i32 tmp
= tcg_const_i32(dc
->type_b
&& (dc
->tb_flags
& IMM_FLAG
));
1205 dc
->delayed_branch
= 2;
1206 dc
->tb_flags
|= D_FLAG
;
1208 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUMBState
, bimm
));
1209 tcg_temp_free_i32(tmp
);
1212 static void dec_bcc(DisasContext
*dc
)
1217 cc
= EXTRACT_FIELD(dc
->ir
, 21, 23);
1218 dslot
= dc
->ir
& (1 << 25);
1219 LOG_DIS("bcc%s r%d %x\n", dslot
? "d" : "", dc
->ra
, dc
->imm
);
1221 dc
->delayed_branch
= 1;
1223 dec_setup_dslot(dc
);
1226 if (dec_alu_op_b_is_small_imm(dc
)) {
1227 int32_t offset
= (int32_t)((int16_t)dc
->imm
); /* sign-extend. */
1229 tcg_gen_movi_i32(cpu_btarget
, dc
->pc
+ offset
);
1230 dc
->jmp
= JMP_DIRECT_CC
;
1231 dc
->jmp_pc
= dc
->pc
+ offset
;
1233 dc
->jmp
= JMP_INDIRECT
;
1234 tcg_gen_addi_i32(cpu_btarget
, *dec_alu_op_b(dc
), dc
->pc
);
1236 eval_cc(dc
, cc
, env_btaken
, cpu_R
[dc
->ra
]);
1239 static void dec_br(DisasContext
*dc
)
1241 unsigned int dslot
, link
, abs
, mbar
;
1243 dslot
= dc
->ir
& (1 << 20);
1244 abs
= dc
->ir
& (1 << 19);
1245 link
= dc
->ir
& (1 << 18);
1247 /* Memory barrier. */
1248 mbar
= (dc
->ir
>> 16) & 31;
1249 if (mbar
== 2 && dc
->imm
== 4) {
1250 uint16_t mbar_imm
= dc
->rd
;
1252 LOG_DIS("mbar %d\n", mbar_imm
);
1254 /* Data access memory barrier. */
1255 if ((mbar_imm
& 2) == 0) {
1256 tcg_gen_mb(TCG_BAR_SC
| TCG_MO_ALL
);
1259 /* mbar IMM & 16 decodes to sleep. */
1260 if (mbar_imm
& 16) {
1261 TCGv_i32 tmp_hlt
= tcg_const_i32(EXCP_HLT
);
1262 TCGv_i32 tmp_1
= tcg_const_i32(1);
1266 if (trap_userspace(dc
, true)) {
1267 /* Sleep is a privileged instruction. */
1272 tcg_gen_st_i32(tmp_1
, cpu_env
,
1273 -offsetof(MicroBlazeCPU
, env
)
1274 +offsetof(CPUState
, halted
));
1275 tcg_gen_movi_i32(cpu_pc
, dc
->pc
+ 4);
1276 gen_helper_raise_exception(cpu_env
, tmp_hlt
);
1277 tcg_temp_free_i32(tmp_hlt
);
1278 tcg_temp_free_i32(tmp_1
);
1282 dc
->cpustate_changed
= 1;
1286 LOG_DIS("br%s%s%s%s imm=%x\n",
1287 abs
? "a" : "", link
? "l" : "",
1288 dc
->type_b
? "i" : "", dslot
? "d" : "",
1291 dc
->delayed_branch
= 1;
1293 dec_setup_dslot(dc
);
1296 tcg_gen_movi_i32(cpu_R
[dc
->rd
], dc
->pc
);
1298 dc
->jmp
= JMP_INDIRECT
;
1300 tcg_gen_movi_i32(env_btaken
, 1);
1301 tcg_gen_mov_i32(cpu_btarget
, *(dec_alu_op_b(dc
)));
1302 if (link
&& !dslot
) {
1303 if (!(dc
->tb_flags
& IMM_FLAG
) && (dc
->imm
== 8 || dc
->imm
== 0x18))
1304 t_gen_raise_exception(dc
, EXCP_BREAK
);
1306 if (trap_userspace(dc
, true)) {
1310 t_gen_raise_exception(dc
, EXCP_DEBUG
);
1314 if (dec_alu_op_b_is_small_imm(dc
)) {
1315 dc
->jmp
= JMP_DIRECT
;
1316 dc
->jmp_pc
= dc
->pc
+ (int32_t)((int16_t)dc
->imm
);
1318 tcg_gen_movi_i32(env_btaken
, 1);
1319 tcg_gen_addi_i32(cpu_btarget
, *dec_alu_op_b(dc
), dc
->pc
);
1324 static inline void do_rti(DisasContext
*dc
)
1327 t0
= tcg_temp_new_i32();
1328 t1
= tcg_temp_new_i32();
1329 tcg_gen_mov_i32(t1
, cpu_msr
);
1330 tcg_gen_shri_i32(t0
, t1
, 1);
1331 tcg_gen_ori_i32(t1
, t1
, MSR_IE
);
1332 tcg_gen_andi_i32(t0
, t0
, (MSR_VM
| MSR_UM
));
1334 tcg_gen_andi_i32(t1
, t1
, ~(MSR_VM
| MSR_UM
));
1335 tcg_gen_or_i32(t1
, t1
, t0
);
1337 tcg_temp_free_i32(t1
);
1338 tcg_temp_free_i32(t0
);
1339 dc
->tb_flags
&= ~DRTI_FLAG
;
1342 static inline void do_rtb(DisasContext
*dc
)
1345 t0
= tcg_temp_new_i32();
1346 t1
= tcg_temp_new_i32();
1347 tcg_gen_mov_i32(t1
, cpu_msr
);
1348 tcg_gen_andi_i32(t1
, t1
, ~MSR_BIP
);
1349 tcg_gen_shri_i32(t0
, t1
, 1);
1350 tcg_gen_andi_i32(t0
, t0
, (MSR_VM
| MSR_UM
));
1352 tcg_gen_andi_i32(t1
, t1
, ~(MSR_VM
| MSR_UM
));
1353 tcg_gen_or_i32(t1
, t1
, t0
);
1355 tcg_temp_free_i32(t1
);
1356 tcg_temp_free_i32(t0
);
1357 dc
->tb_flags
&= ~DRTB_FLAG
;
1360 static inline void do_rte(DisasContext
*dc
)
1363 t0
= tcg_temp_new_i32();
1364 t1
= tcg_temp_new_i32();
1366 tcg_gen_mov_i32(t1
, cpu_msr
);
1367 tcg_gen_ori_i32(t1
, t1
, MSR_EE
);
1368 tcg_gen_andi_i32(t1
, t1
, ~MSR_EIP
);
1369 tcg_gen_shri_i32(t0
, t1
, 1);
1370 tcg_gen_andi_i32(t0
, t0
, (MSR_VM
| MSR_UM
));
1372 tcg_gen_andi_i32(t1
, t1
, ~(MSR_VM
| MSR_UM
));
1373 tcg_gen_or_i32(t1
, t1
, t0
);
1375 tcg_temp_free_i32(t1
);
1376 tcg_temp_free_i32(t0
);
1377 dc
->tb_flags
&= ~DRTE_FLAG
;
1380 static void dec_rts(DisasContext
*dc
)
1382 unsigned int b_bit
, i_bit
, e_bit
;
1384 i_bit
= dc
->ir
& (1 << 21);
1385 b_bit
= dc
->ir
& (1 << 22);
1386 e_bit
= dc
->ir
& (1 << 23);
1388 if (trap_userspace(dc
, i_bit
|| b_bit
|| e_bit
)) {
1392 dec_setup_dslot(dc
);
1395 LOG_DIS("rtid ir=%x\n", dc
->ir
);
1396 dc
->tb_flags
|= DRTI_FLAG
;
1398 LOG_DIS("rtbd ir=%x\n", dc
->ir
);
1399 dc
->tb_flags
|= DRTB_FLAG
;
1401 LOG_DIS("rted ir=%x\n", dc
->ir
);
1402 dc
->tb_flags
|= DRTE_FLAG
;
1404 LOG_DIS("rts ir=%x\n", dc
->ir
);
1406 dc
->jmp
= JMP_INDIRECT
;
1407 tcg_gen_movi_i32(env_btaken
, 1);
1408 tcg_gen_add_i32(cpu_btarget
, cpu_R
[dc
->ra
], *dec_alu_op_b(dc
));
1411 static int dec_check_fpuv2(DisasContext
*dc
)
1413 if ((dc
->cpu
->cfg
.use_fpu
!= 2) && (dc
->tb_flags
& MSR_EE_FLAG
)) {
1414 tcg_gen_movi_i32(cpu_esr
, ESR_EC_FPU
);
1415 t_gen_raise_exception(dc
, EXCP_HW_EXCP
);
1417 return (dc
->cpu
->cfg
.use_fpu
== 2) ? PVR2_USE_FPU2_MASK
: 0;
1420 static void dec_fpu(DisasContext
*dc
)
1422 unsigned int fpu_insn
;
1424 if (trap_illegal(dc
, !dc
->cpu
->cfg
.use_fpu
)) {
1428 fpu_insn
= (dc
->ir
>> 7) & 7;
1432 gen_helper_fadd(cpu_R
[dc
->rd
], cpu_env
, cpu_R
[dc
->ra
],
1437 gen_helper_frsub(cpu_R
[dc
->rd
], cpu_env
, cpu_R
[dc
->ra
],
1442 gen_helper_fmul(cpu_R
[dc
->rd
], cpu_env
, cpu_R
[dc
->ra
],
1447 gen_helper_fdiv(cpu_R
[dc
->rd
], cpu_env
, cpu_R
[dc
->ra
],
1452 switch ((dc
->ir
>> 4) & 7) {
1454 gen_helper_fcmp_un(cpu_R
[dc
->rd
], cpu_env
,
1455 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
1458 gen_helper_fcmp_lt(cpu_R
[dc
->rd
], cpu_env
,
1459 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
1462 gen_helper_fcmp_eq(cpu_R
[dc
->rd
], cpu_env
,
1463 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
1466 gen_helper_fcmp_le(cpu_R
[dc
->rd
], cpu_env
,
1467 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
1470 gen_helper_fcmp_gt(cpu_R
[dc
->rd
], cpu_env
,
1471 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
1474 gen_helper_fcmp_ne(cpu_R
[dc
->rd
], cpu_env
,
1475 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
1478 gen_helper_fcmp_ge(cpu_R
[dc
->rd
], cpu_env
,
1479 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
1482 qemu_log_mask(LOG_UNIMP
,
1483 "unimplemented fcmp fpu_insn=%x pc=%x"
1485 fpu_insn
, dc
->pc
, dc
->opcode
);
1486 dc
->abort_at_next_insn
= 1;
1492 if (!dec_check_fpuv2(dc
)) {
1495 gen_helper_flt(cpu_R
[dc
->rd
], cpu_env
, cpu_R
[dc
->ra
]);
1499 if (!dec_check_fpuv2(dc
)) {
1502 gen_helper_fint(cpu_R
[dc
->rd
], cpu_env
, cpu_R
[dc
->ra
]);
1506 if (!dec_check_fpuv2(dc
)) {
1509 gen_helper_fsqrt(cpu_R
[dc
->rd
], cpu_env
, cpu_R
[dc
->ra
]);
1513 qemu_log_mask(LOG_UNIMP
, "unimplemented FPU insn fpu_insn=%x pc=%x"
1515 fpu_insn
, dc
->pc
, dc
->opcode
);
1516 dc
->abort_at_next_insn
= 1;
1521 static void dec_null(DisasContext
*dc
)
1523 if (trap_illegal(dc
, true)) {
1526 qemu_log_mask(LOG_GUEST_ERROR
, "unknown insn pc=%x opc=%x\n", dc
->pc
, dc
->opcode
);
1527 dc
->abort_at_next_insn
= 1;
1530 /* Insns connected to FSL or AXI stream attached devices. */
1531 static void dec_stream(DisasContext
*dc
)
1533 TCGv_i32 t_id
, t_ctrl
;
1536 LOG_DIS("%s%s imm=%x\n", dc
->rd
? "get" : "put",
1537 dc
->type_b
? "" : "d", dc
->imm
);
1539 if (trap_userspace(dc
, true)) {
1543 t_id
= tcg_temp_new_i32();
1545 tcg_gen_movi_i32(t_id
, dc
->imm
& 0xf);
1546 ctrl
= dc
->imm
>> 10;
1548 tcg_gen_andi_i32(t_id
, cpu_R
[dc
->rb
], 0xf);
1549 ctrl
= dc
->imm
>> 5;
1552 t_ctrl
= tcg_const_i32(ctrl
);
1555 gen_helper_put(t_id
, t_ctrl
, cpu_R
[dc
->ra
]);
1557 gen_helper_get(cpu_R
[dc
->rd
], t_id
, t_ctrl
);
1559 tcg_temp_free_i32(t_id
);
1560 tcg_temp_free_i32(t_ctrl
);
1563 static struct decoder_info
{
1568 void (*dec
)(DisasContext
*dc
);
1576 {DEC_BARREL
, dec_barrel
},
1578 {DEC_ST
, dec_store
},
1587 {DEC_STREAM
, dec_stream
},
1591 static inline void decode(DisasContext
*dc
, uint32_t ir
)
1596 LOG_DIS("%8.8x\t", dc
->ir
);
1599 trap_illegal(dc
, dc
->cpu
->cfg
.opcode_0_illegal
);
1600 /* Don't decode nop/zero instructions any further. */
1604 /* bit 2 seems to indicate insn type. */
1605 dc
->type_b
= ir
& (1 << 29);
1607 dc
->opcode
= EXTRACT_FIELD(ir
, 26, 31);
1608 dc
->rd
= EXTRACT_FIELD(ir
, 21, 25);
1609 dc
->ra
= EXTRACT_FIELD(ir
, 16, 20);
1610 dc
->rb
= EXTRACT_FIELD(ir
, 11, 15);
1611 dc
->imm
= EXTRACT_FIELD(ir
, 0, 15);
1613 /* Large switch for all insns. */
1614 for (i
= 0; i
< ARRAY_SIZE(decinfo
); i
++) {
1615 if ((dc
->opcode
& decinfo
[i
].mask
) == decinfo
[i
].bits
) {
1622 /* generate intermediate code for basic block 'tb'. */
1623 void gen_intermediate_code(CPUState
*cs
, TranslationBlock
*tb
, int max_insns
)
1625 CPUMBState
*env
= cs
->env_ptr
;
1626 MicroBlazeCPU
*cpu
= env_archcpu(env
);
1628 struct DisasContext ctx
;
1629 struct DisasContext
*dc
= &ctx
;
1630 uint32_t page_start
, org_flags
;
1637 org_flags
= dc
->synced_flags
= dc
->tb_flags
= tb
->flags
;
1639 dc
->is_jmp
= DISAS_NEXT
;
1641 dc
->delayed_branch
= !!(dc
->tb_flags
& D_FLAG
);
1642 if (dc
->delayed_branch
) {
1643 dc
->jmp
= JMP_INDIRECT
;
1646 dc
->singlestep_enabled
= cs
->singlestep_enabled
;
1647 dc
->cpustate_changed
= 0;
1648 dc
->abort_at_next_insn
= 0;
1651 cpu_abort(cs
, "Microblaze: unaligned PC=%x\n", pc_start
);
1654 page_start
= pc_start
& TARGET_PAGE_MASK
;
1660 tcg_gen_insn_start(dc
->pc
);
1664 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
1665 tcg_gen_movi_i32(cpu_pc
, dc
->pc
);
1670 if (unlikely(cpu_breakpoint_test(cs
, dc
->pc
, BP_ANY
))) {
1671 t_gen_raise_exception(dc
, EXCP_DEBUG
);
1672 dc
->is_jmp
= DISAS_UPDATE
;
1673 /* The address covered by the breakpoint must be included in
1674 [tb->pc, tb->pc + tb->size) in order to for it to be
1675 properly cleared -- thus we increment the PC here so that
1676 the logic setting tb->size below does the right thing. */
1682 LOG_DIS("%8.8x:\t", dc
->pc
);
1684 if (num_insns
== max_insns
&& (tb_cflags(tb
) & CF_LAST_IO
)) {
1689 decode(dc
, cpu_ldl_code(env
, dc
->pc
));
1691 dc
->tb_flags
&= ~IMM_FLAG
;
1694 if (dc
->delayed_branch
) {
1695 dc
->delayed_branch
--;
1696 if (!dc
->delayed_branch
) {
1697 if (dc
->tb_flags
& DRTI_FLAG
)
1699 if (dc
->tb_flags
& DRTB_FLAG
)
1701 if (dc
->tb_flags
& DRTE_FLAG
)
1703 /* Clear the delay slot flag. */
1704 dc
->tb_flags
&= ~D_FLAG
;
1705 /* If it is a direct jump, try direct chaining. */
1706 if (dc
->jmp
== JMP_INDIRECT
) {
1707 TCGv_i32 tmp_pc
= tcg_const_i32(dc
->pc
);
1708 eval_cond_jmp(dc
, cpu_btarget
, tmp_pc
);
1709 tcg_temp_free_i32(tmp_pc
);
1710 dc
->is_jmp
= DISAS_JUMP
;
1711 } else if (dc
->jmp
== JMP_DIRECT
) {
1713 gen_goto_tb(dc
, 0, dc
->jmp_pc
);
1714 dc
->is_jmp
= DISAS_TB_JUMP
;
1715 } else if (dc
->jmp
== JMP_DIRECT_CC
) {
1716 TCGLabel
*l1
= gen_new_label();
1718 /* Conditional jmp. */
1719 tcg_gen_brcondi_i32(TCG_COND_NE
, env_btaken
, 0, l1
);
1720 gen_goto_tb(dc
, 1, dc
->pc
);
1722 gen_goto_tb(dc
, 0, dc
->jmp_pc
);
1724 dc
->is_jmp
= DISAS_TB_JUMP
;
1729 if (cs
->singlestep_enabled
) {
1732 } while (!dc
->is_jmp
&& !dc
->cpustate_changed
1733 && !tcg_op_buf_full()
1735 && (dc
->pc
- page_start
< TARGET_PAGE_SIZE
)
1736 && num_insns
< max_insns
);
1739 if (dc
->jmp
== JMP_DIRECT
|| dc
->jmp
== JMP_DIRECT_CC
) {
1740 if (dc
->tb_flags
& D_FLAG
) {
1741 dc
->is_jmp
= DISAS_UPDATE
;
1742 tcg_gen_movi_i32(cpu_pc
, npc
);
1748 /* Force an update if the per-tb cpu state has changed. */
1749 if (dc
->is_jmp
== DISAS_NEXT
1750 && (dc
->cpustate_changed
|| org_flags
!= dc
->tb_flags
)) {
1751 dc
->is_jmp
= DISAS_UPDATE
;
1752 tcg_gen_movi_i32(cpu_pc
, npc
);
1756 if (unlikely(cs
->singlestep_enabled
)) {
1757 TCGv_i32 tmp
= tcg_const_i32(EXCP_DEBUG
);
1759 if (dc
->is_jmp
!= DISAS_JUMP
) {
1760 tcg_gen_movi_i32(cpu_pc
, npc
);
1762 gen_helper_raise_exception(cpu_env
, tmp
);
1763 tcg_temp_free_i32(tmp
);
1765 switch(dc
->is_jmp
) {
1767 gen_goto_tb(dc
, 1, npc
);
1772 /* indicate that the hash table must be used
1773 to find the next TB */
1774 tcg_gen_exit_tb(NULL
, 0);
1777 /* nothing more to generate */
1781 gen_tb_end(tb
, num_insns
);
1783 tb
->size
= dc
->pc
- pc_start
;
1784 tb
->icount
= num_insns
;
1788 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)
1789 && qemu_log_in_addr_range(pc_start
)) {
1790 FILE *logfile
= qemu_log_lock();
1791 qemu_log("--------------\n");
1792 log_target_disas(cs
, pc_start
, dc
->pc
- pc_start
);
1793 qemu_log_unlock(logfile
);
1797 assert(!dc
->abort_at_next_insn
);
1800 void mb_cpu_dump_state(CPUState
*cs
, FILE *f
, int flags
)
1802 MicroBlazeCPU
*cpu
= MICROBLAZE_CPU(cs
);
1803 CPUMBState
*env
= &cpu
->env
;
1810 qemu_fprintf(f
, "IN: PC=%x %s\n",
1811 env
->pc
, lookup_symbol(env
->pc
));
1812 qemu_fprintf(f
, "rmsr=%x resr=%x rear=%" PRIx64
" "
1813 "debug=%x imm=%x iflags=%x fsr=%x rbtr=%x\n",
1814 env
->msr
, env
->esr
, env
->ear
,
1815 env
->debug
, env
->imm
, env
->iflags
, env
->fsr
,
1817 qemu_fprintf(f
, "btaken=%d btarget=%x mode=%s(saved=%s) eip=%d ie=%d\n",
1818 env
->btaken
, env
->btarget
,
1819 (env
->msr
& MSR_UM
) ? "user" : "kernel",
1820 (env
->msr
& MSR_UMS
) ? "user" : "kernel",
1821 (bool)(env
->msr
& MSR_EIP
),
1822 (bool)(env
->msr
& MSR_IE
));
1823 for (i
= 0; i
< 12; i
++) {
1824 qemu_fprintf(f
, "rpvr%2.2d=%8.8x ", i
, env
->pvr
.regs
[i
]);
1825 if ((i
+ 1) % 4 == 0) {
1826 qemu_fprintf(f
, "\n");
1830 /* Registers that aren't modeled are reported as 0 */
1831 qemu_fprintf(f
, "redr=%x rpid=0 rzpr=0 rtlbx=0 rtlbsx=0 "
1832 "rtlblo=0 rtlbhi=0\n", env
->edr
);
1833 qemu_fprintf(f
, "slr=%x shr=%x\n", env
->slr
, env
->shr
);
1834 for (i
= 0; i
< 32; i
++) {
1835 qemu_fprintf(f
, "r%2.2d=%8.8x ", i
, env
->regs
[i
]);
1836 if ((i
+ 1) % 4 == 0)
1837 qemu_fprintf(f
, "\n");
1839 qemu_fprintf(f
, "\n\n");
1842 void mb_tcg_init(void)
1846 env_debug
= tcg_global_mem_new_i32(cpu_env
,
1847 offsetof(CPUMBState
, debug
),
1849 env_iflags
= tcg_global_mem_new_i32(cpu_env
,
1850 offsetof(CPUMBState
, iflags
),
1852 env_imm
= tcg_global_mem_new_i32(cpu_env
,
1853 offsetof(CPUMBState
, imm
),
1855 cpu_btarget
= tcg_global_mem_new_i32(cpu_env
,
1856 offsetof(CPUMBState
, btarget
),
1858 env_btaken
= tcg_global_mem_new_i32(cpu_env
,
1859 offsetof(CPUMBState
, btaken
),
1861 env_res_addr
= tcg_global_mem_new(cpu_env
,
1862 offsetof(CPUMBState
, res_addr
),
1864 env_res_val
= tcg_global_mem_new_i32(cpu_env
,
1865 offsetof(CPUMBState
, res_val
),
1867 for (i
= 0; i
< ARRAY_SIZE(cpu_R
); i
++) {
1868 cpu_R
[i
] = tcg_global_mem_new_i32(cpu_env
,
1869 offsetof(CPUMBState
, regs
[i
]),
1874 tcg_global_mem_new_i32(cpu_env
, offsetof(CPUMBState
, pc
), "rpc");
1876 tcg_global_mem_new_i32(cpu_env
, offsetof(CPUMBState
, msr
), "rmsr");
1878 tcg_global_mem_new_i32(cpu_env
, offsetof(CPUMBState
, esr
), "resr");
1881 void restore_state_to_opc(CPUMBState
*env
, TranslationBlock
*tb
,