Core: Fix up tlb Probe and call EXC_MOD when tlb is not dirty

This commit is contained in:
zilmar 2023-10-05 14:45:17 +10:30
parent e74e8f6a23
commit f73c3708a5
4 changed files with 37 additions and 28 deletions

View File

@ -788,7 +788,12 @@ void CRegisters::TriggerAddressException(uint64_t Address, uint32_t ExceptionCod
bool SpecialOffset = false;
if (ExceptionCode == EXC_RMISS || ExceptionCode == EXC_WMISS)
{
SpecialOffset = !m_TLB.AddressDefined(Address);
bool Dirty;
SpecialOffset = !m_TLB.AddressDefined(Address, Dirty);
if (!Dirty)
{
ExceptionCode = EXC_MOD;
}
}
BAD_VADDR_REGISTER = Address;

View File

@ -53,21 +53,26 @@ void CTLB::Reset(bool InvalidateTLB)
COP0StatusChanged();
}
bool CTLB::AddressDefined(uint64_t VAddr)
bool CTLB::AddressDefined(uint64_t VAddr, bool & Dirty)
{
if (VAddr >= 0x80000000 && VAddr <= 0xBFFFFFFF)
Dirty = true;
MemorySegment Segment = VAddrMemorySegment(VAddr);
if (Segment == MemorySegment_Mapped)
{
return true;
}
for (uint32_t i = 0; i < 64; i++)
{
if (m_FastTlb[i].ValidEntry &&
VAddr >= m_FastTlb[i].VSTART &&
VAddr <= m_FastTlb[i].VEND)
if (!m_FastTlb[i].GLOBAL || !m_FastTlb[i].ValidEntry || VAddr < m_FastTlb[i].VSTART || VAddr > m_FastTlb[i].VEND + 1)
{
continue;
}
if (!m_FastTlb[i].VALID)
{
return true;
}
Dirty = m_FastTlb[i].DIRTY;
return true;
}
return false;
}
return false;
}
@ -88,23 +93,22 @@ void CTLB::Probe()
continue;
}
uint64_t & TlbEntryHiValue = m_tlb[i].EntryHi.Value;
uint32_t Mask = (uint32_t)(~m_tlb[i].PageMask.Mask << 13);
uint32_t TlbValueMasked = TlbEntryHiValue & Mask;
uint32_t EntryHiMasked = m_Reg.ENTRYHI_REGISTER.Value & Mask;
const COP0EntryHi & TlbEntryHiValue = m_tlb[i].EntryHi;
uint64_t Mask = ~m_tlb[i].PageMask.Mask << 13;
uint64_t TlbValueMasked = TlbEntryHiValue.Value & Mask;
uint64_t EntryHiMasked = m_Reg.ENTRYHI_REGISTER.Value & Mask;
if (TlbValueMasked == EntryHiMasked)
{
if ((TlbEntryHiValue & 0x100) != 0 || // Global
((TlbEntryHiValue & 0xFF) == (m_Reg.ENTRYHI_REGISTER.Value & 0xFF))) // SameAsid
if (TlbValueMasked != EntryHiMasked ||
TlbEntryHiValue.R != m_Reg.ENTRYHI_REGISTER.R ||
(m_tlb[i].EntryLo0.GLOBAL == 0 || m_tlb[i].EntryLo1.GLOBAL == 0) && TlbEntryHiValue.ASID != m_Reg.ENTRYHI_REGISTER.ASID)
{
continue;
}
m_Reg.INDEX_REGISTER = i;
uint32_t FastIndx = i << 1;
m_FastTlb[FastIndx].Probed = true;
m_FastTlb[FastIndx + 1].Probed = true;
return;
}
}
break;
}
WriteTrace(TraceTLB, TraceDebug, "Done");
}

View File

@ -58,7 +58,7 @@ public:
void ReadEntry();
void WriteEntry(uint32_t Index, bool Random);
void COP0StatusChanged(void);
bool AddressDefined(uint64_t VAddr);
bool AddressDefined(uint64_t VAddr, bool & Dirty);
TLB_ENTRY & TlbEntry(int32_t Entry);
bool VAddrToPAddr(uint64_t VAddr, uint32_t & PAddr, bool & MemoryUnused);

View File

@ -2028,13 +2028,13 @@ bool CN64System::LoadState(const char * FileName)
LoadedZipFile = true;
continue;
}
if (LoadedZipFile && Value == SaveID_1 && port == UNZ_OK)
if (LoadedZipFile && SaveID == SaveID_1 && port == UNZ_OK)
{
// Extra info v1
// System timers info
m_SystemTimer.LoadData(file);
}
if (LoadedZipFile && Value == SaveID_2 && port == UNZ_OK)
if (LoadedZipFile && SaveID == SaveID_2 && port == UNZ_OK)
{
// Extra info v2 (Project64 2.4)
// Disk interface info