mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-22 15:40:02 +00:00
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:
commit
73590b1323
@ -151,8 +151,16 @@ inline void ReadFromHardware(T &_var, const u32 em_address, const u32 effective_
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_var <<= 8;
|
if (m_pEXRAM && (tlb_addr & 0xF0000000) == 0x10000000)
|
||||||
_var |= m_pRAM[tlb_addr & RAM_MASK];
|
{
|
||||||
|
_var <<= 8;
|
||||||
|
_var = m_pEXRAM[tlb_addr & EXRAM_MASK];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_var <<= 8;
|
||||||
|
_var |= m_pRAM[tlb_addr & RAM_MASK];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,7 +176,14 @@ inline void ReadFromHardware(T &_var, const u32 em_address, const u32 effective_
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_var = bswap((*(const T*)&m_pRAM[tlb_addr & RAM_MASK]));
|
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]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -263,8 +278,16 @@ inline void WriteToHardware(u32 em_address, const T data, u32 effective_address,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_pRAM[tlb_addr & RAM_MASK] = (u8)val;
|
if (m_pEXRAM && (tlb_addr & 0xF0000000) == 0x10000000)
|
||||||
val >>= 8;
|
{
|
||||||
|
m_pEXRAM[tlb_addr & EXRAM_MASK] = (u8)val;
|
||||||
|
val >>= 8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_pRAM[tlb_addr & RAM_MASK] = (u8)val;
|
||||||
|
val >>= 8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -280,7 +303,14 @@ inline void WriteToHardware(u32 em_address, const T data, u32 effective_address,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*(T*)&m_pRAM[tlb_addr & RAM_MASK] = bswap(data);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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))
|
||||||
{
|
{
|
||||||
tlbe[0].flags |= TLB_FLAG_MOST_RECENT;
|
if (_Flag != FLAG_NO_EXCEPTION)
|
||||||
tlbe[1].flags &= ~TLB_FLAG_MOST_RECENT;
|
{
|
||||||
|
tlbe[0].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))
|
||||||
{
|
{
|
||||||
tlbe[1].flags |= TLB_FLAG_MOST_RECENT;
|
if (_Flag != FLAG_NO_EXCEPTION)
|
||||||
tlbe[0].flags &= ~TLB_FLAG_MOST_RECENT;
|
{
|
||||||
|
tlbe[1].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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user