Commit f2e9ebef12c6f00d650eb06f33dbdd06db0919f2

Authored by ths
1 parent 388bb21a

MMU code improvements, by Aurelien Jarno.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2811 c046a42c-6fe2-441c-8c8c-71466251a162
target-mips/helper.c
@@ -73,19 +73,18 @@ int r4k_map_address (CPUState *env, target_ulong *physical, int *prot, @@ -73,19 +73,18 @@ int r4k_map_address (CPUState *env, target_ulong *physical, int *prot,
73 for (i = 0; i < env->tlb_in_use; i++) { 73 for (i = 0; i < env->tlb_in_use; i++) {
74 r4k_tlb_t *tlb = &env->mmu.r4k.tlb[i]; 74 r4k_tlb_t *tlb = &env->mmu.r4k.tlb[i];
75 /* 1k pages are not supported. */ 75 /* 1k pages are not supported. */
76 - target_ulong mask = tlb->PageMask | 0x1FFF; 76 + target_ulong mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
77 target_ulong tag = address & ~mask; 77 target_ulong tag = address & ~mask;
78 - int n; 78 + target_ulong VPN = tlb->VPN & ~mask;
79 79
80 /* Check ASID, virtual page number & size */ 80 /* Check ASID, virtual page number & size */
81 - if ((tlb->G == 1 || tlb->ASID == ASID) &&  
82 - tlb->VPN == tag) { 81 + if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
83 /* TLB match */ 82 /* TLB match */
84 - n = !!(address & mask & ~(mask >> 1)); 83 + int n = !!(address & mask & ~(mask >> 1));
85 /* Check access rights */ 84 /* Check access rights */
86 - if (!(n ? tlb->V1 : tlb->V0)) 85 + if (!(n ? tlb->V1 : tlb->V0))
87 return TLBRET_INVALID; 86 return TLBRET_INVALID;
88 - if (rw == 0 || (n ? tlb->D1 : tlb->D0)) { 87 + if (rw == 0 || (n ? tlb->D1 : tlb->D0)) {
89 *physical = tlb->PFN[n] | (address & (mask >> 1)); 88 *physical = tlb->PFN[n] | (address & (mask >> 1));
90 *prot = PAGE_READ; 89 *prot = PAGE_READ;
91 if (n ? tlb->D1 : tlb->D0) 90 if (n ? tlb->D1 : tlb->D0)
@@ -502,7 +501,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra) @@ -502,7 +501,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra)
502 target_ulong mask; 501 target_ulong mask;
503 502
504 tlb = &env->mmu.r4k.tlb[idx]; 503 tlb = &env->mmu.r4k.tlb[idx];
505 - /* The qemu TLB is flushed then the ASID changes, so no need to 504 + /* The qemu TLB is flushed when the ASID changes, so no need to
506 flush these entries again. */ 505 flush these entries again. */
507 if (tlb->G == 0 && tlb->ASID != ASID) { 506 if (tlb->G == 0 && tlb->ASID != ASID) {
508 return; 507 return;
@@ -518,9 +517,9 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra) @@ -518,9 +517,9 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra)
518 } 517 }
519 518
520 /* 1k pages are not supported. */ 519 /* 1k pages are not supported. */
521 - mask = tlb->PageMask | 0x1FFF; 520 + mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
522 if (tlb->V0) { 521 if (tlb->V0) {
523 - addr = tlb->VPN; 522 + addr = tlb->VPN & ~mask;
524 end = addr | (mask >> 1); 523 end = addr | (mask >> 1);
525 while (addr < end) { 524 while (addr < end) {
526 tlb_flush_page (env, addr); 525 tlb_flush_page (env, addr);
@@ -528,8 +527,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra) @@ -528,8 +527,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra)
528 } 527 }
529 } 528 }
530 if (tlb->V1) { 529 if (tlb->V1) {
531 - addr = tlb->VPN | ((mask >> 1) + 1);  
532 - addr = tlb->VPN + TARGET_PAGE_SIZE; 530 + addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1);
533 end = addr | mask; 531 end = addr | mask;
534 while (addr < end) { 532 while (addr < end) {
535 tlb_flush_page (env, addr); 533 tlb_flush_page (env, addr);
target-mips/op.c
@@ -1283,7 +1283,7 @@ void op_mtc0_context (void) @@ -1283,7 +1283,7 @@ void op_mtc0_context (void)
1283 void op_mtc0_pagemask (void) 1283 void op_mtc0_pagemask (void)
1284 { 1284 {
1285 /* 1k pages not implemented */ 1285 /* 1k pages not implemented */
1286 - env->CP0_PageMask = T0 & 0x1FFFE000; 1286 + env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
1287 RETURN(); 1287 RETURN();
1288 } 1288 }
1289 1289
target-mips/op_helper.c
@@ -390,7 +390,7 @@ static void r4k_fill_tlb (int idx) @@ -390,7 +390,7 @@ static void r4k_fill_tlb (int idx)
390 390
391 /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */ 391 /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
392 tlb = &env->mmu.r4k.tlb[idx]; 392 tlb = &env->mmu.r4k.tlb[idx];
393 - tlb->VPN = env->CP0_EntryHi & ~(target_ulong)0x1FFF; 393 + tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
394 tlb->ASID = env->CP0_EntryHi & 0xFF; 394 tlb->ASID = env->CP0_EntryHi & 0xFF;
395 tlb->PageMask = env->CP0_PageMask; 395 tlb->PageMask = env->CP0_PageMask;
396 tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; 396 tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
@@ -426,16 +426,21 @@ void r4k_do_tlbwr (void) @@ -426,16 +426,21 @@ void r4k_do_tlbwr (void)
426 void r4k_do_tlbp (void) 426 void r4k_do_tlbp (void)
427 { 427 {
428 r4k_tlb_t *tlb; 428 r4k_tlb_t *tlb;
  429 + target_ulong mask;
429 target_ulong tag; 430 target_ulong tag;
  431 + target_ulong VPN;
430 uint8_t ASID; 432 uint8_t ASID;
431 int i; 433 int i;
432 434
433 - tag = env->CP0_EntryHi & (int32_t)0xFFFFE000;  
434 ASID = env->CP0_EntryHi & 0xFF; 435 ASID = env->CP0_EntryHi & 0xFF;
435 for (i = 0; i < env->nb_tlb; i++) { 436 for (i = 0; i < env->nb_tlb; i++) {
436 tlb = &env->mmu.r4k.tlb[i]; 437 tlb = &env->mmu.r4k.tlb[i];
  438 + /* 1k pages are not supported. */
  439 + mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
  440 + tag = env->CP0_EntryHi & ~mask;
  441 + VPN = tlb->VPN & ~mask;
437 /* Check ASID, virtual page number & size */ 442 /* Check ASID, virtual page number & size */
438 - if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) { 443 + if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
439 /* TLB match */ 444 /* TLB match */
440 env->CP0_Index = i; 445 env->CP0_Index = i;
441 break; 446 break;
@@ -445,9 +450,12 @@ void r4k_do_tlbp (void) @@ -445,9 +450,12 @@ void r4k_do_tlbp (void)
445 /* No match. Discard any shadow entries, if any of them match. */ 450 /* No match. Discard any shadow entries, if any of them match. */
446 for (i = env->nb_tlb; i < env->tlb_in_use; i++) { 451 for (i = env->nb_tlb; i < env->tlb_in_use; i++) {
447 tlb = &env->mmu.r4k.tlb[i]; 452 tlb = &env->mmu.r4k.tlb[i];
448 - 453 + /* 1k pages are not supported. */
  454 + mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
  455 + tag = env->CP0_EntryHi & ~mask;
  456 + VPN = tlb->VPN & ~mask;
449 /* Check ASID, virtual page number & size */ 457 /* Check ASID, virtual page number & size */
450 - if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) { 458 + if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
451 r4k_mips_tlb_flush_extra (env, i); 459 r4k_mips_tlb_flush_extra (env, i);
452 break; 460 break;
453 } 461 }