SaveState: Only remap changed TLB slots on load

This commit is contained in:
Connor McLaughlin 2022-10-29 21:00:38 +10:00 committed by refractionpcsx2
parent 1ccddb92d4
commit 0e73bf1e6d
4 changed files with 58 additions and 39 deletions

View File

@ -235,81 +235,81 @@ __fi void COP0_UpdatePCCR()
// //
void MapTLB(int i) void MapTLB(const tlbs& t, int i)
{ {
u32 mask, addr; u32 mask, addr;
u32 saddr, eaddr; u32 saddr, eaddr;
COP0_LOG("MAP TLB %d: 0x%08X-> [0x%08X 0x%08X] S=%d G=%d ASID=%d Mask=0x%03X EntryLo0 PFN=%x EntryLo0 Cache=%x EntryLo1 PFN=%x EntryLo1 Cache=%x VPN2=%x", COP0_LOG("MAP TLB %d: 0x%08X-> [0x%08X 0x%08X] S=%d G=%d ASID=%d Mask=0x%03X EntryLo0 PFN=%x EntryLo0 Cache=%x EntryLo1 PFN=%x EntryLo1 Cache=%x VPN2=%x",
i, tlb[i].VPN2, tlb[i].PFN0, tlb[i].PFN1, tlb[i].S >> 31, tlb[i].G, tlb[i].ASID, i, t.VPN2, t.PFN0, t.PFN1, t.S >> 31, t.G, t.ASID,
tlb[i].Mask, tlb[i].EntryLo0 >> 6, (tlb[i].EntryLo0 & 0x38) >> 3, tlb[i].EntryLo1 >> 6, (tlb[i].EntryLo1 & 0x38) >> 3, tlb[i].VPN2); t.Mask, t.EntryLo0 >> 6, (t.EntryLo0 & 0x38) >> 3, t.EntryLo1 >> 6, (t.EntryLo1 & 0x38) >> 3, t.VPN2);
if (tlb[i].S) if (t.S)
{ {
vtlb_VMapBuffer(tlb[i].VPN2, eeMem->Scratch, Ps2MemSize::Scratch); vtlb_VMapBuffer(t.VPN2, eeMem->Scratch, Ps2MemSize::Scratch);
} }
if (tlb[i].VPN2 == 0x70000000) return; //uh uhh right ... if (t.VPN2 == 0x70000000) return; //uh uhh right ...
if (tlb[i].EntryLo0 & 0x2) { if (t.EntryLo0 & 0x2) {
mask = ((~tlb[i].Mask) << 1) & 0xfffff; mask = ((~t.Mask) << 1) & 0xfffff;
saddr = tlb[i].VPN2 >> 12; saddr = t.VPN2 >> 12;
eaddr = saddr + tlb[i].Mask + 1; eaddr = saddr + t.Mask + 1;
for (addr=saddr; addr<eaddr; addr++) { for (addr=saddr; addr<eaddr; addr++) {
if ((addr & mask) == ((tlb[i].VPN2 >> 12) & mask)) { //match if ((addr & mask) == ((t.VPN2 >> 12) & mask)) { //match
memSetPageAddr(addr << 12, tlb[i].PFN0 + ((addr - saddr) << 12)); memSetPageAddr(addr << 12, t.PFN0 + ((addr - saddr) << 12));
Cpu->Clear(addr << 12, 0x400); Cpu->Clear(addr << 12, 0x400);
} }
} }
} }
if (tlb[i].EntryLo1 & 0x2) { if (t.EntryLo1 & 0x2) {
mask = ((~tlb[i].Mask) << 1) & 0xfffff; mask = ((~t.Mask) << 1) & 0xfffff;
saddr = (tlb[i].VPN2 >> 12) + tlb[i].Mask + 1; saddr = (t.VPN2 >> 12) + t.Mask + 1;
eaddr = saddr + tlb[i].Mask + 1; eaddr = saddr + t.Mask + 1;
for (addr=saddr; addr<eaddr; addr++) { for (addr=saddr; addr<eaddr; addr++) {
if ((addr & mask) == ((tlb[i].VPN2 >> 12) & mask)) { //match if ((addr & mask) == ((t.VPN2 >> 12) & mask)) { //match
memSetPageAddr(addr << 12, tlb[i].PFN1 + ((addr - saddr) << 12)); memSetPageAddr(addr << 12, t.PFN1 + ((addr - saddr) << 12));
Cpu->Clear(addr << 12, 0x400); Cpu->Clear(addr << 12, 0x400);
} }
} }
} }
} }
void UnmapTLB(int i) void UnmapTLB(const tlbs& t, int i)
{ {
//Console.WriteLn("Clear TLB %d: %08x-> [%08x %08x] S=%d G=%d ASID=%d Mask= %03X", i,tlb[i].VPN2,tlb[i].PFN0,tlb[i].PFN1,tlb[i].S,tlb[i].G,tlb[i].ASID,tlb[i].Mask); //Console.WriteLn("Clear TLB %d: %08x-> [%08x %08x] S=%d G=%d ASID=%d Mask= %03X", i,t.VPN2,t.PFN0,t.PFN1,t.S,t.G,t.ASID,t.Mask);
u32 mask, addr; u32 mask, addr;
u32 saddr, eaddr; u32 saddr, eaddr;
if (tlb[i].S) if (t.S)
{ {
vtlb_VMapUnmap(tlb[i].VPN2,0x4000); vtlb_VMapUnmap(t.VPN2,0x4000);
return; return;
} }
if (tlb[i].EntryLo0 & 0x2) if (t.EntryLo0 & 0x2)
{ {
mask = ((~tlb[i].Mask) << 1) & 0xfffff; mask = ((~t.Mask) << 1) & 0xfffff;
saddr = tlb[i].VPN2 >> 12; saddr = t.VPN2 >> 12;
eaddr = saddr + tlb[i].Mask + 1; eaddr = saddr + t.Mask + 1;
// Console.WriteLn("Clear TLB: %08x ~ %08x",saddr,eaddr-1); // Console.WriteLn("Clear TLB: %08x ~ %08x",saddr,eaddr-1);
for (addr=saddr; addr<eaddr; addr++) { for (addr=saddr; addr<eaddr; addr++) {
if ((addr & mask) == ((tlb[i].VPN2 >> 12) & mask)) { //match if ((addr & mask) == ((t.VPN2 >> 12) & mask)) { //match
memClearPageAddr(addr << 12); memClearPageAddr(addr << 12);
Cpu->Clear(addr << 12, 0x400); Cpu->Clear(addr << 12, 0x400);
} }
} }
} }
if (tlb[i].EntryLo1 & 0x2) { if (t.EntryLo1 & 0x2) {
mask = ((~tlb[i].Mask) << 1) & 0xfffff; mask = ((~t.Mask) << 1) & 0xfffff;
saddr = (tlb[i].VPN2 >> 12) + tlb[i].Mask + 1; saddr = (t.VPN2 >> 12) + t.Mask + 1;
eaddr = saddr + tlb[i].Mask + 1; eaddr = saddr + t.Mask + 1;
// Console.WriteLn("Clear TLB: %08x ~ %08x",saddr,eaddr-1); // Console.WriteLn("Clear TLB: %08x ~ %08x",saddr,eaddr-1);
for (addr=saddr; addr<eaddr; addr++) { for (addr=saddr; addr<eaddr; addr++) {
if ((addr & mask) == ((tlb[i].VPN2 >> 12) & mask)) { //match if ((addr & mask) == ((t.VPN2 >> 12) & mask)) { //match
memClearPageAddr(addr << 12); memClearPageAddr(addr << 12);
Cpu->Clear(addr << 12, 0x400); Cpu->Clear(addr << 12, 0x400);
} }
@ -333,7 +333,7 @@ void WriteTLB(int i)
tlb[i].PFN1 = (((cpuRegs.CP0.n.EntryLo1 >> 6) & 0xFFFFF) & (~tlb[i].Mask)) << 12; tlb[i].PFN1 = (((cpuRegs.CP0.n.EntryLo1 >> 6) & 0xFFFFF) & (~tlb[i].Mask)) << 12;
tlb[i].S = cpuRegs.CP0.n.EntryLo0&0x80000000; tlb[i].S = cpuRegs.CP0.n.EntryLo0&0x80000000;
MapTLB(i); MapTLB(tlb[i], i);
} }
namespace R5900 { namespace R5900 {
@ -363,7 +363,7 @@ void TLBWI() {
cpuRegs.CP0.n.Index, cpuRegs.CP0.n.PageMask, cpuRegs.CP0.n.EntryHi, cpuRegs.CP0.n.Index, cpuRegs.CP0.n.PageMask, cpuRegs.CP0.n.EntryHi,
cpuRegs.CP0.n.EntryLo0, cpuRegs.CP0.n.EntryLo1); cpuRegs.CP0.n.EntryLo0, cpuRegs.CP0.n.EntryLo1);
UnmapTLB(j); UnmapTLB(tlb[j], j);
tlb[j].PageMask = cpuRegs.CP0.n.PageMask; tlb[j].PageMask = cpuRegs.CP0.n.PageMask;
tlb[j].EntryHi = cpuRegs.CP0.n.EntryHi; tlb[j].EntryHi = cpuRegs.CP0.n.EntryHi;
tlb[j].EntryLo0 = cpuRegs.CP0.n.EntryLo0; tlb[j].EntryLo0 = cpuRegs.CP0.n.EntryLo0;
@ -382,7 +382,7 @@ DevCon.Warning("COP0_TLBWR %d:%x,%x,%x,%x\n",
//if (j > 48) return; //if (j > 48) return;
UnmapTLB(j); UnmapTLB(tlb[j], j);
tlb[j].PageMask = cpuRegs.CP0.n.PageMask; tlb[j].PageMask = cpuRegs.CP0.n.PageMask;
tlb[j].EntryHi = cpuRegs.CP0.n.EntryHi; tlb[j].EntryHi = cpuRegs.CP0.n.EntryHi;
tlb[j].EntryLo0 = cpuRegs.CP0.n.EntryLo0; tlb[j].EntryLo0 = cpuRegs.CP0.n.EntryLo0;

View File

@ -15,12 +15,14 @@
#pragma once #pragma once
struct tlbs;
extern void WriteCP0Status(u32 value); extern void WriteCP0Status(u32 value);
extern void WriteCP0Config(u32 value); extern void WriteCP0Config(u32 value);
extern void cpuUpdateOperationMode(); extern void cpuUpdateOperationMode();
extern void WriteTLB(int i); extern void WriteTLB(int i);
extern void UnmapTLB(int i); extern void UnmapTLB(const tlbs& t, int i);
extern void MapTLB(int i); extern void MapTLB(const tlbs& t, int i);
extern void COP0_UpdatePCCR(); extern void COP0_UpdatePCCR();
extern void COP0_DiagnosticPCCR(); extern void COP0_DiagnosticPCCR();

View File

@ -62,12 +62,21 @@
using namespace R5900; using namespace R5900;
static tlbs s_tlb_backup[std::size(tlb)];
static void PreLoadPrep() static void PreLoadPrep()
{ {
// ensure everything is in sync before we start overwriting stuff. // ensure everything is in sync before we start overwriting stuff.
if (THREAD_VU1) if (THREAD_VU1)
vu1Thread.WaitVU(); vu1Thread.WaitVU();
GetMTGS().WaitGS(false); GetMTGS().WaitGS(false);
// backup current TLBs, since we're going to overwrite them all
std::memcpy(s_tlb_backup, tlb, sizeof(s_tlb_backup));
// clear protected pages, since we don't want to fault loading EE memory
mmap_ResetBlockTracking();
SysClearExecutionCache(); SysClearExecutionCache();
#ifndef PCSX2_CORE #ifndef PCSX2_CORE
PatchesVerboseReset(); PatchesVerboseReset();
@ -78,7 +87,15 @@ static void PostLoadPrep()
{ {
resetCache(); resetCache();
// WriteCP0Status(cpuRegs.CP0.n.Status.val); // WriteCP0Status(cpuRegs.CP0.n.Status.val);
for(int i=0; i<48; i++) MapTLB(i); for (int i = 0; i < 48; i++)
{
if (std::memcmp(&s_tlb_backup[i], &tlb[i], sizeof(tlbs)) != 0)
{
UnmapTLB(s_tlb_backup[i], i);
MapTLB(tlb[i], i);
}
}
if (EmuConfig.Gamefixes.GoemonTlbHack) GoemonPreloadTlb(); if (EmuConfig.Gamefixes.GoemonTlbHack) GoemonPreloadTlb();
CBreakPoints::SetSkipFirst(BREAKPOINT_EE, 0); CBreakPoints::SetSkipFirst(BREAKPOINT_EE, 0);
CBreakPoints::SetSkipFirst(BREAKPOINT_IOP, 0); CBreakPoints::SetSkipFirst(BREAKPOINT_IOP, 0);

View File

@ -1183,7 +1183,7 @@ void vtlb_Init()
void vtlb_Reset() void vtlb_Reset()
{ {
vtlb_RemoveFastmemMappings(); vtlb_RemoveFastmemMappings();
for(int i=0; i<48; i++) UnmapTLB(i); for(int i=0; i<48; i++) UnmapTLB(tlb[i], i);
} }
void vtlb_Shutdown() void vtlb_Shutdown()