Revision 98c1b82b target-mips/op_helper.c
b/target-mips/op_helper.c | ||
---|---|---|
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 |
|
Also available in: Unified diff