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 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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in New Issue