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.
This commit is contained in:
parent
997681b65a
commit
d485acdb51
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ struct tlb_entry
|
|||
{
|
||||
u32 tag;
|
||||
u32 paddr;
|
||||
u32 pteg;
|
||||
u32 pte;
|
||||
u8 flags;
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue