Search
lxdream.org :: lxdream/src/sh4/mmu.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/mmu.c
changeset 569:a1c49e1e8776
prev561:533f6b478071
next570:d2893980fbf5
author nkeynes
date Fri Jan 04 11:54:17 2008 +0000 (13 years ago)
branchlxdream-mmu
permissions -rw-r--r--
last change Bring icache partially into line with the mmu, a little less slow with AT off
now.
file annotate diff log raw
1.1 --- a/src/sh4/mmu.c Tue Jan 01 05:08:38 2008 +0000
1.2 +++ b/src/sh4/mmu.c Fri Jan 04 11:54:17 2008 +0000
1.3 @@ -70,6 +70,7 @@
1.4 static uint32_t mmu_urc;
1.5 static uint32_t mmu_urb;
1.6 static uint32_t mmu_lrui;
1.7 +static uint32_t mmu_asid; // current asid
1.8
1.9 static sh4ptr_t cache = NULL;
1.10
1.11 @@ -101,6 +102,10 @@
1.12 switch(reg) {
1.13 case PTEH:
1.14 val &= 0xFFFFFCFF;
1.15 + if( (val & 0xFF) != mmu_asid ) {
1.16 + mmu_asid = val&0xFF;
1.17 + sh4_icache.page_vma = -1; // invalidate icache as asid has changed
1.18 + }
1.19 break;
1.20 case PTEL:
1.21 val &= 0x1FFFFDFF;
1.22 @@ -234,17 +239,15 @@
1.23 */
1.24
1.25 /**
1.26 - * Perform the actual utlb lookup.
1.27 + * Perform the actual utlb lookup w/ asid matching.
1.28 * Possible utcomes are:
1.29 * 0..63 Single match - good, return entry found
1.30 * -1 No match - raise a tlb data miss exception
1.31 * -2 Multiple matches - raise a multi-hit exception (reset)
1.32 * @param vpn virtual address to resolve
1.33 - * @param asid Address space identifier
1.34 - * @param use_asid whether to require an asid match on non-shared pages.
1.35 * @return the resultant UTLB entry, or an error.
1.36 */
1.37 -static inline int mmu_utlb_lookup_vpn( uint32_t vpn, uint32_t asid, int use_asid )
1.38 +static inline int mmu_utlb_lookup_vpn_asid( uint32_t vpn )
1.39 {
1.40 int result = -1;
1.41 unsigned int i;
1.42 @@ -254,32 +257,52 @@
1.43 mmu_urc = 0;
1.44 }
1.45
1.46 - if( use_asid ) {
1.47 - for( i = 0; i < UTLB_ENTRY_COUNT; i++ ) {
1.48 - if( (mmu_utlb[i].flags & TLB_VALID) &&
1.49 - ((mmu_utlb[i].flags & TLB_SHARE) || asid == mmu_utlb[i].asid) &&
1.50 - ((mmu_utlb[i].vpn ^ vpn) & mmu_utlb[i].mask) == 0 ) {
1.51 - if( result != -1 ) {
1.52 - return -2;
1.53 - }
1.54 - result = i;
1.55 + for( i = 0; i < UTLB_ENTRY_COUNT; i++ ) {
1.56 + if( (mmu_utlb[i].flags & TLB_VALID) &&
1.57 + ((mmu_utlb[i].flags & TLB_SHARE) || mmu_asid == mmu_utlb[i].asid) &&
1.58 + ((mmu_utlb[i].vpn ^ vpn) & mmu_utlb[i].mask) == 0 ) {
1.59 + if( result != -1 ) {
1.60 + return -2;
1.61 }
1.62 - }
1.63 - } else {
1.64 - for( i = 0; i < UTLB_ENTRY_COUNT; i++ ) {
1.65 - if( (mmu_utlb[i].flags & TLB_VALID) &&
1.66 - ((mmu_utlb[i].vpn ^ vpn) & mmu_utlb[i].mask) == 0 ) {
1.67 - if( result != -1 ) {
1.68 - return -2;
1.69 - }
1.70 - result = i;
1.71 - }
1.72 + result = i;
1.73 }
1.74 }
1.75 return result;
1.76 }
1.77
1.78 /**
1.79 + * Perform the actual utlb lookup matching on vpn only
1.80 + * Possible utcomes are:
1.81 + * 0..63 Single match - good, return entry found
1.82 + * -1 No match - raise a tlb data miss exception
1.83 + * -2 Multiple matches - raise a multi-hit exception (reset)
1.84 + * @param vpn virtual address to resolve
1.85 + * @return the resultant UTLB entry, or an error.
1.86 + */
1.87 +static inline int mmu_utlb_lookup_vpn( uint32_t vpn )
1.88 +{
1.89 + int result = -1;
1.90 + unsigned int i;
1.91 +
1.92 + mmu_urc++;
1.93 + if( mmu_urc == mmu_urb || mmu_urc == 0x40 ) {
1.94 + mmu_urc = 0;
1.95 + }
1.96 +
1.97 + for( i = 0; i < UTLB_ENTRY_COUNT; i++ ) {
1.98 + if( (mmu_utlb[i].flags & TLB_VALID) &&
1.99 + ((mmu_utlb[i].vpn ^ vpn) & mmu_utlb[i].mask) == 0 ) {
1.100 + if( result != -1 ) {
1.101 + return -2;
1.102 + }
1.103 + result = i;
1.104 + }
1.105 + }
1.106 +
1.107 + return result;
1.108 +}
1.109 +
1.110 +/**
1.111 * Find a UTLB entry for the associative TLB write - same as the normal
1.112 * lookup but ignores the valid bit.
1.113 */
1.114 @@ -300,53 +323,9 @@
1.115 }
1.116
1.117 /**
1.118 - * Perform the actual itlb lookup.
1.119 - * Possible utcomes are:
1.120 - * 0..63 Single match - good, return entry found
1.121 - * -1 No match - raise a tlb data miss exception
1.122 - * -2 Multiple matches - raise a multi-hit exception (reset)
1.123 - * @param vpn virtual address to resolve
1.124 - * @param asid Address space identifier
1.125 - * @param use_asid whether to require an asid match on non-shared pages.
1.126 - * @return the resultant ITLB entry, or an error.
1.127 + * Update the ITLB by replacing the LRU entry with the specified UTLB entry.
1.128 + * @return the number (0-3) of the replaced entry.
1.129 */
1.130 -static inline int mmu_itlb_lookup_vpn( uint32_t vpn, uint32_t asid, int use_asid )
1.131 -{
1.132 - int result = -1;
1.133 - unsigned int i;
1.134 - if( use_asid ) {
1.135 - for( i = 0; i < ITLB_ENTRY_COUNT; i++ ) {
1.136 - if( (mmu_itlb[i].flags & TLB_VALID) &&
1.137 - ((mmu_itlb[i].flags & TLB_SHARE) || asid == mmu_itlb[i].asid) &&
1.138 - ((mmu_itlb[i].vpn ^ vpn) & mmu_itlb[i].mask) == 0 ) {
1.139 - if( result != -1 ) {
1.140 - return -2;
1.141 - }
1.142 - result = i;
1.143 - }
1.144 - }
1.145 - } else {
1.146 - for( i = 0; i < ITLB_ENTRY_COUNT; i++ ) {
1.147 - if( (mmu_itlb[i].flags & TLB_VALID) &&
1.148 - ((mmu_itlb[i].vpn ^ vpn) & mmu_itlb[i].mask) == 0 ) {
1.149 - if( result != -1 ) {
1.150 - return -2;
1.151 - }
1.152 - result = i;
1.153 - }
1.154 - }
1.155 - }
1.156 -
1.157 - switch( result ) {
1.158 - case 0: mmu_lrui = (mmu_lrui & 0x07); break;
1.159 - case 1: mmu_lrui = (mmu_lrui & 0x19) | 0x20; break;
1.160 - case 2: mmu_lrui = (mmu_lrui & 0x3E) | 0x14; break;
1.161 - case 3: mmu_lrui = (mmu_lrui | 0x0B); break;
1.162 - }
1.163 -
1.164 - return result;
1.165 -}
1.166 -
1.167 static int inline mmu_itlb_update_from_utlb( int entryNo )
1.168 {
1.169 int replace;
1.170 @@ -374,6 +353,93 @@
1.171 }
1.172
1.173 /**
1.174 + * Perform the actual itlb lookup w/ asid protection
1.175 + * Possible utcomes are:
1.176 + * 0..63 Single match - good, return entry found
1.177 + * -1 No match - raise a tlb data miss exception
1.178 + * -2 Multiple matches - raise a multi-hit exception (reset)
1.179 + * @param vpn virtual address to resolve
1.180 + * @return the resultant ITLB entry, or an error.
1.181 + */
1.182 +static inline int mmu_itlb_lookup_vpn_asid( uint32_t vpn )
1.183 +{
1.184 + int result = -1;
1.185 + unsigned int i;
1.186 +
1.187 + for( i = 0; i < ITLB_ENTRY_COUNT; i++ ) {
1.188 + if( (mmu_itlb[i].flags & TLB_VALID) &&
1.189 + ((mmu_itlb[i].flags & TLB_SHARE) || mmu_asid == mmu_itlb[i].asid) &&
1.190 + ((mmu_itlb[i].vpn ^ vpn) & mmu_itlb[i].mask) == 0 ) {
1.191 + if( result != -1 ) {
1.192 + return -2;
1.193 + }
1.194 + result = i;
1.195 + }
1.196 + }
1.197 +
1.198 + if( result == -1 ) {
1.199 + int utlbEntry = mmu_utlb_lookup_vpn( vpn );
1.200 + if( utlbEntry == -1 ) {
1.201 + return -1;
1.202 + } else {
1.203 + return mmu_itlb_update_from_utlb( utlbEntry );
1.204 + }
1.205 + }
1.206 +
1.207 + switch( result ) {
1.208 + case 0: mmu_lrui = (mmu_lrui & 0x07); break;
1.209 + case 1: mmu_lrui = (mmu_lrui & 0x19) | 0x20; break;
1.210 + case 2: mmu_lrui = (mmu_lrui & 0x3E) | 0x14; break;
1.211 + case 3: mmu_lrui = (mmu_lrui | 0x0B); break;
1.212 + }
1.213 +
1.214 + return result;
1.215 +}
1.216 +
1.217 +/**
1.218 + * Perform the actual itlb lookup on vpn only
1.219 + * Possible utcomes are:
1.220 + * 0..63 Single match - good, return entry found
1.221 + * -1 No match - raise a tlb data miss exception
1.222 + * -2 Multiple matches - raise a multi-hit exception (reset)
1.223 + * @param vpn virtual address to resolve
1.224 + * @return the resultant ITLB entry, or an error.
1.225 + */
1.226 +static inline int mmu_itlb_lookup_vpn( uint32_t vpn )
1.227 +{
1.228 + int result = -1;
1.229 + unsigned int i;
1.230 +
1.231 + for( i = 0; i < ITLB_ENTRY_COUNT; i++ ) {
1.232 + if( (mmu_itlb[i].flags & TLB_VALID) &&
1.233 + ((mmu_itlb[i].vpn ^ vpn) & mmu_itlb[i].mask) == 0 ) {
1.234 + if( result != -1 ) {
1.235 + return -2;
1.236 + }
1.237 + result = i;
1.238 + }
1.239 + }
1.240 +
1.241 + if( result == -1 ) {
1.242 + int utlbEntry = mmu_utlb_lookup_vpn( vpn );
1.243 + if( utlbEntry == -1 ) {
1.244 + return -1;
1.245 + } else {
1.246 + return mmu_itlb_update_from_utlb( utlbEntry );
1.247 + }
1.248 + }
1.249 +
1.250 + switch( result ) {
1.251 + case 0: mmu_lrui = (mmu_lrui & 0x07); break;
1.252 + case 1: mmu_lrui = (mmu_lrui & 0x19) | 0x20; break;
1.253 + case 2: mmu_lrui = (mmu_lrui & 0x3E) | 0x14; break;
1.254 + case 3: mmu_lrui = (mmu_lrui | 0x0B); break;
1.255 + }
1.256 +
1.257 + return result;
1.258 +}
1.259 +
1.260 +/**
1.261 * Find a ITLB entry for the associative TLB write - same as the normal
1.262 * lookup but ignores the valid bit.
1.263 */
1.264 @@ -396,18 +462,15 @@
1.265 #define RAISE_TLB_ERROR(code, vpn) \
1.266 MMIO_WRITE(MMU, TEA, vpn); \
1.267 MMIO_WRITE(MMU, PTEH, ((MMIO_READ(MMU, PTEH) & 0x000003FF) | (vpn&0xFFFFFC00))); \
1.268 - sh4_raise_tlb_exception(code); \
1.269 - return (((uint64_t)code)<<32)
1.270 + sh4_raise_tlb_exception(code);
1.271
1.272 #define RAISE_MEM_ERROR(code, vpn) \
1.273 MMIO_WRITE(MMU, TEA, vpn); \
1.274 MMIO_WRITE(MMU, PTEH, ((MMIO_READ(MMU, PTEH) & 0x000003FF) | (vpn&0xFFFFFC00))); \
1.275 - sh4_raise_exception(code); \
1.276 - return (((uint64_t)code)<<32)
1.277 + sh4_raise_exception(code);
1.278
1.279 #define RAISE_OTHER_ERROR(code) \
1.280 - sh4_raise_exception(code); \
1.281 - return (((uint64_t)EXV_EXCEPTION)<<32)
1.282 + sh4_raise_exception(code);
1.283
1.284 /**
1.285 * Abort with a non-MMU address error. Caused by user-mode code attempting
1.286 @@ -423,8 +486,7 @@
1.287 #define MMU_TLB_WRITE_PROT_ERROR(vpn) RAISE_MEM_ERROR(EXC_TLB_PROT_WRITE, vpn)
1.288 #define MMU_TLB_MULTI_HIT_ERROR(vpn) sh4_raise_reset(EXC_TLB_MULTI_HIT); \
1.289 MMIO_WRITE(MMU, TEA, vpn); \
1.290 - MMIO_WRITE(MMU, PTEH, ((MMIO_READ(MMU, PTEH) & 0x000003FF) | (vpn&0xFFFFFC00))); \
1.291 - return (((uint64_t)EXC_TLB_MULTI_HIT)<<32)
1.292 + MMIO_WRITE(MMU, PTEH, ((MMIO_READ(MMU, PTEH) & 0x000003FF) | (vpn&0xFFFFFC00)));
1.293
1.294 uint64_t mmu_vma_to_phys_write( sh4addr_t addr )
1.295 {
1.296 @@ -442,6 +504,7 @@
1.297 return (uint64_t)addr;
1.298 }
1.299 MMU_WRITE_ADDR_ERROR();
1.300 + return 0x100000000LL;
1.301 }
1.302 }
1.303
1.304 @@ -450,28 +513,31 @@
1.305 }
1.306
1.307 /* If we get this far, translation is required */
1.308 -
1.309 - int use_asid = ((mmucr & MMUCR_SV) == 0) || !IS_SH4_PRIVMODE();
1.310 - uint32_t asid = MMIO_READ( MMU, PTEH ) & 0xFF;
1.311 -
1.312 - int entryNo = mmu_utlb_lookup_vpn( addr, asid, use_asid );
1.313 + int entryNo;
1.314 + if( ((mmucr & MMUCR_SV) == 0) || !IS_SH4_PRIVMODE() ) {
1.315 + entryNo = mmu_utlb_lookup_vpn_asid( addr );
1.316 + } else {
1.317 + entryNo = mmu_utlb_lookup_vpn( addr );
1.318 + }
1.319
1.320 switch(entryNo) {
1.321 case -1:
1.322 MMU_TLB_WRITE_MISS_ERROR(addr);
1.323 - break;
1.324 + return 0x100000000LL;
1.325 case -2:
1.326 MMU_TLB_MULTI_HIT_ERROR(addr);
1.327 - break;
1.328 + return 0x100000000LL;
1.329 default:
1.330 if( IS_SH4_PRIVMODE() ? ((mmu_utlb[entryNo].flags & TLB_WRITABLE) == 0)
1.331 : ((mmu_utlb[entryNo].flags & TLB_USERWRITABLE) != TLB_USERWRITABLE) ) {
1.332 /* protection violation */
1.333 MMU_TLB_WRITE_PROT_ERROR(addr);
1.334 + return 0x100000000LL;
1.335 }
1.336
1.337 if( (mmu_utlb[entryNo].flags & TLB_DIRTY) == 0 ) {
1.338 MMU_TLB_INITIAL_WRITE_ERROR(addr);
1.339 + return 0x100000000LL;
1.340 }
1.341
1.342 /* finally generate the target address */
1.343 @@ -482,64 +548,6 @@
1.344
1.345 }
1.346
1.347 -uint64_t mmu_vma_to_phys_exec( sh4addr_t addr )
1.348 -{
1.349 - uint32_t mmucr = MMIO_READ(MMU,MMUCR);
1.350 - if( addr & 0x80000000 ) {
1.351 - if( IS_SH4_PRIVMODE() ) {
1.352 - if( addr < 0xC0000000 ) {
1.353 - /* P1, P2 and P4 regions are pass-through (no translation) */
1.354 - return (uint64_t)addr;
1.355 - } else if( addr >= 0xE0000000 ) {
1.356 - MMU_READ_ADDR_ERROR();
1.357 - }
1.358 - } else {
1.359 - MMU_READ_ADDR_ERROR();
1.360 - }
1.361 - }
1.362 -
1.363 - if( (mmucr & MMUCR_AT) == 0 ) {
1.364 - return (uint64_t)addr;
1.365 - }
1.366 -
1.367 - /* If we get this far, translation is required */
1.368 - int use_asid = ((mmucr & MMUCR_SV) == 0) || !IS_SH4_PRIVMODE();
1.369 - uint32_t asid = MMIO_READ( MMU, PTEH ) & 0xFF;
1.370 -
1.371 - int entryNo = mmu_itlb_lookup_vpn( addr, asid, use_asid );
1.372 - if( entryNo == -1 ) {
1.373 - entryNo = mmu_utlb_lookup_vpn( addr, asid, use_asid );
1.374 - if( entryNo >= 0 ) {
1.375 - entryNo = mmu_itlb_update_from_utlb( entryNo );
1.376 - }
1.377 - }
1.378 - switch(entryNo) {
1.379 - case -1:
1.380 - MMU_TLB_READ_MISS_ERROR(addr);
1.381 - break;
1.382 - case -2:
1.383 - MMU_TLB_MULTI_HIT_ERROR(addr);
1.384 - break;
1.385 - default:
1.386 - if( (mmu_itlb[entryNo].flags & TLB_USERMODE) == 0 &&
1.387 - !IS_SH4_PRIVMODE() ) {
1.388 - /* protection violation */
1.389 - MMU_TLB_READ_PROT_ERROR(addr);
1.390 - }
1.391 -
1.392 - /* finally generate the target address */
1.393 - return (mmu_itlb[entryNo].ppn & mmu_itlb[entryNo].mask) |
1.394 - (addr & (~mmu_itlb[entryNo].mask));
1.395 - }
1.396 - return -1;
1.397 -}
1.398 -
1.399 -uint64_t mmu_vma_to_phys_read_noexc( sh4addr_t addr ) {
1.400 -
1.401 -
1.402 -}
1.403 -
1.404 -
1.405 uint64_t mmu_vma_to_phys_read( sh4addr_t addr )
1.406 {
1.407 uint32_t mmucr = MMIO_READ(MMU,MMUCR);
1.408 @@ -556,6 +564,7 @@
1.409 return (uint64_t)addr;
1.410 }
1.411 MMU_READ_ADDR_ERROR();
1.412 + return 0x100000000LL;
1.413 }
1.414 }
1.415
1.416 @@ -564,24 +573,26 @@
1.417 }
1.418
1.419 /* If we get this far, translation is required */
1.420 -
1.421 - int use_asid = ((mmucr & MMUCR_SV) == 0) || !IS_SH4_PRIVMODE();
1.422 - uint32_t asid = MMIO_READ( MMU, PTEH ) & 0xFF;
1.423 -
1.424 - int entryNo = mmu_utlb_lookup_vpn( addr, asid, use_asid );
1.425 + int entryNo;
1.426 + if( ((mmucr & MMUCR_SV) == 0) || !IS_SH4_PRIVMODE() ) {
1.427 + entryNo = mmu_utlb_lookup_vpn_asid( addr );
1.428 + } else {
1.429 + entryNo = mmu_utlb_lookup_vpn( addr );
1.430 + }
1.431
1.432 switch(entryNo) {
1.433 case -1:
1.434 MMU_TLB_READ_MISS_ERROR(addr);
1.435 - break;
1.436 + return 0x100000000LL;
1.437 case -2:
1.438 MMU_TLB_MULTI_HIT_ERROR(addr);
1.439 - break;
1.440 + return 0x100000000LL;
1.441 default:
1.442 if( (mmu_utlb[entryNo].flags & TLB_USERMODE) == 0 &&
1.443 !IS_SH4_PRIVMODE() ) {
1.444 /* protection violation */
1.445 MMU_TLB_READ_PROT_ERROR(addr);
1.446 + return 0x100000000LL;
1.447 }
1.448
1.449 /* finally generate the target address */
1.450 @@ -720,3 +731,106 @@
1.451 void mmu_ocache_data_write( sh4addr_t addr, uint32_t val )
1.452 {
1.453 }
1.454 +
1.455 +/**
1.456 + * Update the icache for an untranslated address
1.457 + */
1.458 +void mmu_update_icache_phys( sh4addr_t addr )
1.459 +{
1.460 + if( (addr & 0x1C000000) == 0x0C000000 ) {
1.461 + /* Main ram */
1.462 + sh4_icache.page_vma = addr & 0xFF000000;
1.463 + sh4_icache.page_ppa = 0x0C000000;
1.464 + sh4_icache.mask = 0xFF000000;
1.465 + sh4_icache.page = sh4_main_ram;
1.466 + } else if( (addr & 0x1FE00000 == 0 ) ) {
1.467 + /* BIOS ROM */
1.468 + sh4_icache.page_vma = addr & 0xFFE00000;
1.469 + sh4_icache.page_ppa = 0;
1.470 + sh4_icache.mask = 0xFFE00000;
1.471 + sh4_icache.page = mem_get_region(0);
1.472 + } else {
1.473 + /* not supported */
1.474 + sh4_icache.page_vma = -1;
1.475 + }
1.476 +}
1.477 +
1.478 +/**
1.479 + * Update the sh4_icache structure to describe the page(s) containing the
1.480 + * given vma. If the address does not reference a RAM/ROM region, the icache
1.481 + * will be invalidated instead.
1.482 + * If AT is on, this method will raise TLB exceptions normally
1.483 + * (hence this method should only be used immediately prior to execution of
1.484 + * code), and otherwise will set the icache according to the matching TLB entry.
1.485 + * If AT is off, this method will set the entire referenced RAM/ROM region in
1.486 + * the icache.
1.487 + * @return TRUE if the update completed (successfully or otherwise), FALSE
1.488 + * if an exception was raised.
1.489 + */
1.490 +gboolean mmu_update_icache( sh4vma_t addr )
1.491 +{
1.492 + int entryNo;
1.493 + if( IS_SH4_PRIVMODE() ) {
1.494 + if( addr & 0x80000000 ) {
1.495 + if( addr < 0xC0000000 ) {
1.496 + /* P1, P2 and P4 regions are pass-through (no translation) */
1.497 + mmu_update_icache_phys(addr);
1.498 + return TRUE;
1.499 + } else if( addr >= 0xE0000000 && addr < 0xFFFFFF00 ) {
1.500 + MMU_READ_ADDR_ERROR();
1.501 + return FALSE;
1.502 + }
1.503 + } else {
1.504 + MMU_READ_ADDR_ERROR();
1.505 + return FALSE;
1.506 + }
1.507 +
1.508 + uint32_t mmucr = MMIO_READ(MMU,MMUCR);
1.509 + if( (mmucr & MMUCR_AT) == 0 ) {
1.510 + mmu_update_icache_phys(addr);
1.511 + return TRUE;
1.512 + }
1.513 +
1.514 + entryNo = mmu_itlb_lookup_vpn( addr );
1.515 + } else {
1.516 + if( addr & 0x80000000 ) {
1.517 + MMU_READ_ADDR_ERROR();
1.518 + return FALSE;
1.519 + }
1.520 +
1.521 + uint32_t mmucr = MMIO_READ(MMU,MMUCR);
1.522 + if( (mmucr & MMUCR_AT) == 0 ) {
1.523 + mmu_update_icache_phys(addr);
1.524 + return TRUE;
1.525 + }
1.526 +
1.527 + if( mmucr & MMUCR_SV ) {
1.528 + entryNo = mmu_itlb_lookup_vpn( addr );
1.529 + } else {
1.530 + entryNo = mmu_itlb_lookup_vpn_asid( addr );
1.531 + }
1.532 + if( entryNo != -1 && (mmu_itlb[entryNo].flags & TLB_USERMODE) == 0 ) {
1.533 + MMU_TLB_READ_PROT_ERROR(addr);
1.534 + return FALSE;
1.535 + }
1.536 + }
1.537 +
1.538 + switch(entryNo) {
1.539 + case -1:
1.540 + MMU_TLB_READ_MISS_ERROR(addr);
1.541 + return FALSE;
1.542 + case -2:
1.543 + MMU_TLB_MULTI_HIT_ERROR(addr);
1.544 + return FALSE;
1.545 + default:
1.546 + sh4_icache.page_ppa = mmu_itlb[entryNo].ppn & mmu_itlb[entryNo].mask;
1.547 + sh4_icache.page = mem_get_region( sh4_icache.page_ppa );
1.548 + if( sh4_icache.page == NULL ) {
1.549 + sh4_icache.page_vma = -1;
1.550 + } else {
1.551 + sh4_icache.page_vma = mmu_itlb[entryNo].vpn & mmu_itlb[entryNo].mask;
1.552 + sh4_icache.mask = mmu_itlb[entryNo].mask;
1.553 + }
1.554 + return TRUE;
1.555 + }
1.556 +}
.