25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_mips_coproc.c,v 1.33 2006/06/22 13:30:38 debug Exp $ |
* $Id: cpu_mips_coproc.c,v 1.37 2006/06/25 02:46:07 debug Exp $ |
29 |
* |
* |
30 |
* Emulation of MIPS coprocessors. |
* Emulation of MIPS coprocessors. |
31 |
*/ |
*/ |
557 |
if (cp->coproc_nr==0 && reg_nr==COP0_PAGEMASK) unimpl = 0; |
if (cp->coproc_nr==0 && reg_nr==COP0_PAGEMASK) unimpl = 0; |
558 |
if (cp->coproc_nr==0 && reg_nr==COP0_WIRED) unimpl = 0; |
if (cp->coproc_nr==0 && reg_nr==COP0_WIRED) unimpl = 0; |
559 |
if (cp->coproc_nr==0 && reg_nr==COP0_BADVADDR) unimpl = 0; |
if (cp->coproc_nr==0 && reg_nr==COP0_BADVADDR) unimpl = 0; |
560 |
if (cp->coproc_nr==0 && reg_nr==COP0_COUNT) { |
if (cp->coproc_nr==0 && reg_nr==COP0_COUNT) unimpl = 0; |
|
#if 0 |
|
|
/* |
|
|
* This speeds up delay-loops that just read the count |
|
|
* register until it has reached a certain value. (Only for |
|
|
* R4000 etc.) |
|
|
* |
|
|
* TODO: Maybe this should be optional? |
|
|
*/ |
|
|
if (cpu->cd.mips.cpu_type.exc_model != EXC3K) { |
|
|
int increase = 500; |
|
|
int32_t x = cp->reg[COP0_COUNT]; |
|
|
int32_t y = cp->reg[COP0_COMPARE]; |
|
|
int32_t diff = x - y; |
|
|
if (diff < 0 && diff + increase >= 0 |
|
|
&& cpu->cd.mips.compare_register_set) { |
|
|
mips_cpu_interrupt(cpu, 7); |
|
|
cpu->cd.mips.compare_register_set = 0; |
|
|
} |
|
|
cp->reg[COP0_COUNT] = (int64_t) |
|
|
(int32_t)(cp->reg[COP0_COUNT] + increase); |
|
|
} |
|
|
#endif |
|
|
unimpl = 0; |
|
|
} |
|
561 |
if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYHI) unimpl = 0; |
if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYHI) unimpl = 0; |
562 |
if (cp->coproc_nr==0 && reg_nr==COP0_COMPARE) unimpl = 0; |
if (cp->coproc_nr==0 && reg_nr==COP0_COMPARE) unimpl = 0; |
563 |
if (cp->coproc_nr==0 && reg_nr==COP0_STATUS) unimpl = 0; |
if (cp->coproc_nr==0 && reg_nr==COP0_STATUS) unimpl = 0; |
804 |
case COP0_STATUS: |
case COP0_STATUS: |
805 |
oldmode = cp->reg[COP0_STATUS]; |
oldmode = cp->reg[COP0_STATUS]; |
806 |
tmp &= ~(1 << 21); /* bit 21 is read-only */ |
tmp &= ~(1 << 21); /* bit 21 is read-only */ |
807 |
|
|
808 |
/* |
/* |
809 |
* TODO: Perhaps this can be solved some other |
* When isolating caches, invalidate all translations. |
810 |
* way, like in the old bintrans system? |
* During the isolation, a special hack in memory_rw.c |
811 |
|
* prevents translation tables from being updated, so |
812 |
|
* the translation caches don't have to be invalidated |
813 |
|
* when switching back to normal mode. |
814 |
*/ |
*/ |
815 |
if (cpu->cd.mips.cpu_type.mmu_model == MMU3K && |
if (cpu->cd.mips.cpu_type.mmu_model == MMU3K && |
816 |
(oldmode & MIPS1_ISOL_CACHES) != |
(oldmode & MIPS1_ISOL_CACHES) != |
817 |
(tmp & MIPS1_ISOL_CACHES)) { |
(tmp & MIPS1_ISOL_CACHES)) { |
818 |
cpu->invalidate_translation_caches( |
/* Invalidate everything if we are switching |
819 |
cpu, 0, INVALIDATE_ALL); |
to isolated mode: */ |
820 |
|
if (tmp & MIPS1_ISOL_CACHES) { |
821 |
|
cpu->invalidate_translation_caches( |
822 |
|
cpu, 0, INVALIDATE_ALL); |
823 |
|
} |
824 |
|
|
825 |
/* Perhaps add some kind of INVALIDATE_ |
#if 1 |
826 |
ALL_PADDR_WHICH_HAS_A_CORRESPONDING_ |
/* |
827 |
VADDR of some kind? :-) */ |
* NOTE: This is not needed for NetBSD, but |
828 |
|
* Ultrix and Linux still needs this. They |
829 |
|
* shouldn't, though. Something else is buggy. |
830 |
|
*/ |
831 |
cpu_create_or_reset_tc(cpu); |
cpu_create_or_reset_tc(cpu); |
832 |
|
#endif |
833 |
} |
} |
834 |
unimpl = 0; |
unimpl = 0; |
835 |
break; |
break; |
1744 |
cp->tlbs[index].hi |= TLB_G; |
cp->tlbs[index].hi |= TLB_G; |
1745 |
} |
} |
1746 |
|
|
|
#if 1 |
|
|
cpu_create_or_reset_tc(cpu); |
|
|
#else |
|
1747 |
/* Invalidate any code translations, if we are writing |
/* Invalidate any code translations, if we are writing |
1748 |
Dirty pages to the TLB: */ |
Dirty pages to the TLB: */ |
1749 |
if (cp->reg[COP0_PAGEMASK] != 0) |
if (cp->reg[COP0_PAGEMASK] != 0 && |
1750 |
printf("MASK = %08"PRIx32"\n", (uint32_t)cp->reg[COP0_PAGEMASK]); |
cp->reg[COP0_PAGEMASK] != 0x1800) { |
1751 |
|
printf("TODO: MASK = %08"PRIx32"\n", |
1752 |
|
(uint32_t)cp->reg[COP0_PAGEMASK]); |
1753 |
|
exit(1); |
1754 |
|
} |
1755 |
|
|
1756 |
// if (cp->tlbs[index].lo0 & ENTRYLO_D) |
if (cp->tlbs[index].lo0 & ENTRYLO_D) |
1757 |
cpu->invalidate_code_translation(cpu, |
cpu->invalidate_code_translation(cpu, |
1758 |
((cp->tlbs[index].lo0 & ENTRYLO_PFN_MASK) |
((cp->tlbs[index].lo0 & ENTRYLO_PFN_MASK) |
1759 |
>> ENTRYLO_PFN_SHIFT) << 12, |
>> ENTRYLO_PFN_SHIFT) << 12, |
1760 |
INVALIDATE_PADDR); |
INVALIDATE_PADDR); |
1761 |
// if (cp->tlbs[index].lo1 & ENTRYLO_D) |
if (cp->tlbs[index].lo1 & ENTRYLO_D) |
1762 |
cpu->invalidate_code_translation(cpu, |
cpu->invalidate_code_translation(cpu, |
1763 |
((cp->tlbs[index].lo1 & ENTRYLO_PFN_MASK) |
((cp->tlbs[index].lo1 & ENTRYLO_PFN_MASK) |
1764 |
>> ENTRYLO_PFN_SHIFT) << 12, |
>> ENTRYLO_PFN_SHIFT) << 12, |
1765 |
INVALIDATE_PADDR); |
INVALIDATE_PADDR); |
1766 |
|
|
1767 |
|
#if 1 |
1768 |
if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) { |
if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) { |
1769 |
oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK_R10K; |
oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK_R10K; |
1770 |
/* 44 addressable bits: */ |
/* 44 addressable bits: */ |
1786 |
cpu->invalidate_translation_caches(cpu, ((cp->tlbs[index].lo1 & |
cpu->invalidate_translation_caches(cpu, ((cp->tlbs[index].lo1 & |
1787 |
ENTRYLO_PFN_MASK) >> ENTRYLO_PFN_SHIFT) << 12, INVALIDATE_PADDR); |
ENTRYLO_PFN_MASK) >> ENTRYLO_PFN_SHIFT) << 12, INVALIDATE_PADDR); |
1788 |
|
|
|
cpu->invalidate_translation_caches(cpu, oldvaddr, INVALIDATE_VADDR); |
|
|
cpu->invalidate_translation_caches(cpu, oldvaddr | 0x1000, INVALIDATE_VADDR); |
|
|
|
|
|
|
|
1789 |
#endif |
#endif |
1790 |
} |
} |
1791 |
} |
} |