535 |
535 |
|
536 |
536 |
/* TLB management */
|
537 |
537 |
#if defined(MIPS_USES_R4K_TLB)
|
538 |
|
static void invalidate_tb (int idx)
|
|
538 |
static void invalidate_tlb (int idx)
|
539 |
539 |
{
|
540 |
540 |
tlb_t *tlb;
|
541 |
|
target_ulong addr, end;
|
|
541 |
target_ulong addr;
|
542 |
542 |
|
543 |
543 |
tlb = &env->tlb[idx];
|
544 |
|
if (tlb->V[0]) {
|
545 |
|
addr = tlb->PFN[0];
|
546 |
|
end = addr + (tlb->end - tlb->VPN);
|
547 |
|
tb_invalidate_page_range(addr, end);
|
548 |
|
/* FIXME: Might be faster to just invalidate the whole "tlb" here
|
549 |
|
and refill it on demand from our simulated TLB. */
|
|
544 |
if (tlb->V0) {
|
|
545 |
tb_invalidate_page_range(tlb->PFN[0], tlb->end - tlb->VPN);
|
550 |
546 |
addr = tlb->VPN;
|
551 |
547 |
while (addr < tlb->end) {
|
552 |
548 |
tlb_flush_page (env, addr);
|
553 |
549 |
addr += TARGET_PAGE_SIZE;
|
554 |
550 |
}
|
555 |
551 |
}
|
556 |
|
if (tlb->V[1]) {
|
557 |
|
addr = tlb->PFN[1];
|
558 |
|
end = addr + (tlb->end - tlb->VPN);
|
559 |
|
tb_invalidate_page_range(addr, end);
|
560 |
|
/* FIXME: Might be faster to just invalidate the whole "tlb" here
|
561 |
|
and refill it on demand from our simulated TLB. */
|
|
552 |
if (tlb->V1) {
|
|
553 |
tb_invalidate_page_range(tlb->PFN[1], tlb->end2 - tlb->end);
|
562 |
554 |
addr = tlb->end;
|
563 |
555 |
while (addr < tlb->end2) {
|
564 |
556 |
tlb_flush_page (env, addr);
|
... | ... | |
567 |
559 |
}
|
568 |
560 |
}
|
569 |
561 |
|
570 |
|
static void fill_tb (int idx)
|
|
562 |
static void fill_tlb (int idx)
|
571 |
563 |
{
|
572 |
564 |
tlb_t *tlb;
|
573 |
565 |
int size;
|
... | ... | |
575 |
567 |
/* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
|
576 |
568 |
tlb = &env->tlb[idx];
|
577 |
569 |
tlb->VPN = env->CP0_EntryHi & 0xFFFFE000;
|
578 |
|
tlb->ASID = env->CP0_EntryHi & 0x000000FF;
|
|
570 |
tlb->ASID = env->CP0_EntryHi & 0xFF;
|
579 |
571 |
size = env->CP0_PageMask >> 13;
|
580 |
572 |
size = 4 * (size + 1);
|
581 |
573 |
tlb->end = tlb->VPN + (1 << (8 + size));
|
582 |
574 |
tlb->end2 = tlb->end + (1 << (8 + size));
|
583 |
575 |
tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
|
584 |
|
tlb->V[0] = env->CP0_EntryLo0 & 2;
|
585 |
|
tlb->D[0] = env->CP0_EntryLo0 & 4;
|
586 |
|
tlb->C[0] = (env->CP0_EntryLo0 >> 3) & 0x7;
|
|
576 |
tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
|
|
577 |
tlb->D0 = (env->CP0_EntryLo0 & 4) != 0;
|
|
578 |
tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
|
587 |
579 |
tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12;
|
588 |
|
tlb->V[1] = env->CP0_EntryLo1 & 2;
|
589 |
|
tlb->D[1] = env->CP0_EntryLo1 & 4;
|
590 |
|
tlb->C[1] = (env->CP0_EntryLo1 >> 3) & 0x7;
|
|
580 |
tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
|
|
581 |
tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
|
|
582 |
tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
|
591 |
583 |
tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12;
|
592 |
584 |
}
|
593 |
585 |
|
... | ... | |
595 |
587 |
{
|
596 |
588 |
/* Wildly undefined effects for CP0_index containing a too high value and
|
597 |
589 |
MIPS_TLB_NB not being a power of two. But so does real silicon. */
|
598 |
|
invalidate_tb(env->CP0_index & (MIPS_TLB_NB - 1));
|
599 |
|
fill_tb(env->CP0_index & (MIPS_TLB_NB - 1));
|
|
590 |
invalidate_tlb(env->CP0_index & (MIPS_TLB_NB - 1));
|
|
591 |
fill_tlb(env->CP0_index & (MIPS_TLB_NB - 1));
|
600 |
592 |
}
|
601 |
593 |
|
602 |
594 |
void do_tlbwr (void)
|
603 |
595 |
{
|
604 |
596 |
int r = cpu_mips_get_random(env);
|
605 |
597 |
|
606 |
|
invalidate_tb(r);
|
607 |
|
fill_tb(r);
|
|
598 |
invalidate_tlb(r);
|
|
599 |
fill_tlb(r);
|
608 |
600 |
}
|
609 |
601 |
|
610 |
602 |
void do_tlbp (void)
|
... | ... | |
645 |
637 |
env->CP0_EntryHi = tlb->VPN | tlb->ASID;
|
646 |
638 |
size = (tlb->end - tlb->VPN) >> 12;
|
647 |
639 |
env->CP0_PageMask = (size - 1) << 13;
|
648 |
|
env->CP0_EntryLo0 = tlb->V[0] | tlb->D[0] | (tlb->C[0] << 3) |
|
649 |
|
(tlb->PFN[0] >> 6);
|
650 |
|
env->CP0_EntryLo1 = tlb->V[1] | tlb->D[1] | (tlb->C[1] << 3) |
|
651 |
|
(tlb->PFN[1] >> 6);
|
|
640 |
env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2)
|
|
641 |
| (tlb->C0 << 3) | (tlb->PFN[0] >> 6);
|
|
642 |
env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2)
|
|
643 |
| (tlb->C1 << 3) | (tlb->PFN[1] >> 6);
|
652 |
644 |
}
|
653 |
645 |
#endif
|
654 |
646 |
|