Commit 43057ab1272ba2b9b052b19a3453fb0f3b510149

Authored by bellard
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
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;