Commit 43057ab1272ba2b9b052b19a3453fb0f3b510149
1 parent
c5d6edc3
use constants for TLB handling (Thiemo Seufer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1978 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
36 additions
and
33 deletions
target-mips/cpu.h
| @@ -87,7 +87,7 @@ struct CPUMIPSState { | @@ -87,7 +87,7 @@ struct CPUMIPSState { | ||
| 87 | 87 | ||
| 88 | #endif | 88 | #endif |
| 89 | #if defined(MIPS_USES_R4K_TLB) | 89 | #if defined(MIPS_USES_R4K_TLB) |
| 90 | - tlb_t tlb[16]; | 90 | + tlb_t tlb[MIPS_TLB_NB]; |
| 91 | #endif | 91 | #endif |
| 92 | uint32_t CP0_index; | 92 | uint32_t CP0_index; |
| 93 | uint32_t CP0_random; | 93 | uint32_t CP0_random; |
target-mips/helper.c
| @@ -28,53 +28,56 @@ | @@ -28,53 +28,56 @@ | ||
| 28 | #include "cpu.h" | 28 | #include "cpu.h" |
| 29 | #include "exec-all.h" | 29 | #include "exec-all.h" |
| 30 | 30 | ||
| 31 | +enum { | ||
| 32 | + TLBRET_DIRTY = -4, | ||
| 33 | + TLBRET_INVALID = -3, | ||
| 34 | + TLBRET_NOMATCH = -2, | ||
| 35 | + TLBRET_BADADDR = -1, | ||
| 36 | + TLBRET_MATCH = 0 | ||
| 37 | +}; | ||
| 38 | + | ||
| 31 | /* MIPS32 4K MMU emulation */ | 39 | /* MIPS32 4K MMU emulation */ |
| 32 | #ifdef MIPS_USES_R4K_TLB | 40 | #ifdef MIPS_USES_R4K_TLB |
| 33 | static int map_address (CPUState *env, target_ulong *physical, int *prot, | 41 | static int map_address (CPUState *env, target_ulong *physical, int *prot, |
| 34 | target_ulong address, int rw, int access_type) | 42 | target_ulong address, int rw, int access_type) |
| 35 | { | 43 | { |
| 44 | + target_ulong tag = address & (TARGET_PAGE_MASK << 1); | ||
| 45 | + uint8_t ASID = env->CP0_EntryHi & 0xFF; | ||
| 36 | tlb_t *tlb; | 46 | tlb_t *tlb; |
| 37 | - target_ulong tag; | ||
| 38 | - uint8_t ASID; | ||
| 39 | int i, n; | 47 | int i, n; |
| 40 | - int ret; | ||
| 41 | 48 | ||
| 42 | - ret = -2; | ||
| 43 | - tag = address & 0xFFFFE000; | ||
| 44 | - ASID = env->CP0_EntryHi & 0xFF; | ||
| 45 | for (i = 0; i < MIPS_TLB_NB; i++) { | 49 | for (i = 0; i < MIPS_TLB_NB; i++) { |
| 46 | tlb = &env->tlb[i]; | 50 | tlb = &env->tlb[i]; |
| 47 | /* Check ASID, virtual page number & size */ | 51 | /* Check ASID, virtual page number & size */ |
| 48 | if ((tlb->G == 1 || tlb->ASID == ASID) && | 52 | if ((tlb->G == 1 || tlb->ASID == ASID) && |
| 49 | tlb->VPN == tag && address < tlb->end2) { | 53 | tlb->VPN == tag && address < tlb->end2) { |
| 50 | /* TLB match */ | 54 | /* TLB match */ |
| 51 | - n = (address >> 12) & 1; | 55 | + n = (address >> TARGET_PAGE_BITS) & 1; |
| 52 | /* Check access rights */ | 56 | /* Check access rights */ |
| 53 | - if (!(n ? tlb->V1 : tlb->V0)) | ||
| 54 | - return -3; | ||
| 55 | - if (rw == 0 || (n ? tlb->D1 : tlb->D0)) { | ||
| 56 | - *physical = tlb->PFN[n] | (address & 0xFFF); | 57 | + if (!(n ? tlb->V1 : tlb->V0)) |
| 58 | + return TLBRET_INVALID; | ||
| 59 | + if (rw == 0 || (n ? tlb->D1 : tlb->D0)) { | ||
| 60 | + *physical = tlb->PFN[n] | (address & ~TARGET_PAGE_MASK); | ||
| 57 | *prot = PAGE_READ; | 61 | *prot = PAGE_READ; |
| 58 | if (n ? tlb->D1 : tlb->D0) | 62 | if (n ? tlb->D1 : tlb->D0) |
| 59 | *prot |= PAGE_WRITE; | 63 | *prot |= PAGE_WRITE; |
| 60 | - return 0; | 64 | + return TLBRET_MATCH; |
| 61 | } | 65 | } |
| 62 | - return -4; | 66 | + return TLBRET_DIRTY; |
| 63 | } | 67 | } |
| 64 | } | 68 | } |
| 65 | - | ||
| 66 | - return ret; | 69 | + return TLBRET_NOMATCH; |
| 67 | } | 70 | } |
| 68 | #endif | 71 | #endif |
| 69 | 72 | ||
| 70 | -int get_physical_address (CPUState *env, target_ulong *physical, int *prot, | ||
| 71 | - target_ulong address, int rw, int access_type) | 73 | +static int get_physical_address (CPUState *env, target_ulong *physical, |
| 74 | + int *prot, target_ulong address, | ||
| 75 | + int rw, int access_type) | ||
| 72 | { | 76 | { |
| 73 | - int user_mode; | ||
| 74 | - int ret; | ||
| 75 | - | ||
| 76 | /* User mode can only access useg */ | 77 | /* User mode can only access useg */ |
| 77 | - user_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM; | 78 | + int user_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM; |
| 79 | + int ret = TLBRET_MATCH; | ||
| 80 | + | ||
| 78 | #if 0 | 81 | #if 0 |
| 79 | if (logfile) { | 82 | if (logfile) { |
| 80 | fprintf(logfile, "user mode %d h %08x\n", | 83 | fprintf(logfile, "user mode %d h %08x\n", |
| @@ -82,8 +85,7 @@ int get_physical_address (CPUState *env, target_ulong *physical, int *prot, | @@ -82,8 +85,7 @@ int get_physical_address (CPUState *env, target_ulong *physical, int *prot, | ||
| 82 | } | 85 | } |
| 83 | #endif | 86 | #endif |
| 84 | if (user_mode && address > 0x7FFFFFFFUL) | 87 | if (user_mode && address > 0x7FFFFFFFUL) |
| 85 | - return -1; | ||
| 86 | - ret = 0; | 88 | + return TLBRET_BADADDR; |
| 87 | if (address < 0x80000000UL) { | 89 | if (address < 0x80000000UL) { |
| 88 | if (!(env->hflags & MIPS_HFLAG_ERL)) { | 90 | if (!(env->hflags & MIPS_HFLAG_ERL)) { |
| 89 | #ifdef MIPS_USES_R4K_TLB | 91 | #ifdef MIPS_USES_R4K_TLB |
| @@ -181,7 +183,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | @@ -181,7 +183,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | ||
| 181 | access_type = ACCESS_INT; | 183 | access_type = ACCESS_INT; |
| 182 | if (env->user_mode_only) { | 184 | if (env->user_mode_only) { |
| 183 | /* user mode only emulation */ | 185 | /* user mode only emulation */ |
| 184 | - ret = -2; | 186 | + ret = TLBRET_NOMATCH; |
| 185 | goto do_fault; | 187 | goto do_fault; |
| 186 | } | 188 | } |
| 187 | ret = get_physical_address(env, &physical, &prot, | 189 | ret = get_physical_address(env, &physical, &prot, |
| @@ -190,14 +192,15 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | @@ -190,14 +192,15 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | ||
| 190 | fprintf(logfile, "%s address=%08x ret %d physical %08x prot %d\n", | 192 | fprintf(logfile, "%s address=%08x ret %d physical %08x prot %d\n", |
| 191 | __func__, address, ret, physical, prot); | 193 | __func__, address, ret, physical, prot); |
| 192 | } | 194 | } |
| 193 | - if (ret == 0) { | ||
| 194 | - ret = tlb_set_page(env, address & ~0xFFF, physical & ~0xFFF, prot, | ||
| 195 | - is_user, is_softmmu); | 195 | + if (ret == TLBRET_MATCH) { |
| 196 | + ret = tlb_set_page(env, address & TARGET_PAGE_MASK, | ||
| 197 | + physical & TARGET_PAGE_MASK, prot, | ||
| 198 | + is_user, is_softmmu); | ||
| 196 | } else if (ret < 0) { | 199 | } else if (ret < 0) { |
| 197 | do_fault: | 200 | do_fault: |
| 198 | switch (ret) { | 201 | switch (ret) { |
| 199 | default: | 202 | default: |
| 200 | - case -1: | 203 | + case TLBRET_BADADDR: |
| 201 | /* Reference to kernel address from user mode or supervisor mode */ | 204 | /* Reference to kernel address from user mode or supervisor mode */ |
| 202 | /* Reference to supervisor address from user mode */ | 205 | /* Reference to supervisor address from user mode */ |
| 203 | if (rw) | 206 | if (rw) |
| @@ -205,7 +208,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | @@ -205,7 +208,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | ||
| 205 | else | 208 | else |
| 206 | exception = EXCP_AdEL; | 209 | exception = EXCP_AdEL; |
| 207 | break; | 210 | break; |
| 208 | - case -2: | 211 | + case TLBRET_NOMATCH: |
| 209 | /* No TLB match for a mapped address */ | 212 | /* No TLB match for a mapped address */ |
| 210 | if (rw) | 213 | if (rw) |
| 211 | exception = EXCP_TLBS; | 214 | exception = EXCP_TLBS; |
| @@ -213,14 +216,14 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | @@ -213,14 +216,14 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | ||
| 213 | exception = EXCP_TLBL; | 216 | exception = EXCP_TLBL; |
| 214 | error_code = 1; | 217 | error_code = 1; |
| 215 | break; | 218 | break; |
| 216 | - case -3: | 219 | + case TLBRET_INVALID: |
| 217 | /* TLB match with no valid bit */ | 220 | /* TLB match with no valid bit */ |
| 218 | if (rw) | 221 | if (rw) |
| 219 | exception = EXCP_TLBS; | 222 | exception = EXCP_TLBS; |
| 220 | else | 223 | else |
| 221 | exception = EXCP_TLBL; | 224 | exception = EXCP_TLBL; |
| 222 | break; | 225 | break; |
| 223 | - case -4: | 226 | + case TLBRET_DIRTY: |
| 224 | /* TLB match but 'D' bit is cleared */ | 227 | /* TLB match but 'D' bit is cleared */ |
| 225 | exception = EXCP_LTLBL; | 228 | exception = EXCP_LTLBL; |
| 226 | break; | 229 | break; |
| @@ -231,7 +234,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | @@ -231,7 +234,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | ||
| 231 | env->CP0_Context = (env->CP0_Context & 0xff800000) | | 234 | env->CP0_Context = (env->CP0_Context & 0xff800000) | |
| 232 | ((address >> 9) & 0x007ffff0); | 235 | ((address >> 9) & 0x007ffff0); |
| 233 | env->CP0_EntryHi = | 236 | env->CP0_EntryHi = |
| 234 | - (env->CP0_EntryHi & 0xFF) | (address & 0xFFFFE000); | 237 | + (env->CP0_EntryHi & 0xFF) | (address & (TARGET_PAGE_MASK << 1)); |
| 235 | env->exception_index = exception; | 238 | env->exception_index = exception; |
| 236 | env->error_code = error_code; | 239 | env->error_code = error_code; |
| 237 | ret = 1; | 240 | ret = 1; |