Revision f2e9ebef
b/target-mips/helper.c | ||
---|---|---|
73 | 73 |
for (i = 0; i < env->tlb_in_use; i++) { |
74 | 74 |
r4k_tlb_t *tlb = &env->mmu.r4k.tlb[i]; |
75 | 75 |
/* 1k pages are not supported. */ |
76 |
target_ulong mask = tlb->PageMask | 0x1FFF;
|
|
76 |
target_ulong mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
|
|
77 | 77 |
target_ulong tag = address & ~mask; |
78 |
int n;
|
|
78 |
target_ulong VPN = tlb->VPN & ~mask;
|
|
79 | 79 |
|
80 | 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 | 82 |
/* TLB match */ |
84 |
n = !!(address & mask & ~(mask >> 1)); |
|
83 |
int n = !!(address & mask & ~(mask >> 1));
|
|
85 | 84 |
/* Check access rights */ |
86 |
if (!(n ? tlb->V1 : tlb->V0)) |
|
85 |
if (!(n ? tlb->V1 : tlb->V0))
|
|
87 | 86 |
return TLBRET_INVALID; |
88 |
if (rw == 0 || (n ? tlb->D1 : tlb->D0)) { |
|
87 |
if (rw == 0 || (n ? tlb->D1 : tlb->D0)) {
|
|
89 | 88 |
*physical = tlb->PFN[n] | (address & (mask >> 1)); |
90 | 89 |
*prot = PAGE_READ; |
91 | 90 |
if (n ? tlb->D1 : tlb->D0) |
... | ... | |
502 | 501 |
target_ulong mask; |
503 | 502 |
|
504 | 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 | 505 |
flush these entries again. */ |
507 | 506 |
if (tlb->G == 0 && tlb->ASID != ASID) { |
508 | 507 |
return; |
... | ... | |
518 | 517 |
} |
519 | 518 |
|
520 | 519 |
/* 1k pages are not supported. */ |
521 |
mask = tlb->PageMask | 0x1FFF;
|
|
520 |
mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
|
|
522 | 521 |
if (tlb->V0) { |
523 |
addr = tlb->VPN; |
|
522 |
addr = tlb->VPN & ~mask;
|
|
524 | 523 |
end = addr | (mask >> 1); |
525 | 524 |
while (addr < end) { |
526 | 525 |
tlb_flush_page (env, addr); |
... | ... | |
528 | 527 |
} |
529 | 528 |
} |
530 | 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 | 531 |
end = addr | mask; |
534 | 532 |
while (addr < end) { |
535 | 533 |
tlb_flush_page (env, addr); |
b/target-mips/op.c | ||
---|---|---|
1283 | 1283 |
void op_mtc0_pagemask (void) |
1284 | 1284 |
{ |
1285 | 1285 |
/* 1k pages not implemented */ |
1286 |
env->CP0_PageMask = T0 & 0x1FFFE000;
|
|
1286 |
env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
|
|
1287 | 1287 |
RETURN(); |
1288 | 1288 |
} |
1289 | 1289 |
|
b/target-mips/op_helper.c | ||
---|---|---|
390 | 390 |
|
391 | 391 |
/* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */ |
392 | 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 | 394 |
tlb->ASID = env->CP0_EntryHi & 0xFF; |
395 | 395 |
tlb->PageMask = env->CP0_PageMask; |
396 | 396 |
tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; |
... | ... | |
426 | 426 |
void r4k_do_tlbp (void) |
427 | 427 |
{ |
428 | 428 |
r4k_tlb_t *tlb; |
429 |
target_ulong mask; |
|
429 | 430 |
target_ulong tag; |
431 |
target_ulong VPN; |
|
430 | 432 |
uint8_t ASID; |
431 | 433 |
int i; |
432 | 434 |
|
433 |
tag = env->CP0_EntryHi & (int32_t)0xFFFFE000; |
|
434 | 435 |
ASID = env->CP0_EntryHi & 0xFF; |
435 | 436 |
for (i = 0; i < env->nb_tlb; i++) { |
436 | 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 | 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 | 444 |
/* TLB match */ |
440 | 445 |
env->CP0_Index = i; |
441 | 446 |
break; |
... | ... | |
445 | 450 |
/* No match. Discard any shadow entries, if any of them match. */ |
446 | 451 |
for (i = env->nb_tlb; i < env->tlb_in_use; i++) { |
447 | 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 | 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 | 459 |
r4k_mips_tlb_flush_extra (env, i); |
452 | 460 |
break; |
453 | 461 |
} |
Also available in: Unified diff