Merge pull request #1266 from skidau/mmu-exram

Corrected the physical memory access to MEM2 via the MMU. Fixes Toy Story 3.
This commit is contained in:
skidau 2014-10-17 17:10:51 +11:00
commit 73590b1323

View File

@ -150,12 +150,20 @@ inline void ReadFromHardware(T &_var, const u32 em_address, const u32 effective_
} }
} }
else else
{
if (m_pEXRAM && (tlb_addr & 0xF0000000) == 0x10000000)
{
_var <<= 8;
_var = m_pEXRAM[tlb_addr & EXRAM_MASK];
}
else
{ {
_var <<= 8; _var <<= 8;
_var |= m_pRAM[tlb_addr & RAM_MASK]; _var |= m_pRAM[tlb_addr & RAM_MASK];
} }
} }
} }
}
else else
{ {
u32 tlb_addr = TranslateAddress(em_address, flag); u32 tlb_addr = TranslateAddress(em_address, flag);
@ -167,11 +175,18 @@ inline void ReadFromHardware(T &_var, const u32 em_address, const u32 effective_
} }
} }
else else
{
if (m_pEXRAM && (tlb_addr & 0xF0000000) == 0x10000000)
{
_var = bswap((*(const T*)&m_pEXRAM[tlb_addr & EXRAM_MASK]));
}
else
{ {
_var = bswap((*(const T*)&m_pRAM[tlb_addr & RAM_MASK])); _var = bswap((*(const T*)&m_pRAM[tlb_addr & RAM_MASK]));
} }
} }
} }
}
} }
@ -262,12 +277,20 @@ inline void WriteToHardware(u32 em_address, const T data, u32 effective_address,
} }
} }
else else
{
if (m_pEXRAM && (tlb_addr & 0xF0000000) == 0x10000000)
{
m_pEXRAM[tlb_addr & EXRAM_MASK] = (u8)val;
val >>= 8;
}
else
{ {
m_pRAM[tlb_addr & RAM_MASK] = (u8)val; m_pRAM[tlb_addr & RAM_MASK] = (u8)val;
val >>= 8; val >>= 8;
} }
} }
} }
}
else else
{ {
u32 tlb_addr = TranslateAddress(em_address, flag); u32 tlb_addr = TranslateAddress(em_address, flag);
@ -279,11 +302,18 @@ inline void WriteToHardware(u32 em_address, const T data, u32 effective_address,
} }
} }
else else
{
if (m_pEXRAM && (tlb_addr & 0xF0000000) == 0x10000000)
{
*(T*)&m_pEXRAM[tlb_addr & EXRAM_MASK] = bswap(data);
}
else
{ {
*(T*)&m_pRAM[tlb_addr & RAM_MASK] = bswap(data); *(T*)&m_pRAM[tlb_addr & RAM_MASK] = bswap(data);
} }
} }
} }
}
} }
// ===================== // =====================
@ -663,8 +693,6 @@ void SDRUpdated()
// TLB cache // TLB cache
//#define FAST_TLB_CACHE
#define TLB_SIZE 128 #define TLB_SIZE 128
#define TLB_WAYS 2 #define TLB_WAYS 2
#define NUM_TLBS 2 #define NUM_TLBS 2
@ -684,62 +712,39 @@ struct tlb_entry
}; };
// TODO: tlb needs to be in ppcState for save-state purposes. // TODO: tlb needs to be in ppcState for save-state purposes.
#ifdef FAST_TLB_CACHE
static tlb_entry tlb[NUM_TLBS][TLB_SIZE/TLB_WAYS][TLB_WAYS]; static tlb_entry tlb[NUM_TLBS][TLB_SIZE/TLB_WAYS][TLB_WAYS];
#endif
static u32 LookupTLBPageAddress(const XCheckTLBFlag _Flag, const u32 vpa, u32 *paddr) static u32 LookupTLBPageAddress(const XCheckTLBFlag _Flag, const u32 vpa, u32 *paddr)
{ {
#ifdef FAST_TLB_CACHE
tlb_entry *tlbe = tlb[_Flag == FLAG_OPCODE][(vpa>>HW_PAGE_INDEX_SHIFT)&HW_PAGE_INDEX_MASK]; tlb_entry *tlbe = 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 (tlbe[0].tag == (vpa & ~0xfff) && !(tlbe[0].flags & TLB_FLAG_INVALID))
{
if (_Flag != FLAG_NO_EXCEPTION)
{ {
tlbe[0].flags |= TLB_FLAG_MOST_RECENT; tlbe[0].flags |= TLB_FLAG_MOST_RECENT;
tlbe[1].flags &= ~TLB_FLAG_MOST_RECENT; tlbe[1].flags &= ~TLB_FLAG_MOST_RECENT;
}
*paddr = tlbe[0].paddr | (vpa & 0xfff); *paddr = tlbe[0].paddr | (vpa & 0xfff);
return 1; return 1;
} }
if (tlbe[1].tag == (vpa & ~0xfff) && !(tlbe[1].flags & TLB_FLAG_INVALID)) 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[1].flags |= TLB_FLAG_MOST_RECENT;
tlbe[0].flags &= ~TLB_FLAG_MOST_RECENT; tlbe[0].flags &= ~TLB_FLAG_MOST_RECENT;
}
*paddr = tlbe[1].paddr | (vpa & 0xfff); *paddr = tlbe[1].paddr | (vpa & 0xfff);
return 1; return 1;
} }
return 0; return 0;
#else
u32 _Address = vpa;
if (_Flag == FLAG_OPCODE)
{
for (u32 i = (PowerPC::ppcState.itlb_last); i > (PowerPC::ppcState.itlb_last - 128); i--)
{
if ((_Address & ~0xfff) == (PowerPC::ppcState.itlb_va[i & 127]))
{
*paddr = PowerPC::ppcState.itlb_pa[i & 127] | (_Address & 0xfff);
PowerPC::ppcState.itlb_last = i;
return 1;
}
}
}
else
{
for (u32 i = (PowerPC::ppcState.dtlb_last); i > (PowerPC::ppcState.dtlb_last - 128); i--)
{
if ((_Address & ~0xfff) == (PowerPC::ppcState.dtlb_va[i & 127]))
{
*paddr = PowerPC::ppcState.dtlb_pa[i & 127] | (_Address & 0xfff);
PowerPC::ppcState.dtlb_last = i;
return 1;
}
}
}
return 0;
#endif
} }
static void UpdateTLBEntry(const XCheckTLBFlag _Flag, UPTE2 PTE2, const u32 vpa) static void UpdateTLBEntry(const XCheckTLBFlag _Flag, UPTE2 PTE2, const u32 vpa)
{ {
#ifdef FAST_TLB_CACHE if (_Flag != FLAG_NO_EXCEPTION)
return;
tlb_entry *tlbe = tlb[_Flag == FLAG_OPCODE][(vpa>>HW_PAGE_INDEX_SHIFT)&HW_PAGE_INDEX_MASK]; 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) if ((tlbe[0].flags & TLB_FLAG_MOST_RECENT) == 0)
{ {
@ -755,29 +760,10 @@ static void UpdateTLBEntry(const XCheckTLBFlag _Flag, UPTE2 PTE2, const u32 vpa)
tlbe[1].paddr = PTE2.RPN << HW_PAGE_INDEX_SHIFT; tlbe[1].paddr = PTE2.RPN << HW_PAGE_INDEX_SHIFT;
tlbe[1].tag = vpa & ~0xfff; tlbe[1].tag = vpa & ~0xfff;
} }
#else
if (_Flag == FLAG_OPCODE)
{
// ITLB cache
PowerPC::ppcState.itlb_last++;
PowerPC::ppcState.itlb_last &= 127;
PowerPC::ppcState.itlb_pa[PowerPC::ppcState.itlb_last] = PTE2.RPN << HW_PAGE_INDEX_SHIFT;
PowerPC::ppcState.itlb_va[PowerPC::ppcState.itlb_last] = vpa & ~0xfff;
}
else
{
// DTLB cache
PowerPC::ppcState.dtlb_last++;
PowerPC::ppcState.dtlb_last &= 127;
PowerPC::ppcState.dtlb_pa[PowerPC::ppcState.dtlb_last] = PTE2.RPN << HW_PAGE_INDEX_SHIFT;
PowerPC::ppcState.dtlb_va[PowerPC::ppcState.dtlb_last] = vpa & ~0xfff;
}
#endif
} }
void InvalidateTLBEntry(u32 vpa) void InvalidateTLBEntry(u32 vpa)
{ {
#ifdef FAST_TLB_CACHE
tlb_entry *tlbe = tlb[0][(vpa>>HW_PAGE_INDEX_SHIFT)&HW_PAGE_INDEX_MASK]; tlb_entry *tlbe = tlb[0][(vpa>>HW_PAGE_INDEX_SHIFT)&HW_PAGE_INDEX_MASK];
if (tlbe[0].tag == (vpa & ~0xfff)) if (tlbe[0].tag == (vpa & ~0xfff))
{ {
@ -796,22 +782,6 @@ void InvalidateTLBEntry(u32 vpa)
{ {
tlbe_i[1].flags |= TLB_FLAG_INVALID; tlbe_i[1].flags |= TLB_FLAG_INVALID;
} }
#else
u32 _Address = vpa;
for (int i = 0; i < 128; i++)
{
if ((_Address & ~0xfff) == (PowerPC::ppcState.dtlb_va[(PowerPC::ppcState.dtlb_last + i) & 127]))
{
PowerPC::ppcState.dtlb_pa[(PowerPC::ppcState.dtlb_last + i) & 127] = 0;
PowerPC::ppcState.dtlb_va[(PowerPC::ppcState.dtlb_last + i) & 127] = 0;
}
if ((_Address & ~0xfff) == (PowerPC::ppcState.itlb_va[(PowerPC::ppcState.itlb_last + i) & 127]))
{
PowerPC::ppcState.itlb_pa[(PowerPC::ppcState.itlb_last + i) & 127] = 0;
PowerPC::ppcState.itlb_va[(PowerPC::ppcState.itlb_last + i) & 127] = 0;
}
}
#endif
} }
// Page Address Translation // Page Address Translation