Core: Have load/store ops be able to use 64bit addresses

This commit is contained in:
zilmar 2023-10-05 14:28:32 +10:30
parent 9f07fe2aac
commit e74e8f6a23
4 changed files with 408 additions and 70 deletions

View File

@ -364,10 +364,16 @@ bool CMipsMemoryVM::UpdateMemoryValue32(uint32_t VAddr, uint32_t Value)
bool CMipsMemoryVM::LB_Memory(uint64_t VAddr, uint8_t & Value) bool CMipsMemoryVM::LB_Memory(uint64_t VAddr, uint8_t & Value)
{ {
if (!b32BitCore() && (uint64_t)((int32_t)VAddr) != VAddr) if ((uint64_t)((int32_t)VAddr) != VAddr)
{ {
m_Reg.DoAddressError(VAddr, true); uint32_t PAddr;
return false; bool MemoryUnused;
if (!g_TLB->VAddrToPAddr(VAddr, PAddr, MemoryUnused))
{
m_Reg.TriggerAddressException(VAddr, MemoryUnused ? EXC_RADE : EXC_RMISS);
return false;
}
return LB_PhysicalAddress(PAddr, Value);
} }
uint32_t VAddr32 = (uint32_t)VAddr; uint32_t VAddr32 = (uint32_t)VAddr;
if (HaveReadBP() && g_Debugger->ReadBP8(VAddr32) && MemoryBreakpoint()) if (HaveReadBP() && g_Debugger->ReadBP8(VAddr32) && MemoryBreakpoint())
@ -385,17 +391,23 @@ bool CMipsMemoryVM::LB_Memory(uint64_t VAddr, uint8_t & Value)
bool CMipsMemoryVM::LH_Memory(uint64_t VAddr, uint16_t & Value) bool CMipsMemoryVM::LH_Memory(uint64_t VAddr, uint16_t & Value)
{ {
if (!b32BitCore() && (uint64_t)((int32_t)VAddr) != VAddr) if ((VAddr & 1) != 0)
{ {
m_Reg.DoAddressError(VAddr, true); m_Reg.TriggerAddressException(VAddr, EXC_RADE);
return false; return false;
} }
if ((uint64_t)((int32_t)VAddr) != VAddr)
{
uint32_t PAddr;
bool MemoryUnused;
if (!g_TLB->VAddrToPAddr(VAddr, PAddr, MemoryUnused))
{
m_Reg.TriggerAddressException(VAddr, MemoryUnused ? EXC_RADE : EXC_RMISS);
return false;
}
return LH_PhysicalAddress(PAddr, Value);
}
uint32_t VAddr32 = (uint32_t)VAddr; uint32_t VAddr32 = (uint32_t)VAddr;
if ((VAddr32 & 1) != 0)
{
m_Reg.DoAddressError(VAddr, true);
return false;
}
if (HaveReadBP() && g_Debugger->ReadBP16(VAddr32) && MemoryBreakpoint()) if (HaveReadBP() && g_Debugger->ReadBP16(VAddr32) && MemoryBreakpoint())
{ {
return false; return false;
@ -411,17 +423,23 @@ bool CMipsMemoryVM::LH_Memory(uint64_t VAddr, uint16_t & Value)
bool CMipsMemoryVM::LW_Memory(uint64_t VAddr, uint32_t & Value) bool CMipsMemoryVM::LW_Memory(uint64_t VAddr, uint32_t & Value)
{ {
if (!b32BitCore() && (uint64_t)((int32_t)VAddr) != VAddr) if ((VAddr & 3) != 0)
{ {
m_Reg.DoAddressError(VAddr, true); m_Reg.TriggerAddressException(VAddr, EXC_RADE);
return false; return false;
} }
if ((uint64_t)((int32_t)VAddr) != VAddr)
{
uint32_t PAddr;
bool MemoryUnused;
if (!g_TLB->VAddrToPAddr(VAddr, PAddr, MemoryUnused))
{
m_Reg.TriggerAddressException(VAddr, MemoryUnused ? EXC_RADE : EXC_RMISS);
return false;
}
return LW_PhysicalAddress(PAddr, Value);
}
uint32_t VAddr32 = (uint32_t)VAddr; uint32_t VAddr32 = (uint32_t)VAddr;
if ((VAddr32 & 3) != 0)
{
m_Reg.DoAddressError(VAddr, true);
return false;
}
if (HaveReadBP() && g_Debugger->ReadBP32(VAddr32) && MemoryBreakpoint()) if (HaveReadBP() && g_Debugger->ReadBP32(VAddr32) && MemoryBreakpoint())
{ {
return false; return false;
@ -437,18 +455,23 @@ bool CMipsMemoryVM::LW_Memory(uint64_t VAddr, uint32_t & Value)
bool CMipsMemoryVM::LD_Memory(uint64_t VAddr, uint64_t & Value) bool CMipsMemoryVM::LD_Memory(uint64_t VAddr, uint64_t & Value)
{ {
if (!b32BitCore() && (uint64_t)((int32_t)VAddr) != VAddr) if ((VAddr & 7) != 0)
{ {
m_Reg.DoAddressError(VAddr, true); m_Reg.TriggerAddressException(VAddr, EXC_RADE);
return false; return false;
} }
if ((uint64_t)((int32_t)VAddr) != VAddr)
{
uint32_t PAddr;
bool MemoryUnused;
if (!g_TLB->VAddrToPAddr(VAddr, PAddr, MemoryUnused))
{
m_Reg.TriggerAddressException(VAddr, MemoryUnused ? EXC_RADE : EXC_RMISS);
return false;
}
return LD_PhysicalAddress(PAddr, Value);
}
uint32_t VAddr32 = (uint32_t)VAddr; uint32_t VAddr32 = (uint32_t)VAddr;
if ((VAddr32 & 7) != 0)
{
m_Reg.DoAddressError(VAddr, true);
return false;
}
if (HaveReadBP() && g_Debugger->ReadBP64(VAddr32) && MemoryBreakpoint()) if (HaveReadBP() && g_Debugger->ReadBP64(VAddr32) && MemoryBreakpoint())
{ {
return false; return false;
@ -465,13 +488,18 @@ bool CMipsMemoryVM::LD_Memory(uint64_t VAddr, uint64_t & Value)
bool CMipsMemoryVM::SB_Memory(uint64_t VAddr, uint32_t Value) bool CMipsMemoryVM::SB_Memory(uint64_t VAddr, uint32_t Value)
{ {
if (!b32BitCore() && (uint64_t)((int32_t)VAddr) != VAddr) if ((uint64_t)((int32_t)VAddr) != VAddr)
{ {
m_Reg.DoAddressError(VAddr, false); uint32_t PAddr;
return false; bool MemoryUnused;
if (!g_TLB->VAddrToPAddr(VAddr, PAddr, MemoryUnused))
{
m_Reg.TriggerAddressException(VAddr, MemoryUnused ? EXC_WADE : EXC_WMISS);
return false;
}
return SB_PhysicalAddress(PAddr, Value);
} }
uint32_t VAddr32 = (uint32_t)VAddr; uint32_t VAddr32 = (uint32_t)VAddr;
if (HaveWriteBP() && g_Debugger->WriteBP8(VAddr32) && MemoryBreakpoint()) if (HaveWriteBP() && g_Debugger->WriteBP8(VAddr32) && MemoryBreakpoint())
{ {
return false; return false;
@ -487,18 +515,23 @@ bool CMipsMemoryVM::SB_Memory(uint64_t VAddr, uint32_t Value)
bool CMipsMemoryVM::SH_Memory(uint64_t VAddr, uint32_t Value) bool CMipsMemoryVM::SH_Memory(uint64_t VAddr, uint32_t Value)
{ {
if (!b32BitCore() && (uint64_t)((int32_t)VAddr) != VAddr) if ((VAddr & 1) != 0)
{ {
m_Reg.DoAddressError(VAddr, false); m_Reg.TriggerAddressException(VAddr, EXC_WADE);
return false; return false;
} }
if ((uint64_t)((int32_t)VAddr) != VAddr)
{
uint32_t PAddr;
bool MemoryUnused;
if (!g_TLB->VAddrToPAddr(VAddr, PAddr, MemoryUnused))
{
m_Reg.TriggerAddressException(VAddr, MemoryUnused ? EXC_WADE : EXC_WMISS);
return false;
}
return SH_PhysicalAddress(PAddr, Value);
}
uint32_t VAddr32 = (uint32_t)VAddr; uint32_t VAddr32 = (uint32_t)VAddr;
if ((VAddr32 & 1) != 0)
{
m_Reg.DoAddressError(VAddr, false);
return false;
}
if (HaveWriteBP() && g_Debugger->WriteBP16(VAddr32) && MemoryBreakpoint()) if (HaveWriteBP() && g_Debugger->WriteBP16(VAddr32) && MemoryBreakpoint())
{ {
return false; return false;
@ -514,18 +547,23 @@ bool CMipsMemoryVM::SH_Memory(uint64_t VAddr, uint32_t Value)
bool CMipsMemoryVM::SW_Memory(uint64_t VAddr, uint32_t Value) bool CMipsMemoryVM::SW_Memory(uint64_t VAddr, uint32_t Value)
{ {
if (!b32BitCore() && (uint64_t)((int32_t)VAddr) != VAddr) if ((VAddr & 3) != 0)
{ {
m_Reg.DoAddressError(VAddr, false); m_Reg.TriggerAddressException(VAddr, EXC_WADE);
return false; return false;
} }
if ((uint64_t)((int32_t)VAddr) != VAddr)
{
uint32_t PAddr;
bool MemoryUnused;
if (!g_TLB->VAddrToPAddr(VAddr, PAddr, MemoryUnused))
{
m_Reg.TriggerAddressException(VAddr, MemoryUnused ? EXC_WADE : EXC_WMISS);
return false;
}
return SW_PhysicalAddress(PAddr, Value);
}
uint32_t VAddr32 = (uint32_t)VAddr; uint32_t VAddr32 = (uint32_t)VAddr;
if ((VAddr32 & 3) != 0)
{
m_Reg.DoAddressError(VAddr, false);
return false;
}
if (HaveWriteBP() && g_Debugger->WriteBP32(VAddr32) && MemoryBreakpoint()) if (HaveWriteBP() && g_Debugger->WriteBP32(VAddr32) && MemoryBreakpoint())
{ {
return false; return false;
@ -541,23 +579,27 @@ bool CMipsMemoryVM::SW_Memory(uint64_t VAddr, uint32_t Value)
bool CMipsMemoryVM::SD_Memory(uint64_t VAddr, uint64_t Value) bool CMipsMemoryVM::SD_Memory(uint64_t VAddr, uint64_t Value)
{ {
if (!b32BitCore() && (uint64_t)((int32_t)VAddr) != VAddr)
{
m_Reg.DoAddressError(VAddr, false);
return false;
}
uint32_t VAddr32 = (uint32_t)VAddr;
if ((VAddr & 7) != 0) if ((VAddr & 7) != 0)
{ {
m_Reg.DoAddressError(VAddr, false); m_Reg.TriggerAddressException(VAddr, EXC_WADE);
return false; return false;
} }
if ((uint64_t)((int32_t)VAddr) != VAddr)
{
uint32_t PAddr;
bool MemoryUnused;
if (!g_TLB->VAddrToPAddr(VAddr, PAddr, MemoryUnused))
{
m_Reg.TriggerAddressException(VAddr, MemoryUnused ? EXC_WADE : EXC_WMISS);
return false;
}
return SD_PhysicalAddress(PAddr, Value);
}
uint32_t VAddr32 = (uint32_t)VAddr;
if (HaveWriteBP() && g_Debugger->WriteBP64(VAddr32) && MemoryBreakpoint()) if (HaveWriteBP() && g_Debugger->WriteBP64(VAddr32) && MemoryBreakpoint())
{ {
return false; return false;
} }
uint8_t * MemoryPtr = (uint8_t *)m_MemoryWriteMap[VAddr32 >> 12]; uint8_t * MemoryPtr = (uint8_t *)m_MemoryWriteMap[VAddr32 >> 12];
if (MemoryPtr != (uint8_t *)-1) if (MemoryPtr != (uint8_t *)-1)
{ {
@ -635,7 +677,12 @@ bool CMipsMemoryVM::LB_PhysicalAddress(uint32_t PAddr, uint8_t & Value)
{ {
case 0x1FC00000: m_PifRamHandler.Read32(ReadAddress, Value32); break; case 0x1FC00000: m_PifRamHandler.Read32(ReadAddress, Value32); break;
default: default:
if (PAddr >= 0x10000000 && PAddr < 0x20000000) if (PAddr < RdramSize())
{
Value = *(uint8_t *)(m_RDRAM + (PAddr ^ 3));
return true;
}
else if (PAddr >= 0x10000000 && PAddr < 0x20000000)
{ {
if (!m_RomMemoryHandler.Read32(PAddr, Value32)) if (!m_RomMemoryHandler.Read32(PAddr, Value32))
{ {
@ -665,7 +712,12 @@ bool CMipsMemoryVM::LH_PhysicalAddress(uint32_t PAddr, uint16_t & Value)
{ {
case 0x1FC00000: m_PifRamHandler.Read32(ReadAddress, Value32); break; case 0x1FC00000: m_PifRamHandler.Read32(ReadAddress, Value32); break;
default: default:
if (PAddr >= 0x10000000 && PAddr < 0x20000000) if (PAddr < RdramSize())
{
Value = *(uint16_t *)(m_RDRAM + (PAddr ^ 2));
return true;
}
else if (PAddr >= 0x10000000 && PAddr < 0x20000000)
{ {
if (!m_RomMemoryHandler.Read32(PAddr, Value32)) if (!m_RomMemoryHandler.Read32(PAddr, Value32))
{ {
@ -707,7 +759,11 @@ bool CMipsMemoryVM::LW_PhysicalAddress(uint32_t PAddr, uint32_t & Value)
case 0x1FC00000: m_PifRamHandler.Read32(PAddr, Value); break; case 0x1FC00000: m_PifRamHandler.Read32(PAddr, Value); break;
case 0x1FF00000: m_CartridgeDomain1Address3Handler.Read32(PAddr, Value); break; case 0x1FF00000: m_CartridgeDomain1Address3Handler.Read32(PAddr, Value); break;
default: default:
if (PAddr >= 0x10000000 && PAddr < 0x20000000) if (PAddr < RdramSize())
{
Value = *(uint32_t *)(m_RDRAM + PAddr);
}
else if (PAddr >= 0x10000000 && PAddr < 0x20000000)
{ {
m_RomMemoryHandler.Read32(PAddr, Value); m_RomMemoryHandler.Read32(PAddr, Value);
} }
@ -726,7 +782,13 @@ bool CMipsMemoryVM::LW_PhysicalAddress(uint32_t PAddr, uint32_t & Value)
bool CMipsMemoryVM::LD_PhysicalAddress(uint32_t PAddr, uint64_t & Value) bool CMipsMemoryVM::LD_PhysicalAddress(uint32_t PAddr, uint64_t & Value)
{ {
if (PAddr < 0x800000) if (PAddr < RdramSize())
{
*((uint32_t *)(&Value) + 1) = *(uint32_t *)(m_RDRAM + PAddr);
*((uint32_t *)(&Value) + 0) = *(uint32_t *)(m_RDRAM + PAddr + 4);
return true;
}
else if (PAddr < 0x800000)
{ {
Value = 0; Value = 0;
return true; return true;

View File

@ -526,6 +526,7 @@ void CRegisters::Reset(bool bPostPif, CMipsMemoryVM & MMU)
case CIC_NUS_6106: PIF_Ram[37] = 0x02; PIF_Ram[38] = 0x85; break; case CIC_NUS_6106: PIF_Ram[37] = 0x02; PIF_Ram[38] = 0x85; break;
}*/ }*/
} }
m_System.m_TLB.COP0StatusChanged();
} }
void CRegisters::SetAsCurrentSystem() void CRegisters::SetAsCurrentSystem()
@ -630,6 +631,7 @@ void CRegisters::Cop0_MT(COP0Reg Reg, uint64_t Value)
{ {
FixFpuLocations(); FixFpuLocations();
} }
m_System.m_TLB.COP0StatusChanged();
CheckInterrupts(); CheckInterrupts();
break; break;
} }
@ -790,7 +792,7 @@ void CRegisters::TriggerAddressException(uint64_t Address, uint32_t ExceptionCod
} }
BAD_VADDR_REGISTER = Address; BAD_VADDR_REGISTER = Address;
ENTRYHI_REGISTER.VPN2 = Address >> 13; ENTRYHI_REGISTER.VPN2 = ((Address >> 13) & 0x7FFFFFF);
ENTRYHI_REGISTER.R = Address >> 62; ENTRYHI_REGISTER.R = Address >> 62;
CONTEXT_REGISTER.BadVPN2 = Address >> 13; CONTEXT_REGISTER.BadVPN2 = Address >> 13;
XCONTEXT_REGISTER.BadVPN2 = Address >> 13; XCONTEXT_REGISTER.BadVPN2 = Address >> 13;
@ -831,7 +833,7 @@ void CRegisters::TriggerException(uint32_t ExceptionCode, uint32_t Coprocessor)
CAUSE_REGISTER.ExceptionCode = ExceptionCode; CAUSE_REGISTER.ExceptionCode = ExceptionCode;
CAUSE_REGISTER.CoprocessorUnitNumber = Coprocessor; CAUSE_REGISTER.CoprocessorUnitNumber = Coprocessor;
CAUSE_REGISTER.BranchDelay = m_System.m_PipelineStage == PIPELINE_STAGE_JUMP; CAUSE_REGISTER.BranchDelay = m_System.m_PipelineStage == PIPELINE_STAGE_JUMP || m_System.m_PipelineStage == PIPELINE_STAGE_PERMLOOP_DELAY_DONE;
EPC_REGISTER = (int64_t)((int32_t)m_PROGRAM_COUNTER - (CAUSE_REGISTER.BranchDelay ? 4 : 0)); EPC_REGISTER = (int64_t)((int32_t)m_PROGRAM_COUNTER - (CAUSE_REGISTER.BranchDelay ? 4 : 0));
STATUS_REGISTER.ExceptionLevel = 1; STATUS_REGISTER.ExceptionLevel = 1;
m_System.m_PipelineStage = PIPELINE_STAGE_JUMP; m_System.m_PipelineStage = PIPELINE_STAGE_JUMP;

View File

@ -10,7 +10,9 @@
CTLB::CTLB(CMipsMemoryVM & MMU, CRegisters & Reg, CRecompiler *& Recomp) : CTLB::CTLB(CMipsMemoryVM & MMU, CRegisters & Reg, CRecompiler *& Recomp) :
m_MMU(MMU), m_MMU(MMU),
m_Reg(Reg), m_Reg(Reg),
m_Recomp(Recomp) m_Recomp(Recomp),
m_PrivilegeMode(PrivilegeMode_Kernel),
m_AddressSize32bit(true)
{ {
WriteTrace(TraceTLB, TraceDebug, "Start"); WriteTrace(TraceTLB, TraceDebug, "Start");
memset(m_tlb, 0, sizeof(m_tlb)); memset(m_tlb, 0, sizeof(m_tlb));
@ -48,6 +50,7 @@ void CTLB::Reset(bool InvalidateTLB)
SetupTLB_Entry(count, false); SetupTLB_Entry(count, false);
} }
} }
COP0StatusChanged();
} }
bool CTLB::AddressDefined(uint64_t VAddr) bool CTLB::AddressDefined(uint64_t VAddr)
@ -188,6 +191,23 @@ void CTLB::WriteEntry(uint32_t Index, bool Random)
} }
} }
void CTLB::COP0StatusChanged(void)
{
m_PrivilegeMode = m_Reg.STATUS_REGISTER.PrivilegeMode;
switch (m_PrivilegeMode)
{
case PrivilegeMode_Kernel:
m_AddressSize32bit = m_Reg.STATUS_REGISTER.KernelExtendedAddressing == 0;
break;
case PrivilegeMode_Supervisor:
m_AddressSize32bit = m_Reg.STATUS_REGISTER.SupervisorExtendedAddressing == 0;
break;
case PrivilegeMode_User:
m_AddressSize32bit = m_Reg.STATUS_REGISTER.UserExtendedAddressing == 0;
break;
}
}
void CTLB::SetupTLB_Entry(uint32_t Index, bool Random) void CTLB::SetupTLB_Entry(uint32_t Index, bool Random)
{ {
// Fix up fast TLB entries // Fix up fast TLB entries
@ -201,10 +221,10 @@ void CTLB::SetupTLB_Entry(uint32_t Index, bool Random)
{ {
TLB_Unmaped(m_FastTlb[FastIndx].VSTART, m_FastTlb[FastIndx].Length); TLB_Unmaped(m_FastTlb[FastIndx].VSTART, m_FastTlb[FastIndx].Length);
} }
m_FastTlb[FastIndx].Length = (m_tlb[Index].PageMask.Mask << 12) + 0xFFF; m_FastTlb[FastIndx].Length = (uint32_t)((m_tlb[Index].PageMask.Mask << 12) + 0xFFF);
m_FastTlb[FastIndx].VSTART = m_tlb[Index].EntryHi.R << 62 | m_tlb[Index].EntryHi.VPN2 << 13; m_FastTlb[FastIndx].VSTART = m_tlb[Index].EntryHi.R << 62 | m_tlb[Index].EntryHi.VPN2 << 13;
m_FastTlb[FastIndx].VEND = m_FastTlb[FastIndx].VSTART + m_FastTlb[FastIndx].Length; m_FastTlb[FastIndx].VEND = m_FastTlb[FastIndx].VSTART + m_FastTlb[FastIndx].Length;
m_FastTlb[FastIndx].PHYSSTART = m_tlb[Index].EntryLo0.PFN << 12; m_FastTlb[FastIndx].PHYSSTART = (uint32_t)(m_tlb[Index].EntryLo0.PFN << 12);
m_FastTlb[FastIndx].PHYSEND = m_FastTlb[FastIndx].PHYSSTART + m_FastTlb[FastIndx].Length; m_FastTlb[FastIndx].PHYSEND = m_FastTlb[FastIndx].PHYSSTART + m_FastTlb[FastIndx].Length;
m_FastTlb[FastIndx].VALID = m_tlb[Index].EntryLo0.V; m_FastTlb[FastIndx].VALID = m_tlb[Index].EntryLo0.V;
m_FastTlb[FastIndx].DIRTY = m_tlb[Index].EntryLo0.D; m_FastTlb[FastIndx].DIRTY = m_tlb[Index].EntryLo0.D;
@ -218,10 +238,10 @@ void CTLB::SetupTLB_Entry(uint32_t Index, bool Random)
{ {
TLB_Unmaped(m_FastTlb[FastIndx].VSTART, m_FastTlb[FastIndx].Length); TLB_Unmaped(m_FastTlb[FastIndx].VSTART, m_FastTlb[FastIndx].Length);
} }
m_FastTlb[FastIndx].Length = (m_tlb[Index].PageMask.Mask << 12) + 0xFFF; m_FastTlb[FastIndx].Length = (uint32_t)((m_tlb[Index].PageMask.Mask << 12) + 0xFFF);
m_FastTlb[FastIndx].VSTART = (m_tlb[Index].EntryHi.R << 62 | (m_tlb[Index].EntryHi.VPN2 << 13)) + (m_FastTlb[FastIndx].Length + 1); m_FastTlb[FastIndx].VSTART = (m_tlb[Index].EntryHi.R << 62 | (m_tlb[Index].EntryHi.VPN2 << 13)) + (m_FastTlb[FastIndx].Length + 1);
m_FastTlb[FastIndx].VEND = m_FastTlb[FastIndx].VSTART + m_FastTlb[FastIndx].Length; m_FastTlb[FastIndx].VEND = m_FastTlb[FastIndx].VSTART + m_FastTlb[FastIndx].Length;
m_FastTlb[FastIndx].PHYSSTART = m_tlb[Index].EntryLo1.PFN << 12; m_FastTlb[FastIndx].PHYSSTART = (uint32_t)m_tlb[Index].EntryLo1.PFN << 12;
m_FastTlb[FastIndx].PHYSEND = m_FastTlb[FastIndx].PHYSSTART + m_FastTlb[FastIndx].Length; m_FastTlb[FastIndx].PHYSEND = m_FastTlb[FastIndx].PHYSSTART + m_FastTlb[FastIndx].Length;
m_FastTlb[FastIndx].VALID = m_tlb[Index].EntryLo1.V; m_FastTlb[FastIndx].VALID = m_tlb[Index].EntryLo1.V;
m_FastTlb[FastIndx].DIRTY = m_tlb[Index].EntryLo1.D; m_FastTlb[FastIndx].DIRTY = m_tlb[Index].EntryLo1.D;
@ -258,15 +278,254 @@ void CTLB::SetupTLB_Entry(uint32_t Index, bool Random)
} }
} }
void CTLB::TLB_Unmaped(uint32_t VAddr, uint32_t Len) void CTLB::TLB_Unmaped(uint64_t VAddr, uint32_t Len)
{ {
m_MMU.TLB_Unmaped(VAddr, Len); m_MMU.TLB_Unmaped(VAddr, Len);
if (m_Recomp && bSMM_TLB()) if (m_Recomp && bSMM_TLB() && (uint64_t)((int32_t)VAddr) == VAddr)
{ {
m_Recomp->ClearRecompCode_Virt(VAddr, Len, CRecompiler::Remove_TLB); m_Recomp->ClearRecompCode_Virt((uint32_t)VAddr, Len, CRecompiler::Remove_TLB);
} }
} }
bool CTLB::VAddrToPAddr(uint64_t VAddr, uint32_t & PAddr, bool & MemoryUnused)
{
MemoryUnused = false;
if (b32BitCore() && (uint64_t)((int32_t)VAddr) != VAddr)
{
MemoryUnused = true;
return false;
}
MemorySegment Segment = VAddrMemorySegment(VAddr);
if (Segment == MemorySegment_Mapped)
{
for (int i = 0; i < 64; i++)
{
if (m_FastTlb[i].ValidEntry == false)
{
continue;
}
if (VAddr >= m_FastTlb[i].VSTART && VAddr < m_FastTlb[i].VEND)
{
PAddr = (uint32_t)(m_FastTlb[i].PHYSSTART + (VAddr - m_FastTlb[i].VSTART));
return true;
}
}
return false;
}
if (Segment == MemorySegment_Unused)
{
MemoryUnused = true;
return false;
}
if (Segment == MemorySegment_Direct32 || Segment == MemorySegment_Cached32)
{
PAddr = VAddr & 0x1FFFFFFF;
return true;
}
return false;
}
MemorySegment CTLB::VAddrMemorySegment(uint64_t VAddr)
{
if (m_AddressSize32bit)
{
if ((uint64_t)((int32_t)VAddr) != VAddr)
{
return MemorySegment_Unused;
}
uint32_t VAddr32 = (uint32_t)VAddr;
if (m_PrivilegeMode == PrivilegeMode_Kernel)
{
if (VAddr32 <= 0x7fffffff) //kuseg
{
return MemorySegment_Mapped;
}
if (VAddr32 <= 0x9fffffff) //kseg0
{
return MemorySegment_Cached32;
}
if (VAddr32 <= 0xbfffffff) //kseg1
{
return MemorySegment_Direct32;
}
if (VAddr32 <= 0xdfffffff) //ksseg
{
return MemorySegment_Mapped;
}
if (VAddr32 <= 0xffffffff) //kseg3
{
return MemorySegment_Mapped;
}
}
else if (m_PrivilegeMode == PrivilegeMode_Supervisor)
{
if (VAddr32 <= 0x7fffffff) //suseg
{
return MemorySegment_Mapped;
}
if (VAddr32 <= 0xbfffffff)
{
return MemorySegment_Unused;
}
if (VAddr32 <= 0xdfffffff) //sseg
{
return MemorySegment_Mapped;
}
}
else if (m_PrivilegeMode == PrivilegeMode_User)
{
if (VAddr32 <= 0x7fffffff) //useg
{
return MemorySegment_Mapped;
}
}
return MemorySegment_Unused;
}
if (m_PrivilegeMode == PrivilegeMode_Kernel)
{
if (VAddr <= 0x000000ffffffffffull) //xkuseg
{
return MemorySegment_Mapped;
}
if (VAddr <= 0x3fffffffffffffffull)
{
return MemorySegment_Unused;
}
if (VAddr <= 0x400000ffffffffffull) //xksseg
{
return MemorySegment_Mapped;
}
if (VAddr <= 0x7fffffffffffffffull)
{
return MemorySegment_Unused;
}
if (VAddr <= 0x80000000ffffffffull) //xkphys*
{
return MemorySegment_Cached32;
}
if (VAddr <= 0x87ffffffffffffffull)
{
return MemorySegment_Unused;
}
if (VAddr <= 0x88000000ffffffffull)
{
return MemorySegment_Cached32; //xkphys*
}
if (VAddr <= 0x8fffffffffffffffull)
{
return MemorySegment_Unused;
}
if (VAddr <= 0x90000000ffffffffull) //xkphys*
{
return MemorySegment_Direct32;
}
if (VAddr <= 0x97ffffffffffffffull)
{
return MemorySegment_Unused;
}
if (VAddr <= 0x98000000ffffffffull) //xkphys*
{
return MemorySegment_Cached32;
}
if (VAddr <= 0x9fffffffffffffffull)
{
return MemorySegment_Unused;
}
if (VAddr <= 0xa0000000ffffffffull) //xkphys*
{
return MemorySegment_Cached32;
}
if (VAddr <= 0xa7ffffffffffffffull)
{
return MemorySegment_Unused;
}
if (VAddr <= 0xa8000000ffffffffull) //xkphys*
{
return MemorySegment_Cached32;
}
if (VAddr <= 0xafffffffffffffffull)
{
return MemorySegment_Unused;
}
if (VAddr <= 0xb0000000ffffffffull) //xkphys*
{
return MemorySegment_Cached32;
}
if (VAddr <= 0xb7ffffffffffffffull)
{
return MemorySegment_Unused;
}
if (VAddr <= 0xb8000000ffffffffull) //xkphys*
{
return MemorySegment_Cached32;
}
if (VAddr <= 0xbfffffffffffffffull)
{
return MemorySegment_Unused;
}
if (VAddr <= 0xc00000ff7fffffffull) //xkseg
{
return MemorySegment_Mapped;
}
if (VAddr <= 0xffffffff7fffffffull)
{
return MemorySegment_Unused;
}
if (VAddr <= 0xffffffff9fffffffull) //ckseg0
{
return MemorySegment_Cached32;
}
if (VAddr <= 0xffffffffbfffffffull) //ckseg1
{
return MemorySegment_Direct32;
}
if (VAddr <= 0xffffffffdfffffffull) //ckseg2
{
return MemorySegment_Mapped;
}
if (VAddr <= 0xffffffffffffffffull) //ckseg3
{
return MemorySegment_Mapped;
}
}
else if (m_PrivilegeMode == PrivilegeMode_Kernel)
{
if (VAddr <= 0x000000ffffffffffull) //xsuseg
{
return MemorySegment_Mapped;
}
if (VAddr <= 0x3fffffffffffffffull)
{
return MemorySegment_Unused;
}
if (VAddr <= 0x400000ffffffffffull) //xsseg
{
return MemorySegment_Mapped;
}
if (VAddr <= 0xffffffffbfffffffull)
{
return MemorySegment_Unused;
}
if (VAddr <= 0xffffffffdfffffffull) //csseg
{
return MemorySegment_Mapped;
}
if (VAddr <= 0xffffffffffffffffull)
{
return MemorySegment_Unused;
}
}
else if (m_PrivilegeMode == PrivilegeMode_User)
{
if (VAddr <= 0x000000ffffffffffull)
{
return MemorySegment_Mapped; //xuseg
}
}
return MemorySegment_Unused;
}
bool CTLB::PAddrToVAddr(uint32_t PAddr, uint32_t & VAddr, uint32_t & Index) bool CTLB::PAddrToVAddr(uint32_t PAddr, uint32_t & VAddr, uint32_t & Index)
{ {
for (int i = Index; i < 64; i++) for (int i = Index; i < 64; i++)
@ -277,7 +536,7 @@ bool CTLB::PAddrToVAddr(uint32_t PAddr, uint32_t & VAddr, uint32_t & Index)
} }
if (PAddr >= m_FastTlb[i].PHYSSTART && PAddr < m_FastTlb[i].PHYSEND) if (PAddr >= m_FastTlb[i].PHYSSTART && PAddr < m_FastTlb[i].PHYSEND)
{ {
VAddr = m_FastTlb[i].VSTART + (PAddr - m_FastTlb[i].PHYSSTART); VAddr = (uint32_t)(m_FastTlb[i].VSTART + (PAddr - m_FastTlb[i].PHYSSTART));
Index = i + 1; Index = i + 1;
return true; return true;
} }

View File

@ -9,6 +9,16 @@ class CRecompiler;
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4201) // warning C4201: nonstandard extension used : nameless struct/union #pragma warning(disable : 4201) // warning C4201: nonstandard extension used : nameless struct/union
enum MemorySegment
{
MemorySegment_Mapped,
MemorySegment_Cached,
MemorySegment_Cached32,
MemorySegment_Direct,
MemorySegment_Direct32,
MemorySegment_Unused,
};
struct TLB_ENTRY struct TLB_ENTRY
{ {
bool EntryDefined; bool EntryDefined;
@ -47,9 +57,11 @@ public:
void Probe(); void Probe();
void ReadEntry(); void ReadEntry();
void WriteEntry(uint32_t Index, bool Random); void WriteEntry(uint32_t Index, bool Random);
void COP0StatusChanged(void);
bool AddressDefined(uint64_t VAddr); bool AddressDefined(uint64_t VAddr);
TLB_ENTRY & TlbEntry(int32_t Entry); TLB_ENTRY & TlbEntry(int32_t Entry);
bool VAddrToPAddr(uint64_t VAddr, uint32_t & PAddr, bool & MemoryUnused);
bool PAddrToVAddr(uint32_t PAddr, uint32_t & VAddr, uint32_t & Index); bool PAddrToVAddr(uint32_t PAddr, uint32_t & VAddr, uint32_t & Index);
void RecordDifference(CLog & LogFile, const CTLB & rTLB); void RecordDifference(CLog & LogFile, const CTLB & rTLB);
@ -62,8 +74,11 @@ private:
CTLB & operator=(const CTLB &); CTLB & operator=(const CTLB &);
void SetupTLB_Entry(uint32_t Index, bool Random); void SetupTLB_Entry(uint32_t Index, bool Random);
void TLB_Unmaped(uint32_t VAddr, uint32_t Len); void TLB_Unmaped(uint64_t VAddr, uint32_t Len);
MemorySegment VAddrMemorySegment(uint64_t VAddr);
PRIVILEGE_MODE m_PrivilegeMode;
bool m_AddressSize32bit;
CMipsMemoryVM & m_MMU; CMipsMemoryVM & m_MMU;
CRegisters & m_Reg; CRegisters & m_Reg;
CRecompiler *& m_Recomp; CRecompiler *& m_Recomp;