Lines Matching full:env

31 static void r4k_mips_tlb_flush_extra(CPUMIPSState *env, int first)  in r4k_mips_tlb_flush_extra()  argument
33 /* Discard entries from env->tlb[first] onwards. */ in r4k_mips_tlb_flush_extra()
34 while (env->tlb->tlb_in_use > first) { in r4k_mips_tlb_flush_extra()
35 r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0); in r4k_mips_tlb_flush_extra()
49 static void r4k_fill_tlb(CPUMIPSState *env, int idx) in r4k_fill_tlb() argument
52 uint64_t mask = env->CP0_PageMask >> (TARGET_PAGE_BITS + 1); in r4k_fill_tlb()
55 tlb = &env->tlb->mmu.r4k.tlb[idx]; in r4k_fill_tlb()
56 if (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) { in r4k_fill_tlb()
61 tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1); in r4k_fill_tlb()
63 tlb->VPN &= env->SEGMask; in r4k_fill_tlb()
65 tlb->ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; in r4k_fill_tlb()
66 tlb->MMID = env->CP0_MemoryMapID; in r4k_fill_tlb()
67 tlb->PageMask = env->CP0_PageMask; in r4k_fill_tlb()
68 tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; in r4k_fill_tlb()
69 tlb->V0 = (env->CP0_EntryLo0 & 2) != 0; in r4k_fill_tlb()
70 tlb->D0 = (env->CP0_EntryLo0 & 4) != 0; in r4k_fill_tlb()
71 tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7; in r4k_fill_tlb()
72 tlb->XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1; in r4k_fill_tlb()
73 tlb->RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1; in r4k_fill_tlb()
74 tlb->PFN[0] = (get_tlb_pfn_from_entrylo(env->CP0_EntryLo0) & ~mask) << 12; in r4k_fill_tlb()
75 tlb->V1 = (env->CP0_EntryLo1 & 2) != 0; in r4k_fill_tlb()
76 tlb->D1 = (env->CP0_EntryLo1 & 4) != 0; in r4k_fill_tlb()
77 tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7; in r4k_fill_tlb()
78 tlb->XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1; in r4k_fill_tlb()
79 tlb->RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1; in r4k_fill_tlb()
80 tlb->PFN[1] = (get_tlb_pfn_from_entrylo(env->CP0_EntryLo1) & ~mask) << 12; in r4k_fill_tlb()
83 static void r4k_helper_tlbinv(CPUMIPSState *env) in r4k_helper_tlbinv() argument
85 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); in r4k_helper_tlbinv()
86 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; in r4k_helper_tlbinv()
87 uint32_t MMID = env->CP0_MemoryMapID; in r4k_helper_tlbinv()
93 for (idx = 0; idx < env->tlb->nb_tlb; idx++) { in r4k_helper_tlbinv()
94 tlb = &env->tlb->mmu.r4k.tlb[idx]; in r4k_helper_tlbinv()
100 cpu_mips_tlb_flush(env); in r4k_helper_tlbinv()
103 static void r4k_helper_tlbinvf(CPUMIPSState *env) in r4k_helper_tlbinvf() argument
107 for (idx = 0; idx < env->tlb->nb_tlb; idx++) { in r4k_helper_tlbinvf()
108 env->tlb->mmu.r4k.tlb[idx].EHINV = 1; in r4k_helper_tlbinvf()
110 cpu_mips_tlb_flush(env); in r4k_helper_tlbinvf()
113 static void r4k_helper_tlbwi(CPUMIPSState *env) in r4k_helper_tlbwi() argument
115 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); in r4k_helper_tlbwi()
117 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; in r4k_helper_tlbwi()
118 uint32_t MMID = env->CP0_MemoryMapID; in r4k_helper_tlbwi()
126 idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb; in r4k_helper_tlbwi()
127 tlb = &env->tlb->mmu.r4k.tlb[idx]; in r4k_helper_tlbwi()
128 VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1); in r4k_helper_tlbwi()
130 VPN &= env->SEGMask; in r4k_helper_tlbwi()
132 EHINV = (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) != 0; in r4k_helper_tlbwi()
133 G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; in r4k_helper_tlbwi()
134 V0 = (env->CP0_EntryLo0 & 2) != 0; in r4k_helper_tlbwi()
135 D0 = (env->CP0_EntryLo0 & 4) != 0; in r4k_helper_tlbwi()
136 XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) &1; in r4k_helper_tlbwi()
137 RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) &1; in r4k_helper_tlbwi()
138 V1 = (env->CP0_EntryLo1 & 2) != 0; in r4k_helper_tlbwi()
139 D1 = (env->CP0_EntryLo1 & 4) != 0; in r4k_helper_tlbwi()
140 XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) &1; in r4k_helper_tlbwi()
141 RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) &1; in r4k_helper_tlbwi()
154 r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb); in r4k_helper_tlbwi()
157 r4k_invalidate_tlb(env, idx, 0); in r4k_helper_tlbwi()
158 r4k_fill_tlb(env, idx); in r4k_helper_tlbwi()
161 static void r4k_helper_tlbwr(CPUMIPSState *env) in r4k_helper_tlbwr() argument
163 int r = cpu_mips_get_random(env); in r4k_helper_tlbwr()
165 r4k_invalidate_tlb(env, r, 1); in r4k_helper_tlbwr()
166 r4k_fill_tlb(env, r); in r4k_helper_tlbwr()
169 static void r4k_helper_tlbp(CPUMIPSState *env) in r4k_helper_tlbp() argument
171 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); in r4k_helper_tlbp()
176 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; in r4k_helper_tlbp()
177 uint32_t MMID = env->CP0_MemoryMapID; in r4k_helper_tlbp()
182 for (i = 0; i < env->tlb->nb_tlb; i++) { in r4k_helper_tlbp()
183 tlb = &env->tlb->mmu.r4k.tlb[i]; in r4k_helper_tlbp()
186 tag = env->CP0_EntryHi & ~mask; in r4k_helper_tlbp()
189 tag &= env->SEGMask; in r4k_helper_tlbp()
195 env->CP0_Index = i; in r4k_helper_tlbp()
199 if (i == env->tlb->nb_tlb) { in r4k_helper_tlbp()
201 for (i = env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) { in r4k_helper_tlbp()
202 tlb = &env->tlb->mmu.r4k.tlb[i]; in r4k_helper_tlbp()
205 tag = env->CP0_EntryHi & ~mask; in r4k_helper_tlbp()
208 tag &= env->SEGMask; in r4k_helper_tlbp()
213 r4k_mips_tlb_flush_extra(env, i); in r4k_helper_tlbp()
218 env->CP0_Index |= 0x80000000; in r4k_helper_tlbp()
232 static void r4k_helper_tlbr(CPUMIPSState *env) in r4k_helper_tlbr() argument
234 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); in r4k_helper_tlbr()
235 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; in r4k_helper_tlbr()
236 uint32_t MMID = env->CP0_MemoryMapID; in r4k_helper_tlbr()
242 idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb; in r4k_helper_tlbr()
243 tlb = &env->tlb->mmu.r4k.tlb[idx]; in r4k_helper_tlbr()
248 cpu_mips_tlb_flush(env); in r4k_helper_tlbr()
251 r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb); in r4k_helper_tlbr()
254 env->CP0_EntryHi = 1 << CP0EnHi_EHINV; in r4k_helper_tlbr()
255 env->CP0_PageMask = 0; in r4k_helper_tlbr()
256 env->CP0_EntryLo0 = 0; in r4k_helper_tlbr()
257 env->CP0_EntryLo1 = 0; in r4k_helper_tlbr()
259 env->CP0_EntryHi = mi ? tlb->VPN : tlb->VPN | tlb->ASID; in r4k_helper_tlbr()
260 env->CP0_MemoryMapID = tlb->MMID; in r4k_helper_tlbr()
261 env->CP0_PageMask = tlb->PageMask; in r4k_helper_tlbr()
262 env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) | in r4k_helper_tlbr()
266 env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) | in r4k_helper_tlbr()
273 void helper_tlbwi(CPUMIPSState *env) in helper_tlbwi() argument
275 env->tlb->helper_tlbwi(env); in helper_tlbwi()
278 void helper_tlbwr(CPUMIPSState *env) in helper_tlbwr() argument
280 env->tlb->helper_tlbwr(env); in helper_tlbwr()
283 void helper_tlbp(CPUMIPSState *env) in helper_tlbp() argument
285 env->tlb->helper_tlbp(env); in helper_tlbp()
288 void helper_tlbr(CPUMIPSState *env) in helper_tlbr() argument
290 env->tlb->helper_tlbr(env); in helper_tlbr()
293 void helper_tlbinv(CPUMIPSState *env) in helper_tlbinv() argument
295 env->tlb->helper_tlbinv(env); in helper_tlbinv()
298 void helper_tlbinvf(CPUMIPSState *env) in helper_tlbinvf() argument
300 env->tlb->helper_tlbinvf(env); in helper_tlbinvf()
303 static void global_invalidate_tlb(CPUMIPSState *env, in global_invalidate_tlb() argument
318 for (idx = 0; idx < env->tlb->nb_tlb; idx++) { in global_invalidate_tlb()
319 tlb = &env->tlb->mmu.r4k.tlb[idx]; in global_invalidate_tlb()
324 (extract64(env->CP0_EntryHi, 62, 2) == invMsgR) in global_invalidate_tlb()
328 if ((invAll && (idx > env->CP0_Wired)) || in global_invalidate_tlb()
335 cpu_mips_tlb_flush(env); in global_invalidate_tlb()
338 void helper_ginvt(CPUMIPSState *env, target_ulong arg, uint32_t type) in helper_ginvt() argument
346 uint32_t invMsgMMid = env->CP0_MemoryMapID; in helper_ginvt()
355 global_invalidate_tlb(&other_cpu->env, invMsgVPN2, invMsgR, invMsgMMid, in helper_ginvt()
361 static int no_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, in no_mmu_map_address() argument
370 static int fixed_mmu_map_address(CPUMIPSState *env, hwaddr *physical, in fixed_mmu_map_address() argument
375 if (!(env->CP0_Status & (1 << CP0St_ERL))) { in fixed_mmu_map_address()
391 static int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, in r4k_map_address() argument
394 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; in r4k_map_address()
395 uint32_t MMID = env->CP0_MemoryMapID; in r4k_map_address()
396 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); in r4k_map_address()
402 for (i = 0; i < env->tlb->tlb_in_use; i++) { in r4k_map_address()
403 r4k_tlb_t *tlb = &env->tlb->mmu.r4k.tlb[i]; in r4k_map_address()
409 tag &= env->SEGMask; in r4k_map_address()
444 static void no_mmu_init(CPUMIPSState *env, const mips_def_t *def) in no_mmu_init() argument
446 env->tlb->nb_tlb = 1; in no_mmu_init()
447 env->tlb->map_address = &no_mmu_map_address; in no_mmu_init()
450 static void fixed_mmu_init(CPUMIPSState *env, const mips_def_t *def) in fixed_mmu_init() argument
452 env->tlb->nb_tlb = 1; in fixed_mmu_init()
453 env->tlb->map_address = &fixed_mmu_map_address; in fixed_mmu_init()
456 static void r4k_mmu_init(CPUMIPSState *env, const mips_def_t *def) in r4k_mmu_init() argument
458 env->tlb->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63); in r4k_mmu_init()
459 env->tlb->map_address = &r4k_map_address; in r4k_mmu_init()
460 env->tlb->helper_tlbwi = r4k_helper_tlbwi; in r4k_mmu_init()
461 env->tlb->helper_tlbwr = r4k_helper_tlbwr; in r4k_mmu_init()
462 env->tlb->helper_tlbp = r4k_helper_tlbp; in r4k_mmu_init()
463 env->tlb->helper_tlbr = r4k_helper_tlbr; in r4k_mmu_init()
464 env->tlb->helper_tlbinv = r4k_helper_tlbinv; in r4k_mmu_init()
465 env->tlb->helper_tlbinvf = r4k_helper_tlbinvf; in r4k_mmu_init()
468 void mmu_init(CPUMIPSState *env, const mips_def_t *def) in mmu_init() argument
470 env->tlb = g_malloc0(sizeof(CPUMIPSTLBContext)); in mmu_init()
474 no_mmu_init(env, def); in mmu_init()
477 r4k_mmu_init(env, def); in mmu_init()
480 fixed_mmu_init(env, def); in mmu_init()
486 cpu_abort(env_cpu(env), "MMU type not supported\n"); in mmu_init()
490 void cpu_mips_tlb_flush(CPUMIPSState *env) in cpu_mips_tlb_flush() argument
493 tlb_flush(env_cpu(env)); in cpu_mips_tlb_flush()
494 env->tlb->tlb_in_use = env->tlb->nb_tlb; in cpu_mips_tlb_flush()
497 static void raise_mmu_exception(CPUMIPSState *env, target_ulong address, in raise_mmu_exception() argument
500 CPUState *cs = env_cpu(env); in raise_mmu_exception()
541 if (env->CP0_PageGrain & (1 << CP0PG_IEC)) { in raise_mmu_exception()
549 if (env->CP0_PageGrain & (1 << CP0PG_IEC)) { in raise_mmu_exception()
557 if (!(env->hflags & MIPS_HFLAG_DM)) { in raise_mmu_exception()
558 env->CP0_BadVAddr = address; in raise_mmu_exception()
560 env->CP0_Context = (env->CP0_Context & ~0x007fffff) | in raise_mmu_exception()
562 env->CP0_EntryHi = (env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask) | in raise_mmu_exception()
563 (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) | in raise_mmu_exception()
566 env->CP0_EntryHi &= env->SEGMask; in raise_mmu_exception()
567 env->CP0_XContext = in raise_mmu_exception()
568 (env->CP0_XContext & ((~0ULL) << (env->SEGBITS - 7))) | /* PTEBase */ in raise_mmu_exception()
569 (extract64(address, 62, 2) << (env->SEGBITS - 9)) | /* R */ in raise_mmu_exception()
570 (extract64(address, 13, env->SEGBITS - 13) << 4); /* BadVPN2 */ in raise_mmu_exception()
573 env->error_code = error_code; in raise_mmu_exception()
595 static bool get_pte(CPUMIPSState *env, uint64_t vaddr, MemOp op, in get_pte() argument
604 oi = make_memop_idx(op | mo_endian_env(env), ptw_mmu_idx); in get_pte()
606 *pte = cpu_ldq_mmu(env, vaddr, oi, 0); in get_pte()
608 *pte = cpu_ldl_mmu(env, vaddr, oi, 0); in get_pte()
614 static uint64_t get_tlb_entry_layout(CPUMIPSState *env, uint64_t entry, in get_tlb_entry_layout() argument
630 static int walk_directory(CPUMIPSState *env, uint64_t *vaddr, in walk_directory() argument
635 int dph = (env->CP0_PWCtl >> CP0PC_DPH) & 0x1; in walk_directory()
636 int psn = (env->CP0_PWCtl >> CP0PC_PSN) & 0x3F; in walk_directory()
637 int hugepg = (env->CP0_PWCtl >> CP0PC_HUGEPG) & 0x1; in walk_directory()
638 int pf_ptew = (env->CP0_PWField >> CP0PF_PTEW) & 0x3F; in walk_directory()
645 if (get_physical_address(env, &paddr, &prot, *vaddr, MMU_DATA_LOAD, in walk_directory()
650 if (!get_pte(env, *vaddr, directory_mop, &entry, ptw_mmu_idx)) { in walk_directory()
657 entry = get_tlb_entry_layout(env, entry, leaf_mop, pf_ptew); in walk_directory()
672 if (get_physical_address(env, &paddr, &prot, vaddr2, MMU_DATA_LOAD, in walk_directory()
676 if (!get_pte(env, vaddr2, leaf_mop, &entry, ptw_mmu_idx)) { in walk_directory()
679 entry = get_tlb_entry_layout(env, entry, leaf_mop, pf_ptew); in walk_directory()
695 static bool page_table_walk_refill(CPUMIPSState *env, vaddr address, in page_table_walk_refill() argument
698 int gdw = (env->CP0_PWSize >> CP0PS_GDW) & 0x3F; in page_table_walk_refill()
699 int udw = (env->CP0_PWSize >> CP0PS_UDW) & 0x3F; in page_table_walk_refill()
700 int mdw = (env->CP0_PWSize >> CP0PS_MDW) & 0x3F; in page_table_walk_refill()
701 int ptw = (env->CP0_PWSize >> CP0PS_PTW) & 0x3F; in page_table_walk_refill()
702 int ptew = (env->CP0_PWSize >> CP0PS_PTEW) & 0x3F; in page_table_walk_refill()
718 MemOp native_op = (((env->CP0_PWSize >> CP0PS_PS) & 1) == 0) ? MO_32 : MO_64; in page_table_walk_refill()
721 int pf_gdw = (env->CP0_PWField >> CP0PF_GDW) & 0x3F; in page_table_walk_refill()
722 int pf_udw = (env->CP0_PWField >> CP0PF_UDW) & 0x3F; in page_table_walk_refill()
723 int pf_mdw = (env->CP0_PWField >> CP0PF_MDW) & 0x3F; in page_table_walk_refill()
724 int pf_ptw = (env->CP0_PWField >> CP0PF_PTW) & 0x3F; in page_table_walk_refill()
725 int pf_ptew = (env->CP0_PWField >> CP0PF_PTEW) & 0x3F; in page_table_walk_refill()
734 int hugepg = (env->CP0_PWCtl >> CP0PC_HUGEPG) & 0x1; in page_table_walk_refill()
741 uint64_t vaddr = env->CP0_PWBase; in page_table_walk_refill()
748 if (!(env->CP0_Config3 & (1 << CP0C3_PW))) { in page_table_walk_refill()
752 if (!(env->CP0_PWCtl & (1 << CP0PC_PWEN))) { in page_table_walk_refill()
777 switch (walk_directory(env, &vaddr, pf_gdw, &huge_page, &hgpg_gdhit, in page_table_walk_refill()
794 switch (walk_directory(env, &vaddr, pf_udw, &huge_page, &hgpg_udhit, in page_table_walk_refill()
811 switch (walk_directory(env, &vaddr, pf_mdw, &huge_page, &hgpg_mdhit, in page_table_walk_refill()
827 if (get_physical_address(env, &paddr, &prot, vaddr, MMU_DATA_LOAD, in page_table_walk_refill()
831 if (!get_pte(env, vaddr, leaf_mop, &dir_entry, ptw_mmu_idx)) { in page_table_walk_refill()
834 dir_entry = get_tlb_entry_layout(env, dir_entry, leaf_mop, pf_ptew); in page_table_walk_refill()
839 if (get_physical_address(env, &paddr, &prot, vaddr, MMU_DATA_LOAD, in page_table_walk_refill()
843 if (!get_pte(env, vaddr, leaf_mop, &dir_entry, ptw_mmu_idx)) { in page_table_walk_refill()
846 dir_entry = get_tlb_entry_layout(env, dir_entry, leaf_mop, pf_ptew); in page_table_walk_refill()
878 update_pagemask(env, pw_pagemask << CP0PM_MASK, &pw_pagemask); in page_table_walk_refill()
879 pw_entryhi = (address & ~0x1fff) | (env->CP0_EntryHi & 0xFF); in page_table_walk_refill()
881 target_ulong tmp_entryhi = env->CP0_EntryHi; in page_table_walk_refill()
882 int32_t tmp_pagemask = env->CP0_PageMask; in page_table_walk_refill()
883 uint64_t tmp_entrylo0 = env->CP0_EntryLo0; in page_table_walk_refill()
884 uint64_t tmp_entrylo1 = env->CP0_EntryLo1; in page_table_walk_refill()
886 env->CP0_EntryHi = pw_entryhi; in page_table_walk_refill()
887 env->CP0_PageMask = pw_pagemask; in page_table_walk_refill()
888 env->CP0_EntryLo0 = pw_entrylo0; in page_table_walk_refill()
889 env->CP0_EntryLo1 = pw_entrylo1; in page_table_walk_refill()
896 r4k_helper_tlbwr(env); in page_table_walk_refill()
898 env->CP0_EntryHi = tmp_entryhi; in page_table_walk_refill()
899 env->CP0_PageMask = tmp_pagemask; in page_table_walk_refill()
900 env->CP0_EntryLo0 = tmp_entrylo0; in page_table_walk_refill()
901 env->CP0_EntryLo1 = tmp_entrylo1; in page_table_walk_refill()
911 CPUMIPSState *env = cpu_env(cs); in mips_cpu_tlb_fill() local
918 ret = get_physical_address(env, &physical, &prot, address, in mips_cpu_tlb_fill()
939 if ((ret == TLBRET_NOMATCH) && (env->tlb->nb_tlb > 1)) { in mips_cpu_tlb_fill()
944 int ptw_mmu_idx = (env->hflags & MIPS_HFLAG_ERL ? in mips_cpu_tlb_fill()
947 if (page_table_walk_refill(env, address, ptw_mmu_idx)) { in mips_cpu_tlb_fill()
948 ret = get_physical_address(env, &physical, &prot, address, in mips_cpu_tlb_fill()
963 raise_mmu_exception(env, address, access_type, ret); in mips_cpu_tlb_fill()
964 do_raise_exception_err(env, cs->exception_index, env->error_code, retaddr); in mips_cpu_tlb_fill()
967 hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, in cpu_mips_translate_address() argument
973 CPUState *cs = env_cpu(env); in cpu_mips_translate_address()
976 ret = get_physical_address(env, &physical, &prot, address, access_type, in cpu_mips_translate_address()
977 mips_env_mmu_index(env)); in cpu_mips_translate_address()
982 raise_mmu_exception(env, address, access_type, ret); in cpu_mips_translate_address()
986 static void set_hflags_for_handler(CPUMIPSState *env) in set_hflags_for_handler() argument
989 env->hflags &= ~(MIPS_HFLAG_M16); in set_hflags_for_handler()
991 if (env->insn_flags & ASE_MICROMIPS) { in set_hflags_for_handler()
992 env->hflags |= (!!(env->CP0_Config3 & in set_hflags_for_handler()
998 static inline void set_badinstr_registers(CPUMIPSState *env) in set_badinstr_registers() argument
1000 if (env->insn_flags & ISA_NANOMIPS32) { in set_badinstr_registers()
1001 if (env->CP0_Config3 & (1 << CP0C3_BI)) { in set_badinstr_registers()
1002 uint32_t instr = (cpu_lduw_code(env, env->active_tc.PC)) << 16; in set_badinstr_registers()
1004 instr |= cpu_lduw_code(env, env->active_tc.PC + 2); in set_badinstr_registers()
1006 env->CP0_BadInstr = instr; in set_badinstr_registers()
1009 instr = cpu_lduw_code(env, env->active_tc.PC + 4) << 16; in set_badinstr_registers()
1010 env->CP0_BadInstrX = instr; in set_badinstr_registers()
1016 if (env->hflags & MIPS_HFLAG_M16) { in set_badinstr_registers()
1020 if (env->CP0_Config3 & (1 << CP0C3_BI)) { in set_badinstr_registers()
1021 env->CP0_BadInstr = cpu_ldl_code(env, env->active_tc.PC); in set_badinstr_registers()
1023 if ((env->CP0_Config3 & (1 << CP0C3_BP)) && in set_badinstr_registers()
1024 (env->hflags & MIPS_HFLAG_BMASK)) { in set_badinstr_registers()
1025 env->CP0_BadInstrP = cpu_ldl_code(env, env->active_tc.PC - 4); in set_badinstr_registers()
1032 CPUMIPSState *env = &cpu->env; in mips_cpu_do_interrupt() local
1041 __func__, env->active_tc.PC, env->CP0_EPC, in mips_cpu_do_interrupt()
1045 (env->hflags & MIPS_HFLAG_DM)) { in mips_cpu_do_interrupt()
1052 mips_semihosting(env); in mips_cpu_do_interrupt()
1053 env->active_tc.PC += env->error_code; in mips_cpu_do_interrupt()
1056 env->CP0_Debug |= 1 << CP0DB_DSS; in mips_cpu_do_interrupt()
1063 env->CP0_DEPC = env->active_tc.PC | !!(env->hflags & MIPS_HFLAG_M16); in mips_cpu_do_interrupt()
1066 env->CP0_Debug |= 1 << CP0DB_DINT; in mips_cpu_do_interrupt()
1069 env->CP0_Debug |= 1 << CP0DB_DIB; in mips_cpu_do_interrupt()
1072 env->CP0_Debug |= 1 << CP0DB_DBp; in mips_cpu_do_interrupt()
1074 env->CP0_Debug = (env->CP0_Debug & ~(0x1fULL << CP0DB_DEC)) | in mips_cpu_do_interrupt()
1078 env->CP0_Debug |= 1 << CP0DB_DDBS; in mips_cpu_do_interrupt()
1081 env->CP0_Debug |= 1 << CP0DB_DDBL; in mips_cpu_do_interrupt()
1083 env->CP0_DEPC = exception_resume_pc(env); in mips_cpu_do_interrupt()
1084 env->hflags &= ~MIPS_HFLAG_BMASK; in mips_cpu_do_interrupt()
1086 if (env->insn_flags & ISA_MIPS3) { in mips_cpu_do_interrupt()
1087 env->hflags |= MIPS_HFLAG_64; in mips_cpu_do_interrupt()
1088 if (!(env->insn_flags & ISA_MIPS_R6) || in mips_cpu_do_interrupt()
1089 env->CP0_Status & (1 << CP0St_KX)) { in mips_cpu_do_interrupt()
1090 env->hflags &= ~MIPS_HFLAG_AWRAP; in mips_cpu_do_interrupt()
1093 env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_CP0; in mips_cpu_do_interrupt()
1094 env->hflags &= ~(MIPS_HFLAG_KSU); in mips_cpu_do_interrupt()
1096 if (!(env->CP0_Status & (1 << CP0St_EXL))) { in mips_cpu_do_interrupt()
1097 env->CP0_Cause &= ~(1U << CP0Ca_BD); in mips_cpu_do_interrupt()
1099 env->active_tc.PC = env->exception_base + 0x480; in mips_cpu_do_interrupt()
1100 set_hflags_for_handler(env); in mips_cpu_do_interrupt()
1106 env->CP0_Status |= (1 << CP0St_SR); in mips_cpu_do_interrupt()
1107 memset(env->CP0_WatchLo, 0, sizeof(env->CP0_WatchLo)); in mips_cpu_do_interrupt()
1110 env->CP0_Status |= (1 << CP0St_NMI); in mips_cpu_do_interrupt()
1112 env->CP0_ErrorEPC = exception_resume_pc(env); in mips_cpu_do_interrupt()
1113 env->hflags &= ~MIPS_HFLAG_BMASK; in mips_cpu_do_interrupt()
1114 env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); in mips_cpu_do_interrupt()
1115 if (env->insn_flags & ISA_MIPS3) { in mips_cpu_do_interrupt()
1116 env->hflags |= MIPS_HFLAG_64; in mips_cpu_do_interrupt()
1117 if (!(env->insn_flags & ISA_MIPS_R6) || in mips_cpu_do_interrupt()
1118 env->CP0_Status & (1 << CP0St_KX)) { in mips_cpu_do_interrupt()
1119 env->hflags &= ~MIPS_HFLAG_AWRAP; in mips_cpu_do_interrupt()
1122 env->hflags |= MIPS_HFLAG_CP0; in mips_cpu_do_interrupt()
1123 env->hflags &= ~(MIPS_HFLAG_KSU); in mips_cpu_do_interrupt()
1124 if (!(env->CP0_Status & (1 << CP0St_EXL))) { in mips_cpu_do_interrupt()
1125 env->CP0_Cause &= ~(1U << CP0Ca_BD); in mips_cpu_do_interrupt()
1127 env->active_tc.PC = env->exception_base; in mips_cpu_do_interrupt()
1128 set_hflags_for_handler(env); in mips_cpu_do_interrupt()
1132 if (env->CP0_Cause & (1 << CP0Ca_IV)) { in mips_cpu_do_interrupt()
1133 uint32_t spacing = (env->CP0_IntCtl >> CP0IntCtl_VS) & 0x1f; in mips_cpu_do_interrupt()
1135 if ((env->CP0_Status & (1 << CP0St_BEV)) || spacing == 0) { in mips_cpu_do_interrupt()
1139 uint32_t pending = (env->CP0_Cause & CP0Ca_IP_mask) >> CP0Ca_IP; in mips_cpu_do_interrupt()
1141 if (env->CP0_Config3 & (1 << CP0C3_VEIC)) { in mips_cpu_do_interrupt()
1152 pending &= (env->CP0_Status >> CP0St_IM) & 0xff; in mips_cpu_do_interrupt()
1164 update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL); in mips_cpu_do_interrupt()
1168 update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL); in mips_cpu_do_interrupt()
1169 if ((env->error_code & EXCP_TLB_NOMATCH) && in mips_cpu_do_interrupt()
1170 !(env->CP0_Status & (1 << CP0St_EXL))) { in mips_cpu_do_interrupt()
1172 int R = env->CP0_BadVAddr >> 62; in mips_cpu_do_interrupt()
1173 int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0; in mips_cpu_do_interrupt()
1174 int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0; in mips_cpu_do_interrupt()
1177 (!(env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)))) { in mips_cpu_do_interrupt()
1190 if ((env->error_code & EXCP_TLB_NOMATCH) && in mips_cpu_do_interrupt()
1191 !(env->CP0_Status & (1 << CP0St_EXL))) { in mips_cpu_do_interrupt()
1193 int R = env->CP0_BadVAddr >> 62; in mips_cpu_do_interrupt()
1194 int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0; in mips_cpu_do_interrupt()
1195 int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0; in mips_cpu_do_interrupt()
1198 (!(env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)))) { in mips_cpu_do_interrupt()
1210 update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL); in mips_cpu_do_interrupt()
1237 env->CP0_Cause = (env->CP0_Cause & ~(0x3 << CP0Ca_CE)) | in mips_cpu_do_interrupt()
1238 (env->error_code << CP0Ca_CE); in mips_cpu_do_interrupt()
1290 if (!(env->CP0_Status & (1 << CP0St_EXL))) { in mips_cpu_do_interrupt()
1291 env->CP0_EPC = exception_resume_pc(env); in mips_cpu_do_interrupt()
1293 set_badinstr_registers(env); in mips_cpu_do_interrupt()
1295 if (env->hflags & MIPS_HFLAG_BMASK) { in mips_cpu_do_interrupt()
1296 env->CP0_Cause |= (1U << CP0Ca_BD); in mips_cpu_do_interrupt()
1298 env->CP0_Cause &= ~(1U << CP0Ca_BD); in mips_cpu_do_interrupt()
1300 env->CP0_Status |= (1 << CP0St_EXL); in mips_cpu_do_interrupt()
1301 if (env->insn_flags & ISA_MIPS3) { in mips_cpu_do_interrupt()
1302 env->hflags |= MIPS_HFLAG_64; in mips_cpu_do_interrupt()
1303 if (!(env->insn_flags & ISA_MIPS_R6) || in mips_cpu_do_interrupt()
1304 env->CP0_Status & (1 << CP0St_KX)) { in mips_cpu_do_interrupt()
1305 env->hflags &= ~MIPS_HFLAG_AWRAP; in mips_cpu_do_interrupt()
1308 env->hflags |= MIPS_HFLAG_CP0; in mips_cpu_do_interrupt()
1309 env->hflags &= ~(MIPS_HFLAG_KSU); in mips_cpu_do_interrupt()
1311 env->hflags &= ~MIPS_HFLAG_BMASK; in mips_cpu_do_interrupt()
1312 if (env->CP0_Status & (1 << CP0St_BEV)) { in mips_cpu_do_interrupt()
1313 env->active_tc.PC = env->exception_base + 0x200; in mips_cpu_do_interrupt()
1314 } else if (cause == 30 && !(env->CP0_Config3 & (1 << CP0C3_SC) && in mips_cpu_do_interrupt()
1315 env->CP0_Config5 & (1 << CP0C5_CV))) { in mips_cpu_do_interrupt()
1317 env->active_tc.PC = KSEG1_BASE | (env->CP0_EBase & 0x1FFFF000); in mips_cpu_do_interrupt()
1319 env->active_tc.PC = env->CP0_EBase & ~0xfff; in mips_cpu_do_interrupt()
1322 env->active_tc.PC += offset; in mips_cpu_do_interrupt()
1323 set_hflags_for_handler(env); in mips_cpu_do_interrupt()
1324 env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | in mips_cpu_do_interrupt()
1334 __func__, env->active_tc.PC, env->CP0_EPC, cause, in mips_cpu_do_interrupt()
1335 env->CP0_Status, env->CP0_Cause, env->CP0_BadVAddr, in mips_cpu_do_interrupt()
1336 env->CP0_DEPC); in mips_cpu_do_interrupt()
1344 CPUMIPSState *env = cpu_env(cs); in mips_cpu_exec_interrupt() local
1346 if (cpu_mips_hw_interrupts_enabled(env) && in mips_cpu_exec_interrupt()
1347 cpu_mips_hw_interrupts_pending(env)) { in mips_cpu_exec_interrupt()
1350 env->error_code = 0; in mips_cpu_exec_interrupt()
1358 void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra) in r4k_invalidate_tlb() argument
1360 CPUState *cs = env_cpu(env); in r4k_invalidate_tlb()
1364 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; in r4k_invalidate_tlb()
1365 uint32_t MMID = env->CP0_MemoryMapID; in r4k_invalidate_tlb()
1366 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); in r4k_invalidate_tlb()
1372 tlb = &env->tlb->mmu.r4k.tlb[idx]; in r4k_invalidate_tlb()
1382 if (use_extra && env->tlb->tlb_in_use < MIPS_TLB_MAX) { in r4k_invalidate_tlb()
1388 env->tlb->mmu.r4k.tlb[env->tlb->tlb_in_use] = *tlb; in r4k_invalidate_tlb()
1389 env->tlb->tlb_in_use++; in r4k_invalidate_tlb()
1398 if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) { in r4k_invalidate_tlb()
1411 if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) { in r4k_invalidate_tlb()