Commit 98c1b82b6cf96d650bf07a6a2bf0414907924ffe
1 parent
6d6f7c28
e bitfields in mips TLB structures (Thiemo Seufer).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1774 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
35 additions
and
41 deletions
target-mips/cpu.h
@@ -21,11 +21,14 @@ struct tlb_t { | @@ -21,11 +21,14 @@ struct tlb_t { | ||
21 | target_ulong VPN; | 21 | target_ulong VPN; |
22 | target_ulong end; | 22 | target_ulong end; |
23 | target_ulong end2; | 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 | target_ulong PFN[2]; | 32 | target_ulong PFN[2]; |
30 | }; | 33 | }; |
31 | #endif | 34 | #endif |
target-mips/helper.c
@@ -50,17 +50,16 @@ static int map_address (CPUState *env, target_ulong *physical, int *prot, | @@ -50,17 +50,16 @@ static int map_address (CPUState *env, target_ulong *physical, int *prot, | ||
50 | /* TLB match */ | 50 | /* TLB match */ |
51 | n = (address >> 12) & 1; | 51 | n = (address >> 12) & 1; |
52 | /* Check access rights */ | 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 | *physical = tlb->PFN[n] | (address & 0xFFF); | 56 | *physical = tlb->PFN[n] | (address & 0xFFF); |
55 | *prot = PAGE_READ; | 57 | *prot = PAGE_READ; |
56 | - if (tlb->D[n]) | 58 | + if (n ? tlb->D1 : tlb->D0) |
57 | *prot |= PAGE_WRITE; | 59 | *prot |= PAGE_WRITE; |
58 | return 0; | 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 |
target-mips/op_helper.c
@@ -535,30 +535,22 @@ void do_mtc0 (int reg, int sel) | @@ -535,30 +535,22 @@ void do_mtc0 (int reg, int sel) | ||
535 | 535 | ||
536 | /* TLB management */ | 536 | /* TLB management */ |
537 | #if defined(MIPS_USES_R4K_TLB) | 537 | #if defined(MIPS_USES_R4K_TLB) |
538 | -static void invalidate_tb (int idx) | 538 | +static void invalidate_tlb (int idx) |
539 | { | 539 | { |
540 | tlb_t *tlb; | 540 | tlb_t *tlb; |
541 | - target_ulong addr, end; | 541 | + target_ulong addr; |
542 | 542 | ||
543 | tlb = &env->tlb[idx]; | 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 | addr = tlb->VPN; | 546 | addr = tlb->VPN; |
551 | while (addr < tlb->end) { | 547 | while (addr < tlb->end) { |
552 | tlb_flush_page (env, addr); | 548 | tlb_flush_page (env, addr); |
553 | addr += TARGET_PAGE_SIZE; | 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 | addr = tlb->end; | 554 | addr = tlb->end; |
563 | while (addr < tlb->end2) { | 555 | while (addr < tlb->end2) { |
564 | tlb_flush_page (env, addr); | 556 | tlb_flush_page (env, addr); |
@@ -567,7 +559,7 @@ static void invalidate_tb (int idx) | @@ -567,7 +559,7 @@ static void invalidate_tb (int idx) | ||
567 | } | 559 | } |
568 | } | 560 | } |
569 | 561 | ||
570 | -static void fill_tb (int idx) | 562 | +static void fill_tlb (int idx) |
571 | { | 563 | { |
572 | tlb_t *tlb; | 564 | tlb_t *tlb; |
573 | int size; | 565 | int size; |
@@ -575,19 +567,19 @@ static void fill_tb (int idx) | @@ -575,19 +567,19 @@ static void fill_tb (int idx) | ||
575 | /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */ | 567 | /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */ |
576 | tlb = &env->tlb[idx]; | 568 | tlb = &env->tlb[idx]; |
577 | tlb->VPN = env->CP0_EntryHi & 0xFFFFE000; | 569 | tlb->VPN = env->CP0_EntryHi & 0xFFFFE000; |
578 | - tlb->ASID = env->CP0_EntryHi & 0x000000FF; | 570 | + tlb->ASID = env->CP0_EntryHi & 0xFF; |
579 | size = env->CP0_PageMask >> 13; | 571 | size = env->CP0_PageMask >> 13; |
580 | size = 4 * (size + 1); | 572 | size = 4 * (size + 1); |
581 | tlb->end = tlb->VPN + (1 << (8 + size)); | 573 | tlb->end = tlb->VPN + (1 << (8 + size)); |
582 | tlb->end2 = tlb->end + (1 << (8 + size)); | 574 | tlb->end2 = tlb->end + (1 << (8 + size)); |
583 | tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; | 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 | tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12; | 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 | tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12; | 583 | tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12; |
592 | } | 584 | } |
593 | 585 | ||
@@ -595,16 +587,16 @@ void do_tlbwi (void) | @@ -595,16 +587,16 @@ void do_tlbwi (void) | ||
595 | { | 587 | { |
596 | /* Wildly undefined effects for CP0_index containing a too high value and | 588 | /* Wildly undefined effects for CP0_index containing a too high value and |
597 | MIPS_TLB_NB not being a power of two. But so does real silicon. */ | 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 | void do_tlbwr (void) | 594 | void do_tlbwr (void) |
603 | { | 595 | { |
604 | int r = cpu_mips_get_random(env); | 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 | void do_tlbp (void) | 602 | void do_tlbp (void) |
@@ -645,10 +637,10 @@ void do_tlbr (void) | @@ -645,10 +637,10 @@ void do_tlbr (void) | ||
645 | env->CP0_EntryHi = tlb->VPN | tlb->ASID; | 637 | env->CP0_EntryHi = tlb->VPN | tlb->ASID; |
646 | size = (tlb->end - tlb->VPN) >> 12; | 638 | size = (tlb->end - tlb->VPN) >> 12; |
647 | env->CP0_PageMask = (size - 1) << 13; | 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 | #endif | 645 | #endif |
654 | 646 |