Lines Matching full:env
32 static void r4k_mips_tlb_flush_extra(CPUMIPSState *env, int first) in r4k_mips_tlb_flush_extra() argument
34 /* Discard entries from env->tlb[first] onwards. */ in r4k_mips_tlb_flush_extra()
35 while (env->tlb->tlb_in_use > first) { in r4k_mips_tlb_flush_extra()
36 r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0); in r4k_mips_tlb_flush_extra()
50 static void r4k_fill_tlb(CPUMIPSState *env, int idx) in r4k_fill_tlb() argument
53 uint64_t mask = env->CP0_PageMask >> (TARGET_PAGE_BITS + 1); in r4k_fill_tlb()
56 tlb = &env->tlb->mmu.r4k.tlb[idx]; in r4k_fill_tlb()
57 if (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) { in r4k_fill_tlb()
62 tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1); in r4k_fill_tlb()
64 tlb->VPN &= env->SEGMask; in r4k_fill_tlb()
66 tlb->ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; in r4k_fill_tlb()
67 tlb->MMID = env->CP0_MemoryMapID; in r4k_fill_tlb()
68 tlb->PageMask = env->CP0_PageMask; in r4k_fill_tlb()
69 tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; in r4k_fill_tlb()
70 tlb->V0 = (env->CP0_EntryLo0 & 2) != 0; in r4k_fill_tlb()
71 tlb->D0 = (env->CP0_EntryLo0 & 4) != 0; in r4k_fill_tlb()
72 tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7; in r4k_fill_tlb()
73 tlb->XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1; in r4k_fill_tlb()
74 tlb->RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1; in r4k_fill_tlb()
75 tlb->PFN[0] = (get_tlb_pfn_from_entrylo(env->CP0_EntryLo0) & ~mask) << 12; in r4k_fill_tlb()
76 tlb->V1 = (env->CP0_EntryLo1 & 2) != 0; in r4k_fill_tlb()
77 tlb->D1 = (env->CP0_EntryLo1 & 4) != 0; in r4k_fill_tlb()
78 tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7; in r4k_fill_tlb()
79 tlb->XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1; in r4k_fill_tlb()
80 tlb->RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1; in r4k_fill_tlb()
81 tlb->PFN[1] = (get_tlb_pfn_from_entrylo(env->CP0_EntryLo1) & ~mask) << 12; in r4k_fill_tlb()
84 static void r4k_helper_tlbinv(CPUMIPSState *env) in r4k_helper_tlbinv() argument
86 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); in r4k_helper_tlbinv()
87 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; in r4k_helper_tlbinv()
88 uint32_t MMID = env->CP0_MemoryMapID; in r4k_helper_tlbinv()
94 for (idx = 0; idx < env->tlb->nb_tlb; idx++) { in r4k_helper_tlbinv()
95 tlb = &env->tlb->mmu.r4k.tlb[idx]; in r4k_helper_tlbinv()
101 cpu_mips_tlb_flush(env); in r4k_helper_tlbinv()
104 static void r4k_helper_tlbinvf(CPUMIPSState *env) in r4k_helper_tlbinvf() argument
108 for (idx = 0; idx < env->tlb->nb_tlb; idx++) { in r4k_helper_tlbinvf()
109 env->tlb->mmu.r4k.tlb[idx].EHINV = 1; in r4k_helper_tlbinvf()
111 cpu_mips_tlb_flush(env); in r4k_helper_tlbinvf()
114 static void r4k_helper_tlbwi(CPUMIPSState *env) in r4k_helper_tlbwi() argument
116 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); in r4k_helper_tlbwi()
118 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; in r4k_helper_tlbwi()
119 uint32_t MMID = env->CP0_MemoryMapID; in r4k_helper_tlbwi()
127 idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb; in r4k_helper_tlbwi()
128 tlb = &env->tlb->mmu.r4k.tlb[idx]; in r4k_helper_tlbwi()
129 VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1); in r4k_helper_tlbwi()
131 VPN &= env->SEGMask; in r4k_helper_tlbwi()
133 EHINV = (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) != 0; in r4k_helper_tlbwi()
134 G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; in r4k_helper_tlbwi()
135 V0 = (env->CP0_EntryLo0 & 2) != 0; in r4k_helper_tlbwi()
136 D0 = (env->CP0_EntryLo0 & 4) != 0; in r4k_helper_tlbwi()
137 XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) &1; in r4k_helper_tlbwi()
138 RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) &1; in r4k_helper_tlbwi()
139 V1 = (env->CP0_EntryLo1 & 2) != 0; in r4k_helper_tlbwi()
140 D1 = (env->CP0_EntryLo1 & 4) != 0; in r4k_helper_tlbwi()
141 XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) &1; in r4k_helper_tlbwi()
142 RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) &1; in r4k_helper_tlbwi()
155 r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb); in r4k_helper_tlbwi()
158 r4k_invalidate_tlb(env, idx, 0); in r4k_helper_tlbwi()
159 r4k_fill_tlb(env, idx); in r4k_helper_tlbwi()
162 static void r4k_helper_tlbwr(CPUMIPSState *env) in r4k_helper_tlbwr() argument
164 int r = cpu_mips_get_random(env); in r4k_helper_tlbwr()
166 r4k_invalidate_tlb(env, r, 1); in r4k_helper_tlbwr()
167 r4k_fill_tlb(env, r); in r4k_helper_tlbwr()
170 static void r4k_helper_tlbp(CPUMIPSState *env) in r4k_helper_tlbp() argument
172 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); in r4k_helper_tlbp()
177 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; in r4k_helper_tlbp()
178 uint32_t MMID = env->CP0_MemoryMapID; in r4k_helper_tlbp()
183 for (i = 0; i < env->tlb->nb_tlb; i++) { in r4k_helper_tlbp()
184 tlb = &env->tlb->mmu.r4k.tlb[i]; in r4k_helper_tlbp()
187 tag = env->CP0_EntryHi & ~mask; in r4k_helper_tlbp()
190 tag &= env->SEGMask; in r4k_helper_tlbp()
196 env->CP0_Index = i; in r4k_helper_tlbp()
200 if (i == env->tlb->nb_tlb) { in r4k_helper_tlbp()
202 for (i = env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) { in r4k_helper_tlbp()
203 tlb = &env->tlb->mmu.r4k.tlb[i]; in r4k_helper_tlbp()
206 tag = env->CP0_EntryHi & ~mask; in r4k_helper_tlbp()
209 tag &= env->SEGMask; in r4k_helper_tlbp()
214 r4k_mips_tlb_flush_extra(env, i); in r4k_helper_tlbp()
219 env->CP0_Index |= 0x80000000; in r4k_helper_tlbp()
233 static void r4k_helper_tlbr(CPUMIPSState *env) in r4k_helper_tlbr() argument
235 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); in r4k_helper_tlbr()
236 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; in r4k_helper_tlbr()
237 uint32_t MMID = env->CP0_MemoryMapID; in r4k_helper_tlbr()
243 idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb; in r4k_helper_tlbr()
244 tlb = &env->tlb->mmu.r4k.tlb[idx]; in r4k_helper_tlbr()
249 cpu_mips_tlb_flush(env); in r4k_helper_tlbr()
252 r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb); in r4k_helper_tlbr()
255 env->CP0_EntryHi = 1 << CP0EnHi_EHINV; in r4k_helper_tlbr()
256 env->CP0_PageMask = 0; in r4k_helper_tlbr()
257 env->CP0_EntryLo0 = 0; in r4k_helper_tlbr()
258 env->CP0_EntryLo1 = 0; in r4k_helper_tlbr()
260 env->CP0_EntryHi = mi ? tlb->VPN : tlb->VPN | tlb->ASID; in r4k_helper_tlbr()
261 env->CP0_MemoryMapID = tlb->MMID; in r4k_helper_tlbr()
262 env->CP0_PageMask = tlb->PageMask; in r4k_helper_tlbr()
263 env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) | in r4k_helper_tlbr()
267 env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) | in r4k_helper_tlbr()
274 void helper_tlbwi(CPUMIPSState *env) in helper_tlbwi() argument
276 env->tlb->helper_tlbwi(env); in helper_tlbwi()
279 void helper_tlbwr(CPUMIPSState *env) in helper_tlbwr() argument
281 env->tlb->helper_tlbwr(env); in helper_tlbwr()
284 void helper_tlbp(CPUMIPSState *env) in helper_tlbp() argument
286 env->tlb->helper_tlbp(env); in helper_tlbp()
289 void helper_tlbr(CPUMIPSState *env) in helper_tlbr() argument
291 env->tlb->helper_tlbr(env); in helper_tlbr()
294 void helper_tlbinv(CPUMIPSState *env) in helper_tlbinv() argument
296 env->tlb->helper_tlbinv(env); in helper_tlbinv()
299 void helper_tlbinvf(CPUMIPSState *env) in helper_tlbinvf() argument
301 env->tlb->helper_tlbinvf(env); in helper_tlbinvf()
304 static void global_invalidate_tlb(CPUMIPSState *env, in global_invalidate_tlb() argument
319 for (idx = 0; idx < env->tlb->nb_tlb; idx++) { in global_invalidate_tlb()
320 tlb = &env->tlb->mmu.r4k.tlb[idx]; in global_invalidate_tlb()
325 (extract64(env->CP0_EntryHi, 62, 2) == invMsgR) in global_invalidate_tlb()
329 if ((invAll && (idx > env->CP0_Wired)) || in global_invalidate_tlb()
336 cpu_mips_tlb_flush(env); in global_invalidate_tlb()
339 void helper_ginvt(CPUMIPSState *env, target_ulong arg, uint32_t type) in helper_ginvt() argument
347 uint32_t invMsgMMid = env->CP0_MemoryMapID; in helper_ginvt()
356 global_invalidate_tlb(&other_cpu->env, invMsgVPN2, invMsgR, invMsgMMid, in helper_ginvt()
362 static int no_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, in no_mmu_map_address() argument
371 static int fixed_mmu_map_address(CPUMIPSState *env, hwaddr *physical, in fixed_mmu_map_address() argument
376 if (!(env->CP0_Status & (1 << CP0St_ERL))) { in fixed_mmu_map_address()
392 static int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, in r4k_map_address() argument
395 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; in r4k_map_address()
396 uint32_t MMID = env->CP0_MemoryMapID; in r4k_map_address()
397 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); in r4k_map_address()
403 for (i = 0; i < env->tlb->tlb_in_use; i++) { in r4k_map_address()
404 r4k_tlb_t *tlb = &env->tlb->mmu.r4k.tlb[i]; in r4k_map_address()
410 tag &= env->SEGMask; in r4k_map_address()
445 static void no_mmu_init(CPUMIPSState *env, const mips_def_t *def) in no_mmu_init() argument
447 env->tlb->nb_tlb = 1; in no_mmu_init()
448 env->tlb->map_address = &no_mmu_map_address; in no_mmu_init()
451 static void fixed_mmu_init(CPUMIPSState *env, const mips_def_t *def) in fixed_mmu_init() argument
453 env->tlb->nb_tlb = 1; in fixed_mmu_init()
454 env->tlb->map_address = &fixed_mmu_map_address; in fixed_mmu_init()
457 static void r4k_mmu_init(CPUMIPSState *env, const mips_def_t *def) in r4k_mmu_init() argument
459 env->tlb->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63); in r4k_mmu_init()
460 env->tlb->map_address = &r4k_map_address; in r4k_mmu_init()
461 env->tlb->helper_tlbwi = r4k_helper_tlbwi; in r4k_mmu_init()
462 env->tlb->helper_tlbwr = r4k_helper_tlbwr; in r4k_mmu_init()
463 env->tlb->helper_tlbp = r4k_helper_tlbp; in r4k_mmu_init()
464 env->tlb->helper_tlbr = r4k_helper_tlbr; in r4k_mmu_init()
465 env->tlb->helper_tlbinv = r4k_helper_tlbinv; in r4k_mmu_init()
466 env->tlb->helper_tlbinvf = r4k_helper_tlbinvf; in r4k_mmu_init()
469 void mmu_init(CPUMIPSState *env, const mips_def_t *def) in mmu_init() argument
471 env->tlb = g_malloc0(sizeof(CPUMIPSTLBContext)); in mmu_init()
475 no_mmu_init(env, def); in mmu_init()
478 r4k_mmu_init(env, def); in mmu_init()
481 fixed_mmu_init(env, def); in mmu_init()
487 cpu_abort(env_cpu(env), "MMU type not supported\n"); in mmu_init()
491 void cpu_mips_tlb_flush(CPUMIPSState *env) in cpu_mips_tlb_flush() argument
494 tlb_flush(env_cpu(env)); in cpu_mips_tlb_flush()
495 env->tlb->tlb_in_use = env->tlb->nb_tlb; in cpu_mips_tlb_flush()
498 static void raise_mmu_exception(CPUMIPSState *env, target_ulong address, in raise_mmu_exception() argument
501 CPUState *cs = env_cpu(env); in raise_mmu_exception()
542 if (env->CP0_PageGrain & (1 << CP0PG_IEC)) { in raise_mmu_exception()
550 if (env->CP0_PageGrain & (1 << CP0PG_IEC)) { in raise_mmu_exception()
558 if (!(env->hflags & MIPS_HFLAG_DM)) { in raise_mmu_exception()
559 env->CP0_BadVAddr = address; in raise_mmu_exception()
561 env->CP0_Context = (env->CP0_Context & ~0x007fffff) | in raise_mmu_exception()
563 env->CP0_EntryHi = (env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask) | in raise_mmu_exception()
564 (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) | in raise_mmu_exception()
567 env->CP0_EntryHi &= env->SEGMask; in raise_mmu_exception()
568 env->CP0_XContext = in raise_mmu_exception()
569 (env->CP0_XContext & ((~0ULL) << (env->SEGBITS - 7))) | /* PTEBase */ in raise_mmu_exception()
570 (extract64(address, 62, 2) << (env->SEGBITS - 9)) | /* R */ in raise_mmu_exception()
571 (extract64(address, 13, env->SEGBITS - 13) << 4); /* BadVPN2 */ in raise_mmu_exception()
574 env->error_code = error_code; in raise_mmu_exception()
596 static bool get_pte(CPUMIPSState *env, uint64_t vaddr, MemOp op, in get_pte() argument
605 oi = make_memop_idx(op | mo_endian_env(env), ptw_mmu_idx); in get_pte()
607 *pte = cpu_ldq_mmu(env, vaddr, oi, 0); in get_pte()
609 *pte = cpu_ldl_mmu(env, vaddr, oi, 0); in get_pte()
615 static uint64_t get_tlb_entry_layout(CPUMIPSState *env, uint64_t entry, in get_tlb_entry_layout() argument
631 static int walk_directory(CPUMIPSState *env, uint64_t *vaddr, in walk_directory() argument
636 int dph = (env->CP0_PWCtl >> CP0PC_DPH) & 0x1; in walk_directory()
637 int psn = (env->CP0_PWCtl >> CP0PC_PSN) & 0x3F; in walk_directory()
638 int hugepg = (env->CP0_PWCtl >> CP0PC_HUGEPG) & 0x1; in walk_directory()
639 int pf_ptew = (env->CP0_PWField >> CP0PF_PTEW) & 0x3F; in walk_directory()
646 if (get_physical_address(env, &paddr, &prot, *vaddr, MMU_DATA_LOAD, in walk_directory()
651 if (!get_pte(env, *vaddr, directory_mop, &entry, ptw_mmu_idx)) { in walk_directory()
658 entry = get_tlb_entry_layout(env, entry, leaf_mop, pf_ptew); in walk_directory()
673 if (get_physical_address(env, &paddr, &prot, vaddr2, MMU_DATA_LOAD, in walk_directory()
677 if (!get_pte(env, vaddr2, leaf_mop, &entry, ptw_mmu_idx)) { in walk_directory()
680 entry = get_tlb_entry_layout(env, entry, leaf_mop, pf_ptew); in walk_directory()
696 static bool page_table_walk_refill(CPUMIPSState *env, vaddr address, in page_table_walk_refill() argument
699 int gdw = (env->CP0_PWSize >> CP0PS_GDW) & 0x3F; in page_table_walk_refill()
700 int udw = (env->CP0_PWSize >> CP0PS_UDW) & 0x3F; in page_table_walk_refill()
701 int mdw = (env->CP0_PWSize >> CP0PS_MDW) & 0x3F; in page_table_walk_refill()
702 int ptw = (env->CP0_PWSize >> CP0PS_PTW) & 0x3F; in page_table_walk_refill()
703 int ptew = (env->CP0_PWSize >> CP0PS_PTEW) & 0x3F; in page_table_walk_refill()
719 MemOp native_op = (((env->CP0_PWSize >> CP0PS_PS) & 1) == 0) ? MO_32 : MO_64; in page_table_walk_refill()
722 int pf_gdw = (env->CP0_PWField >> CP0PF_GDW) & 0x3F; in page_table_walk_refill()
723 int pf_udw = (env->CP0_PWField >> CP0PF_UDW) & 0x3F; in page_table_walk_refill()
724 int pf_mdw = (env->CP0_PWField >> CP0PF_MDW) & 0x3F; in page_table_walk_refill()
725 int pf_ptw = (env->CP0_PWField >> CP0PF_PTW) & 0x3F; in page_table_walk_refill()
726 int pf_ptew = (env->CP0_PWField >> CP0PF_PTEW) & 0x3F; in page_table_walk_refill()
735 int hugepg = (env->CP0_PWCtl >> CP0PC_HUGEPG) & 0x1; in page_table_walk_refill()
742 uint64_t vaddr = env->CP0_PWBase; in page_table_walk_refill()
749 if (!(env->CP0_Config3 & (1 << CP0C3_PW))) { in page_table_walk_refill()
753 if (!(env->CP0_PWCtl & (1 << CP0PC_PWEN))) { in page_table_walk_refill()
778 switch (walk_directory(env, &vaddr, pf_gdw, &huge_page, &hgpg_gdhit, in page_table_walk_refill()
795 switch (walk_directory(env, &vaddr, pf_udw, &huge_page, &hgpg_udhit, in page_table_walk_refill()
812 switch (walk_directory(env, &vaddr, pf_mdw, &huge_page, &hgpg_mdhit, in page_table_walk_refill()
828 if (get_physical_address(env, &paddr, &prot, vaddr, MMU_DATA_LOAD, in page_table_walk_refill()
832 if (!get_pte(env, vaddr, leaf_mop, &dir_entry, ptw_mmu_idx)) { in page_table_walk_refill()
835 dir_entry = get_tlb_entry_layout(env, dir_entry, leaf_mop, pf_ptew); in page_table_walk_refill()
840 if (get_physical_address(env, &paddr, &prot, vaddr, MMU_DATA_LOAD, in page_table_walk_refill()
844 if (!get_pte(env, vaddr, leaf_mop, &dir_entry, ptw_mmu_idx)) { in page_table_walk_refill()
847 dir_entry = get_tlb_entry_layout(env, dir_entry, leaf_mop, pf_ptew); in page_table_walk_refill()
880 pw_entryhi = (address & ~0x1fff) | (env->CP0_EntryHi & 0xFF); in page_table_walk_refill()
882 target_ulong tmp_entryhi = env->CP0_EntryHi; in page_table_walk_refill()
883 int32_t tmp_pagemask = env->CP0_PageMask; in page_table_walk_refill()
884 uint64_t tmp_entrylo0 = env->CP0_EntryLo0; in page_table_walk_refill()
885 uint64_t tmp_entrylo1 = env->CP0_EntryLo1; in page_table_walk_refill()
887 env->CP0_EntryHi = pw_entryhi; in page_table_walk_refill()
888 env->CP0_PageMask = pw_pagemask; in page_table_walk_refill()
889 env->CP0_EntryLo0 = pw_entrylo0; in page_table_walk_refill()
890 env->CP0_EntryLo1 = pw_entrylo1; in page_table_walk_refill()
897 r4k_helper_tlbwr(env); in page_table_walk_refill()
899 env->CP0_EntryHi = tmp_entryhi; in page_table_walk_refill()
900 env->CP0_PageMask = tmp_pagemask; in page_table_walk_refill()
901 env->CP0_EntryLo0 = tmp_entrylo0; in page_table_walk_refill()
902 env->CP0_EntryLo1 = tmp_entrylo1; in page_table_walk_refill()
912 CPUMIPSState *env = cpu_env(cs); in mips_cpu_tlb_fill() local
919 ret = get_physical_address(env, &physical, &prot, address, in mips_cpu_tlb_fill()
940 if ((ret == TLBRET_NOMATCH) && (env->tlb->nb_tlb > 1)) { in mips_cpu_tlb_fill()
945 int ptw_mmu_idx = (env->hflags & MIPS_HFLAG_ERL ? in mips_cpu_tlb_fill()
948 if (page_table_walk_refill(env, address, ptw_mmu_idx)) { in mips_cpu_tlb_fill()
949 ret = get_physical_address(env, &physical, &prot, address, in mips_cpu_tlb_fill()
964 raise_mmu_exception(env, address, access_type, ret); in mips_cpu_tlb_fill()
965 do_raise_exception_err(env, cs->exception_index, env->error_code, retaddr); in mips_cpu_tlb_fill()
968 hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, in cpu_mips_translate_address() argument
974 CPUState *cs = env_cpu(env); in cpu_mips_translate_address()
977 ret = get_physical_address(env, &physical, &prot, address, access_type, in cpu_mips_translate_address()
978 mips_env_mmu_index(env)); in cpu_mips_translate_address()
983 raise_mmu_exception(env, address, access_type, ret); in cpu_mips_translate_address()
987 static void set_hflags_for_handler(CPUMIPSState *env) in set_hflags_for_handler() argument
990 env->hflags &= ~(MIPS_HFLAG_M16); in set_hflags_for_handler()
992 if (env->insn_flags & ASE_MICROMIPS) { in set_hflags_for_handler()
993 env->hflags |= (!!(env->CP0_Config3 & in set_hflags_for_handler()
999 static inline void set_badinstr_registers(CPUMIPSState *env) in set_badinstr_registers() argument
1001 if (env->insn_flags & ISA_NANOMIPS32) { in set_badinstr_registers()
1002 if (env->CP0_Config3 & (1 << CP0C3_BI)) { in set_badinstr_registers()
1003 uint32_t instr = (cpu_lduw_code(env, env->active_tc.PC)) << 16; in set_badinstr_registers()
1005 instr |= cpu_lduw_code(env, env->active_tc.PC + 2); in set_badinstr_registers()
1007 env->CP0_BadInstr = instr; in set_badinstr_registers()
1010 instr = cpu_lduw_code(env, env->active_tc.PC + 4) << 16; in set_badinstr_registers()
1011 env->CP0_BadInstrX = instr; in set_badinstr_registers()
1017 if (env->hflags & MIPS_HFLAG_M16) { in set_badinstr_registers()
1021 if (env->CP0_Config3 & (1 << CP0C3_BI)) { in set_badinstr_registers()
1022 env->CP0_BadInstr = cpu_ldl_code(env, env->active_tc.PC); in set_badinstr_registers()
1024 if ((env->CP0_Config3 & (1 << CP0C3_BP)) && in set_badinstr_registers()
1025 (env->hflags & MIPS_HFLAG_BMASK)) { in set_badinstr_registers()
1026 env->CP0_BadInstrP = cpu_ldl_code(env, env->active_tc.PC - 4); in set_badinstr_registers()
1033 CPUMIPSState *env = &cpu->env; in mips_cpu_do_interrupt() local
1042 __func__, env->active_tc.PC, env->CP0_EPC, in mips_cpu_do_interrupt()
1046 (env->hflags & MIPS_HFLAG_DM)) { in mips_cpu_do_interrupt()
1053 mips_semihosting(env); in mips_cpu_do_interrupt()
1054 env->active_tc.PC += env->error_code; in mips_cpu_do_interrupt()
1057 env->CP0_Debug |= 1 << CP0DB_DSS; in mips_cpu_do_interrupt()
1064 env->CP0_DEPC = env->active_tc.PC | !!(env->hflags & MIPS_HFLAG_M16); in mips_cpu_do_interrupt()
1067 env->CP0_Debug |= 1 << CP0DB_DINT; in mips_cpu_do_interrupt()
1070 env->CP0_Debug |= 1 << CP0DB_DIB; in mips_cpu_do_interrupt()
1073 env->CP0_Debug |= 1 << CP0DB_DBp; in mips_cpu_do_interrupt()
1075 env->CP0_Debug = (env->CP0_Debug & ~(0x1fULL << CP0DB_DEC)) | in mips_cpu_do_interrupt()
1079 env->CP0_Debug |= 1 << CP0DB_DDBS; in mips_cpu_do_interrupt()
1082 env->CP0_Debug |= 1 << CP0DB_DDBL; in mips_cpu_do_interrupt()
1084 env->CP0_DEPC = exception_resume_pc(env); in mips_cpu_do_interrupt()
1085 env->hflags &= ~MIPS_HFLAG_BMASK; in mips_cpu_do_interrupt()
1087 if (env->insn_flags & ISA_MIPS3) { in mips_cpu_do_interrupt()
1088 env->hflags |= MIPS_HFLAG_64; in mips_cpu_do_interrupt()
1089 if (!(env->insn_flags & ISA_MIPS_R6) || in mips_cpu_do_interrupt()
1090 env->CP0_Status & (1 << CP0St_KX)) { in mips_cpu_do_interrupt()
1091 env->hflags &= ~MIPS_HFLAG_AWRAP; in mips_cpu_do_interrupt()
1094 env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_CP0; in mips_cpu_do_interrupt()
1095 env->hflags &= ~(MIPS_HFLAG_KSU); in mips_cpu_do_interrupt()
1097 if (!(env->CP0_Status & (1 << CP0St_EXL))) { in mips_cpu_do_interrupt()
1098 env->CP0_Cause &= ~(1U << CP0Ca_BD); in mips_cpu_do_interrupt()
1100 env->active_tc.PC = env->exception_base + 0x480; in mips_cpu_do_interrupt()
1101 set_hflags_for_handler(env); in mips_cpu_do_interrupt()
1107 env->CP0_Status |= (1 << CP0St_SR); in mips_cpu_do_interrupt()
1108 memset(env->CP0_WatchLo, 0, sizeof(env->CP0_WatchLo)); in mips_cpu_do_interrupt()
1111 env->CP0_Status |= (1 << CP0St_NMI); in mips_cpu_do_interrupt()
1113 env->CP0_ErrorEPC = exception_resume_pc(env); in mips_cpu_do_interrupt()
1114 env->hflags &= ~MIPS_HFLAG_BMASK; in mips_cpu_do_interrupt()
1115 env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); in mips_cpu_do_interrupt()
1116 if (env->insn_flags & ISA_MIPS3) { in mips_cpu_do_interrupt()
1117 env->hflags |= MIPS_HFLAG_64; in mips_cpu_do_interrupt()
1118 if (!(env->insn_flags & ISA_MIPS_R6) || in mips_cpu_do_interrupt()
1119 env->CP0_Status & (1 << CP0St_KX)) { in mips_cpu_do_interrupt()
1120 env->hflags &= ~MIPS_HFLAG_AWRAP; in mips_cpu_do_interrupt()
1123 env->hflags |= MIPS_HFLAG_CP0; in mips_cpu_do_interrupt()
1124 env->hflags &= ~(MIPS_HFLAG_KSU); in mips_cpu_do_interrupt()
1125 if (!(env->CP0_Status & (1 << CP0St_EXL))) { in mips_cpu_do_interrupt()
1126 env->CP0_Cause &= ~(1U << CP0Ca_BD); in mips_cpu_do_interrupt()
1128 env->active_tc.PC = env->exception_base; in mips_cpu_do_interrupt()
1129 set_hflags_for_handler(env); in mips_cpu_do_interrupt()
1133 if (env->CP0_Cause & (1 << CP0Ca_IV)) { in mips_cpu_do_interrupt()
1134 uint32_t spacing = (env->CP0_IntCtl >> CP0IntCtl_VS) & 0x1f; in mips_cpu_do_interrupt()
1136 if ((env->CP0_Status & (1 << CP0St_BEV)) || spacing == 0) { in mips_cpu_do_interrupt()
1140 uint32_t pending = (env->CP0_Cause & CP0Ca_IP_mask) >> CP0Ca_IP; in mips_cpu_do_interrupt()
1142 if (env->CP0_Config3 & (1 << CP0C3_VEIC)) { in mips_cpu_do_interrupt()
1153 pending &= (env->CP0_Status >> CP0St_IM) & 0xff; in mips_cpu_do_interrupt()
1165 update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL); in mips_cpu_do_interrupt()
1169 update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL); in mips_cpu_do_interrupt()
1170 if ((env->error_code & EXCP_TLB_NOMATCH) && in mips_cpu_do_interrupt()
1171 !(env->CP0_Status & (1 << CP0St_EXL))) { in mips_cpu_do_interrupt()
1173 int R = env->CP0_BadVAddr >> 62; in mips_cpu_do_interrupt()
1174 int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0; in mips_cpu_do_interrupt()
1175 int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0; in mips_cpu_do_interrupt()
1178 (!(env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)))) { in mips_cpu_do_interrupt()
1191 if ((env->error_code & EXCP_TLB_NOMATCH) && in mips_cpu_do_interrupt()
1192 !(env->CP0_Status & (1 << CP0St_EXL))) { in mips_cpu_do_interrupt()
1194 int R = env->CP0_BadVAddr >> 62; in mips_cpu_do_interrupt()
1195 int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0; in mips_cpu_do_interrupt()
1196 int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0; in mips_cpu_do_interrupt()
1199 (!(env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)))) { in mips_cpu_do_interrupt()
1211 update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL); in mips_cpu_do_interrupt()
1238 env->CP0_Cause = (env->CP0_Cause & ~(0x3 << CP0Ca_CE)) | in mips_cpu_do_interrupt()
1239 (env->error_code << CP0Ca_CE); in mips_cpu_do_interrupt()
1291 if (!(env->CP0_Status & (1 << CP0St_EXL))) { in mips_cpu_do_interrupt()
1292 env->CP0_EPC = exception_resume_pc(env); in mips_cpu_do_interrupt()
1294 set_badinstr_registers(env); in mips_cpu_do_interrupt()
1296 if (env->hflags & MIPS_HFLAG_BMASK) { in mips_cpu_do_interrupt()
1297 env->CP0_Cause |= (1U << CP0Ca_BD); in mips_cpu_do_interrupt()
1299 env->CP0_Cause &= ~(1U << CP0Ca_BD); in mips_cpu_do_interrupt()
1301 env->CP0_Status |= (1 << CP0St_EXL); in mips_cpu_do_interrupt()
1302 if (env->insn_flags & ISA_MIPS3) { in mips_cpu_do_interrupt()
1303 env->hflags |= MIPS_HFLAG_64; in mips_cpu_do_interrupt()
1304 if (!(env->insn_flags & ISA_MIPS_R6) || in mips_cpu_do_interrupt()
1305 env->CP0_Status & (1 << CP0St_KX)) { in mips_cpu_do_interrupt()
1306 env->hflags &= ~MIPS_HFLAG_AWRAP; in mips_cpu_do_interrupt()
1309 env->hflags |= MIPS_HFLAG_CP0; in mips_cpu_do_interrupt()
1310 env->hflags &= ~(MIPS_HFLAG_KSU); in mips_cpu_do_interrupt()
1312 env->hflags &= ~MIPS_HFLAG_BMASK; in mips_cpu_do_interrupt()
1313 if (env->CP0_Status & (1 << CP0St_BEV)) { in mips_cpu_do_interrupt()
1314 env->active_tc.PC = env->exception_base + 0x200; in mips_cpu_do_interrupt()
1315 } else if (cause == 30 && !(env->CP0_Config3 & (1 << CP0C3_SC) && in mips_cpu_do_interrupt()
1316 env->CP0_Config5 & (1 << CP0C5_CV))) { in mips_cpu_do_interrupt()
1318 env->active_tc.PC = KSEG1_BASE | (env->CP0_EBase & 0x1FFFF000); in mips_cpu_do_interrupt()
1320 env->active_tc.PC = env->CP0_EBase & ~0xfff; in mips_cpu_do_interrupt()
1323 env->active_tc.PC += offset; in mips_cpu_do_interrupt()
1324 set_hflags_for_handler(env); in mips_cpu_do_interrupt()
1325 env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | in mips_cpu_do_interrupt()
1335 __func__, env->active_tc.PC, env->CP0_EPC, cause, in mips_cpu_do_interrupt()
1336 env->CP0_Status, env->CP0_Cause, env->CP0_BadVAddr, in mips_cpu_do_interrupt()
1337 env->CP0_DEPC); in mips_cpu_do_interrupt()
1345 CPUMIPSState *env = cpu_env(cs); in mips_cpu_exec_interrupt() local
1347 if (cpu_mips_hw_interrupts_enabled(env) && in mips_cpu_exec_interrupt()
1348 cpu_mips_hw_interrupts_pending(env)) { in mips_cpu_exec_interrupt()
1351 env->error_code = 0; in mips_cpu_exec_interrupt()
1359 void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra) in r4k_invalidate_tlb() argument
1361 CPUState *cs = env_cpu(env); in r4k_invalidate_tlb()
1365 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; in r4k_invalidate_tlb()
1366 uint32_t MMID = env->CP0_MemoryMapID; in r4k_invalidate_tlb()
1367 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); in r4k_invalidate_tlb()
1373 tlb = &env->tlb->mmu.r4k.tlb[idx]; in r4k_invalidate_tlb()
1383 if (use_extra && env->tlb->tlb_in_use < MIPS_TLB_MAX) { in r4k_invalidate_tlb()
1389 env->tlb->mmu.r4k.tlb[env->tlb->tlb_in_use] = *tlb; in r4k_invalidate_tlb()
1390 env->tlb->tlb_in_use++; in r4k_invalidate_tlb()
1399 if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) { in r4k_invalidate_tlb()
1412 if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) { in r4k_invalidate_tlb()