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 {