From 693f413364d44f67c8ca994b3b79ccf4c7ffcb7c Mon Sep 17 00:00:00 2001 From: skidau Date: Fri, 5 Dec 2014 14:29:13 +1100 Subject: [PATCH 1/3] Updated C bit on TLB cache hits. Added TLB state to the save state file. --- .../Core/Core/Debugger/PPCDebugInterface.cpp | 2 +- Source/Core/Core/HW/MemmapFunctions.cpp | 84 ++++++++++--------- Source/Core/Core/PowerPC/PPCAnalyst.cpp | 2 +- Source/Core/Core/PowerPC/PowerPC.cpp | 6 -- Source/Core/Core/PowerPC/PowerPC.h | 28 +++++-- 5 files changed, 69 insertions(+), 53 deletions(-) diff --git a/Source/Core/Core/Debugger/PPCDebugInterface.cpp b/Source/Core/Core/Debugger/PPCDebugInterface.cpp index 988d0de20d..ddc2fec12e 100644 --- a/Source/Core/Core/Debugger/PPCDebugInterface.cpp +++ b/Source/Core/Core/Debugger/PPCDebugInterface.cpp @@ -28,7 +28,7 @@ std::string PPCDebugInterface::Disassemble(unsigned int address) if (!Memory::IsRAMAddress(address, true, true)) { if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU || !((address & JIT_ICACHE_VMEM_BIT) && - Memory::TranslateAddress(address, Memory::FLAG_OPCODE))) + Memory::TranslateAddress(address, Memory::FLAG_NO_EXCEPTION))) { return "(No RAM here)"; } diff --git a/Source/Core/Core/HW/MemmapFunctions.cpp b/Source/Core/Core/HW/MemmapFunctions.cpp index e3aea97418..4e87406efa 100644 --- a/Source/Core/Core/HW/MemmapFunctions.cpp +++ b/Source/Core/Core/HW/MemmapFunctions.cpp @@ -704,31 +704,9 @@ void SDRUpdated() } -// TLB cache -#define TLB_SIZE 128 -#define TLB_WAYS 2 -#define NUM_TLBS 2 - -#define HW_PAGE_INDEX_SHIFT 12 -#define HW_PAGE_INDEX_MASK 0x3f -#define HW_PAGE_TAG_SHIFT 18 - -#define TLB_FLAG_MOST_RECENT 0x01 -#define TLB_FLAG_INVALID 0x02 - -struct tlb_entry -{ - u32 tag; - u32 paddr; - u8 flags; -}; - -// TODO: tlb needs to be in ppcState for save-state purposes. -static tlb_entry tlb[NUM_TLBS][TLB_SIZE/TLB_WAYS][TLB_WAYS]; - static u32 LookupTLBPageAddress(const XCheckTLBFlag _Flag, const u32 vpa, u32 *paddr) { - tlb_entry *tlbe = tlb[_Flag == FLAG_OPCODE][(vpa>>HW_PAGE_INDEX_SHIFT)&HW_PAGE_INDEX_MASK]; + PowerPC::tlb_entry *tlbe = PowerPC::ppcState.tlb[_Flag == FLAG_OPCODE][(vpa >> HW_PAGE_INDEX_SHIFT) & HW_PAGE_INDEX_MASK]; if (tlbe[0].tag == (vpa & ~0xfff) && !(tlbe[0].flags & TLB_FLAG_INVALID)) { if (_Flag != FLAG_NO_EXCEPTION) @@ -736,7 +714,19 @@ static u32 LookupTLBPageAddress(const XCheckTLBFlag _Flag, const u32 vpa, u32 *p tlbe[0].flags |= TLB_FLAG_MOST_RECENT; tlbe[1].flags &= ~TLB_FLAG_MOST_RECENT; } + *paddr = tlbe[0].paddr | (vpa & 0xfff); + + // Check if C bit requires updating + if (_Flag == FLAG_WRITE) + { + u8* pRAM = Memory::base; + UPTE2 PTE2; + PTE2.Hex = bswap((*(u32*)&pRAM[tlbe[0].pteg])); + if (PTE2.C == 0) + return 0; + } + return 1; } if (tlbe[1].tag == (vpa & ~0xfff) && !(tlbe[1].flags & TLB_FLAG_INVALID)) @@ -746,23 +736,36 @@ static u32 LookupTLBPageAddress(const XCheckTLBFlag _Flag, const u32 vpa, u32 *p tlbe[1].flags |= TLB_FLAG_MOST_RECENT; tlbe[0].flags &= ~TLB_FLAG_MOST_RECENT; } + *paddr = tlbe[1].paddr | (vpa & 0xfff); + + // Check if C bit requires updating + if (_Flag == FLAG_WRITE) + { + u8* pRAM = Memory::base; + UPTE2 PTE2; + PTE2.Hex = bswap((*(u32*)&pRAM[tlbe[1].pteg])); + if (PTE2.C == 0) + return 0; + } + return 1; } return 0; } -static void UpdateTLBEntry(const XCheckTLBFlag _Flag, UPTE2 PTE2, const u32 vpa) +static void UpdateTLBEntry(const XCheckTLBFlag _Flag, UPTE2 PTE2, const u32 vpa, const u32 pteg) { if (_Flag == FLAG_NO_EXCEPTION) return; - tlb_entry *tlbe = tlb[_Flag == FLAG_OPCODE][(vpa>>HW_PAGE_INDEX_SHIFT)&HW_PAGE_INDEX_MASK]; - if ((tlbe[0].flags & TLB_FLAG_MOST_RECENT) == 0) + PowerPC::tlb_entry *tlbe = PowerPC::ppcState.tlb[_Flag == FLAG_OPCODE][(vpa >> HW_PAGE_INDEX_SHIFT) & HW_PAGE_INDEX_MASK]; + if ((tlbe[0].flags & TLB_FLAG_MOST_RECENT) == 0 || (tlbe[0].flags & TLB_FLAG_INVALID)) { tlbe[0].flags = TLB_FLAG_MOST_RECENT; tlbe[1].flags &= ~TLB_FLAG_MOST_RECENT; tlbe[0].paddr = PTE2.RPN << HW_PAGE_INDEX_SHIFT; + tlbe[0].pteg = pteg; tlbe[0].tag = vpa & ~0xfff; } else @@ -770,13 +773,14 @@ static void UpdateTLBEntry(const XCheckTLBFlag _Flag, UPTE2 PTE2, const u32 vpa) tlbe[1].flags = TLB_FLAG_MOST_RECENT; tlbe[0].flags &= ~TLB_FLAG_MOST_RECENT; tlbe[1].paddr = PTE2.RPN << HW_PAGE_INDEX_SHIFT; + tlbe[1].pteg = pteg; tlbe[1].tag = vpa & ~0xfff; } } void InvalidateTLBEntry(u32 vpa) { - tlb_entry *tlbe = tlb[0][(vpa>>HW_PAGE_INDEX_SHIFT)&HW_PAGE_INDEX_MASK]; + PowerPC::tlb_entry *tlbe = PowerPC::ppcState.tlb[0][(vpa >> HW_PAGE_INDEX_SHIFT) & HW_PAGE_INDEX_MASK]; if (tlbe[0].tag == (vpa & ~0xfff)) { tlbe[0].flags |= TLB_FLAG_INVALID; @@ -785,7 +789,7 @@ void InvalidateTLBEntry(u32 vpa) { tlbe[1].flags |= TLB_FLAG_INVALID; } - tlb_entry *tlbe_i = tlb[1][(vpa>>HW_PAGE_INDEX_SHIFT)&HW_PAGE_INDEX_MASK]; + PowerPC::tlb_entry *tlbe_i = PowerPC::ppcState.tlb[1][(vpa >> HW_PAGE_INDEX_SHIFT) & HW_PAGE_INDEX_MASK]; if (tlbe_i[0].tag == (vpa & ~0xfff)) { tlbe_i[0].flags |= TLB_FLAG_INVALID; @@ -832,8 +836,6 @@ static u32 TranslatePageAddress(const u32 _Address, const XCheckTLBFlag _Flag) UPTE2 PTE2; PTE2.Hex = bswap((*(u32*)&pRAM[(pteg_addr + 4)])); - UpdateTLBEntry(_Flag, PTE2, _Address); - // set the access bits switch (_Flag) { @@ -842,12 +844,16 @@ static u32 TranslatePageAddress(const u32 _Address, const XCheckTLBFlag _Flag) case FLAG_NO_EXCEPTION: break; case FLAG_OPCODE: break; } - *(u32*)&pRAM[(pteg_addr + 4)] = bswap(PTE2.Hex); - return ((PTE2.RPN << 12) | offset); + if (_Flag != FLAG_NO_EXCEPTION) + *(u32*)&pRAM[(pteg_addr + 4)] = bswap(PTE2.Hex); + + UpdateTLBEntry(_Flag, PTE2, _Address, pteg_addr + 4); + + return (PTE2.RPN << 12) | offset; } } - pteg_addr+=8; + pteg_addr += 8; } // hash function no 2 "not" .360 @@ -863,8 +869,6 @@ static u32 TranslatePageAddress(const u32 _Address, const XCheckTLBFlag _Flag) UPTE2 PTE2; PTE2.Hex = bswap((*(u32*)&pRAM[(pteg_addr + 4)])); - UpdateTLBEntry(_Flag, PTE2, _Address); - switch (_Flag) { case FLAG_READ: PTE2.R = 1; break; @@ -872,12 +876,16 @@ static u32 TranslatePageAddress(const u32 _Address, const XCheckTLBFlag _Flag) case FLAG_NO_EXCEPTION: break; case FLAG_OPCODE: break; } - *(u32*)&pRAM[(pteg_addr + 4)] = bswap(PTE2.Hex); - return ((PTE2.RPN << 12) | offset); + if (_Flag != FLAG_NO_EXCEPTION) + *(u32*)&pRAM[(pteg_addr + 4)] = bswap(PTE2.Hex); + + UpdateTLBEntry(_Flag, PTE2, _Address, pteg_addr + 4); + + return (PTE2.RPN << 12) | offset; } } - pteg_addr+=8; + pteg_addr += 8; } return 0; } diff --git a/Source/Core/Core/PowerPC/PPCAnalyst.cpp b/Source/Core/Core/PowerPC/PPCAnalyst.cpp index 13b4b3d49d..5827b99845 100644 --- a/Source/Core/Core/PowerPC/PPCAnalyst.cpp +++ b/Source/Core/Core/PowerPC/PPCAnalyst.cpp @@ -648,7 +648,7 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock *block, CodeBuffer *buffer, u32 if (SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU && (address & JIT_ICACHE_VMEM_BIT)) { - if (!Memory::TranslateAddress(address, Memory::FLAG_OPCODE)) + if (!Memory::TranslateAddress(address, Memory::FLAG_NO_EXCEPTION)) { // Memory exception occurred during instruction fetch block->m_memory_exception = true; diff --git a/Source/Core/Core/PowerPC/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp index f75cd9f7be..ad2fb808f0 100644 --- a/Source/Core/Core/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/PowerPC/PowerPC.cpp @@ -118,12 +118,6 @@ void Init(int cpu_core) FPURoundMode::SetPrecisionMode(FPURoundMode::PREC_53); memset(ppcState.sr, 0, sizeof(ppcState.sr)); - ppcState.dtlb_last = 0; - memset(ppcState.dtlb_va, 0, sizeof(ppcState.dtlb_va)); - memset(ppcState.dtlb_pa, 0, sizeof(ppcState.dtlb_pa)); - ppcState.itlb_last = 0; - memset(ppcState.itlb_va, 0, sizeof(ppcState.itlb_va)); - memset(ppcState.itlb_pa, 0, sizeof(ppcState.itlb_pa)); ppcState.pagetable_base = 0; ppcState.pagetable_hashmask = 0; diff --git a/Source/Core/Core/PowerPC/PowerPC.h b/Source/Core/Core/PowerPC/PowerPC.h index e9f3aee367..b93b79f4d3 100644 --- a/Source/Core/Core/PowerPC/PowerPC.h +++ b/Source/Core/Core/PowerPC/PowerPC.h @@ -27,6 +27,26 @@ enum CoreMode MODE_JIT, }; +// TLB cache +#define TLB_SIZE 128 +#define TLB_WAYS 2 +#define NUM_TLBS 2 + +#define HW_PAGE_INDEX_SHIFT 12 +#define HW_PAGE_INDEX_MASK 0x3f +#define HW_PAGE_TAG_SHIFT 18 + +#define TLB_FLAG_MOST_RECENT 0x01 +#define TLB_FLAG_INVALID 0x02 + +struct tlb_entry +{ + u32 tag; + u32 paddr; + u32 pteg; + u8 flags; +}; + // This contains the entire state of the emulated PowerPC "Gekko" CPU. struct GC_ALIGNED64(PowerPCState) { @@ -87,13 +107,7 @@ struct GC_ALIGNED64(PowerPCState) // also for power management, but we don't care about that. u32 spr[1024]; - u32 dtlb_last; - u32 dtlb_va[128]; - u32 dtlb_pa[128]; - - u32 itlb_last; - u32 itlb_va[128]; - u32 itlb_pa[128]; + tlb_entry tlb[NUM_TLBS][TLB_SIZE / TLB_WAYS][TLB_WAYS]; u32 pagetable_base; u32 pagetable_hashmask; From 997681b65aba1227c5117427c26fe7965a09c2dd Mon Sep 17 00:00:00 2001 From: skidau Date: Fri, 5 Dec 2014 19:56:45 +1100 Subject: [PATCH 2/3] Removed the tag check in InvalidateTLBEntry. All four TLB entries are always cleared on each invalidate command. Initialised the TLB cache to start from a consistent state on reset. --- Source/Core/Core/HW/MemmapFunctions.cpp | 53 ++++++++++--------------- Source/Core/Core/PowerPC/PowerPC.cpp | 14 +++++++ 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/Source/Core/Core/HW/MemmapFunctions.cpp b/Source/Core/Core/HW/MemmapFunctions.cpp index 4e87406efa..4129fef467 100644 --- a/Source/Core/Core/HW/MemmapFunctions.cpp +++ b/Source/Core/Core/HW/MemmapFunctions.cpp @@ -709,14 +709,6 @@ static u32 LookupTLBPageAddress(const XCheckTLBFlag _Flag, const u32 vpa, u32 *p PowerPC::tlb_entry *tlbe = PowerPC::ppcState.tlb[_Flag == FLAG_OPCODE][(vpa >> HW_PAGE_INDEX_SHIFT) & HW_PAGE_INDEX_MASK]; if (tlbe[0].tag == (vpa & ~0xfff) && !(tlbe[0].flags & TLB_FLAG_INVALID)) { - if (_Flag != FLAG_NO_EXCEPTION) - { - tlbe[0].flags |= TLB_FLAG_MOST_RECENT; - tlbe[1].flags &= ~TLB_FLAG_MOST_RECENT; - } - - *paddr = tlbe[0].paddr | (vpa & 0xfff); - // Check if C bit requires updating if (_Flag == FLAG_WRITE) { @@ -727,18 +719,18 @@ static u32 LookupTLBPageAddress(const XCheckTLBFlag _Flag, const u32 vpa, u32 *p return 0; } + if (_Flag != FLAG_NO_EXCEPTION) + { + tlbe[0].flags |= TLB_FLAG_MOST_RECENT; + tlbe[1].flags &= ~TLB_FLAG_MOST_RECENT; + } + + *paddr = tlbe[0].paddr | (vpa & 0xfff); + return 1; } if (tlbe[1].tag == (vpa & ~0xfff) && !(tlbe[1].flags & TLB_FLAG_INVALID)) { - if (_Flag != FLAG_NO_EXCEPTION) - { - tlbe[1].flags |= TLB_FLAG_MOST_RECENT; - tlbe[0].flags &= ~TLB_FLAG_MOST_RECENT; - } - - *paddr = tlbe[1].paddr | (vpa & 0xfff); - // Check if C bit requires updating if (_Flag == FLAG_WRITE) { @@ -749,6 +741,14 @@ static u32 LookupTLBPageAddress(const XCheckTLBFlag _Flag, const u32 vpa, u32 *p return 0; } + if (_Flag != FLAG_NO_EXCEPTION) + { + tlbe[1].flags |= TLB_FLAG_MOST_RECENT; + tlbe[0].flags &= ~TLB_FLAG_MOST_RECENT; + } + + *paddr = tlbe[1].paddr | (vpa & 0xfff); + return 1; } return 0; @@ -781,23 +781,11 @@ static void UpdateTLBEntry(const XCheckTLBFlag _Flag, UPTE2 PTE2, const u32 vpa, void InvalidateTLBEntry(u32 vpa) { PowerPC::tlb_entry *tlbe = PowerPC::ppcState.tlb[0][(vpa >> HW_PAGE_INDEX_SHIFT) & HW_PAGE_INDEX_MASK]; - if (tlbe[0].tag == (vpa & ~0xfff)) - { - tlbe[0].flags |= TLB_FLAG_INVALID; - } - if (tlbe[1].tag == (vpa & ~0xfff)) - { - tlbe[1].flags |= TLB_FLAG_INVALID; - } + tlbe[0].flags |= TLB_FLAG_INVALID; + tlbe[1].flags |= TLB_FLAG_INVALID; PowerPC::tlb_entry *tlbe_i = PowerPC::ppcState.tlb[1][(vpa >> HW_PAGE_INDEX_SHIFT) & HW_PAGE_INDEX_MASK]; - if (tlbe_i[0].tag == (vpa & ~0xfff)) - { - tlbe_i[0].flags |= TLB_FLAG_INVALID; - } - if (tlbe_i[1].tag == (vpa & ~0xfff)) - { - tlbe_i[1].flags |= TLB_FLAG_INVALID; - } + tlbe_i[0].flags |= TLB_FLAG_INVALID; + tlbe_i[1].flags |= TLB_FLAG_INVALID; } // Page Address Translation @@ -869,6 +857,7 @@ static u32 TranslatePageAddress(const u32 _Address, const XCheckTLBFlag _Flag) UPTE2 PTE2; PTE2.Hex = bswap((*(u32*)&pRAM[(pteg_addr + 4)])); + // set the access bits switch (_Flag) { case FLAG_READ: PTE2.R = 1; break; diff --git a/Source/Core/Core/PowerPC/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp index ad2fb808f0..000f34da59 100644 --- a/Source/Core/Core/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/PowerPC/PowerPC.cpp @@ -121,6 +121,20 @@ void Init(int cpu_core) ppcState.pagetable_base = 0; ppcState.pagetable_hashmask = 0; + for (int tlb = 0; tlb < 2; tlb++) + { + for (int set = 0; set < 64; set++) + { + for (int way = 0; way < 2; way++) + { + ppcState.tlb[tlb][set][way].flags = TLB_FLAG_INVALID; + ppcState.tlb[tlb][set][way].paddr = 0; + ppcState.tlb[tlb][set][way].pteg = 0; + ppcState.tlb[tlb][set][way].tag = 0; + } + } + } + ResetRegisters(); PPCTables::InitTables(cpu_core); From d485acdb5149361ed15317b313cac5b3198ba8a4 Mon Sep 17 00:00:00 2001 From: skidau Date: Sat, 6 Dec 2014 10:28:34 +1100 Subject: [PATCH 3/3] Stored a copy of the PTE in the TLB like the real hardware does. Updated PTE.R bit on Write and Instruction fetch. Added code to read the PTE from MEM2 if the PTE is stored there. Refactored the two hash functions to reduce code duplication. Updated save state version. --- Source/Core/Core/HW/MemmapFunctions.cpp | 116 +++++++++++------------- Source/Core/Core/PowerPC/PowerPC.cpp | 2 +- Source/Core/Core/PowerPC/PowerPC.h | 2 +- Source/Core/Core/State.cpp | 2 +- 4 files changed, 55 insertions(+), 67 deletions(-) diff --git a/Source/Core/Core/HW/MemmapFunctions.cpp b/Source/Core/Core/HW/MemmapFunctions.cpp index 4129fef467..059019bbe6 100644 --- a/Source/Core/Core/HW/MemmapFunctions.cpp +++ b/Source/Core/Core/HW/MemmapFunctions.cpp @@ -712,11 +712,14 @@ static u32 LookupTLBPageAddress(const XCheckTLBFlag _Flag, const u32 vpa, u32 *p // Check if C bit requires updating if (_Flag == FLAG_WRITE) { - u8* pRAM = Memory::base; UPTE2 PTE2; - PTE2.Hex = bswap((*(u32*)&pRAM[tlbe[0].pteg])); + PTE2.Hex = tlbe[0].pte; if (PTE2.C == 0) + { + PTE2.C = 1; + tlbe[0].pte = PTE2.Hex; return 0; + } } if (_Flag != FLAG_NO_EXCEPTION) @@ -734,11 +737,14 @@ static u32 LookupTLBPageAddress(const XCheckTLBFlag _Flag, const u32 vpa, u32 *p // Check if C bit requires updating if (_Flag == FLAG_WRITE) { - u8* pRAM = Memory::base; UPTE2 PTE2; - PTE2.Hex = bswap((*(u32*)&pRAM[tlbe[1].pteg])); + PTE2.Hex = tlbe[1].pte; if (PTE2.C == 0) + { + PTE2.C = 1; + tlbe[1].pte = PTE2.Hex; return 0; + } } if (_Flag != FLAG_NO_EXCEPTION) @@ -754,7 +760,7 @@ static u32 LookupTLBPageAddress(const XCheckTLBFlag _Flag, const u32 vpa, u32 *p return 0; } -static void UpdateTLBEntry(const XCheckTLBFlag _Flag, UPTE2 PTE2, const u32 vpa, const u32 pteg) +static void UpdateTLBEntry(const XCheckTLBFlag _Flag, UPTE2 PTE2, const u32 vpa) { if (_Flag == FLAG_NO_EXCEPTION) return; @@ -765,7 +771,7 @@ static void UpdateTLBEntry(const XCheckTLBFlag _Flag, UPTE2 PTE2, const u32 vpa, tlbe[0].flags = TLB_FLAG_MOST_RECENT; tlbe[1].flags &= ~TLB_FLAG_MOST_RECENT; tlbe[0].paddr = PTE2.RPN << HW_PAGE_INDEX_SHIFT; - tlbe[0].pteg = pteg; + tlbe[0].pte = PTE2.Hex; tlbe[0].tag = vpa & ~0xfff; } else @@ -773,7 +779,7 @@ static void UpdateTLBEntry(const XCheckTLBFlag _Flag, UPTE2 PTE2, const u32 vpa, tlbe[1].flags = TLB_FLAG_MOST_RECENT; tlbe[0].flags &= ~TLB_FLAG_MOST_RECENT; tlbe[1].paddr = PTE2.RPN << HW_PAGE_INDEX_SHIFT; - tlbe[1].pteg = pteg; + tlbe[1].pte = PTE2.Hex; tlbe[1].tag = vpa & ~0xfff; } } @@ -805,76 +811,58 @@ static u32 TranslatePageAddress(const u32 _Address, const XCheckTLBFlag _Flag) // Direct access to the fastmem Arena // FIXME: is this the best idea for clean code? - u8* pRAM = Memory::base; + u8* base = Memory::base; // hash function no 1 "xor" .360 - u32 hash1 = (VSID ^ page_index); - u32 pteg_addr = ((hash1 & PowerPC::ppcState.pagetable_hashmask) << 6) | PowerPC::ppcState.pagetable_base; + u32 hash = (VSID ^ page_index); - // hash1 - for (int i = 0; i < 8; i++) + for (int hash_func = 0; hash_func < 2; hash_func++) { - UPTE1 PTE1; - PTE1.Hex = bswap(*(u32*)&pRAM[pteg_addr]); - - if (PTE1.V && !PTE1.H) + if (hash_func == 1) { - if (VSID == PTE1.VSID && (api == PTE1.API)) - { - UPTE2 PTE2; - PTE2.Hex = bswap((*(u32*)&pRAM[(pteg_addr + 4)])); - - // set the access bits - switch (_Flag) - { - case FLAG_READ: PTE2.R = 1; break; - case FLAG_WRITE: PTE2.C = 1; break; - case FLAG_NO_EXCEPTION: break; - case FLAG_OPCODE: break; - } - - if (_Flag != FLAG_NO_EXCEPTION) - *(u32*)&pRAM[(pteg_addr + 4)] = bswap(PTE2.Hex); - - UpdateTLBEntry(_Flag, PTE2, _Address, pteg_addr + 4); - - return (PTE2.RPN << 12) | offset; - } + // hash function no 2 "not" .360 + hash = ~hash; } - pteg_addr += 8; - } - // hash function no 2 "not" .360 - hash1 = ~hash1; - pteg_addr = ((hash1 & PowerPC::ppcState.pagetable_hashmask) << 6) | PowerPC::ppcState.pagetable_base; - for (int i = 0; i < 8; i++) - { - u32 pte = bswap(*(u32*)&pRAM[pteg_addr]); - if ((pte & PTE1_V) && (pte & PTE1_H)) + u32 pteg_addr = ((hash & PowerPC::ppcState.pagetable_hashmask) << 6) | PowerPC::ppcState.pagetable_base; + + if ((pteg_addr >> 28) == 1) + base = Memory::m_pEXRAM; + + for (int i = 0; i < 8; i++) { - if (VSID == PTE1_VSID(pte) && (api == PTE1_API(pte))) + u32 pte = bswap(*(u32*)&base[pteg_addr]); + bool pteh = (pte & PTE1_H) == 0; + + if (hash_func == 1) + pteh = !pteh; + + if ((pte & PTE1_V) && pteh) { - UPTE2 PTE2; - PTE2.Hex = bswap((*(u32*)&pRAM[(pteg_addr + 4)])); - - // set the access bits - switch (_Flag) + if (VSID == PTE1_VSID(pte) && (api == PTE1_API(pte))) { - case FLAG_READ: PTE2.R = 1; break; - case FLAG_WRITE: PTE2.C = 1; break; - case FLAG_NO_EXCEPTION: break; - case FLAG_OPCODE: break; + UPTE2 PTE2; + PTE2.Hex = bswap((*(u32*)&base[(pteg_addr + 4)])); + + // set the access bits + switch (_Flag) + { + case FLAG_NO_EXCEPTION: break; + case FLAG_READ: PTE2.R = 1; break; + case FLAG_WRITE: PTE2.R = 1; PTE2.C = 1; break; + case FLAG_OPCODE: PTE2.R = 1; break; + } + + if (_Flag != FLAG_NO_EXCEPTION) + *(u32*)&base[(pteg_addr + 4)] = bswap(PTE2.Hex); + + UpdateTLBEntry(_Flag, PTE2, _Address); + + return (PTE2.RPN << 12) | offset; } - - if (_Flag != FLAG_NO_EXCEPTION) - *(u32*)&pRAM[(pteg_addr + 4)] = bswap(PTE2.Hex); - - UpdateTLBEntry(_Flag, PTE2, _Address, pteg_addr + 4); - - return (PTE2.RPN << 12) | offset; } + pteg_addr += 8; } - pteg_addr += 8; } return 0; } diff --git a/Source/Core/Core/PowerPC/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp index 000f34da59..35f96fb495 100644 --- a/Source/Core/Core/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/PowerPC/PowerPC.cpp @@ -129,7 +129,7 @@ void Init(int cpu_core) { ppcState.tlb[tlb][set][way].flags = TLB_FLAG_INVALID; ppcState.tlb[tlb][set][way].paddr = 0; - ppcState.tlb[tlb][set][way].pteg = 0; + ppcState.tlb[tlb][set][way].pte = 0; ppcState.tlb[tlb][set][way].tag = 0; } } diff --git a/Source/Core/Core/PowerPC/PowerPC.h b/Source/Core/Core/PowerPC/PowerPC.h index b93b79f4d3..69eb0da28b 100644 --- a/Source/Core/Core/PowerPC/PowerPC.h +++ b/Source/Core/Core/PowerPC/PowerPC.h @@ -43,7 +43,7 @@ struct tlb_entry { u32 tag; u32 paddr; - u32 pteg; + u32 pte; u8 flags; }; diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index c8d3db9d7c..d156bb4adc 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -64,7 +64,7 @@ static Common::Event g_compressAndDumpStateSyncEvent; static std::thread g_save_thread; // Don't forget to increase this after doing changes on the savestate system -static const u32 STATE_VERSION = 36; +static const u32 STATE_VERSION = 37; enum {