Skip to content

Commit

Permalink
SaveState: Only remap changed TLB slots on load
Browse files Browse the repository at this point in the history
  • Loading branch information
stenzek committed Nov 17, 2022
1 parent 36cd0d1 commit 3ee2567
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 39 deletions.
70 changes: 35 additions & 35 deletions pcsx2/COP0.cpp
Expand Up @@ -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<eaddr; addr++) {
if ((addr & mask) == ((tlb[i].VPN2 >> 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<eaddr; addr++) {
if ((addr & mask) == ((tlb[i].VPN2 >> 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<eaddr; addr++) {
if ((addr & mask) == ((tlb[i].VPN2 >> 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<eaddr; addr++) {
if ((addr & mask) == ((tlb[i].VPN2 >> 12) & mask)) { //match
if ((addr & mask) == ((t.VPN2 >> 12) & mask)) { //match
memClearPageAddr(addr << 12);
Cpu->Clear(addr << 12, 0x400);
}
Expand All @@ -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 {
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
6 changes: 4 additions & 2 deletions pcsx2/COP0.h
Expand Up @@ -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();
19 changes: 18 additions & 1 deletion pcsx2/SaveState.cpp
Expand Up @@ -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();
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion pcsx2/vtlb.cpp
Expand Up @@ -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()
Expand Down

0 comments on commit 3ee2567

Please sign in to comment.