- reg_t idx = (addr >> PGSHIFT) % TLB_ENTRIES;
- reg_t expected_tag = addr >> PGSHIFT;
-
- reg_t pte = 0;
- reg_t mstatus = proc ? proc->state.mstatus : 0;
-
- bool vm_disabled = get_field(mstatus, MSTATUS_VM) == VM_MBARE;
- bool mode_m = get_field(mstatus, MSTATUS_PRV) == PRV_M;
- bool mode_s = get_field(mstatus, MSTATUS_PRV) == PRV_S;
- bool mprv_m = get_field(mstatus, MSTATUS_MPRV) == PRV_M;
- bool mprv_s = get_field(mstatus, MSTATUS_MPRV) == PRV_S;
-
- reg_t want_perm = store ? (mode_s || (mode_m && mprv_s) ? PTE_SW : PTE_UW) :
- !fetch ? (mode_s || (mode_m && mprv_s) ? PTE_SR : PTE_UR) :
- (mode_s ? PTE_SX : PTE_UX);
-
- if (vm_disabled || (mode_m && (mprv_m || fetch))) {
- // virtual memory is disabled. merely check legality of physical address.
- if (addr < memsz) {
- // produce a fake PTE for the TLB's benefit.
- pte = PTE_V | PTE_UX | PTE_SX | ((addr >> PGSHIFT) << PGSHIFT);
- if (vm_disabled || !(mode_m && !mprv_m))
- pte |= PTE_UR | PTE_SR | PTE_UW | PTE_SW;
- }
+ if (!proc)
+ return addr;
+
+ reg_t mode = proc->state.prv;
+ if (type != FETCH) {
+ if (!proc->state.dcsr.cause && get_field(proc->state.mstatus, MSTATUS_MPRV))
+ mode = get_field(proc->state.mstatus, MSTATUS_MPP);
+ }
+
+ return walk(addr, type, mode) | (addr & (PGSIZE-1));
+}
+
+tlb_entry_t mmu_t::fetch_slow_path(reg_t vaddr)
+{
+ reg_t paddr = translate(vaddr, FETCH);
+
+ if (auto host_addr = sim->addr_to_mem(paddr)) {
+ return refill_tlb(vaddr, paddr, host_addr, FETCH);