summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorskidau <skidau@gmail.com>2014-12-06 10:28:34 +1100
committerskidau <skidau@gmail.com>2014-12-06 10:28:34 +1100
commitd485acdb5149361ed15317b313cac5b3198ba8a4 (patch)
tree33169859c7ada4d2b1e606a30b95baadf227c9d1 /Source
parent997681b65aba1227c5117427c26fe7965a09c2dd (diff)
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.
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Core/HW/MemmapFunctions.cpp108
-rw-r--r--Source/Core/Core/PowerPC/PowerPC.cpp2
-rw-r--r--Source/Core/Core/PowerPC/PowerPC.h2
-rw-r--r--Source/Core/Core/State.cpp2
4 files changed, 51 insertions, 63 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)]));
+ // hash function no 2 "not" .360
+ hash = ~hash;
+ }
- // 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;
- }
+ u32 pteg_addr = ((hash & PowerPC::ppcState.pagetable_hashmask) << 6) | PowerPC::ppcState.pagetable_base;
- if (_Flag != FLAG_NO_EXCEPTION)
- *(u32*)&pRAM[(pteg_addr + 4)] = bswap(PTE2.Hex);
+ if ((pteg_addr >> 28) == 1)
+ base = Memory::m_pEXRAM;
- UpdateTLBEntry(_Flag, PTE2, _Address, pteg_addr + 4);
+ for (int i = 0; i < 8; i++)
+ {
+ u32 pte = bswap(*(u32*)&base[pteg_addr]);
+ bool pteh = (pte & PTE1_H) == 0;
- return (PTE2.RPN << 12) | offset;
- }
- }
- pteg_addr += 8;
- }
+ if (hash_func == 1)
+ pteh = !pteh;
- // 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))
- {
- if (VSID == PTE1_VSID(pte) && (api == PTE1_API(pte)))
+ 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)]));
- if (_Flag != FLAG_NO_EXCEPTION)
- *(u32*)&pRAM[(pteg_addr + 4)] = bswap(PTE2.Hex);
+ // 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;
+ }
- UpdateTLBEntry(_Flag, PTE2, _Address, pteg_addr + 4);
+ if (_Flag != FLAG_NO_EXCEPTION)
+ *(u32*)&base[(pteg_addr + 4)] = bswap(PTE2.Hex);
- return (PTE2.RPN << 12) | offset;
+ UpdateTLBEntry(_Flag, PTE2, _Address);
+
+ 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
{