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
target-mips/helper.c
... | ... | @@ -28,53 +28,56 @@ |
28 | 28 | #include "cpu.h" |
29 | 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 | 39 | /* MIPS32 4K MMU emulation */ |
32 | 40 | #ifdef MIPS_USES_R4K_TLB |
33 | 41 | static int map_address (CPUState *env, target_ulong *physical, int *prot, |
34 | 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 | 46 | tlb_t *tlb; |
37 | - target_ulong tag; | |
38 | - uint8_t ASID; | |
39 | 47 | int i, n; |
40 | - int ret; | |
41 | 48 | |
42 | - ret = -2; | |
43 | - tag = address & 0xFFFFE000; | |
44 | - ASID = env->CP0_EntryHi & 0xFF; | |
45 | 49 | for (i = 0; i < MIPS_TLB_NB; i++) { |
46 | 50 | tlb = &env->tlb[i]; |
47 | 51 | /* Check ASID, virtual page number & size */ |
48 | 52 | if ((tlb->G == 1 || tlb->ASID == ASID) && |
49 | 53 | tlb->VPN == tag && address < tlb->end2) { |
50 | 54 | /* TLB match */ |
51 | - n = (address >> 12) & 1; | |
55 | + n = (address >> TARGET_PAGE_BITS) & 1; | |
52 | 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 | 61 | *prot = PAGE_READ; |
58 | 62 | if (n ? tlb->D1 : tlb->D0) |
59 | 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 | 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 | 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 | 81 | #if 0 |
79 | 82 | if (logfile) { |
80 | 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 | 85 | } |
83 | 86 | #endif |
84 | 87 | if (user_mode && address > 0x7FFFFFFFUL) |
85 | - return -1; | |
86 | - ret = 0; | |
88 | + return TLBRET_BADADDR; | |
87 | 89 | if (address < 0x80000000UL) { |
88 | 90 | if (!(env->hflags & MIPS_HFLAG_ERL)) { |
89 | 91 | #ifdef MIPS_USES_R4K_TLB |
... | ... | @@ -181,7 +183,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, |
181 | 183 | access_type = ACCESS_INT; |
182 | 184 | if (env->user_mode_only) { |
183 | 185 | /* user mode only emulation */ |
184 | - ret = -2; | |
186 | + ret = TLBRET_NOMATCH; | |
185 | 187 | goto do_fault; |
186 | 188 | } |
187 | 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 | 192 | fprintf(logfile, "%s address=%08x ret %d physical %08x prot %d\n", |
191 | 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 | 199 | } else if (ret < 0) { |
197 | 200 | do_fault: |
198 | 201 | switch (ret) { |
199 | 202 | default: |
200 | - case -1: | |
203 | + case TLBRET_BADADDR: | |
201 | 204 | /* Reference to kernel address from user mode or supervisor mode */ |
202 | 205 | /* Reference to supervisor address from user mode */ |
203 | 206 | if (rw) |
... | ... | @@ -205,7 +208,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, |
205 | 208 | else |
206 | 209 | exception = EXCP_AdEL; |
207 | 210 | break; |
208 | - case -2: | |
211 | + case TLBRET_NOMATCH: | |
209 | 212 | /* No TLB match for a mapped address */ |
210 | 213 | if (rw) |
211 | 214 | exception = EXCP_TLBS; |
... | ... | @@ -213,14 +216,14 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, |
213 | 216 | exception = EXCP_TLBL; |
214 | 217 | error_code = 1; |
215 | 218 | break; |
216 | - case -3: | |
219 | + case TLBRET_INVALID: | |
217 | 220 | /* TLB match with no valid bit */ |
218 | 221 | if (rw) |
219 | 222 | exception = EXCP_TLBS; |
220 | 223 | else |
221 | 224 | exception = EXCP_TLBL; |
222 | 225 | break; |
223 | - case -4: | |
226 | + case TLBRET_DIRTY: | |
224 | 227 | /* TLB match but 'D' bit is cleared */ |
225 | 228 | exception = EXCP_LTLBL; |
226 | 229 | break; |
... | ... | @@ -231,7 +234,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, |
231 | 234 | env->CP0_Context = (env->CP0_Context & 0xff800000) | |
232 | 235 | ((address >> 9) & 0x007ffff0); |
233 | 236 | env->CP0_EntryHi = |
234 | - (env->CP0_EntryHi & 0xFF) | (address & 0xFFFFE000); | |
237 | + (env->CP0_EntryHi & 0xFF) | (address & (TARGET_PAGE_MASK << 1)); | |
235 | 238 | env->exception_index = exception; |
236 | 239 | env->error_code = error_code; |
237 | 240 | ret = 1; | ... | ... |