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_i64 cpu_SR
[14];
59 static TCGv_i32 env_imm
;
60 static TCGv_i32 env_btaken
;
61 static TCGv_i64 env_btarget
;
62 static TCGv_i32 env_iflags
;
63 static TCGv env_res_addr
;
64 static TCGv_i32 env_res_val
;
66 #include "exec/gen-icount.h"
68 /* This is the state at translation time. */
69 typedef struct DisasContext
{
80 unsigned int cpustate_changed
;
81 unsigned int delayed_branch
;
82 unsigned int tb_flags
, synced_flags
; /* tb dependent flags. */
83 unsigned int clear_imm
;
88 #define JMP_DIRECT_CC 2
89 #define JMP_INDIRECT 3
93 int abort_at_next_insn
;
94 struct TranslationBlock
*tb
;
95 int singlestep_enabled
;
98 static const char *regnames
[] =
100 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
101 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
102 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
103 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
106 static const char *special_regnames
[] =
108 "rpc", "rmsr", "sr2", "rear", "sr4", "resr", "sr6", "rfsr",
109 "sr8", "sr9", "sr10", "rbtr", "sr12", "redr"
112 static inline void t_sync_flags(DisasContext
*dc
)
114 /* Synch the tb dependent flags between translator and runtime. */
115 if (dc
->tb_flags
!= dc
->synced_flags
) {
116 tcg_gen_movi_i32(env_iflags
, dc
->tb_flags
);
117 dc
->synced_flags
= dc
->tb_flags
;
121 static inline void t_gen_raise_exception(DisasContext
*dc
, uint32_t index
)
123 TCGv_i32 tmp
= tcg_const_i32(index
);
126 tcg_gen_movi_i64(cpu_SR
[SR_PC
], dc
->pc
);
127 gen_helper_raise_exception(cpu_env
, tmp
);
128 tcg_temp_free_i32(tmp
);
129 dc
->is_jmp
= DISAS_UPDATE
;
132 static inline bool use_goto_tb(DisasContext
*dc
, target_ulong dest
)
134 #ifndef CONFIG_USER_ONLY
135 return (dc
->tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
);
141 static void gen_goto_tb(DisasContext
*dc
, int n
, target_ulong dest
)
143 if (use_goto_tb(dc
, dest
)) {
145 tcg_gen_movi_i64(cpu_SR
[SR_PC
], dest
);
146 tcg_gen_exit_tb(dc
->tb
, n
);
148 tcg_gen_movi_i64(cpu_SR
[SR_PC
], dest
);
149 tcg_gen_exit_tb(NULL
, 0);
153 static void read_carry(DisasContext
*dc
, TCGv_i32 d
)
155 tcg_gen_extrl_i64_i32(d
, cpu_SR
[SR_MSR
]);
156 tcg_gen_shri_i32(d
, d
, 31);
160 * write_carry sets the carry bits in MSR based on bit 0 of v.
161 * v[31:1] are ignored.
163 static void write_carry(DisasContext
*dc
, TCGv_i32 v
)
165 TCGv_i64 t0
= tcg_temp_new_i64();
166 tcg_gen_extu_i32_i64(t0
, v
);
167 /* Deposit bit 0 into MSR_C and the alias MSR_CC. */
168 tcg_gen_deposit_i64(cpu_SR
[SR_MSR
], cpu_SR
[SR_MSR
], t0
, 2, 1);
169 tcg_gen_deposit_i64(cpu_SR
[SR_MSR
], cpu_SR
[SR_MSR
], t0
, 31, 1);
170 tcg_temp_free_i64(t0
);
173 static void write_carryi(DisasContext
*dc
, bool carry
)
175 TCGv_i32 t0
= tcg_temp_new_i32();
176 tcg_gen_movi_i32(t0
, carry
);
178 tcg_temp_free_i32(t0
);
182 * Returns true if the insn an illegal operation.
183 * If exceptions are enabled, an exception is raised.
185 static bool trap_illegal(DisasContext
*dc
, bool cond
)
187 if (cond
&& (dc
->tb_flags
& MSR_EE_FLAG
)
188 && dc
->cpu
->cfg
.illegal_opcode_exception
) {
189 tcg_gen_movi_i64(cpu_SR
[SR_ESR
], ESR_EC_ILLEGAL_OP
);
190 t_gen_raise_exception(dc
, EXCP_HW_EXCP
);
196 * Returns true if the insn is illegal in userspace.
197 * If exceptions are enabled, an exception is raised.
199 static bool trap_userspace(DisasContext
*dc
, bool cond
)
201 int mem_index
= cpu_mmu_index(&dc
->cpu
->env
, false);
202 bool cond_user
= cond
&& mem_index
== MMU_USER_IDX
;
204 if (cond_user
&& (dc
->tb_flags
& MSR_EE_FLAG
)) {
205 tcg_gen_movi_i64(cpu_SR
[SR_ESR
], ESR_EC_PRIVINSN
);
206 t_gen_raise_exception(dc
, EXCP_HW_EXCP
);
211 /* True if ALU operand b is a small immediate that may deserve
213 static inline int dec_alu_op_b_is_small_imm(DisasContext
*dc
)
215 /* Immediate insn without the imm prefix ? */
216 return dc
->type_b
&& !(dc
->tb_flags
& IMM_FLAG
);
219 static inline TCGv_i32
*dec_alu_op_b(DisasContext
*dc
)
222 if (dc
->tb_flags
& IMM_FLAG
)
223 tcg_gen_ori_i32(env_imm
, env_imm
, dc
->imm
);
225 tcg_gen_movi_i32(env_imm
, (int32_t)((int16_t)dc
->imm
));
228 return &cpu_R
[dc
->rb
];
231 static void dec_add(DisasContext
*dc
)
239 LOG_DIS("add%s%s%s r%d r%d r%d\n",
240 dc
->type_b
? "i" : "", k
? "k" : "", c
? "c" : "",
241 dc
->rd
, dc
->ra
, dc
->rb
);
243 /* Take care of the easy cases first. */
245 /* k - keep carry, no need to update MSR. */
246 /* If rd == r0, it's a nop. */
248 tcg_gen_add_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], *(dec_alu_op_b(dc
)));
251 /* c - Add carry into the result. */
252 cf
= tcg_temp_new_i32();
255 tcg_gen_add_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->rd
], cf
);
256 tcg_temp_free_i32(cf
);
262 /* From now on, we can assume k is zero. So we need to update MSR. */
264 cf
= tcg_temp_new_i32();
268 tcg_gen_movi_i32(cf
, 0);
272 TCGv_i32 ncf
= tcg_temp_new_i32();
273 gen_helper_carry(ncf
, cpu_R
[dc
->ra
], *(dec_alu_op_b(dc
)), cf
);
274 tcg_gen_add_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], *(dec_alu_op_b(dc
)));
275 tcg_gen_add_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->rd
], cf
);
276 write_carry(dc
, ncf
);
277 tcg_temp_free_i32(ncf
);
279 gen_helper_carry(cf
, cpu_R
[dc
->ra
], *(dec_alu_op_b(dc
)), cf
);
282 tcg_temp_free_i32(cf
);
285 static void dec_sub(DisasContext
*dc
)
287 unsigned int u
, cmp
, k
, c
;
293 cmp
= (dc
->imm
& 1) && (!dc
->type_b
) && k
;
296 LOG_DIS("cmp%s r%d, r%d ir=%x\n", u
? "u" : "", dc
->rd
, dc
->ra
, dc
->ir
);
299 gen_helper_cmpu(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
301 gen_helper_cmp(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
306 LOG_DIS("sub%s%s r%d, r%d r%d\n",
307 k
? "k" : "", c
? "c" : "", dc
->rd
, dc
->ra
, dc
->rb
);
309 /* Take care of the easy cases first. */
311 /* k - keep carry, no need to update MSR. */
312 /* If rd == r0, it's a nop. */
314 tcg_gen_sub_i32(cpu_R
[dc
->rd
], *(dec_alu_op_b(dc
)), cpu_R
[dc
->ra
]);
317 /* c - Add carry into the result. */
318 cf
= tcg_temp_new_i32();
321 tcg_gen_add_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->rd
], cf
);
322 tcg_temp_free_i32(cf
);
328 /* From now on, we can assume k is zero. So we need to update MSR. */
329 /* Extract carry. And complement a into na. */
330 cf
= tcg_temp_new_i32();
331 na
= tcg_temp_new_i32();
335 tcg_gen_movi_i32(cf
, 1);
338 /* d = b + ~a + c. carry defaults to 1. */
339 tcg_gen_not_i32(na
, cpu_R
[dc
->ra
]);
342 TCGv_i32 ncf
= tcg_temp_new_i32();
343 gen_helper_carry(ncf
, na
, *(dec_alu_op_b(dc
)), cf
);
344 tcg_gen_add_i32(cpu_R
[dc
->rd
], na
, *(dec_alu_op_b(dc
)));
345 tcg_gen_add_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->rd
], cf
);
346 write_carry(dc
, ncf
);
347 tcg_temp_free_i32(ncf
);
349 gen_helper_carry(cf
, na
, *(dec_alu_op_b(dc
)), cf
);
352 tcg_temp_free_i32(cf
);
353 tcg_temp_free_i32(na
);
356 static void dec_pattern(DisasContext
*dc
)
360 if (trap_illegal(dc
, !dc
->cpu
->cfg
.use_pcmp_instr
)) {
364 mode
= dc
->opcode
& 3;
368 LOG_DIS("pcmpbf r%d r%d r%d\n", dc
->rd
, dc
->ra
, dc
->rb
);
370 gen_helper_pcmpbf(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
373 LOG_DIS("pcmpeq r%d r%d r%d\n", dc
->rd
, dc
->ra
, dc
->rb
);
375 tcg_gen_setcond_i32(TCG_COND_EQ
, cpu_R
[dc
->rd
],
376 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
380 LOG_DIS("pcmpne r%d r%d r%d\n", dc
->rd
, dc
->ra
, dc
->rb
);
382 tcg_gen_setcond_i32(TCG_COND_NE
, cpu_R
[dc
->rd
],
383 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
387 cpu_abort(CPU(dc
->cpu
),
388 "unsupported pattern insn opcode=%x\n", dc
->opcode
);
393 static void dec_and(DisasContext
*dc
)
397 if (!dc
->type_b
&& (dc
->imm
& (1 << 10))) {
402 not = dc
->opcode
& (1 << 1);
403 LOG_DIS("and%s\n", not ? "n" : "");
409 tcg_gen_andc_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], *(dec_alu_op_b(dc
)));
411 tcg_gen_and_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], *(dec_alu_op_b(dc
)));
414 static void dec_or(DisasContext
*dc
)
416 if (!dc
->type_b
&& (dc
->imm
& (1 << 10))) {
421 LOG_DIS("or r%d r%d r%d imm=%x\n", dc
->rd
, dc
->ra
, dc
->rb
, dc
->imm
);
423 tcg_gen_or_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], *(dec_alu_op_b(dc
)));
426 static void dec_xor(DisasContext
*dc
)
428 if (!dc
->type_b
&& (dc
->imm
& (1 << 10))) {
433 LOG_DIS("xor r%d\n", dc
->rd
);
435 tcg_gen_xor_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], *(dec_alu_op_b(dc
)));
438 static inline void msr_read(DisasContext
*dc
, TCGv_i32 d
)
440 tcg_gen_extrl_i64_i32(d
, cpu_SR
[SR_MSR
]);
443 static inline void msr_write(DisasContext
*dc
, TCGv_i32 v
)
447 t
= tcg_temp_new_i64();
448 dc
->cpustate_changed
= 1;
449 /* PVR bit is not writable. */
450 tcg_gen_extu_i32_i64(t
, v
);
451 tcg_gen_andi_i64(t
, t
, ~MSR_PVR
);
452 tcg_gen_andi_i64(cpu_SR
[SR_MSR
], cpu_SR
[SR_MSR
], MSR_PVR
);
453 tcg_gen_or_i64(cpu_SR
[SR_MSR
], cpu_SR
[SR_MSR
], t
);
454 tcg_temp_free_i64(t
);
457 static void dec_msr(DisasContext
*dc
)
459 CPUState
*cs
= CPU(dc
->cpu
);
462 bool to
, clrset
, extended
= false;
464 sr
= extract32(dc
->imm
, 0, 14);
465 to
= extract32(dc
->imm
, 14, 1);
466 clrset
= extract32(dc
->imm
, 15, 1) == 0;
469 dc
->cpustate_changed
= 1;
472 /* Extended MSRs are only available if addr_size > 32. */
473 if (dc
->cpu
->cfg
.addr_size
> 32) {
474 /* The E-bit is encoded differently for To/From MSR. */
475 static const unsigned int e_bit
[] = { 19, 24 };
477 extended
= extract32(dc
->imm
, e_bit
[to
], 1);
480 /* msrclr and msrset. */
482 bool clr
= extract32(dc
->ir
, 16, 1);
484 LOG_DIS("msr%s r%d imm=%x\n", clr
? "clr" : "set",
487 if (!dc
->cpu
->cfg
.use_msr_instr
) {
492 if (trap_userspace(dc
, dc
->imm
!= 4 && dc
->imm
!= 0)) {
497 msr_read(dc
, cpu_R
[dc
->rd
]);
499 t0
= tcg_temp_new_i32();
500 t1
= tcg_temp_new_i32();
502 tcg_gen_mov_i32(t1
, *(dec_alu_op_b(dc
)));
505 tcg_gen_not_i32(t1
, t1
);
506 tcg_gen_and_i32(t0
, t0
, t1
);
508 tcg_gen_or_i32(t0
, t0
, t1
);
510 tcg_temp_free_i32(t0
);
511 tcg_temp_free_i32(t1
);
512 tcg_gen_movi_i64(cpu_SR
[SR_PC
], dc
->pc
+ 4);
513 dc
->is_jmp
= DISAS_UPDATE
;
517 if (trap_userspace(dc
, to
)) {
521 #if !defined(CONFIG_USER_ONLY)
522 /* Catch read/writes to the mmu block. */
523 if ((sr
& ~0xff) == 0x1000) {
524 TCGv_i32 tmp_ext
= tcg_const_i32(extended
);
528 tmp_sr
= tcg_const_i32(sr
);
529 LOG_DIS("m%ss sr%d r%d imm=%x\n", to
? "t" : "f", sr
, dc
->ra
, dc
->imm
);
531 gen_helper_mmu_write(cpu_env
, tmp_ext
, tmp_sr
, cpu_R
[dc
->ra
]);
533 gen_helper_mmu_read(cpu_R
[dc
->rd
], cpu_env
, tmp_ext
, tmp_sr
);
535 tcg_temp_free_i32(tmp_sr
);
536 tcg_temp_free_i32(tmp_ext
);
542 LOG_DIS("m%ss sr%x r%d imm=%x\n", to
? "t" : "f", sr
, dc
->ra
, dc
->imm
);
547 msr_write(dc
, cpu_R
[dc
->ra
]);
552 tcg_gen_extu_i32_i64(cpu_SR
[sr
], cpu_R
[dc
->ra
]);
555 tcg_gen_st_i32(cpu_R
[dc
->ra
],
556 cpu_env
, offsetof(CPUMBState
, slr
));
559 tcg_gen_st_i32(cpu_R
[dc
->ra
],
560 cpu_env
, offsetof(CPUMBState
, shr
));
563 cpu_abort(CPU(dc
->cpu
), "unknown mts reg %x\n", sr
);
567 LOG_DIS("m%ss r%d sr%x imm=%x\n", to
? "t" : "f", dc
->rd
, sr
, dc
->imm
);
571 tcg_gen_movi_i32(cpu_R
[dc
->rd
], dc
->pc
);
574 msr_read(dc
, cpu_R
[dc
->rd
]);
578 tcg_gen_extrh_i64_i32(cpu_R
[dc
->rd
], cpu_SR
[sr
]);
585 tcg_gen_extrl_i64_i32(cpu_R
[dc
->rd
], cpu_SR
[sr
]);
588 tcg_gen_ld_i32(cpu_R
[dc
->rd
],
589 cpu_env
, offsetof(CPUMBState
, slr
));
592 tcg_gen_ld_i32(cpu_R
[dc
->rd
],
593 cpu_env
, offsetof(CPUMBState
, shr
));
595 case 0x2000 ... 0x200c:
597 tcg_gen_ld_i32(cpu_R
[dc
->rd
],
598 cpu_env
, offsetof(CPUMBState
, pvr
.regs
[rn
]));
601 cpu_abort(cs
, "unknown mfs reg %x\n", sr
);
607 tcg_gen_movi_i32(cpu_R
[0], 0);
611 /* Multiplier unit. */
612 static void dec_mul(DisasContext
*dc
)
615 unsigned int subcode
;
617 if (trap_illegal(dc
, !dc
->cpu
->cfg
.use_hw_mul
)) {
621 subcode
= dc
->imm
& 3;
624 LOG_DIS("muli r%d r%d %x\n", dc
->rd
, dc
->ra
, dc
->imm
);
625 tcg_gen_mul_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], *(dec_alu_op_b(dc
)));
629 /* mulh, mulhsu and mulhu are not available if C_USE_HW_MUL is < 2. */
630 if (subcode
>= 1 && subcode
<= 3 && dc
->cpu
->cfg
.use_hw_mul
< 2) {
634 tmp
= tcg_temp_new_i32();
637 LOG_DIS("mul r%d r%d r%d\n", dc
->rd
, dc
->ra
, dc
->rb
);
638 tcg_gen_mul_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
641 LOG_DIS("mulh r%d r%d r%d\n", dc
->rd
, dc
->ra
, dc
->rb
);
642 tcg_gen_muls2_i32(tmp
, cpu_R
[dc
->rd
],
643 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
646 LOG_DIS("mulhsu r%d r%d r%d\n", dc
->rd
, dc
->ra
, dc
->rb
);
647 tcg_gen_mulsu2_i32(tmp
, cpu_R
[dc
->rd
],
648 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
651 LOG_DIS("mulhu r%d r%d r%d\n", dc
->rd
, dc
->ra
, dc
->rb
);
652 tcg_gen_mulu2_i32(tmp
, cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
655 cpu_abort(CPU(dc
->cpu
), "unknown MUL insn %x\n", subcode
);
658 tcg_temp_free_i32(tmp
);
662 static void dec_div(DisasContext
*dc
)
669 if (trap_illegal(dc
, !dc
->cpu
->cfg
.use_div
)) {
674 gen_helper_divu(cpu_R
[dc
->rd
], cpu_env
, *(dec_alu_op_b(dc
)),
677 gen_helper_divs(cpu_R
[dc
->rd
], cpu_env
, *(dec_alu_op_b(dc
)),
680 tcg_gen_movi_i32(cpu_R
[dc
->rd
], 0);
683 static void dec_barrel(DisasContext
*dc
)
686 unsigned int imm_w
, imm_s
;
687 bool s
, t
, e
= false, i
= false;
689 if (trap_illegal(dc
, !dc
->cpu
->cfg
.use_barrel
)) {
694 /* Insert and extract are only available in immediate mode. */
695 i
= extract32(dc
->imm
, 15, 1);
696 e
= extract32(dc
->imm
, 14, 1);
698 s
= extract32(dc
->imm
, 10, 1);
699 t
= extract32(dc
->imm
, 9, 1);
700 imm_w
= extract32(dc
->imm
, 6, 5);
701 imm_s
= extract32(dc
->imm
, 0, 5);
703 LOG_DIS("bs%s%s%s r%d r%d r%d\n",
705 s
? "l" : "r", t
? "a" : "l", dc
->rd
, dc
->ra
, dc
->rb
);
708 if (imm_w
+ imm_s
> 32 || imm_w
== 0) {
709 /* These inputs have an undefined behavior. */
710 qemu_log_mask(LOG_GUEST_ERROR
, "bsefi: Bad input w=%d s=%d\n",
713 tcg_gen_extract_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], imm_s
, imm_w
);
716 int width
= imm_w
- imm_s
+ 1;
719 /* These inputs have an undefined behavior. */
720 qemu_log_mask(LOG_GUEST_ERROR
, "bsifi: Bad input w=%d s=%d\n",
723 tcg_gen_deposit_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->rd
], cpu_R
[dc
->ra
],
727 t0
= tcg_temp_new_i32();
729 tcg_gen_mov_i32(t0
, *(dec_alu_op_b(dc
)));
730 tcg_gen_andi_i32(t0
, t0
, 31);
733 tcg_gen_shl_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], t0
);
736 tcg_gen_sar_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], t0
);
738 tcg_gen_shr_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], t0
);
741 tcg_temp_free_i32(t0
);
745 static void dec_bit(DisasContext
*dc
)
747 CPUState
*cs
= CPU(dc
->cpu
);
751 op
= dc
->ir
& ((1 << 9) - 1);
755 t0
= tcg_temp_new_i32();
757 LOG_DIS("src r%d r%d\n", dc
->rd
, dc
->ra
);
758 tcg_gen_extrl_i64_i32(t0
, cpu_SR
[SR_MSR
]);
759 tcg_gen_andi_i32(t0
, t0
, MSR_CC
);
760 write_carry(dc
, cpu_R
[dc
->ra
]);
762 tcg_gen_shri_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], 1);
763 tcg_gen_or_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->rd
], t0
);
765 tcg_temp_free_i32(t0
);
771 LOG_DIS("srl r%d r%d\n", dc
->rd
, dc
->ra
);
773 /* Update carry. Note that write carry only looks at the LSB. */
774 write_carry(dc
, cpu_R
[dc
->ra
]);
777 tcg_gen_shri_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], 1);
779 tcg_gen_sari_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], 1);
783 LOG_DIS("ext8s r%d r%d\n", dc
->rd
, dc
->ra
);
784 tcg_gen_ext8s_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
]);
787 LOG_DIS("ext16s r%d r%d\n", dc
->rd
, dc
->ra
);
788 tcg_gen_ext16s_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
]);
795 LOG_DIS("wdc r%d\n", dc
->ra
);
796 trap_userspace(dc
, true);
800 LOG_DIS("wic r%d\n", dc
->ra
);
801 trap_userspace(dc
, true);
804 if (trap_illegal(dc
, !dc
->cpu
->cfg
.use_pcmp_instr
)) {
807 if (dc
->cpu
->cfg
.use_pcmp_instr
) {
808 tcg_gen_clzi_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], 32);
813 LOG_DIS("swapb r%d r%d\n", dc
->rd
, dc
->ra
);
814 tcg_gen_bswap32_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
]);
818 LOG_DIS("swaph r%d r%d\n", dc
->rd
, dc
->ra
);
819 tcg_gen_rotri_i32(cpu_R
[dc
->rd
], cpu_R
[dc
->ra
], 16);
822 cpu_abort(cs
, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
823 dc
->pc
, op
, dc
->rd
, dc
->ra
, dc
->rb
);
828 static inline void sync_jmpstate(DisasContext
*dc
)
830 if (dc
->jmp
== JMP_DIRECT
|| dc
->jmp
== JMP_DIRECT_CC
) {
831 if (dc
->jmp
== JMP_DIRECT
) {
832 tcg_gen_movi_i32(env_btaken
, 1);
834 dc
->jmp
= JMP_INDIRECT
;
835 tcg_gen_movi_i64(env_btarget
, dc
->jmp_pc
);
839 static void dec_imm(DisasContext
*dc
)
841 LOG_DIS("imm %x\n", dc
->imm
<< 16);
842 tcg_gen_movi_i32(env_imm
, (dc
->imm
<< 16));
843 dc
->tb_flags
|= IMM_FLAG
;
847 static inline void compute_ldst_addr(DisasContext
*dc
, bool ea
, TCGv t
)
849 bool extimm
= dc
->tb_flags
& IMM_FLAG
;
850 /* Should be set to true if r1 is used by loadstores. */
851 bool stackprot
= false;
854 /* All load/stores use ra. */
855 if (dc
->ra
== 1 && dc
->cpu
->cfg
.stackprot
) {
859 /* Treat the common cases first. */
862 int addr_size
= dc
->cpu
->cfg
.addr_size
;
864 if (addr_size
== 32) {
865 tcg_gen_extu_i32_tl(t
, cpu_R
[dc
->rb
]);
869 tcg_gen_concat_i32_i64(t
, cpu_R
[dc
->rb
], cpu_R
[dc
->ra
]);
870 if (addr_size
< 64) {
871 /* Mask off out of range bits. */
872 tcg_gen_andi_i64(t
, t
, MAKE_64BIT_MASK(0, addr_size
));
877 /* If any of the regs is r0, set t to the value of the other reg. */
879 tcg_gen_extu_i32_tl(t
, cpu_R
[dc
->rb
]);
881 } else if (dc
->rb
== 0) {
882 tcg_gen_extu_i32_tl(t
, cpu_R
[dc
->ra
]);
886 if (dc
->rb
== 1 && dc
->cpu
->cfg
.stackprot
) {
890 t32
= tcg_temp_new_i32();
891 tcg_gen_add_i32(t32
, cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
892 tcg_gen_extu_i32_tl(t
, t32
);
893 tcg_temp_free_i32(t32
);
896 gen_helper_stackprot(cpu_env
, t
);
901 t32
= tcg_temp_new_i32();
903 tcg_gen_addi_i32(t32
, cpu_R
[dc
->ra
], (int16_t)dc
->imm
);
905 tcg_gen_add_i32(t32
, cpu_R
[dc
->ra
], *(dec_alu_op_b(dc
)));
907 tcg_gen_extu_i32_tl(t
, t32
);
908 tcg_temp_free_i32(t32
);
911 gen_helper_stackprot(cpu_env
, t
);
916 static void dec_load(DisasContext
*dc
)
921 bool rev
= false, ex
= false, ea
= false;
922 int mem_index
= cpu_mmu_index(&dc
->cpu
->env
, false);
925 mop
= dc
->opcode
& 3;
928 ea
= extract32(dc
->ir
, 7, 1);
929 rev
= extract32(dc
->ir
, 9, 1);
930 ex
= extract32(dc
->ir
, 10, 1);
937 if (trap_illegal(dc
, size
> 4)) {
941 if (trap_userspace(dc
, ea
)) {
945 LOG_DIS("l%d%s%s%s%s\n", size
, dc
->type_b
? "i" : "", rev
? "r" : "",
950 addr
= tcg_temp_new();
951 compute_ldst_addr(dc
, ea
, addr
);
952 /* Extended addressing bypasses the MMU. */
953 mem_index
= ea
? MMU_NOMMU_IDX
: mem_index
;
956 * When doing reverse accesses we need to do two things.
958 * 1. Reverse the address wrt endianness.
959 * 2. Byteswap the data lanes on the way back into the CPU core.
961 if (rev
&& size
!= 4) {
962 /* Endian reverse the address. t is addr. */
966 tcg_gen_xori_tl(addr
, addr
, 3);
973 tcg_gen_xori_tl(addr
, addr
, 2);
976 cpu_abort(CPU(dc
->cpu
), "Invalid reverse size\n");
981 /* lwx does not throw unaligned access errors, so force alignment */
983 tcg_gen_andi_tl(addr
, addr
, ~3);
986 /* If we get a fault on a dslot, the jmpstate better be in sync. */
989 /* Verify alignment if needed. */
991 * Microblaze gives MMU faults priority over faults due to
992 * unaligned addresses. That's why we speculatively do the load
993 * into v. If the load succeeds, we verify alignment of the
994 * address and if that succeeds we write into the destination reg.
996 v
= tcg_temp_new_i32();
997 tcg_gen_qemu_ld_i32(v
, addr
, mem_index
, mop
);
999 if (dc
->cpu
->cfg
.unaligned_exceptions
&& size
> 1) {
1000 TCGv_i32 t0
= tcg_const_i32(0);
1001 TCGv_i32 treg
= tcg_const_i32(dc
->rd
);
1002 TCGv_i32 tsize
= tcg_const_i32(size
- 1);
1004 tcg_gen_movi_i64(cpu_SR
[SR_PC
], dc
->pc
);
1005 gen_helper_memalign(cpu_env
, addr
, treg
, t0
, tsize
);
1007 tcg_temp_free_i32(t0
);
1008 tcg_temp_free_i32(treg
);
1009 tcg_temp_free_i32(tsize
);
1013 tcg_gen_mov_tl(env_res_addr
, addr
);
1014 tcg_gen_mov_i32(env_res_val
, v
);
1017 tcg_gen_mov_i32(cpu_R
[dc
->rd
], v
);
1019 tcg_temp_free_i32(v
);
1022 /* no support for AXI exclusive so always clear C */
1023 write_carryi(dc
, 0);
1026 tcg_temp_free(addr
);
1029 static void dec_store(DisasContext
*dc
)
1032 TCGLabel
*swx_skip
= NULL
;
1034 bool rev
= false, ex
= false, ea
= false;
1035 int mem_index
= cpu_mmu_index(&dc
->cpu
->env
, false);
1038 mop
= dc
->opcode
& 3;
1041 ea
= extract32(dc
->ir
, 7, 1);
1042 rev
= extract32(dc
->ir
, 9, 1);
1043 ex
= extract32(dc
->ir
, 10, 1);
1050 if (trap_illegal(dc
, size
> 4)) {
1054 trap_userspace(dc
, ea
);
1056 LOG_DIS("s%d%s%s%s%s\n", size
, dc
->type_b
? "i" : "", rev
? "r" : "",
1060 /* If we get a fault on a dslot, the jmpstate better be in sync. */
1062 /* SWX needs a temp_local. */
1063 addr
= ex
? tcg_temp_local_new() : tcg_temp_new();
1064 compute_ldst_addr(dc
, ea
, addr
);
1065 /* Extended addressing bypasses the MMU. */
1066 mem_index
= ea
? MMU_NOMMU_IDX
: mem_index
;
1071 /* swx does not throw unaligned access errors, so force alignment */
1072 tcg_gen_andi_tl(addr
, addr
, ~3);
1074 write_carryi(dc
, 1);
1075 swx_skip
= gen_new_label();
1076 tcg_gen_brcond_tl(TCG_COND_NE
, env_res_addr
, addr
, swx_skip
);
1078 /* Compare the value loaded at lwx with current contents of
1079 the reserved location.
1080 FIXME: This only works for system emulation where we can expect
1081 this compare and the following write to be atomic. For user
1082 emulation we need to add atomicity between threads. */
1083 tval
= tcg_temp_new_i32();
1084 tcg_gen_qemu_ld_i32(tval
, addr
, cpu_mmu_index(&dc
->cpu
->env
, false),
1086 tcg_gen_brcond_i32(TCG_COND_NE
, env_res_val
, tval
, swx_skip
);
1087 write_carryi(dc
, 0);
1088 tcg_temp_free_i32(tval
);
1091 if (rev
&& size
!= 4) {
1092 /* Endian reverse the address. t is addr. */
1096 tcg_gen_xori_tl(addr
, addr
, 3);
1103 /* Force addr into the temp. */
1104 tcg_gen_xori_tl(addr
, addr
, 2);
1107 cpu_abort(CPU(dc
->cpu
), "Invalid reverse size\n");
1111 tcg_gen_qemu_st_i32(cpu_R
[dc
->rd
], addr
, mem_index
, mop
);
1113 /* Verify alignment if needed. */
1114 if (dc
->cpu
->cfg
.unaligned_exceptions
&& size
> 1) {
1115 TCGv_i32 t1
= tcg_const_i32(1);
1116 TCGv_i32 treg
= tcg_const_i32(dc
->rd
);
1117 TCGv_i32 tsize
= tcg_const_i32(size
- 1);
1119 tcg_gen_movi_i64(cpu_SR
[SR_PC
], dc
->pc
);
1120 /* FIXME: if the alignment is wrong, we should restore the value
1121 * in memory. One possible way to achieve this is to probe
1122 * the MMU prior to the memaccess, thay way we could put
1123 * the alignment checks in between the probe and the mem
1126 gen_helper_memalign(cpu_env
, addr
, treg
, t1
, tsize
);
1128 tcg_temp_free_i32(t1
);
1129 tcg_temp_free_i32(treg
);
1130 tcg_temp_free_i32(tsize
);
1134 gen_set_label(swx_skip
);
1137 tcg_temp_free(addr
);
1140 static inline void eval_cc(DisasContext
*dc
, unsigned int cc
,
1141 TCGv_i32 d
, TCGv_i32 a
)
1143 static const int mb_to_tcg_cc
[] = {
1144 [CC_EQ
] = TCG_COND_EQ
,
1145 [CC_NE
] = TCG_COND_NE
,
1146 [CC_LT
] = TCG_COND_LT
,
1147 [CC_LE
] = TCG_COND_LE
,
1148 [CC_GE
] = TCG_COND_GE
,
1149 [CC_GT
] = TCG_COND_GT
,
1159 tcg_gen_setcondi_i32(mb_to_tcg_cc
[cc
], d
, a
, 0);
1162 cpu_abort(CPU(dc
->cpu
), "Unknown condition code %x.\n", cc
);
1167 static void eval_cond_jmp(DisasContext
*dc
, TCGv_i64 pc_true
, TCGv_i64 pc_false
)
1169 TCGv_i64 tmp_btaken
= tcg_temp_new_i64();
1170 TCGv_i64 tmp_zero
= tcg_const_i64(0);
1172 tcg_gen_extu_i32_i64(tmp_btaken
, env_btaken
);
1173 tcg_gen_movcond_i64(TCG_COND_NE
, cpu_SR
[SR_PC
],
1174 tmp_btaken
, tmp_zero
,
1177 tcg_temp_free_i64(tmp_btaken
);
1178 tcg_temp_free_i64(tmp_zero
);
1181 static void dec_setup_dslot(DisasContext
*dc
)
1183 TCGv_i32 tmp
= tcg_const_i32(dc
->type_b
&& (dc
->tb_flags
& IMM_FLAG
));
1185 dc
->delayed_branch
= 2;
1186 dc
->tb_flags
|= D_FLAG
;
1188 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUMBState
, bimm
));
1189 tcg_temp_free_i32(tmp
);
1192 static void dec_bcc(DisasContext
*dc
)
1197 cc
= EXTRACT_FIELD(dc
->ir
, 21, 23);
1198 dslot
= dc
->ir
& (1 << 25);
1199 LOG_DIS("bcc%s r%d %x\n", dslot
? "d" : "", dc
->ra
, dc
->imm
);
1201 dc
->delayed_branch
= 1;
1203 dec_setup_dslot(dc
);
1206 if (dec_alu_op_b_is_small_imm(dc
)) {
1207 int32_t offset
= (int32_t)((int16_t)dc
->imm
); /* sign-extend. */
1209 tcg_gen_movi_i64(env_btarget
, dc
->pc
+ offset
);
1210 dc
->jmp
= JMP_DIRECT_CC
;
1211 dc
->jmp_pc
= dc
->pc
+ offset
;
1213 dc
->jmp
= JMP_INDIRECT
;
1214 tcg_gen_extu_i32_i64(env_btarget
, *(dec_alu_op_b(dc
)));
1215 tcg_gen_addi_i64(env_btarget
, env_btarget
, dc
->pc
);
1216 tcg_gen_andi_i64(env_btarget
, env_btarget
, UINT32_MAX
);
1218 eval_cc(dc
, cc
, env_btaken
, cpu_R
[dc
->ra
]);
1221 static void dec_br(DisasContext
*dc
)
1223 unsigned int dslot
, link
, abs
, mbar
;
1225 dslot
= dc
->ir
& (1 << 20);
1226 abs
= dc
->ir
& (1 << 19);
1227 link
= dc
->ir
& (1 << 18);
1229 /* Memory barrier. */
1230 mbar
= (dc
->ir
>> 16) & 31;
1231 if (mbar
== 2 && dc
->imm
== 4) {
1232 /* mbar IMM & 16 decodes to sleep. */
1234 TCGv_i32 tmp_hlt
= tcg_const_i32(EXCP_HLT
);
1235 TCGv_i32 tmp_1
= tcg_const_i32(1);
1240 tcg_gen_st_i32(tmp_1
, cpu_env
,
1241 -offsetof(MicroBlazeCPU
, env
)
1242 +offsetof(CPUState
, halted
));
1243 tcg_gen_movi_i64(cpu_SR
[SR_PC
], dc
->pc
+ 4);
1244 gen_helper_raise_exception(cpu_env
, tmp_hlt
);
1245 tcg_temp_free_i32(tmp_hlt
);
1246 tcg_temp_free_i32(tmp_1
);
1249 LOG_DIS("mbar %d\n", dc
->rd
);
1251 dc
->cpustate_changed
= 1;
1255 LOG_DIS("br%s%s%s%s imm=%x\n",
1256 abs
? "a" : "", link
? "l" : "",
1257 dc
->type_b
? "i" : "", dslot
? "d" : "",
1260 dc
->delayed_branch
= 1;
1262 dec_setup_dslot(dc
);
1265 tcg_gen_movi_i32(cpu_R
[dc
->rd
], dc
->pc
);
1267 dc
->jmp
= JMP_INDIRECT
;
1269 tcg_gen_movi_i32(env_btaken
, 1);
1270 tcg_gen_extu_i32_i64(env_btarget
, *(dec_alu_op_b(dc
)));
1271 if (link
&& !dslot
) {
1272 if (!(dc
->tb_flags
& IMM_FLAG
) && (dc
->imm
== 8 || dc
->imm
== 0x18))
1273 t_gen_raise_exception(dc
, EXCP_BREAK
);
1275 if (trap_userspace(dc
, true)) {
1279 t_gen_raise_exception(dc
, EXCP_DEBUG
);
1283 if (dec_alu_op_b_is_small_imm(dc
)) {
1284 dc
->jmp
= JMP_DIRECT
;
1285 dc
->jmp_pc
= dc
->pc
+ (int32_t)((int16_t)dc
->imm
);
1287 tcg_gen_movi_i32(env_btaken
, 1);
1288 tcg_gen_extu_i32_i64(env_btarget
, *(dec_alu_op_b(dc
)));
1289 tcg_gen_addi_i64(env_btarget
, env_btarget
, dc
->pc
);
1290 tcg_gen_andi_i64(env_btarget
, env_btarget
, UINT32_MAX
);
1295 static inline void do_rti(DisasContext
*dc
)
1298 t0
= tcg_temp_new_i32();
1299 t1
= tcg_temp_new_i32();
1300 tcg_gen_extrl_i64_i32(t1
, cpu_SR
[SR_MSR
]);
1301 tcg_gen_shri_i32(t0
, t1
, 1);
1302 tcg_gen_ori_i32(t1
, t1
, MSR_IE
);
1303 tcg_gen_andi_i32(t0
, t0
, (MSR_VM
| MSR_UM
));
1305 tcg_gen_andi_i32(t1
, t1
, ~(MSR_VM
| MSR_UM
));
1306 tcg_gen_or_i32(t1
, t1
, t0
);
1308 tcg_temp_free_i32(t1
);
1309 tcg_temp_free_i32(t0
);
1310 dc
->tb_flags
&= ~DRTI_FLAG
;
1313 static inline void do_rtb(DisasContext
*dc
)
1316 t0
= tcg_temp_new_i32();
1317 t1
= tcg_temp_new_i32();
1318 tcg_gen_extrl_i64_i32(t1
, cpu_SR
[SR_MSR
]);
1319 tcg_gen_andi_i32(t1
, t1
, ~MSR_BIP
);
1320 tcg_gen_shri_i32(t0
, t1
, 1);
1321 tcg_gen_andi_i32(t0
, t0
, (MSR_VM
| MSR_UM
));
1323 tcg_gen_andi_i32(t1
, t1
, ~(MSR_VM
| MSR_UM
));
1324 tcg_gen_or_i32(t1
, t1
, t0
);
1326 tcg_temp_free_i32(t1
);
1327 tcg_temp_free_i32(t0
);
1328 dc
->tb_flags
&= ~DRTB_FLAG
;
1331 static inline void do_rte(DisasContext
*dc
)
1334 t0
= tcg_temp_new_i32();
1335 t1
= tcg_temp_new_i32();
1337 tcg_gen_extrl_i64_i32(t1
, cpu_SR
[SR_MSR
]);
1338 tcg_gen_ori_i32(t1
, t1
, MSR_EE
);
1339 tcg_gen_andi_i32(t1
, t1
, ~MSR_EIP
);
1340 tcg_gen_shri_i32(t0
, t1
, 1);
1341 tcg_gen_andi_i32(t0
, t0
, (MSR_VM
| MSR_UM
));
1343 tcg_gen_andi_i32(t1
, t1
, ~(MSR_VM
| MSR_UM
));
1344 tcg_gen_or_i32(t1
, t1
, t0
);
1346 tcg_temp_free_i32(t1
);
1347 tcg_temp_free_i32(t0
);
1348 dc
->tb_flags
&= ~DRTE_FLAG
;
1351 static void dec_rts(DisasContext
*dc
)
1353 unsigned int b_bit
, i_bit
, e_bit
;
1356 i_bit
= dc
->ir
& (1 << 21);
1357 b_bit
= dc
->ir
& (1 << 22);
1358 e_bit
= dc
->ir
& (1 << 23);
1360 if (trap_userspace(dc
, i_bit
|| b_bit
|| e_bit
)) {
1364 dec_setup_dslot(dc
);
1367 LOG_DIS("rtid ir=%x\n", dc
->ir
);
1368 dc
->tb_flags
|= DRTI_FLAG
;
1370 LOG_DIS("rtbd ir=%x\n", dc
->ir
);
1371 dc
->tb_flags
|= DRTB_FLAG
;
1373 LOG_DIS("rted ir=%x\n", dc
->ir
);
1374 dc
->tb_flags
|= DRTE_FLAG
;
1376 LOG_DIS("rts ir=%x\n", dc
->ir
);
1378 dc
->jmp
= JMP_INDIRECT
;
1379 tcg_gen_movi_i32(env_btaken
, 1);
1381 tmp64
= tcg_temp_new_i64();
1382 tcg_gen_extu_i32_i64(env_btarget
, *(dec_alu_op_b(dc
)));
1383 tcg_gen_extu_i32_i64(tmp64
, cpu_R
[dc
->ra
]);
1384 tcg_gen_add_i64(env_btarget
, env_btarget
, tmp64
);
1385 tcg_gen_andi_i64(env_btarget
, env_btarget
, UINT32_MAX
);
1386 tcg_temp_free_i64(tmp64
);
1389 static int dec_check_fpuv2(DisasContext
*dc
)
1391 if ((dc
->cpu
->cfg
.use_fpu
!= 2) && (dc
->tb_flags
& MSR_EE_FLAG
)) {
1392 tcg_gen_movi_i64(cpu_SR
[SR_ESR
], ESR_EC_FPU
);
1393 t_gen_raise_exception(dc
, EXCP_HW_EXCP
);
1395 return (dc
->cpu
->cfg
.use_fpu
== 2) ? PVR2_USE_FPU2_MASK
: 0;
1398 static void dec_fpu(DisasContext
*dc
)
1400 unsigned int fpu_insn
;
1402 if (trap_illegal(dc
, !dc
->cpu
->cfg
.use_fpu
)) {
1406 fpu_insn
= (dc
->ir
>> 7) & 7;
1410 gen_helper_fadd(cpu_R
[dc
->rd
], cpu_env
, cpu_R
[dc
->ra
],
1415 gen_helper_frsub(cpu_R
[dc
->rd
], cpu_env
, cpu_R
[dc
->ra
],
1420 gen_helper_fmul(cpu_R
[dc
->rd
], cpu_env
, cpu_R
[dc
->ra
],
1425 gen_helper_fdiv(cpu_R
[dc
->rd
], cpu_env
, cpu_R
[dc
->ra
],
1430 switch ((dc
->ir
>> 4) & 7) {
1432 gen_helper_fcmp_un(cpu_R
[dc
->rd
], cpu_env
,
1433 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
1436 gen_helper_fcmp_lt(cpu_R
[dc
->rd
], cpu_env
,
1437 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
1440 gen_helper_fcmp_eq(cpu_R
[dc
->rd
], cpu_env
,
1441 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
1444 gen_helper_fcmp_le(cpu_R
[dc
->rd
], cpu_env
,
1445 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
1448 gen_helper_fcmp_gt(cpu_R
[dc
->rd
], cpu_env
,
1449 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
1452 gen_helper_fcmp_ne(cpu_R
[dc
->rd
], cpu_env
,
1453 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
1456 gen_helper_fcmp_ge(cpu_R
[dc
->rd
], cpu_env
,
1457 cpu_R
[dc
->ra
], cpu_R
[dc
->rb
]);
1460 qemu_log_mask(LOG_UNIMP
,
1461 "unimplemented fcmp fpu_insn=%x pc=%x"
1463 fpu_insn
, dc
->pc
, dc
->opcode
);
1464 dc
->abort_at_next_insn
= 1;
1470 if (!dec_check_fpuv2(dc
)) {
1473 gen_helper_flt(cpu_R
[dc
->rd
], cpu_env
, cpu_R
[dc
->ra
]);
1477 if (!dec_check_fpuv2(dc
)) {
1480 gen_helper_fint(cpu_R
[dc
->rd
], cpu_env
, cpu_R
[dc
->ra
]);
1484 if (!dec_check_fpuv2(dc
)) {
1487 gen_helper_fsqrt(cpu_R
[dc
->rd
], cpu_env
, cpu_R
[dc
->ra
]);
1491 qemu_log_mask(LOG_UNIMP
, "unimplemented FPU insn fpu_insn=%x pc=%x"
1493 fpu_insn
, dc
->pc
, dc
->opcode
);
1494 dc
->abort_at_next_insn
= 1;
1499 static void dec_null(DisasContext
*dc
)
1501 if (trap_illegal(dc
, true)) {
1504 qemu_log_mask(LOG_GUEST_ERROR
, "unknown insn pc=%x opc=%x\n", dc
->pc
, dc
->opcode
);
1505 dc
->abort_at_next_insn
= 1;
1508 /* Insns connected to FSL or AXI stream attached devices. */
1509 static void dec_stream(DisasContext
*dc
)
1511 TCGv_i32 t_id
, t_ctrl
;
1514 LOG_DIS("%s%s imm=%x\n", dc
->rd
? "get" : "put",
1515 dc
->type_b
? "" : "d", dc
->imm
);
1517 if (trap_userspace(dc
, true)) {
1521 t_id
= tcg_temp_new_i32();
1523 tcg_gen_movi_i32(t_id
, dc
->imm
& 0xf);
1524 ctrl
= dc
->imm
>> 10;
1526 tcg_gen_andi_i32(t_id
, cpu_R
[dc
->rb
], 0xf);
1527 ctrl
= dc
->imm
>> 5;
1530 t_ctrl
= tcg_const_i32(ctrl
);
1533 gen_helper_put(t_id
, t_ctrl
, cpu_R
[dc
->ra
]);
1535 gen_helper_get(cpu_R
[dc
->rd
], t_id
, t_ctrl
);
1537 tcg_temp_free_i32(t_id
);
1538 tcg_temp_free_i32(t_ctrl
);
1541 static struct decoder_info
{
1546 void (*dec
)(DisasContext
*dc
);
1554 {DEC_BARREL
, dec_barrel
},
1556 {DEC_ST
, dec_store
},
1565 {DEC_STREAM
, dec_stream
},
1569 static inline void decode(DisasContext
*dc
, uint32_t ir
)
1574 LOG_DIS("%8.8x\t", dc
->ir
);
1577 trap_illegal(dc
, dc
->cpu
->cfg
.opcode_0_illegal
);
1578 /* Don't decode nop/zero instructions any further. */
1582 /* bit 2 seems to indicate insn type. */
1583 dc
->type_b
= ir
& (1 << 29);
1585 dc
->opcode
= EXTRACT_FIELD(ir
, 26, 31);
1586 dc
->rd
= EXTRACT_FIELD(ir
, 21, 25);
1587 dc
->ra
= EXTRACT_FIELD(ir
, 16, 20);
1588 dc
->rb
= EXTRACT_FIELD(ir
, 11, 15);
1589 dc
->imm
= EXTRACT_FIELD(ir
, 0, 15);
1591 /* Large switch for all insns. */
1592 for (i
= 0; i
< ARRAY_SIZE(decinfo
); i
++) {
1593 if ((dc
->opcode
& decinfo
[i
].mask
) == decinfo
[i
].bits
) {
1600 /* generate intermediate code for basic block 'tb'. */
1601 void gen_intermediate_code(CPUState
*cs
, TranslationBlock
*tb
, int max_insns
)
1603 CPUMBState
*env
= cs
->env_ptr
;
1604 MicroBlazeCPU
*cpu
= env_archcpu(env
);
1606 struct DisasContext ctx
;
1607 struct DisasContext
*dc
= &ctx
;
1608 uint32_t page_start
, org_flags
;
1615 org_flags
= dc
->synced_flags
= dc
->tb_flags
= tb
->flags
;
1617 dc
->is_jmp
= DISAS_NEXT
;
1619 dc
->delayed_branch
= !!(dc
->tb_flags
& D_FLAG
);
1620 if (dc
->delayed_branch
) {
1621 dc
->jmp
= JMP_INDIRECT
;
1624 dc
->singlestep_enabled
= cs
->singlestep_enabled
;
1625 dc
->cpustate_changed
= 0;
1626 dc
->abort_at_next_insn
= 0;
1629 cpu_abort(cs
, "Microblaze: unaligned PC=%x\n", pc_start
);
1632 page_start
= pc_start
& TARGET_PAGE_MASK
;
1638 tcg_gen_insn_start(dc
->pc
);
1642 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
1643 tcg_gen_movi_i64(cpu_SR
[SR_PC
], dc
->pc
);
1648 if (unlikely(cpu_breakpoint_test(cs
, dc
->pc
, BP_ANY
))) {
1649 t_gen_raise_exception(dc
, EXCP_DEBUG
);
1650 dc
->is_jmp
= DISAS_UPDATE
;
1651 /* The address covered by the breakpoint must be included in
1652 [tb->pc, tb->pc + tb->size) in order to for it to be
1653 properly cleared -- thus we increment the PC here so that
1654 the logic setting tb->size below does the right thing. */
1660 LOG_DIS("%8.8x:\t", dc
->pc
);
1662 if (num_insns
== max_insns
&& (tb_cflags(tb
) & CF_LAST_IO
)) {
1667 decode(dc
, cpu_ldl_code(env
, dc
->pc
));
1669 dc
->tb_flags
&= ~IMM_FLAG
;
1672 if (dc
->delayed_branch
) {
1673 dc
->delayed_branch
--;
1674 if (!dc
->delayed_branch
) {
1675 if (dc
->tb_flags
& DRTI_FLAG
)
1677 if (dc
->tb_flags
& DRTB_FLAG
)
1679 if (dc
->tb_flags
& DRTE_FLAG
)
1681 /* Clear the delay slot flag. */
1682 dc
->tb_flags
&= ~D_FLAG
;
1683 /* If it is a direct jump, try direct chaining. */
1684 if (dc
->jmp
== JMP_INDIRECT
) {
1685 TCGv_i64 tmp_pc
= tcg_const_i64(dc
->pc
);
1686 eval_cond_jmp(dc
, env_btarget
, tmp_pc
);
1687 tcg_temp_free_i64(tmp_pc
);
1689 dc
->is_jmp
= DISAS_JUMP
;
1690 } else if (dc
->jmp
== JMP_DIRECT
) {
1692 gen_goto_tb(dc
, 0, dc
->jmp_pc
);
1693 dc
->is_jmp
= DISAS_TB_JUMP
;
1694 } else if (dc
->jmp
== JMP_DIRECT_CC
) {
1695 TCGLabel
*l1
= gen_new_label();
1697 /* Conditional jmp. */
1698 tcg_gen_brcondi_i32(TCG_COND_NE
, env_btaken
, 0, l1
);
1699 gen_goto_tb(dc
, 1, dc
->pc
);
1701 gen_goto_tb(dc
, 0, dc
->jmp_pc
);
1703 dc
->is_jmp
= DISAS_TB_JUMP
;
1708 if (cs
->singlestep_enabled
) {
1711 } while (!dc
->is_jmp
&& !dc
->cpustate_changed
1712 && !tcg_op_buf_full()
1714 && (dc
->pc
- page_start
< TARGET_PAGE_SIZE
)
1715 && num_insns
< max_insns
);
1718 if (dc
->jmp
== JMP_DIRECT
|| dc
->jmp
== JMP_DIRECT_CC
) {
1719 if (dc
->tb_flags
& D_FLAG
) {
1720 dc
->is_jmp
= DISAS_UPDATE
;
1721 tcg_gen_movi_i64(cpu_SR
[SR_PC
], npc
);
1727 /* Force an update if the per-tb cpu state has changed. */
1728 if (dc
->is_jmp
== DISAS_NEXT
1729 && (dc
->cpustate_changed
|| org_flags
!= dc
->tb_flags
)) {
1730 dc
->is_jmp
= DISAS_UPDATE
;
1731 tcg_gen_movi_i64(cpu_SR
[SR_PC
], npc
);
1735 if (unlikely(cs
->singlestep_enabled
)) {
1736 TCGv_i32 tmp
= tcg_const_i32(EXCP_DEBUG
);
1738 if (dc
->is_jmp
!= DISAS_JUMP
) {
1739 tcg_gen_movi_i64(cpu_SR
[SR_PC
], npc
);
1741 gen_helper_raise_exception(cpu_env
, tmp
);
1742 tcg_temp_free_i32(tmp
);
1744 switch(dc
->is_jmp
) {
1746 gen_goto_tb(dc
, 1, npc
);
1751 /* indicate that the hash table must be used
1752 to find the next TB */
1753 tcg_gen_exit_tb(NULL
, 0);
1756 /* nothing more to generate */
1760 gen_tb_end(tb
, num_insns
);
1762 tb
->size
= dc
->pc
- pc_start
;
1763 tb
->icount
= num_insns
;
1767 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)
1768 && qemu_log_in_addr_range(pc_start
)) {
1769 FILE *logfile
= qemu_log_lock();
1770 qemu_log("--------------\n");
1771 log_target_disas(cs
, pc_start
, dc
->pc
- pc_start
);
1772 qemu_log_unlock(logfile
);
1776 assert(!dc
->abort_at_next_insn
);
1779 void mb_cpu_dump_state(CPUState
*cs
, FILE *f
, int flags
)
1781 MicroBlazeCPU
*cpu
= MICROBLAZE_CPU(cs
);
1782 CPUMBState
*env
= &cpu
->env
;
1789 qemu_fprintf(f
, "IN: PC=%" PRIx64
" %s\n",
1790 env
->sregs
[SR_PC
], lookup_symbol(env
->sregs
[SR_PC
]));
1791 qemu_fprintf(f
, "rmsr=%" PRIx64
" resr=%" PRIx64
" rear=%" PRIx64
" "
1792 "debug=%x imm=%x iflags=%x fsr=%" PRIx64
" "
1793 "rbtr=%" PRIx64
"\n",
1794 env
->sregs
[SR_MSR
], env
->sregs
[SR_ESR
], env
->sregs
[SR_EAR
],
1795 env
->debug
, env
->imm
, env
->iflags
, env
->sregs
[SR_FSR
],
1796 env
->sregs
[SR_BTR
]);
1797 qemu_fprintf(f
, "btaken=%d btarget=%" PRIx64
" mode=%s(saved=%s) "
1799 env
->btaken
, env
->btarget
,
1800 (env
->sregs
[SR_MSR
] & MSR_UM
) ? "user" : "kernel",
1801 (env
->sregs
[SR_MSR
] & MSR_UMS
) ? "user" : "kernel",
1802 (bool)(env
->sregs
[SR_MSR
] & MSR_EIP
),
1803 (bool)(env
->sregs
[SR_MSR
] & MSR_IE
));
1804 for (i
= 0; i
< 12; i
++) {
1805 qemu_fprintf(f
, "rpvr%2.2d=%8.8x ", i
, env
->pvr
.regs
[i
]);
1806 if ((i
+ 1) % 4 == 0) {
1807 qemu_fprintf(f
, "\n");
1811 /* Registers that aren't modeled are reported as 0 */
1812 qemu_fprintf(f
, "redr=%" PRIx64
" rpid=0 rzpr=0 rtlbx=0 rtlbsx=0 "
1813 "rtlblo=0 rtlbhi=0\n", env
->sregs
[SR_EDR
]);
1814 qemu_fprintf(f
, "slr=%x shr=%x\n", env
->slr
, env
->shr
);
1815 for (i
= 0; i
< 32; i
++) {
1816 qemu_fprintf(f
, "r%2.2d=%8.8x ", i
, env
->regs
[i
]);
1817 if ((i
+ 1) % 4 == 0)
1818 qemu_fprintf(f
, "\n");
1820 qemu_fprintf(f
, "\n\n");
1823 void mb_tcg_init(void)
1827 env_debug
= tcg_global_mem_new_i32(cpu_env
,
1828 offsetof(CPUMBState
, debug
),
1830 env_iflags
= tcg_global_mem_new_i32(cpu_env
,
1831 offsetof(CPUMBState
, iflags
),
1833 env_imm
= tcg_global_mem_new_i32(cpu_env
,
1834 offsetof(CPUMBState
, imm
),
1836 env_btarget
= tcg_global_mem_new_i64(cpu_env
,
1837 offsetof(CPUMBState
, btarget
),
1839 env_btaken
= tcg_global_mem_new_i32(cpu_env
,
1840 offsetof(CPUMBState
, btaken
),
1842 env_res_addr
= tcg_global_mem_new(cpu_env
,
1843 offsetof(CPUMBState
, res_addr
),
1845 env_res_val
= tcg_global_mem_new_i32(cpu_env
,
1846 offsetof(CPUMBState
, res_val
),
1848 for (i
= 0; i
< ARRAY_SIZE(cpu_R
); i
++) {
1849 cpu_R
[i
] = tcg_global_mem_new_i32(cpu_env
,
1850 offsetof(CPUMBState
, regs
[i
]),
1853 for (i
= 0; i
< ARRAY_SIZE(cpu_SR
); i
++) {
1854 cpu_SR
[i
] = tcg_global_mem_new_i64(cpu_env
,
1855 offsetof(CPUMBState
, sregs
[i
]),
1856 special_regnames
[i
]);
1860 void restore_state_to_opc(CPUMBState
*env
, TranslationBlock
*tb
,
1863 env
->sregs
[SR_PC
] = data
[0];