Revision 29929e34 target-mips/helper.c
b/target-mips/helper.c | ||
---|---|---|
36 | 36 |
TLBRET_MATCH = 0 |
37 | 37 |
}; |
38 | 38 |
|
39 |
/* MIPS32 4K MMU emulation */ |
|
40 |
#ifdef MIPS_USES_R4K_TLB |
|
41 |
static int map_address (CPUState *env, target_ulong *physical, int *prot, |
|
39 |
/* no MMU emulation */ |
|
40 |
int no_mmu_map_address (CPUState *env, target_ulong *physical, int *prot, |
|
42 | 41 |
target_ulong address, int rw, int access_type) |
43 | 42 |
{ |
43 |
*physical = address; |
|
44 |
*prot = PAGE_READ | PAGE_WRITE; |
|
45 |
return TLBRET_MATCH; |
|
46 |
} |
|
47 |
|
|
48 |
/* fixed mapping MMU emulation */ |
|
49 |
int fixed_mmu_map_address (CPUState *env, target_ulong *physical, int *prot, |
|
50 |
target_ulong address, int rw, int access_type) |
|
51 |
{ |
|
52 |
if (address <= (int32_t)0x7FFFFFFFUL) { |
|
53 |
if (!(env->CP0_Status & (1 << CP0St_ERL))) |
|
54 |
*physical = address + 0x40000000UL; |
|
55 |
else |
|
56 |
*physical = address; |
|
57 |
} else if (address <= (int32_t)0xBFFFFFFFUL) |
|
58 |
*physical = address & 0x1FFFFFFF; |
|
59 |
else |
|
60 |
*physical = address; |
|
61 |
|
|
62 |
*prot = PAGE_READ | PAGE_WRITE; |
|
63 |
return TLBRET_MATCH; |
|
64 |
} |
|
65 |
|
|
66 |
/* MIPS32/MIPS64 R4000-style MMU emulation */ |
|
67 |
int r4k_map_address (CPUState *env, target_ulong *physical, int *prot, |
|
68 |
target_ulong address, int rw, int access_type) |
|
69 |
{ |
|
44 | 70 |
uint8_t ASID = env->CP0_EntryHi & 0xFF; |
45 | 71 |
int i; |
46 | 72 |
|
47 | 73 |
for (i = 0; i < env->tlb_in_use; i++) { |
48 |
tlb_t *tlb = &env->tlb[i];
|
|
74 |
r4k_tlb_t *tlb = &env->mmu.r4k.tlb[i];
|
|
49 | 75 |
/* 1k pages are not supported. */ |
50 | 76 |
target_ulong mask = tlb->PageMask | 0x1FFF; |
51 | 77 |
target_ulong tag = address & ~mask; |
... | ... | |
71 | 97 |
} |
72 | 98 |
return TLBRET_NOMATCH; |
73 | 99 |
} |
74 |
#endif |
|
75 | 100 |
|
76 | 101 |
static int get_physical_address (CPUState *env, target_ulong *physical, |
77 | 102 |
int *prot, target_ulong address, |
... | ... | |
104 | 129 |
if (address <= (int32_t)0x7FFFFFFFUL) { |
105 | 130 |
/* useg */ |
106 | 131 |
if (!(env->CP0_Status & (1 << CP0St_ERL) && user_mode)) { |
107 |
#ifdef MIPS_USES_R4K_TLB |
|
108 |
ret = map_address(env, physical, prot, address, rw, access_type); |
|
109 |
#else |
|
110 |
*physical = address + 0x40000000UL; |
|
111 |
*prot = PAGE_READ | PAGE_WRITE; |
|
112 |
#endif |
|
132 |
ret = env->map_address(env, physical, prot, address, rw, access_type); |
|
113 | 133 |
} else { |
114 |
*physical = address; |
|
134 |
*physical = address & 0xFFFFFFFF;
|
|
115 | 135 |
*prot = PAGE_READ | PAGE_WRITE; |
116 | 136 |
} |
117 | 137 |
#ifdef TARGET_MIPS64 |
... | ... | |
123 | 143 |
} else if (address < 0x3FFFFFFFFFFFFFFFULL) { |
124 | 144 |
/* xuseg */ |
125 | 145 |
if (UX && address < 0x000000FFFFFFFFFFULL) { |
126 |
ret = map_address(env, physical, prot, address, rw, access_type); |
|
146 |
ret = env->map_address(env, physical, prot, address, rw, access_type);
|
|
127 | 147 |
} else { |
128 | 148 |
ret = TLBRET_BADADDR; |
129 | 149 |
} |
130 | 150 |
} else if (address < 0x7FFFFFFFFFFFFFFFULL) { |
131 | 151 |
/* xsseg */ |
132 | 152 |
if (SX && address < 0x400000FFFFFFFFFFULL) { |
133 |
ret = map_address(env, physical, prot, address, rw, access_type); |
|
153 |
ret = env->map_address(env, physical, prot, address, rw, access_type);
|
|
134 | 154 |
} else { |
135 | 155 |
ret = TLBRET_BADADDR; |
136 | 156 |
} |
... | ... | |
148 | 168 |
/* xkseg */ |
149 | 169 |
/* XXX: check supervisor mode */ |
150 | 170 |
if (KX && address < 0xC00000FF7FFFFFFFULL) { |
151 |
ret = map_address(env, physical, prot, address, rw, access_type); |
|
171 |
ret = env->map_address(env, physical, prot, address, rw, access_type);
|
|
152 | 172 |
} else { |
153 | 173 |
ret = TLBRET_BADADDR; |
154 | 174 |
} |
... | ... | |
165 | 185 |
*prot = PAGE_READ | PAGE_WRITE; |
166 | 186 |
} else if (address < (int32_t)0xE0000000UL) { |
167 | 187 |
/* kseg2 */ |
168 |
#ifdef MIPS_USES_R4K_TLB |
|
169 |
ret = map_address(env, physical, prot, address, rw, access_type); |
|
170 |
#else |
|
171 |
*physical = address & 0xFFFFFFFF; |
|
172 |
*prot = PAGE_READ | PAGE_WRITE; |
|
173 |
#endif |
|
188 |
ret = env->map_address(env, physical, prot, address, rw, access_type); |
|
174 | 189 |
} else { |
175 | 190 |
/* kseg3 */ |
176 | 191 |
/* XXX: check supervisor mode */ |
177 | 192 |
/* XXX: debug segment is not emulated */ |
178 |
#ifdef MIPS_USES_R4K_TLB |
|
179 |
ret = map_address(env, physical, prot, address, rw, access_type); |
|
180 |
#else |
|
181 |
*physical = address & 0xFFFFFFFF; |
|
182 |
*prot = PAGE_READ | PAGE_WRITE; |
|
183 |
#endif |
|
193 |
ret = env->map_address(env, physical, prot, address, rw, access_type); |
|
184 | 194 |
} |
185 | 195 |
#if 0 |
186 | 196 |
if (logfile) { |
... | ... | |
483 | 493 |
} |
484 | 494 |
#endif /* !defined(CONFIG_USER_ONLY) */ |
485 | 495 |
|
486 |
void invalidate_tlb (CPUState *env, int idx, int use_extra) |
|
496 |
void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra)
|
|
487 | 497 |
{ |
488 |
tlb_t *tlb; |
|
498 |
r4k_tlb_t *tlb;
|
|
489 | 499 |
target_ulong addr; |
490 | 500 |
target_ulong end; |
491 | 501 |
uint8_t ASID = env->CP0_EntryHi & 0xFF; |
492 | 502 |
target_ulong mask; |
493 | 503 |
|
494 |
tlb = &env->tlb[idx]; |
|
504 |
tlb = &env->mmu.r4k.tlb[idx];
|
|
495 | 505 |
/* The qemu TLB is flushed then the ASID changes, so no need to |
496 | 506 |
flush these entries again. */ |
497 | 507 |
if (tlb->G == 0 && tlb->ASID != ASID) { |
... | ... | |
502 | 512 |
/* For tlbwr, we can shadow the discarded entry into |
503 | 513 |
a new (fake) TLB entry, as long as the guest can not |
504 | 514 |
tell that it's there. */ |
505 |
env->tlb[env->tlb_in_use] = *tlb; |
|
515 |
env->mmu.r4k.tlb[env->tlb_in_use] = *tlb;
|
|
506 | 516 |
env->tlb_in_use++; |
507 | 517 |
return; |
508 | 518 |
} |
Also available in: Unified diff