Revision 98c1b82b

b/target-mips/cpu.h
21 21
    target_ulong VPN;
22 22
    target_ulong end;
23 23
    target_ulong end2;
24
    uint8_t ASID;
25
    uint8_t G;
26
    uint8_t C[2];
27
    uint8_t V[2];
28
    uint8_t D[2];
24
    uint_fast8_t ASID;
25
    uint_fast16_t G:1;
26
    uint_fast16_t C0:3;
27
    uint_fast16_t C1:3;
28
    uint_fast16_t V0:1;
29
    uint_fast16_t V1:1;
30
    uint_fast16_t D0:1;
31
    uint_fast16_t D1:1;
29 32
    target_ulong PFN[2];
30 33
};
31 34
#endif
b/target-mips/helper.c
50 50
            /* TLB match */
51 51
            n = (address >> 12) & 1;
52 52
            /* Check access rights */
53
            if ((tlb->V[n] & 2) && (rw == 0 || (tlb->D[n] & 4))) {
53
	    if (!(n ? tlb->V1 : tlb->V0))
54
                return -3;
55
	    if (rw == 0 || (n ? tlb->D1 : tlb->D0)) {
54 56
                *physical = tlb->PFN[n] | (address & 0xFFF);
55 57
                *prot = PAGE_READ;
56
                if (tlb->D[n])
58
                if (n ? tlb->D1 : tlb->D0)
57 59
                    *prot |= PAGE_WRITE;
58 60
                return 0;
59
            } else if (!(tlb->V[n] & 2)) {
60
                return -3;
61
            } else {
62
                return -4;
63 61
            }
62
            return -4;
64 63
        }
65 64
    }
66 65

  
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