From d485acdb5149361ed15317b313cac5b3198ba8a4 Mon Sep 17 00:00:00 2001 From: skidau Date: Sat, 6 Dec 2014 10:28:34 +1100 Subject: [PATCH] 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 {