diff options
Diffstat (limited to 'target-sh4/helper.c')
-rw-r--r-- | target-sh4/helper.c | 114 |
1 files changed, 43 insertions, 71 deletions
diff --git a/target-sh4/helper.c b/target-sh4/helper.c index 088d36a5f7..f38e6abdaf 100644 --- a/target-sh4/helper.c +++ b/target-sh4/helper.c @@ -261,24 +261,6 @@ static int find_tlb_entry(CPUState * env, target_ulong address, continue; /* Invalid entry */ if (!entries[i].sh && use_asid && entries[i].asid != asid) continue; /* Bad ASID */ -#if 0 - switch (entries[i].sz) { - case 0: - size = 1024; /* 1kB */ - break; - case 1: - size = 4 * 1024; /* 4kB */ - break; - case 2: - size = 64 * 1024; /* 64kB */ - break; - case 3: - size = 1024 * 1024; /* 1MB */ - break; - default: - assert(0); - } -#endif start = (entries[i].vpn << 10) & ~(entries[i].size - 1); end = start + entries[i].size - 1; if (address >= start && address <= end) { /* Match */ @@ -290,16 +272,6 @@ static int find_tlb_entry(CPUState * env, target_ulong address, return match; } -static int same_tlb_entry_exists(const tlb_t * haystack, uint8_t nbtlb, - const tlb_t * needle) -{ - int i; - for (i = 0; i < nbtlb; i++) - if (!memcmp(&haystack[i], needle, sizeof(tlb_t))) - return 1; - return 0; -} - static void increment_urc(CPUState * env) { uint8_t urb, urc; @@ -332,8 +304,7 @@ static int find_itlb_entry(CPUState * env, target_ulong address, n = itlb_replacement(env); ientry = &env->itlb[n]; if (ientry->v) { - if (!same_tlb_entry_exists(env->utlb, UTLB_SIZE, ientry)) - tlb_flush_page(env, ientry->vpn << 10); + tlb_flush_page(env, ientry->vpn << 10); } *ientry = env->utlb[e]; e = n; @@ -377,47 +348,37 @@ static int get_mmu_address(CPUState * env, target_ulong * physical, n = find_itlb_entry(env, address, use_asid, 1); if (n >= 0) { matching = &env->itlb[n]; - if ((env->sr & SR_MD) & !(matching->pr & 2)) + if (!(env->sr & SR_MD) && !(matching->pr & 2)) n = MMU_ITLB_VIOLATION; else - *prot = PAGE_READ; + *prot = PAGE_EXEC; } } else { n = find_utlb_entry(env, address, use_asid); if (n >= 0) { matching = &env->utlb[n]; - switch ((matching->pr << 1) | ((env->sr & SR_MD) ? 1 : 0)) { - case 0: /* 000 */ - case 2: /* 010 */ - n = (rw == 1) ? MMU_DTLB_VIOLATION_WRITE : - MMU_DTLB_VIOLATION_READ; - break; - case 1: /* 001 */ - case 4: /* 100 */ - case 5: /* 101 */ - if (rw == 1) - n = MMU_DTLB_VIOLATION_WRITE; - else - *prot = PAGE_READ; - break; - case 3: /* 011 */ - case 6: /* 110 */ - case 7: /* 111 */ - *prot = (rw == 1)? PAGE_WRITE : PAGE_READ; - break; - } + if (!(env->sr & SR_MD) && !(matching->pr & 2)) { + n = (rw == 1) ? MMU_DTLB_VIOLATION_WRITE : + MMU_DTLB_VIOLATION_READ; + } else if ((rw == 1) && !(matching->pr & 1)) { + n = MMU_DTLB_VIOLATION_WRITE; + } else if ((rw == 1) & !matching->d) { + n = MMU_DTLB_INITIAL_WRITE; + } else { + *prot = PAGE_READ; + if ((matching->pr & 1) && matching->d) { + *prot |= PAGE_WRITE; + } + } } else if (n == MMU_DTLB_MISS) { n = (rw == 1) ? MMU_DTLB_MISS_WRITE : MMU_DTLB_MISS_READ; } } if (n >= 0) { + n = MMU_OK; *physical = ((matching->ppn << 10) & ~(matching->size - 1)) | (address & (matching->size - 1)); - if ((rw == 1) & !matching->d) - n = MMU_DTLB_INITIAL_WRITE; - else - n = MMU_OK; } return n; } @@ -430,7 +391,7 @@ static int get_physical_address(CPUState * env, target_ulong * physical, if ((address >= 0x80000000 && address < 0xc0000000) || address >= 0xe0000000) { if (!(env->sr & SR_MD) - && (address < 0xe0000000 || address > 0xe4000000)) { + && (address < 0xe0000000 || address >= 0xe4000000)) { /* Unauthorized access in user mode (only store queues are available) */ fprintf(stderr, "Unauthorized access\n"); if (rw == 0) @@ -446,14 +407,14 @@ static int get_physical_address(CPUState * env, target_ulong * physical, } else { *physical = address; } - *prot = PAGE_READ | PAGE_WRITE; + *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; return MMU_OK; } /* If MMU is disabled, return the corresponding physical page */ if (!env->mmucr & MMUCR_AT) { *physical = address & 0x1FFFFFFF; - *prot = PAGE_READ | PAGE_WRITE; + *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; return MMU_OK; } @@ -464,7 +425,7 @@ static int get_physical_address(CPUState * env, target_ulong * physical, int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw, int mmu_idx, int is_softmmu) { - target_ulong physical, page_offset, page_size; + target_ulong physical; int prot, ret, access_type; access_type = ACCESS_INT; @@ -511,11 +472,8 @@ int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw, return 1; } - page_size = TARGET_PAGE_SIZE; - page_offset = - (address - (address & TARGET_PAGE_MASK)) & ~(page_size - 1); - address = (address & TARGET_PAGE_MASK) + page_offset; - physical = (physical & TARGET_PAGE_MASK) + page_offset; + address &= TARGET_PAGE_MASK; + physical &= TARGET_PAGE_MASK; return tlb_set_page(env, address, physical, prot, mmu_idx, is_softmmu); } @@ -537,9 +495,7 @@ void cpu_load_tlb(CPUSH4State * env) if (entry->v) { /* Overwriting valid entry in utlb. */ target_ulong address = entry->vpn << 10; - if (!same_tlb_entry_exists(env->itlb, ITLB_SIZE, entry)) { - tlb_flush_page(env, address); - } + tlb_flush_page(env, address); } /* Take values into cpu status from registers. */ @@ -574,6 +530,24 @@ void cpu_load_tlb(CPUSH4State * env) entry->tc = (uint8_t)cpu_ptea_tc(env->ptea); } + void cpu_sh4_invalidate_tlb(CPUSH4State *s) +{ + int i; + + /* UTLB */ + for (i = 0; i < UTLB_SIZE; i++) { + tlb_t * entry = &s->utlb[i]; + entry->v = 0; + } + /* ITLB */ + for (i = 0; i < UTLB_SIZE; i++) { + tlb_t * entry = &s->utlb[i]; + entry->v = 0; + } + + tlb_flush(s, 1); +} + void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr, uint32_t mem_value) { @@ -636,9 +610,7 @@ void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr, if (entry->v) { /* Overwriting valid entry in utlb. */ target_ulong address = entry->vpn << 10; - if (!same_tlb_entry_exists(s->itlb, ITLB_SIZE, entry)) { - tlb_flush_page(s, address); - } + tlb_flush_page(s, address); } entry->asid = asid; entry->vpn = vpn; |