mirror of https://github.com/PCSX2/pcsx2.git
SaveState: Only remap changed TLB slots on load
This commit is contained in:
parent
1ccddb92d4
commit
0e73bf1e6d
|
@ -235,81 +235,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);
|
||||
}
|
||||
|
@ -333,7 +333,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 {
|
||||
|
@ -363,7 +363,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;
|
||||
|
@ -382,7 +382,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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue