Lines Matching +full:dc +full:- +full:dc +full:- +full:mode
5 * Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
23 #include "exec/exec-all.h"
25 #include "tcg/tcg-op.h"
26 #include "exec/helper-proto.h"
27 #include "exec/helper-gen.h"
29 #include "exec/translation-block.h"
30 #include "qemu/qemu-print.h"
35 #include "exec/helper-info.c.inc"
39 (((src) >> start) & ((1 << (end - start + 1)) - 1))
78 /* Immediate branch-taken destination, or -1 for indirect. */
82 static int typeb_imm(DisasContext *dc, int x) in typeb_imm() argument
84 if (dc->tb_flags & IMM_FLAG) { in typeb_imm()
85 return deposit32(dc->ext_imm, 0, 16, x); in typeb_imm()
90 /* Include the auto-generated decoder. */
91 #include "decode-insns.c.inc"
93 static void t_sync_flags(DisasContext *dc) in t_sync_flags() argument
96 if ((dc->tb_flags ^ dc->base.tb->flags) & IFLAGS_TB_MASK) { in t_sync_flags()
97 tcg_gen_movi_i32(cpu_iflags, dc->tb_flags & IFLAGS_TB_MASK); in t_sync_flags()
101 static void gen_raise_exception(DisasContext *dc, uint32_t index) in gen_raise_exception() argument
104 dc->base.is_jmp = DISAS_NORETURN; in gen_raise_exception()
107 static void gen_raise_exception_sync(DisasContext *dc, uint32_t index) in gen_raise_exception_sync() argument
109 t_sync_flags(dc); in gen_raise_exception_sync()
110 tcg_gen_movi_i32(cpu_pc, dc->base.pc_next); in gen_raise_exception_sync()
111 gen_raise_exception(dc, index); in gen_raise_exception_sync()
114 static void gen_raise_hw_excp(DisasContext *dc, uint32_t esr_ec) in gen_raise_hw_excp() argument
119 gen_raise_exception_sync(dc, EXCP_HW_EXCP); in gen_raise_hw_excp()
122 static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) in gen_goto_tb() argument
124 if (translator_use_goto_tb(&dc->base, dest)) { in gen_goto_tb()
127 tcg_gen_exit_tb(dc->base.tb, n); in gen_goto_tb()
132 dc->base.is_jmp = DISAS_NORETURN; in gen_goto_tb()
139 static bool trap_illegal(DisasContext *dc, bool cond) in trap_illegal() argument
141 if (cond && (dc->tb_flags & MSR_EE) in trap_illegal()
142 && dc->cfg->illegal_opcode_exception) { in trap_illegal()
143 gen_raise_hw_excp(dc, ESR_EC_ILLEGAL_OP); in trap_illegal()
152 static bool trap_userspace(DisasContext *dc, bool cond) in trap_userspace() argument
154 bool cond_user = cond && dc->mem_index == MMU_USER_IDX; in trap_userspace()
156 if (cond_user && (dc->tb_flags & MSR_EE)) { in trap_userspace()
157 gen_raise_hw_excp(dc, ESR_EC_PRIVINSN); in trap_userspace()
166 static bool invalid_delay_slot(DisasContext *dc, const char *insn_type) in invalid_delay_slot() argument
168 if (dc->tb_flags & D_FLAG) { in invalid_delay_slot()
171 insn_type, (uint32_t)dc->base.pc_next); in invalid_delay_slot()
177 static TCGv_i32 reg_for_read(DisasContext *dc, int reg) in reg_for_read() argument
182 if (!dc->r0_set) { in reg_for_read()
183 if (dc->r0 == NULL) { in reg_for_read()
184 dc->r0 = tcg_temp_new_i32(); in reg_for_read()
186 tcg_gen_movi_i32(dc->r0, 0); in reg_for_read()
187 dc->r0_set = true; in reg_for_read()
189 return dc->r0; in reg_for_read()
192 static TCGv_i32 reg_for_write(DisasContext *dc, int reg) in reg_for_write() argument
197 if (dc->r0 == NULL) { in reg_for_write()
198 dc->r0 = tcg_temp_new_i32(); in reg_for_write()
200 return dc->r0; in reg_for_write()
203 static bool do_typea(DisasContext *dc, arg_typea *arg, bool side_effects, in do_typea() argument
208 if (arg->rd == 0 && !side_effects) { in do_typea()
212 rd = reg_for_write(dc, arg->rd); in do_typea()
213 ra = reg_for_read(dc, arg->ra); in do_typea()
214 rb = reg_for_read(dc, arg->rb); in do_typea()
219 static bool do_typea0(DisasContext *dc, arg_typea0 *arg, bool side_effects, in do_typea0() argument
224 if (arg->rd == 0 && !side_effects) { in do_typea0()
228 rd = reg_for_write(dc, arg->rd); in do_typea0()
229 ra = reg_for_read(dc, arg->ra); in do_typea0()
234 static bool do_typeb_imm(DisasContext *dc, arg_typeb *arg, bool side_effects, in do_typeb_imm() argument
239 if (arg->rd == 0 && !side_effects) { in do_typeb_imm()
243 rd = reg_for_write(dc, arg->rd); in do_typeb_imm()
244 ra = reg_for_read(dc, arg->ra); in do_typeb_imm()
245 fni(rd, ra, arg->imm); in do_typeb_imm()
249 static bool do_typeb_val(DisasContext *dc, arg_typeb *arg, bool side_effects, in do_typeb_val() argument
254 if (arg->rd == 0 && !side_effects) { in do_typeb_val()
258 rd = reg_for_write(dc, arg->rd); in do_typeb_val()
259 ra = reg_for_read(dc, arg->ra); in do_typeb_val()
260 imm = tcg_constant_i32(arg->imm); in do_typeb_val()
267 static bool trans_##NAME(DisasContext *dc, arg_typea *a) \
268 { return do_typea(dc, a, SE, FN); }
271 static bool trans_##NAME(DisasContext *dc, arg_typea *a) \
272 { return dc->cfg->CFG && do_typea(dc, a, SE, FN); }
275 static bool trans_##NAME(DisasContext *dc, arg_typea0 *a) \
276 { return do_typea0(dc, a, SE, FN); }
279 static bool trans_##NAME(DisasContext *dc, arg_typea0 *a) \
280 { return dc->cfg->CFG && do_typea0(dc, a, SE, FN); }
283 static bool trans_##NAME(DisasContext *dc, arg_typeb *a) \
284 { return do_typeb_imm(dc, a, SE, FNI); }
287 static bool trans_##NAME(DisasContext *dc, arg_typeb *a) \
288 { return dc->cfg->CFG && do_typeb_imm(dc, a, SE, FNI); }
291 static bool trans_##NAME(DisasContext *dc, arg_typeb *a) \
292 { return do_typeb_val(dc, a, SE, FN); }
388 int width = imm_w - imm_s + 1; in gen_bsifi()
484 static bool trans_imm(DisasContext *dc, arg_imm *arg) in DO_TYPEA_CFG()
486 if (invalid_delay_slot(dc, "imm")) { in DO_TYPEA_CFG()
489 dc->ext_imm = arg->imm << 16; in DO_TYPEA_CFG()
490 tcg_gen_movi_i32(cpu_imm, dc->ext_imm); in DO_TYPEA_CFG()
491 dc->tb_flags_to_set = IMM_FLAG; in DO_TYPEA_CFG()
616 static bool trans_wdic(DisasContext *dc, arg_wdic *a) in DO_TYPEA0()
618 /* Cache operations are nops: only check for supervisor mode. */ in DO_TYPEA0()
619 trap_userspace(dc, true); in DO_TYPEA0()
626 static TCGv compute_ldst_addr_typea(DisasContext *dc, int ra, int rb) in DO_TYPEA()
643 if ((ra == 1 || rb == 1) && dc->cfg->stackprot) { in DO_TYPEA()
649 static TCGv compute_ldst_addr_typeb(DisasContext *dc, int ra, int imm) in compute_ldst_addr_typeb() argument
662 if (ra == 1 && dc->cfg->stackprot) { in compute_ldst_addr_typeb()
669 static TCGv compute_ldst_addr_ea(DisasContext *dc, int ra, int rb) in compute_ldst_addr_ea() argument
671 int addr_size = dc->cfg->addr_size; in compute_ldst_addr_ea()
697 static void record_unaligned_ess(DisasContext *dc, int rd, in record_unaligned_ess() argument
700 uint32_t iflags = tcg_get_insn_start_param(dc->base.insn_start, 1); in record_unaligned_ess()
707 tcg_set_insn_start_param(dc->base.insn_start, 1, iflags); in record_unaligned_ess()
711 static inline MemOp mo_endian(DisasContext *dc) in mo_endian() argument
713 return dc->cfg->endi ? MO_LE : MO_BE; in mo_endian()
716 static bool do_load(DisasContext *dc, int rd, TCGv addr, MemOp mop, in do_load() argument
721 mop |= mo_endian(dc); in do_load()
734 tcg_gen_xori_tl(addr, addr, 3 - size); in do_load()
739 * For system mode, enforce alignment if the cpu configuration in do_load()
740 * requires it. For user-mode, the Linux kernel will have fixed up in do_load()
745 (dc->tb_flags & MSR_EE) && in do_load()
746 dc->cfg->unaligned_exceptions) { in do_load()
747 record_unaligned_ess(dc, rd, size, false); in do_load()
752 tcg_gen_qemu_ld_i32(reg_for_write(dc, rd), addr, mem_index, mop); in do_load()
756 static bool trans_lbu(DisasContext *dc, arg_typea *arg) in trans_lbu() argument
758 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); in trans_lbu()
759 return do_load(dc, arg->rd, addr, MO_UB, dc->mem_index, false); in trans_lbu()
762 static bool trans_lbur(DisasContext *dc, arg_typea *arg) in trans_lbur() argument
764 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); in trans_lbur()
765 return do_load(dc, arg->rd, addr, MO_UB, dc->mem_index, true); in trans_lbur()
768 static bool trans_lbuea(DisasContext *dc, arg_typea *arg) in trans_lbuea() argument
770 if (trap_userspace(dc, true)) { in trans_lbuea()
776 TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); in trans_lbuea()
777 return do_load(dc, arg->rd, addr, MO_UB, MMU_NOMMU_IDX, false); in trans_lbuea()
781 static bool trans_lbui(DisasContext *dc, arg_typeb *arg) in trans_lbui() argument
783 TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm); in trans_lbui()
784 return do_load(dc, arg->rd, addr, MO_UB, dc->mem_index, false); in trans_lbui()
787 static bool trans_lhu(DisasContext *dc, arg_typea *arg) in trans_lhu() argument
789 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); in trans_lhu()
790 return do_load(dc, arg->rd, addr, MO_UW, dc->mem_index, false); in trans_lhu()
793 static bool trans_lhur(DisasContext *dc, arg_typea *arg) in trans_lhur() argument
795 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); in trans_lhur()
796 return do_load(dc, arg->rd, addr, MO_UW, dc->mem_index, true); in trans_lhur()
799 static bool trans_lhuea(DisasContext *dc, arg_typea *arg) in trans_lhuea() argument
801 if (trap_userspace(dc, true)) { in trans_lhuea()
807 TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); in trans_lhuea()
808 return do_load(dc, arg->rd, addr, MO_UW, MMU_NOMMU_IDX, false); in trans_lhuea()
812 static bool trans_lhui(DisasContext *dc, arg_typeb *arg) in trans_lhui() argument
814 TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm); in trans_lhui()
815 return do_load(dc, arg->rd, addr, MO_UW, dc->mem_index, false); in trans_lhui()
818 static bool trans_lw(DisasContext *dc, arg_typea *arg) in trans_lw() argument
820 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); in trans_lw()
821 return do_load(dc, arg->rd, addr, MO_UL, dc->mem_index, false); in trans_lw()
824 static bool trans_lwr(DisasContext *dc, arg_typea *arg) in trans_lwr() argument
826 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); in trans_lwr()
827 return do_load(dc, arg->rd, addr, MO_UL, dc->mem_index, true); in trans_lwr()
830 static bool trans_lwea(DisasContext *dc, arg_typea *arg) in trans_lwea() argument
832 if (trap_userspace(dc, true)) { in trans_lwea()
838 TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); in trans_lwea()
839 return do_load(dc, arg->rd, addr, MO_UL, MMU_NOMMU_IDX, false); in trans_lwea()
843 static bool trans_lwi(DisasContext *dc, arg_typeb *arg) in trans_lwi() argument
845 TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm); in trans_lwi()
846 return do_load(dc, arg->rd, addr, MO_UL, dc->mem_index, false); in trans_lwi()
849 static bool trans_lwx(DisasContext *dc, arg_typea *arg) in trans_lwx() argument
851 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); in trans_lwx()
856 tcg_gen_qemu_ld_i32(cpu_res_val, addr, dc->mem_index, in trans_lwx()
857 mo_endian(dc) | MO_UL); in trans_lwx()
860 if (arg->rd) { in trans_lwx()
861 tcg_gen_mov_i32(cpu_R[arg->rd], cpu_res_val); in trans_lwx()
869 static bool do_store(DisasContext *dc, int rd, TCGv addr, MemOp mop, in do_store() argument
874 mop |= mo_endian(dc); in do_store()
887 tcg_gen_xori_tl(addr, addr, 3 - size); in do_store()
892 * For system mode, enforce alignment if the cpu configuration in do_store()
893 * requires it. For user-mode, the Linux kernel will have fixed up in do_store()
898 (dc->tb_flags & MSR_EE) && in do_store()
899 dc->cfg->unaligned_exceptions) { in do_store()
900 record_unaligned_ess(dc, rd, size, true); in do_store()
905 tcg_gen_qemu_st_i32(reg_for_read(dc, rd), addr, mem_index, mop); in do_store()
909 static bool trans_sb(DisasContext *dc, arg_typea *arg) in trans_sb() argument
911 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); in trans_sb()
912 return do_store(dc, arg->rd, addr, MO_UB, dc->mem_index, false); in trans_sb()
915 static bool trans_sbr(DisasContext *dc, arg_typea *arg) in trans_sbr() argument
917 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); in trans_sbr()
918 return do_store(dc, arg->rd, addr, MO_UB, dc->mem_index, true); in trans_sbr()
921 static bool trans_sbea(DisasContext *dc, arg_typea *arg) in trans_sbea() argument
923 if (trap_userspace(dc, true)) { in trans_sbea()
929 TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); in trans_sbea()
930 return do_store(dc, arg->rd, addr, MO_UB, MMU_NOMMU_IDX, false); in trans_sbea()
934 static bool trans_sbi(DisasContext *dc, arg_typeb *arg) in trans_sbi() argument
936 TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm); in trans_sbi()
937 return do_store(dc, arg->rd, addr, MO_UB, dc->mem_index, false); in trans_sbi()
940 static bool trans_sh(DisasContext *dc, arg_typea *arg) in trans_sh() argument
942 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); in trans_sh()
943 return do_store(dc, arg->rd, addr, MO_UW, dc->mem_index, false); in trans_sh()
946 static bool trans_shr(DisasContext *dc, arg_typea *arg) in trans_shr() argument
948 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); in trans_shr()
949 return do_store(dc, arg->rd, addr, MO_UW, dc->mem_index, true); in trans_shr()
952 static bool trans_shea(DisasContext *dc, arg_typea *arg) in trans_shea() argument
954 if (trap_userspace(dc, true)) { in trans_shea()
960 TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); in trans_shea()
961 return do_store(dc, arg->rd, addr, MO_UW, MMU_NOMMU_IDX, false); in trans_shea()
965 static bool trans_shi(DisasContext *dc, arg_typeb *arg) in trans_shi() argument
967 TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm); in trans_shi()
968 return do_store(dc, arg->rd, addr, MO_UW, dc->mem_index, false); in trans_shi()
971 static bool trans_sw(DisasContext *dc, arg_typea *arg) in trans_sw() argument
973 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); in trans_sw()
974 return do_store(dc, arg->rd, addr, MO_UL, dc->mem_index, false); in trans_sw()
977 static bool trans_swr(DisasContext *dc, arg_typea *arg) in trans_swr() argument
979 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); in trans_swr()
980 return do_store(dc, arg->rd, addr, MO_UL, dc->mem_index, true); in trans_swr()
983 static bool trans_swea(DisasContext *dc, arg_typea *arg) in trans_swea() argument
985 if (trap_userspace(dc, true)) { in trans_swea()
991 TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); in trans_swea()
992 return do_store(dc, arg->rd, addr, MO_UL, MMU_NOMMU_IDX, false); in trans_swea()
996 static bool trans_swi(DisasContext *dc, arg_typeb *arg) in trans_swi() argument
998 TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm); in trans_swi()
999 return do_store(dc, arg->rd, addr, MO_UL, dc->mem_index, false); in trans_swi()
1002 static bool trans_swx(DisasContext *dc, arg_typea *arg) in trans_swx() argument
1004 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); in trans_swx()
1027 reg_for_write(dc, arg->rd), in trans_swx()
1028 dc->mem_index, mo_endian(dc) | MO_UL); in trans_swx()
1046 tcg_gen_movi_tl(cpu_res_addr, -1); in trans_swx()
1050 static void setup_dslot(DisasContext *dc, bool type_b) in setup_dslot() argument
1052 dc->tb_flags_to_set |= D_FLAG; in setup_dslot()
1053 if (type_b && (dc->tb_flags & IMM_FLAG)) { in setup_dslot()
1054 dc->tb_flags_to_set |= BIMM_FLAG; in setup_dslot()
1058 static bool do_branch(DisasContext *dc, int dest_rb, int dest_imm, in do_branch() argument
1063 if (invalid_delay_slot(dc, "branch")) { in do_branch()
1067 setup_dslot(dc, dest_rb < 0); in do_branch()
1071 tcg_gen_movi_i32(cpu_R[link], dc->base.pc_next); in do_branch()
1075 add_pc = abs ? 0 : dc->base.pc_next; in do_branch()
1077 dc->jmp_dest = -1; in do_branch()
1080 dc->jmp_dest = add_pc + dest_imm; in do_branch()
1081 tcg_gen_movi_i32(cpu_btarget, dc->jmp_dest); in do_branch()
1083 dc->jmp_cond = TCG_COND_ALWAYS; in do_branch()
1088 static bool trans_##NAME(DisasContext *dc, arg_typea_br *arg) \
1089 { return do_branch(dc, arg->rb, 0, DELAY, ABS, LINK ? arg->rd : 0); } \
1090 static bool trans_##NAMEI(DisasContext *dc, arg_typeb_br *arg) \
1091 { return do_branch(dc, -1, arg->imm, DELAY, ABS, LINK ? arg->rd : 0); }
1100 static bool do_bcc(DisasContext *dc, int dest_rb, int dest_imm, in DO_BR()
1105 if (invalid_delay_slot(dc, "bcc")) { in DO_BR()
1109 setup_dslot(dc, dest_rb < 0); in DO_BR()
1112 dc->jmp_cond = cond; in DO_BR()
1115 tcg_gen_mov_i32(cpu_bvalue, reg_for_read(dc, ra)); in DO_BR()
1119 dc->jmp_dest = -1; in DO_BR()
1120 tcg_gen_addi_i32(cpu_btarget, cpu_R[dest_rb], dc->base.pc_next); in DO_BR()
1122 dc->jmp_dest = dc->base.pc_next + dest_imm; in DO_BR()
1123 tcg_gen_movi_i32(cpu_btarget, dc->jmp_dest); in DO_BR()
1128 next = tcg_constant_i32(dc->base.pc_next + (delay + 1) * 4); in DO_BR()
1129 tcg_gen_movcond_i32(dc->jmp_cond, cpu_btarget, in DO_BR()
1130 reg_for_read(dc, ra), zero, in DO_BR()
1137 static bool trans_##NAME(DisasContext *dc, arg_typea_bc *arg) \
1138 { return do_bcc(dc, arg->rb, 0, COND, arg->ra, false); } \
1139 static bool trans_##NAME##d(DisasContext *dc, arg_typea_bc *arg) \
1140 { return do_bcc(dc, arg->rb, 0, COND, arg->ra, true); } \
1141 static bool trans_##NAME##i(DisasContext *dc, arg_typeb_bc *arg) \
1142 { return do_bcc(dc, -1, arg->imm, COND, arg->ra, false); } \
1143 static bool trans_##NAME##id(DisasContext *dc, arg_typeb_bc *arg) \
1144 { return do_bcc(dc, -1, arg->imm, COND, arg->ra, true); }
1153 static bool trans_brk(DisasContext *dc, arg_typea_br *arg) in DO_BCC()
1155 if (trap_userspace(dc, true)) { in DO_BCC()
1158 if (invalid_delay_slot(dc, "brk")) { in DO_BCC()
1162 tcg_gen_mov_i32(cpu_pc, reg_for_read(dc, arg->rb)); in DO_BCC()
1163 if (arg->rd) { in DO_BCC()
1164 tcg_gen_movi_i32(cpu_R[arg->rd], dc->base.pc_next); in DO_BCC()
1167 tcg_gen_movi_tl(cpu_res_addr, -1); in DO_BCC()
1169 dc->base.is_jmp = DISAS_EXIT; in DO_BCC()
1173 static bool trans_brki(DisasContext *dc, arg_typeb_br *arg) in trans_brki() argument
1175 uint32_t imm = arg->imm; in trans_brki()
1177 if (trap_userspace(dc, imm != 0x8 && imm != 0x18)) { in trans_brki()
1180 if (invalid_delay_slot(dc, "brki")) { in trans_brki()
1185 if (arg->rd) { in trans_brki()
1186 tcg_gen_movi_i32(cpu_R[arg->rd], dc->base.pc_next); in trans_brki()
1188 tcg_gen_movi_tl(cpu_res_addr, -1); in trans_brki()
1193 gen_raise_exception_sync(dc, EXCP_SYSCALL); in trans_brki()
1196 gen_raise_exception_sync(dc, EXCP_DEBUG); in trans_brki()
1209 msr_to_set |= (dc->tb_flags & (MSR_UM | MSR_VM)) << 1; in trans_brki()
1214 dc->base.is_jmp = DISAS_EXIT; in trans_brki()
1220 static bool trans_mbar(DisasContext *dc, arg_mbar *arg) in trans_mbar() argument
1222 int mbar_imm = arg->imm; in trans_mbar()
1225 if (invalid_delay_slot(dc, "mbar")) { in trans_mbar()
1236 if (trap_userspace(dc, true)) { in trans_mbar()
1241 t_sync_flags(dc); in trans_mbar()
1244 -offsetof(MicroBlazeCPU, env) in trans_mbar()
1247 tcg_gen_movi_i32(cpu_pc, dc->base.pc_next + 4); in trans_mbar()
1249 gen_raise_exception(dc, EXCP_HLT); in trans_mbar()
1254 * and we need to end the TB so that we recognize self-modified in trans_mbar()
1263 dc->base.is_jmp = DISAS_EXIT_NEXT; in trans_mbar()
1267 static bool do_rts(DisasContext *dc, arg_typeb_bc *arg, int to_set) in do_rts() argument
1269 if (trap_userspace(dc, to_set)) { in do_rts()
1272 if (invalid_delay_slot(dc, "rts")) { in do_rts()
1276 dc->tb_flags_to_set |= to_set; in do_rts()
1277 setup_dslot(dc, true); in do_rts()
1279 dc->jmp_cond = TCG_COND_ALWAYS; in do_rts()
1280 dc->jmp_dest = -1; in do_rts()
1281 tcg_gen_addi_i32(cpu_btarget, reg_for_read(dc, arg->ra), arg->imm); in do_rts()
1286 static bool trans_##NAME(DisasContext *dc, arg_typeb_bc *arg) \
1287 { return do_rts(dc, arg, IFLAG); }
1294 static bool trans_zero(DisasContext *dc, arg_zero *arg) in DO_RTS()
1297 if (dc->cfg->opcode_0_illegal) { in DO_RTS()
1298 trap_illegal(dc, true); in DO_RTS()
1308 static void msr_read(DisasContext *dc, TCGv_i32 d) in msr_read() argument
1318 static bool do_msrclrset(DisasContext *dc, arg_type_msr *arg, bool set) in do_msrclrset() argument
1320 uint32_t imm = arg->imm; in do_msrclrset()
1322 if (trap_userspace(dc, imm != MSR_C)) { in do_msrclrset()
1326 if (arg->rd) { in do_msrclrset()
1327 msr_read(dc, cpu_R[arg->rd]); in do_msrclrset()
1350 dc->base.is_jmp = DISAS_EXIT_NEXT; in do_msrclrset()
1355 static bool trans_msrclr(DisasContext *dc, arg_type_msr *arg) in trans_msrclr() argument
1357 return do_msrclrset(dc, arg, false); in trans_msrclr()
1360 static bool trans_msrset(DisasContext *dc, arg_type_msr *arg) in trans_msrset() argument
1362 return do_msrclrset(dc, arg, true); in trans_msrset()
1365 static bool trans_mts(DisasContext *dc, arg_mts *arg) in trans_mts() argument
1367 if (trap_userspace(dc, true)) { in trans_mts()
1374 if (arg->e && arg->rs != 0x1003) { in trans_mts()
1376 "Invalid extended mts reg 0x%x\n", arg->rs); in trans_mts()
1380 TCGv_i32 src = reg_for_read(dc, arg->ra); in trans_mts()
1381 switch (arg->rs) { in trans_mts()
1408 TCGv_i32 tmp_ext = tcg_constant_i32(arg->e); in trans_mts()
1409 TCGv_i32 tmp_reg = tcg_constant_i32(arg->rs & 7); in trans_mts()
1416 qemu_log_mask(LOG_GUEST_ERROR, "Invalid mts reg 0x%x\n", arg->rs); in trans_mts()
1419 dc->base.is_jmp = DISAS_EXIT_NEXT; in trans_mts()
1424 static bool trans_mfs(DisasContext *dc, arg_mfs *arg) in trans_mfs() argument
1426 TCGv_i32 dest = reg_for_write(dc, arg->rd); in trans_mfs()
1428 if (arg->e) { in trans_mfs()
1429 switch (arg->rs) { in trans_mfs()
1443 /* High bits of PVR6-9 not implemented. */ in trans_mfs()
1448 "Invalid extended mfs reg 0x%x\n", arg->rs); in trans_mfs()
1453 switch (arg->rs) { in trans_mfs()
1455 tcg_gen_movi_i32(dest, dc->base.pc_next); in trans_mfs()
1458 msr_read(dc, dest); in trans_mfs()
1494 TCGv_i32 tmp_ext = tcg_constant_i32(arg->e); in trans_mfs()
1495 TCGv_i32 tmp_reg = tcg_constant_i32(arg->rs & 7); in trans_mfs()
1504 offsetof(MicroBlazeCPU, cfg.pvr_regs[arg->rs - 0x2000]) in trans_mfs()
1505 - offsetof(MicroBlazeCPU, env)); in trans_mfs()
1508 qemu_log_mask(LOG_GUEST_ERROR, "Invalid mfs reg 0x%x\n", arg->rs); in trans_mfs()
1514 static void do_rti(DisasContext *dc) in do_rti() argument
1525 static void do_rtb(DisasContext *dc) in do_rtb() argument
1535 static void do_rte(DisasContext *dc) in do_rte() argument
1547 static bool do_get(DisasContext *dc, int rd, int rb, int imm, int ctrl) in do_get() argument
1551 if (trap_userspace(dc, true)) { in do_get()
1563 gen_helper_get(reg_for_write(dc, rd), t_id, t_ctrl); in do_get()
1567 static bool trans_get(DisasContext *dc, arg_get *arg) in trans_get() argument
1569 return do_get(dc, arg->rd, 0, arg->imm, arg->ctrl); in trans_get()
1572 static bool trans_getd(DisasContext *dc, arg_getd *arg) in trans_getd() argument
1574 return do_get(dc, arg->rd, arg->rb, 0, arg->ctrl); in trans_getd()
1577 static bool do_put(DisasContext *dc, int ra, int rb, int imm, int ctrl) in do_put() argument
1581 if (trap_userspace(dc, true)) { in do_put()
1593 gen_helper_put(t_id, t_ctrl, reg_for_read(dc, ra)); in do_put()
1597 static bool trans_put(DisasContext *dc, arg_put *arg) in trans_put() argument
1599 return do_put(dc, arg->ra, 0, arg->imm, arg->ctrl); in trans_put()
1602 static bool trans_putd(DisasContext *dc, arg_putd *arg) in trans_putd() argument
1604 return do_put(dc, arg->ra, arg->rb, 0, arg->ctrl); in trans_putd()
1609 DisasContext *dc = container_of(dcb, DisasContext, base); in mb_tr_init_disas_context() local
1613 dc->cfg = &cpu->cfg; in mb_tr_init_disas_context()
1614 dc->tb_flags = dc->base.tb->flags; in mb_tr_init_disas_context()
1615 dc->ext_imm = dc->base.tb->cs_base; in mb_tr_init_disas_context()
1616 dc->r0 = NULL; in mb_tr_init_disas_context()
1617 dc->r0_set = false; in mb_tr_init_disas_context()
1618 dc->mem_index = cpu_mmu_index(cs, false); in mb_tr_init_disas_context()
1619 dc->jmp_cond = dc->tb_flags & D_FLAG ? TCG_COND_ALWAYS : TCG_COND_NEVER; in mb_tr_init_disas_context()
1620 dc->jmp_dest = -1; in mb_tr_init_disas_context()
1622 bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; in mb_tr_init_disas_context()
1623 dc->base.max_insns = MIN(dc->base.max_insns, bound); in mb_tr_init_disas_context()
1632 DisasContext *dc = container_of(dcb, DisasContext, base); in mb_tr_insn_start() local
1634 tcg_gen_insn_start(dc->base.pc_next, dc->tb_flags & ~MSR_TB_MASK); in mb_tr_insn_start()
1639 DisasContext *dc = container_of(dcb, DisasContext, base); in mb_tr_translate_insn() local
1643 if (dc->base.pc_next & 3) { in mb_tr_translate_insn()
1645 (uint32_t)dc->base.pc_next); in mb_tr_translate_insn()
1648 dc->tb_flags_to_set = 0; in mb_tr_translate_insn()
1650 ir = translator_ldl_swap(cpu_env(cs), &dc->base, dc->base.pc_next, in mb_tr_translate_insn()
1652 if (!decode(dc, ir)) { in mb_tr_translate_insn()
1653 trap_illegal(dc, true); in mb_tr_translate_insn()
1656 if (dc->r0) { in mb_tr_translate_insn()
1657 dc->r0 = NULL; in mb_tr_translate_insn()
1658 dc->r0_set = false; in mb_tr_translate_insn()
1662 if ((dc->tb_flags & ~dc->tb_flags_to_set) & IMM_FLAG) { in mb_tr_translate_insn()
1666 dc->tb_flags &= ~(IMM_FLAG | BIMM_FLAG | D_FLAG); in mb_tr_translate_insn()
1667 dc->tb_flags |= dc->tb_flags_to_set; in mb_tr_translate_insn()
1668 dc->base.pc_next += 4; in mb_tr_translate_insn()
1670 if (dc->jmp_cond != TCG_COND_NEVER && !(dc->tb_flags & D_FLAG)) { in mb_tr_translate_insn()
1672 * Finish any return-from branch. in mb_tr_translate_insn()
1674 uint32_t rt_ibe = dc->tb_flags & (DRTI_FLAG | DRTB_FLAG | DRTE_FLAG); in mb_tr_translate_insn()
1676 dc->tb_flags &= ~(DRTI_FLAG | DRTB_FLAG | DRTE_FLAG); in mb_tr_translate_insn()
1678 do_rti(dc); in mb_tr_translate_insn()
1680 do_rtb(dc); in mb_tr_translate_insn()
1682 do_rte(dc); in mb_tr_translate_insn()
1687 switch (dc->base.is_jmp) { in mb_tr_translate_insn()
1697 * However, the return-from-exception type insns should in mb_tr_translate_insn()
1700 dc->base.is_jmp = (rt_ibe ? DISAS_EXIT_JUMP : DISAS_JUMP); in mb_tr_translate_insn()
1707 dc->base.is_jmp = DISAS_EXIT_JUMP; in mb_tr_translate_insn()
1717 DisasContext *dc = container_of(dcb, DisasContext, base); in mb_tr_tb_stop() local
1719 if (dc->base.is_jmp == DISAS_NORETURN) { in mb_tr_tb_stop()
1724 t_sync_flags(dc); in mb_tr_tb_stop()
1726 switch (dc->base.is_jmp) { in mb_tr_tb_stop()
1728 gen_goto_tb(dc, 0, dc->base.pc_next); in mb_tr_tb_stop()
1734 tcg_gen_movi_i32(cpu_pc, dc->base.pc_next); in mb_tr_tb_stop()
1742 if (dc->jmp_dest != -1 && !(tb_cflags(dc->base.tb) & CF_NO_GOTO_TB)) { in mb_tr_tb_stop()
1746 if (dc->jmp_cond != TCG_COND_ALWAYS) { in mb_tr_tb_stop()
1759 tcg_gen_brcondi_i32(dc->jmp_cond, tmp, 0, taken); in mb_tr_tb_stop()
1760 gen_goto_tb(dc, 1, dc->base.pc_next); in mb_tr_tb_stop()
1763 gen_goto_tb(dc, 0, dc->jmp_dest); in mb_tr_tb_stop()
1778 if (unlikely(cs->singlestep_enabled)) { in mb_tr_tb_stop()
1779 gen_raise_exception(dc, EXCP_DEBUG); in mb_tr_tb_stop()
1796 DisasContext dc; in mb_translate_code() local
1797 translator_loop(cpu, tb, max_insns, pc, host_pc, &mb_tr_ops, &dc.base); in mb_translate_code()
1806 qemu_fprintf(f, "pc=0x%08x msr=0x%05x mode=%s(saved=%s) eip=%d ie=%d\n", in mb_cpu_dump_state()
1807 env->pc, env->msr, in mb_cpu_dump_state()
1808 (env->msr & MSR_UM) ? "user" : "kernel", in mb_cpu_dump_state()
1809 (env->msr & MSR_UMS) ? "user" : "kernel", in mb_cpu_dump_state()
1810 (bool)(env->msr & MSR_EIP), in mb_cpu_dump_state()
1811 (bool)(env->msr & MSR_IE)); in mb_cpu_dump_state()
1813 iflags = env->iflags; in mb_cpu_dump_state()
1816 qemu_fprintf(f, " IMM(0x%08x)", env->imm); in mb_cpu_dump_state()
1822 qemu_fprintf(f, " D(btarget=0x%08x)", env->btarget); in mb_cpu_dump_state()
1839 env->esr, env->fsr, env->btr, env->edr, in mb_cpu_dump_state()
1840 env->ear, env->slr, env->shr); in mb_cpu_dump_state()
1844 i, env->regs[i], i % 4 == 3 ? '\n' : ' '); in mb_cpu_dump_state()