From 3ee2567540cb711b7187f9b68c33780adba428fd Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 29 Oct 2022 21:00:38 +1000 Subject: [PATCH] SaveState: Only remap changed TLB slots on load --- pcsx2/COP0.cpp | 70 ++++++++++++++++++++++----------------------- pcsx2/COP0.h | 6 ++-- pcsx2/SaveState.cpp | 19 +++++++++++- pcsx2/vtlb.cpp | 2 +- 4 files changed, 58 insertions(+), 39 deletions(-) diff --git a/pcsx2/COP0.cpp b/pcsx2/COP0.cpp index 9c6e315c78c5e..f039a22cdec92 100644 --- a/pcsx2/COP0.cpp +++ b/pcsx2/COP0.cpp @@ -238,81 +238,81 @@ __fi void COP0_UpdatePCCR() // -void MapTLB(int i) +void MapTLB(const tlbs& t, int i) { u32 mask, addr; 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", - i, tlb[i].VPN2, tlb[i].PFN0, tlb[i].PFN1, tlb[i].S >> 31, tlb[i].G, tlb[i].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); + i, t.VPN2, t.PFN0, t.PFN1, t.S >> 31, t.G, t.ASID, + 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 (tlb[i].EntryLo0 & 0x2) { - mask = ((~tlb[i].Mask) << 1) & 0xfffff; - saddr = tlb[i].VPN2 >> 12; - eaddr = saddr + tlb[i].Mask + 1; + if (t.VPN2 == 0x70000000) return; //uh uhh right ... + if (t.EntryLo0 & 0x2) { + mask = ((~t.Mask) << 1) & 0xfffff; + saddr = t.VPN2 >> 12; + eaddr = saddr + t.Mask + 1; for (addr=saddr; addr> 12) & mask)) { //match - memSetPageAddr(addr << 12, tlb[i].PFN0 + ((addr - saddr) << 12)); + if ((addr & mask) == ((t.VPN2 >> 12) & mask)) { //match + memSetPageAddr(addr << 12, t.PFN0 + ((addr - saddr) << 12)); Cpu->Clear(addr << 12, 0x400); } } } - if (tlb[i].EntryLo1 & 0x2) { - mask = ((~tlb[i].Mask) << 1) & 0xfffff; - saddr = (tlb[i].VPN2 >> 12) + tlb[i].Mask + 1; - eaddr = saddr + tlb[i].Mask + 1; + if (t.EntryLo1 & 0x2) { + mask = ((~t.Mask) << 1) & 0xfffff; + saddr = (t.VPN2 >> 12) + t.Mask + 1; + eaddr = saddr + t.Mask + 1; for (addr=saddr; addr> 12) & mask)) { //match - memSetPageAddr(addr << 12, tlb[i].PFN1 + ((addr - saddr) << 12)); + if ((addr & mask) == ((t.VPN2 >> 12) & mask)) { //match + memSetPageAddr(addr << 12, t.PFN1 + ((addr - saddr) << 12)); 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 saddr, eaddr; - if (tlb[i].S) + if (t.S) { - vtlb_VMapUnmap(tlb[i].VPN2,0x4000); + vtlb_VMapUnmap(t.VPN2,0x4000); return; } - if (tlb[i].EntryLo0 & 0x2) + if (t.EntryLo0 & 0x2) { - mask = ((~tlb[i].Mask) << 1) & 0xfffff; - saddr = tlb[i].VPN2 >> 12; - eaddr = saddr + tlb[i].Mask + 1; + mask = ((~t.Mask) << 1) & 0xfffff; + saddr = t.VPN2 >> 12; + eaddr = saddr + t.Mask + 1; // Console.WriteLn("Clear TLB: %08x ~ %08x",saddr,eaddr-1); for (addr=saddr; addr> 12) & mask)) { //match + if ((addr & mask) == ((t.VPN2 >> 12) & mask)) { //match memClearPageAddr(addr << 12); Cpu->Clear(addr << 12, 0x400); } } } - if (tlb[i].EntryLo1 & 0x2) { - mask = ((~tlb[i].Mask) << 1) & 0xfffff; - saddr = (tlb[i].VPN2 >> 12) + tlb[i].Mask + 1; - eaddr = saddr + tlb[i].Mask + 1; + if (t.EntryLo1 & 0x2) { + mask = ((~t.Mask) << 1) & 0xfffff; + saddr = (t.VPN2 >> 12) + t.Mask + 1; + eaddr = saddr + t.Mask + 1; // Console.WriteLn("Clear TLB: %08x ~ %08x",saddr,eaddr-1); for (addr=saddr; addr> 12) & mask)) { //match + if ((addr & mask) == ((t.VPN2 >> 12) & mask)) { //match memClearPageAddr(addr << 12); Cpu->Clear(addr << 12, 0x400); } @@ -336,7 +336,7 @@ void WriteTLB(int i) tlb[i].PFN1 = (((cpuRegs.CP0.n.EntryLo1 >> 6) & 0xFFFFF) & (~tlb[i].Mask)) << 12; tlb[i].S = cpuRegs.CP0.n.EntryLo0&0x80000000; - MapTLB(i); + MapTLB(tlb[i], i); } namespace R5900 { @@ -366,7 +366,7 @@ void TLBWI() { cpuRegs.CP0.n.Index, cpuRegs.CP0.n.PageMask, cpuRegs.CP0.n.EntryHi, cpuRegs.CP0.n.EntryLo0, cpuRegs.CP0.n.EntryLo1); - UnmapTLB(j); + UnmapTLB(tlb[j], j); tlb[j].PageMask = cpuRegs.CP0.n.PageMask; tlb[j].EntryHi = cpuRegs.CP0.n.EntryHi; tlb[j].EntryLo0 = cpuRegs.CP0.n.EntryLo0; @@ -385,7 +385,7 @@ DevCon.Warning("COP0_TLBWR %d:%x,%x,%x,%x\n", //if (j > 48) return; - UnmapTLB(j); + UnmapTLB(tlb[j], j); tlb[j].PageMask = cpuRegs.CP0.n.PageMask; tlb[j].EntryHi = cpuRegs.CP0.n.EntryHi; tlb[j].EntryLo0 = cpuRegs.CP0.n.EntryLo0; diff --git a/pcsx2/COP0.h b/pcsx2/COP0.h index 3ed3c48cbf8a3..834c1b7928992 100644 --- a/pcsx2/COP0.h +++ b/pcsx2/COP0.h @@ -15,12 +15,14 @@ #pragma once +struct tlbs; + extern void WriteCP0Status(u32 value); extern void WriteCP0Config(u32 value); extern void cpuUpdateOperationMode(); extern void WriteTLB(int i); -extern void UnmapTLB(int i); -extern void MapTLB(int i); +extern void UnmapTLB(const tlbs& t, int i); +extern void MapTLB(const tlbs& t, int i); extern void COP0_UpdatePCCR(); extern void COP0_DiagnosticPCCR(); diff --git a/pcsx2/SaveState.cpp b/pcsx2/SaveState.cpp index 3b49e21bcaeb1..e2c544a8d20d7 100644 --- a/pcsx2/SaveState.cpp +++ b/pcsx2/SaveState.cpp @@ -62,12 +62,21 @@ using namespace R5900; +static tlbs s_tlb_backup[std::size(tlb)]; + static void PreLoadPrep() { // ensure everything is in sync before we start overwriting stuff. if (THREAD_VU1) vu1Thread.WaitVU(); 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(); #ifndef PCSX2_CORE PatchesVerboseReset(); @@ -78,7 +87,15 @@ static void PostLoadPrep() { resetCache(); // 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(); CBreakPoints::SetSkipFirst(BREAKPOINT_EE, 0); CBreakPoints::SetSkipFirst(BREAKPOINT_IOP, 0); diff --git a/pcsx2/vtlb.cpp b/pcsx2/vtlb.cpp index 8c925ad96487c..c466712b3db8c 100644 --- a/pcsx2/vtlb.cpp +++ b/pcsx2/vtlb.cpp @@ -1183,7 +1183,7 @@ void vtlb_Init() void vtlb_Reset() { 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()