531 |
|
|
532 |
void do_tlbwi (void) |
void do_tlbwi (void) |
533 |
{ |
{ |
534 |
invalidate_tb(env->CP0_index & 0xF); |
/* Wildly undefined effects for CP0_index containing a too high value and |
535 |
fill_tb(env->CP0_index & 0xF); |
MIPS_TLB_NB not being a power of two. But so does real silicon. */ |
536 |
|
invalidate_tb(env->CP0_index & (MIPS_TLB_NB - 1)); |
537 |
|
fill_tb(env->CP0_index & (MIPS_TLB_NB - 1)); |
538 |
} |
} |
539 |
|
|
540 |
void do_tlbwr (void) |
void do_tlbwr (void) |
554 |
|
|
555 |
tag = (env->CP0_EntryHi & 0xFFFFE000); |
tag = (env->CP0_EntryHi & 0xFFFFE000); |
556 |
ASID = env->CP0_EntryHi & 0x000000FF; |
ASID = env->CP0_EntryHi & 0x000000FF; |
557 |
for (i = 0; i < 16; i++) { |
for (i = 0; i < MIPS_TLB_NB; i++) { |
558 |
tlb = &env->tlb[i]; |
tlb = &env->tlb[i]; |
559 |
/* Check ASID, virtual page number & size */ |
/* Check ASID, virtual page number & size */ |
560 |
if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) { |
if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) { |
563 |
break; |
break; |
564 |
} |
} |
565 |
} |
} |
566 |
if (i == 16) { |
if (i == MIPS_TLB_NB) { |
567 |
env->CP0_index |= 0x80000000; |
env->CP0_index |= 0x80000000; |
568 |
} |
} |
569 |
} |
} |
573 |
tlb_t *tlb; |
tlb_t *tlb; |
574 |
int size; |
int size; |
575 |
|
|
576 |
tlb = &env->tlb[env->CP0_index & 0xF]; |
tlb = &env->tlb[env->CP0_index & (MIPS_TLB_NB - 1)]; |
577 |
env->CP0_EntryHi = tlb->VPN | tlb->ASID; |
env->CP0_EntryHi = tlb->VPN | tlb->ASID; |
578 |
size = (tlb->end - tlb->VPN) >> 12; |
size = (tlb->end - tlb->VPN) >> 12; |
579 |
env->CP0_PageMask = (size - 1) << 13; |
env->CP0_PageMask = (size - 1) << 13; |