MemmapFunctions: various MMU optimizations

Small TLB lookup optimizations: this is the hot path for MMU code, so try to
make it better.

Template the TLB lookup functions based on the lookup type (opcode, data,
no exception).

Clean up the Read/Write functions and make them more consistent.

Add an early-exit path for MMU accesses to ReadFromHardware/WriteToHardware.
This commit is contained in:
Fiora 2014-12-30 18:12:47 -08:00
parent ea23ce2726
commit c2ed29fe0d
5 changed files with 155 additions and 177 deletions

View File

@ -28,7 +28,7 @@ std::string PPCDebugInterface::Disassemble(unsigned int address)
if (!Memory::IsRAMAddress(address, true, true)) if (!Memory::IsRAMAddress(address, true, true))
{ {
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU || !((address & JIT_ICACHE_VMEM_BIT) && if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU || !((address & JIT_ICACHE_VMEM_BIT) &&
Memory::TranslateAddress(address, Memory::FLAG_NO_EXCEPTION))) Memory::TranslateAddress<Memory::FLAG_NO_EXCEPTION>(address)))
{ {
return "(No RAM here)"; return "(No RAM here)";
} }

View File

@ -96,12 +96,12 @@ u16 Read_U16(const u32 _Address);
u32 Read_U32(const u32 _Address); u32 Read_U32(const u32 _Address);
u64 Read_U64(const u32 _Address); u64 Read_U64(const u32 _Address);
u32 Read_S8_Val(u32 address, u32 val); u32 Read_S8_Val(const u32 _Address, u32 _var);
u32 Read_U8_Val(u32 address, u32 val); u32 Read_U8_Val(const u32 _Address, u32 _var);
u32 Read_S16_Val(u32 address, u32 val); u32 Read_S16_Val(const u32 _Address, u32 _var);
u32 Read_U16_Val(u32 address, u32 val); u32 Read_U16_Val(const u32 _Address, u32 _var);
u32 Read_U32_Val(u32 address, u32 val); u32 Read_U32_Val(const u32 _Address, u32 _var);
u64 Read_U64_Val(u32 address, u64 val); u64 Read_U64_Val(const u32 _Address, u64 _var);
// Useful helper functions, used by ARM JIT // Useful helper functions, used by ARM JIT
float Read_F32(const u32 _Address); float Read_F32(const u32 _Address);
@ -111,17 +111,17 @@ double Read_F64(const u32 _Address);
u32 Read_U8_ZX(const u32 _Address); u32 Read_U8_ZX(const u32 _Address);
u32 Read_U16_ZX(const u32 _Address); u32 Read_U16_ZX(const u32 _Address);
void Write_U8(const u8 _Data, const u32 _Address); void Write_U8(const u8 _var, const u32 _Address);
void Write_U16(const u16 _Data, const u32 _Address); void Write_U16(const u16 _var, const u32 _Address);
void Write_U32(const u32 _Data, const u32 _Address); void Write_U32(const u32 _var, const u32 _Address);
void Write_U64(const u64 _Data, const u32 _Address); void Write_U64(const u64 _var, const u32 _Address);
void Write_U16_Swap(const u16 _Data, const u32 _Address); void Write_U16_Swap(const u16 _var, const u32 _Address);
void Write_U32_Swap(const u32 _Data, const u32 _Address); void Write_U32_Swap(const u32 _var, const u32 _Address);
void Write_U64_Swap(const u64 _Data, const u32 _Address); void Write_U64_Swap(const u64 _var, const u32 _Address);
// Useful helper functions, used by ARM JIT // Useful helper functions, used by ARM JIT
void Write_F64(const double _Data, const u32 _Address); void Write_F64(const double _var, const u32 _Address);
std::string GetString(u32 em_address, size_t size = 0); std::string GetString(u32 em_address, size_t size = 0);
@ -142,7 +142,7 @@ enum XCheckTLBFlag
FLAG_WRITE, FLAG_WRITE,
FLAG_OPCODE, FLAG_OPCODE,
}; };
u32 TranslateAddress(u32 _Address, XCheckTLBFlag _Flag); template <const XCheckTLBFlag _Flag> u32 TranslateAddress(const u32 _Address);
void InvalidateTLBEntry(u32 _Address); void InvalidateTLBEntry(u32 _Address);
extern u32 pagetable_base; extern u32 pagetable_base;
extern u32 pagetable_hashmask; extern u32 pagetable_hashmask;

View File

@ -16,6 +16,7 @@
// https://github.com/dolphin-emu/dolphin // https://github.com/dolphin-emu/dolphin
#include "Common/Atomic.h" #include "Common/Atomic.h"
#include "Common/BitSet.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Core/ConfigManager.h" #include "Core/ConfigManager.h"
@ -91,9 +92,14 @@ static u32 EFB_Read(const u32 addr)
static void GenerateDSIException(u32 _EffectiveAddress, bool _bWrite); static void GenerateDSIException(u32 _EffectiveAddress, bool _bWrite);
template <typename T, typename U> template <XCheckTLBFlag flag, typename T, typename U>
__forceinline void ReadFromHardware(U &_var, const u32 em_address, Memory::XCheckTLBFlag flag) __forceinline void ReadFromHardware(U &_var, const u32 em_address)
{ {
int segment = em_address >> 28;
// Quick check for an address that can't meet any of the following conditions,
// to speed up the MMU path.
if (BitSet32(0xCFC)[segment])
goto translateaddress;
// TODO: Figure out the fastest order of tests for both read and write (they are probably different). // TODO: Figure out the fastest order of tests for both read and write (they are probably different).
if ((em_address & 0xC8000000) == 0xC8000000) if ((em_address & 0xC8000000) == 0xC8000000)
{ {
@ -102,30 +108,28 @@ __forceinline void ReadFromHardware(U &_var, const u32 em_address, Memory::XChec
else else
_var = (T)mmio_mapping->Read<typename std::make_unsigned<T>::type>(em_address); _var = (T)mmio_mapping->Read<typename std::make_unsigned<T>::type>(em_address);
} }
else if (((em_address & 0xF0000000) == 0x80000000) || else if (segment == 0x8 || segment == 0xC || segment == 0x0)
((em_address & 0xF0000000) == 0xC0000000) ||
((em_address & 0xF0000000) == 0x00000000))
{ {
_var = bswap((*(const T*)&m_pRAM[em_address & RAM_MASK])); _var = bswap((*(const T*)&m_pRAM[em_address & RAM_MASK]));
} }
else if (m_pEXRAM && (((em_address & 0xF0000000) == 0x90000000) || else if (m_pEXRAM && (segment == 0x9 || segment == 0xD || segment == 0x1))
((em_address & 0xF0000000) == 0xD0000000) ||
((em_address & 0xF0000000) == 0x10000000)))
{ {
_var = bswap((*(const T*)&m_pEXRAM[em_address & EXRAM_MASK])); _var = bswap((*(const T*)&m_pEXRAM[em_address & EXRAM_MASK]));
} }
else if ((em_address >= 0xE0000000) && (em_address < (0xE0000000+L1_CACHE_SIZE))) else if (segment == 0xE && (em_address < (0xE0000000+L1_CACHE_SIZE)))
{ {
_var = bswap((*(const T*)&m_pL1Cache[em_address & L1_CACHE_MASK])); _var = bswap((*(const T*)&m_pL1Cache[em_address & L1_CACHE_MASK]));
} }
else if ((bFakeVMEM && ((em_address &0xF0000000) == 0x70000000)) ||
(bFakeVMEM && ((em_address &0xF0000000) == 0x40000000)))
{
// fake VMEM
_var = bswap((*(const T*)&m_pFakeVMEM[em_address & FAKEVMEM_MASK]));
}
else else
{ {
translateaddress:
if (bFakeVMEM && (segment == 0x7 || segment == 0x4))
{
// fake VMEM
_var = bswap((*(const T*)&m_pFakeVMEM[em_address & FAKEVMEM_MASK]));
return;
}
// MMU // MMU
// Handle loads that cross page boundaries (ewwww) // Handle loads that cross page boundaries (ewwww)
if (sizeof(T) > 1 && (em_address & (HW_PAGE_SIZE - 1)) > HW_PAGE_SIZE - sizeof(T)) if (sizeof(T) > 1 && (em_address & (HW_PAGE_SIZE - 1)) > HW_PAGE_SIZE - sizeof(T))
@ -134,9 +138,9 @@ __forceinline void ReadFromHardware(U &_var, const u32 em_address, Memory::XChec
// way isn't too terrible. // way isn't too terrible.
// TODO: floats on non-word-aligned boundaries should technically cause alignment exceptions. // TODO: floats on non-word-aligned boundaries should technically cause alignment exceptions.
// Note that "word" means 32-bit, so paired singles or doubles might still be 32-bit aligned! // Note that "word" means 32-bit, so paired singles or doubles might still be 32-bit aligned!
u32 tlb_addr = TranslateAddress(em_address, flag); u32 tlb_addr = TranslateAddress<flag>(em_address);
u32 em_address_next_page = (em_address + sizeof(T) - 1) & ~(HW_PAGE_SIZE - 1); u32 em_address_next_page = (em_address + sizeof(T) - 1) & ~(HW_PAGE_SIZE - 1);
u32 tlb_addr_next_page = TranslateAddress(em_address_next_page, flag); u32 tlb_addr_next_page = TranslateAddress<flag>(em_address_next_page);
if (tlb_addr == 0 || tlb_addr_next_page == 0) if (tlb_addr == 0 || tlb_addr_next_page == 0)
{ {
if (flag == FLAG_READ) if (flag == FLAG_READ)
@ -163,7 +167,7 @@ __forceinline void ReadFromHardware(U &_var, const u32 em_address, Memory::XChec
} }
else else
{ {
u32 tlb_addr = TranslateAddress(em_address, flag); u32 tlb_addr = TranslateAddress<flag>(em_address);
if (tlb_addr == 0) if (tlb_addr == 0)
{ {
if (flag == FLAG_READ) if (flag == FLAG_READ)
@ -190,9 +194,14 @@ __forceinline void ReadFromHardware(U &_var, const u32 em_address, Memory::XChec
} }
template <typename T> template <XCheckTLBFlag flag, typename T>
__forceinline void WriteToHardware(u32 em_address, const T data, Memory::XCheckTLBFlag flag) __forceinline void WriteToHardware(u32 em_address, const T data)
{ {
int segment = em_address >> 28;
// Quick check for an address that can't meet any of the following conditions,
// to speed up the MMU path.
if (BitSet32(0xCFC)[segment])
goto translateaddress;
// First, let's check for FIFO writes, since they are probably the most common // First, let's check for FIFO writes, since they are probably the most common
// reason we end up in this function: // reason we end up in this function:
if ((em_address & 0xFFFFF000) == 0xCC008000) if ((em_address & 0xFFFFF000) == 0xCC008000)
@ -231,42 +240,40 @@ __forceinline void WriteToHardware(u32 em_address, const T data, Memory::XCheckT
return; return;
} }
} }
else if (((em_address & 0xF0000000) == 0x80000000) || else if (segment == 0x8 || segment == 0xC || segment == 0x0)
((em_address & 0xF0000000) == 0xC0000000) ||
((em_address & 0xF0000000) == 0x00000000))
{ {
*(T*)&m_pRAM[em_address & RAM_MASK] = bswap(data); *(T*)&m_pRAM[em_address & RAM_MASK] = bswap(data);
return; return;
} }
else if (m_pEXRAM && (((em_address & 0xF0000000) == 0x90000000) || else if (m_pEXRAM && (segment == 0x9 || segment == 0xD || segment == 0x1))
((em_address & 0xF0000000) == 0xD0000000) ||
((em_address & 0xF0000000) == 0x10000000)))
{ {
*(T*)&m_pEXRAM[em_address & EXRAM_MASK] = bswap(data); *(T*)&m_pEXRAM[em_address & EXRAM_MASK] = bswap(data);
return; return;
} }
else if ((em_address >= 0xE0000000) && (em_address < (0xE0000000+L1_CACHE_SIZE))) else if (segment == 0xE && (em_address < (0xE0000000+L1_CACHE_SIZE)))
{ {
*(T*)&m_pL1Cache[em_address & L1_CACHE_MASK] = bswap(data); *(T*)&m_pL1Cache[em_address & L1_CACHE_MASK] = bswap(data);
return; return;
} }
else if ((bFakeVMEM && ((em_address &0xF0000000) == 0x70000000)) || else
(bFakeVMEM && ((em_address &0xF0000000) == 0x40000000)))
{
// fake VMEM
*(T*)&m_pFakeVMEM[em_address & FAKEVMEM_MASK] = bswap(data);
}
else
{ {
translateaddress:
if (bFakeVMEM && (segment == 0x7 || segment == 0x4))
{
// fake VMEM
*(T*)&m_pFakeVMEM[em_address & FAKEVMEM_MASK] = bswap(data);
return;
}
// MMU // MMU
// Handle stores that cross page boundaries (ewwww) // Handle stores that cross page boundaries (ewwww)
if (sizeof(T) > 1 && (em_address & (HW_PAGE_SIZE-1)) > HW_PAGE_SIZE - sizeof(T)) if (sizeof(T) > 1 && (em_address & (HW_PAGE_SIZE - 1)) > HW_PAGE_SIZE - sizeof(T))
{ {
T val = bswap(data); T val = bswap(data);
// We need to check both addresses before writing in case there's a DSI. // We need to check both addresses before writing in case there's a DSI.
u32 tlb_addr = TranslateAddress(em_address, flag); u32 tlb_addr = TranslateAddress<flag>(em_address);
u32 em_address_next_page = (em_address + sizeof(T) - 1) & ~(HW_PAGE_SIZE - 1); u32 em_address_next_page = (em_address + sizeof(T) - 1) & ~(HW_PAGE_SIZE - 1);
u32 tlb_addr_next_page = TranslateAddress(em_address_next_page, flag); u32 tlb_addr_next_page = TranslateAddress<flag>(em_address_next_page);
if (tlb_addr == 0 || tlb_addr_next_page == 0) if (tlb_addr == 0 || tlb_addr_next_page == 0)
{ {
if (flag == FLAG_WRITE) if (flag == FLAG_WRITE)
@ -291,7 +298,7 @@ __forceinline void WriteToHardware(u32 em_address, const T data, Memory::XCheckT
} }
else else
{ {
u32 tlb_addr = TranslateAddress(em_address, flag); u32 tlb_addr = TranslateAddress<flag>(em_address);
if (tlb_addr == 0) if (tlb_addr == 0)
{ {
if (flag == FLAG_WRITE) if (flag == FLAG_WRITE)
@ -339,7 +346,7 @@ u32 Read_Opcode(u32 _Address)
(_Address & ADDR_MASK_MEM1)) (_Address & ADDR_MASK_MEM1))
{ {
// TODO: Check for MSR instruction address translation flag before translating // TODO: Check for MSR instruction address translation flag before translating
u32 tlb_addr = Memory::TranslateAddress(_Address, FLAG_OPCODE); u32 tlb_addr = TranslateAddress<FLAG_OPCODE>(_Address);
if (tlb_addr == 0) if (tlb_addr == 0)
{ {
GenerateISIException(_Address); GenerateISIException(_Address);
@ -354,63 +361,49 @@ u32 Read_Opcode(u32 _Address)
return PowerPC::ppcState.iCache.ReadInstruction(_Address); return PowerPC::ppcState.iCache.ReadInstruction(_Address);
} }
#ifdef ENABLE_MEM_CHECK
#define MEMCHECK(write, size)\
{\
TMemCheck *mc = PowerPC::memchecks.GetMemCheck(_Address);\
if (mc)\
{\
mc->numHits++;\
mc->Action(&PowerPC::debug_interface, (u32)_var, _Address, write, size, PC);\
}\
}
#else
#define MEMCHECK(write, size)
#endif
u8 Read_U8(const u32 _Address) u8 Read_U8(const u32 _Address)
{ {
u8 _var = 0; u8 _var = 0;
ReadFromHardware<u8>(_var, _Address, FLAG_READ); ReadFromHardware<FLAG_READ, u8>(_var, _Address);
#ifdef ENABLE_MEM_CHECK MEMCHECK(false, 1);
TMemCheck *mc = PowerPC::memchecks.GetMemCheck(_Address);
if (mc)
{
mc->numHits++;
mc->Action(&PowerPC::debug_interface, _var, _Address, false, 1, PC);
}
#endif
return (u8)_var; return (u8)_var;
} }
u16 Read_U16(const u32 _Address) u16 Read_U16(const u32 _Address)
{ {
u16 _var = 0; u16 _var = 0;
ReadFromHardware<u16>(_var, _Address, FLAG_READ); ReadFromHardware<FLAG_READ, u16>(_var, _Address);
#ifdef ENABLE_MEM_CHECK MEMCHECK(false, 2);
TMemCheck *mc = PowerPC::memchecks.GetMemCheck(_Address);
if (mc)
{
mc->numHits++;
mc->Action(&PowerPC::debug_interface, _var, _Address, false, 2, PC);
}
#endif
return (u16)_var; return (u16)_var;
} }
u32 Read_U32(const u32 _Address) u32 Read_U32(const u32 _Address)
{ {
u32 _var = 0; u32 _var = 0;
ReadFromHardware<u32>(_var, _Address, FLAG_READ); ReadFromHardware<FLAG_READ, u32>(_var, _Address);
#ifdef ENABLE_MEM_CHECK MEMCHECK(false, 4);
TMemCheck *mc = PowerPC::memchecks.GetMemCheck(_Address);
if (mc)
{
mc->numHits++;
mc->Action(&PowerPC::debug_interface, _var, _Address, false, 4, PC);
}
#endif
return _var; return _var;
} }
u64 Read_U64(const u32 _Address) u64 Read_U64(const u32 _Address)
{ {
u64 _var = 0; u64 _var = 0;
ReadFromHardware<u64>(_var, _Address, FLAG_READ); ReadFromHardware<FLAG_READ, u64>(_var, _Address);
#ifdef ENABLE_MEM_CHECK MEMCHECK(false, 8);
TMemCheck *mc = PowerPC::memchecks.GetMemCheck(_Address);
if (mc)
{
mc->numHits++;
mc->Action(&PowerPC::debug_interface, (u32)_var, _Address, false, 8, PC);
}
#endif
return _var; return _var;
} }
@ -438,40 +431,46 @@ float Read_F32(const u32 _Address)
return cvt.d; return cvt.d;
} }
u32 Read_U8_Val(u32 address, u32 val) u32 Read_U8_Val(const u32 _Address, u32 _var)
{ {
ReadFromHardware<u8>(val, address, FLAG_READ); ReadFromHardware<FLAG_READ, u8>(_var, _Address);
return val; MEMCHECK(false, 1);
return _var;
} }
u32 Read_S8_Val(u32 address, u32 val) u32 Read_S8_Val(const u32 _Address, u32 _var)
{ {
ReadFromHardware<s8>(val, address, FLAG_READ); ReadFromHardware<FLAG_READ, s8>(_var, _Address);
return val; MEMCHECK(false, 1);
return _var;
} }
u32 Read_U16_Val(u32 address, u32 val) u32 Read_U16_Val(const u32 _Address, u32 _var)
{ {
ReadFromHardware<u16>(val, address, FLAG_READ); ReadFromHardware<FLAG_READ, u16>(_var, _Address);
return val; MEMCHECK(false, 2);
return _var;
} }
u32 Read_S16_Val(u32 address, u32 val) u32 Read_S16_Val(const u32 _Address, u32 _var)
{ {
ReadFromHardware<s16>(val, address, FLAG_READ); ReadFromHardware<FLAG_READ, s16>(_var, _Address);
return val; MEMCHECK(false, 2);
return _var;
} }
u32 Read_U32_Val(u32 address, u32 val) u32 Read_U32_Val(const u32 _Address, u32 _var)
{ {
ReadFromHardware<u32>(val, address, FLAG_READ); ReadFromHardware<FLAG_READ, u32>(_var, _Address);
return val; MEMCHECK(false, 4);
return _var;
} }
u64 Read_U64_Val(u32 address, u64 val) u64 Read_U64_Val(const u32 _Address, u64 _var)
{ {
ReadFromHardware<u64>(val, address, FLAG_READ); ReadFromHardware<FLAG_READ, u64>(_var, _Address);
return val; MEMCHECK(false, 8);
return _var;
} }
u32 Read_U8_ZX(const u32 _Address) u32 Read_U8_ZX(const u32 _Address)
@ -484,88 +483,60 @@ u32 Read_U16_ZX(const u32 _Address)
return (u32)Read_U16(_Address); return (u32)Read_U16(_Address);
} }
void Write_U8(const u8 _Data, const u32 _Address) void Write_U8(const u8 _var, const u32 _Address)
{ {
#ifdef ENABLE_MEM_CHECK MEMCHECK(true, 1);
TMemCheck *mc = PowerPC::memchecks.GetMemCheck(_Address); WriteToHardware<FLAG_WRITE, u8>(_Address, _var);
if (mc) }
{
mc->numHits++; void Write_U16(const u16 _var, const u32 _Address)
mc->Action(&PowerPC::debug_interface, _Data,_Address,true,1,PC); {
} MEMCHECK(true, 2);
#endif WriteToHardware<FLAG_WRITE, u16>(_Address, _var);
WriteToHardware<u8>(_Address, _Data, FLAG_WRITE); }
void Write_U16_Swap(const u16 _var, const u32 _Address)
{
MEMCHECK(true, 2);
Write_U16(Common::swap16(_var), _Address);
} }
void Write_U16(const u16 _Data, const u32 _Address) void Write_U32(const u32 _var, const u32 _Address)
{ {
#ifdef ENABLE_MEM_CHECK MEMCHECK(true, 4);
TMemCheck *mc = PowerPC::memchecks.GetMemCheck(_Address); WriteToHardware<FLAG_WRITE, u32>(_Address, _var);
if (mc)
{
mc->numHits++;
mc->Action(&PowerPC::debug_interface, _Data,_Address,true,2,PC);
}
#endif
WriteToHardware<u16>(_Address, _Data, FLAG_WRITE);
} }
void Write_U16_Swap(const u16 _Data, const u32 _Address) void Write_U32_Swap(const u32 _var, const u32 _Address)
{ {
Write_U16(Common::swap16(_Data), _Address); MEMCHECK(true, 4);
Write_U32(Common::swap32(_var), _Address);
} }
void Write_U64(const u64 _var, const u32 _Address)
void Write_U32(const u32 _Data, const u32 _Address)
{ {
#ifdef ENABLE_MEM_CHECK MEMCHECK(true, 8);
TMemCheck *mc = PowerPC::memchecks.GetMemCheck(_Address); WriteToHardware<FLAG_WRITE, u64>(_Address, _var);
if (mc)
{
mc->numHits++;
mc->Action(&PowerPC::debug_interface, _Data,_Address,true,4,PC);
}
#endif
WriteToHardware<u32>(_Address, _Data, FLAG_WRITE);
} }
void Write_U32_Swap(const u32 _Data, const u32 _Address) void Write_U64_Swap(const u64 _var, const u32 _Address)
{ {
Write_U32(Common::swap32(_Data), _Address); MEMCHECK(true, 8);
Write_U64(Common::swap64(_var), _Address);
} }
void Write_U64(const u64 _Data, const u32 _Address) void Write_F64(const double _var, const u32 _Address)
{
#ifdef ENABLE_MEM_CHECK
TMemCheck *mc = PowerPC::memchecks.GetMemCheck(_Address);
if (mc)
{
mc->numHits++;
mc->Action(&PowerPC::debug_interface, (u32)_Data,_Address,true,8,PC);
}
#endif
WriteToHardware<u64>(_Address, _Data, FLAG_WRITE);
}
void Write_U64_Swap(const u64 _Data, const u32 _Address)
{
Write_U64(Common::swap64(_Data), _Address);
}
void Write_F64(const double _Data, const u32 _Address)
{ {
union union
{ {
u64 i; u64 i;
double d; double d;
} cvt; } cvt;
cvt.d = _Data; cvt.d = _var;
Write_U64(cvt.i, _Address); Write_U64(cvt.i, _Address);
} }
u8 ReadUnchecked_U8(const u32 _Address) u8 ReadUnchecked_U8(const u32 _Address)
{ {
u8 _var = 0; u8 _var = 0;
ReadFromHardware<u8>(_var, _Address, FLAG_NO_EXCEPTION); ReadFromHardware<FLAG_NO_EXCEPTION, u8>(_var, _Address);
return _var; return _var;
} }
@ -573,19 +544,19 @@ u8 ReadUnchecked_U8(const u32 _Address)
u32 ReadUnchecked_U32(const u32 _Address) u32 ReadUnchecked_U32(const u32 _Address)
{ {
u32 _var = 0; u32 _var = 0;
ReadFromHardware<u32>(_var, _Address, FLAG_NO_EXCEPTION); ReadFromHardware<FLAG_NO_EXCEPTION, u32>(_var, _Address);
return _var; return _var;
} }
void WriteUnchecked_U8(const u8 _iValue, const u32 _Address) void WriteUnchecked_U8(const u8 _iValue, const u32 _Address)
{ {
WriteToHardware<u8>(_Address, _iValue, FLAG_NO_EXCEPTION); WriteToHardware<FLAG_NO_EXCEPTION, u8>(_Address, _iValue);
} }
void WriteUnchecked_U32(const u32 _iValue, const u32 _Address) void WriteUnchecked_U32(const u32 _iValue, const u32 _Address)
{ {
WriteToHardware<u32>(_Address, _iValue, FLAG_NO_EXCEPTION); WriteToHardware<FLAG_NO_EXCEPTION, u32>(_Address, _iValue);
} }
// ********************************************************************************* // *********************************************************************************
@ -731,8 +702,9 @@ void SDRUpdated()
static __forceinline u32 LookupTLBPageAddress(const XCheckTLBFlag _Flag, const u32 vpa, u32 *paddr) static __forceinline u32 LookupTLBPageAddress(const XCheckTLBFlag _Flag, const u32 vpa, u32 *paddr)
{ {
PowerPC::tlb_entry *tlbe = PowerPC::ppcState.tlb[_Flag == FLAG_OPCODE][(vpa >> HW_PAGE_INDEX_SHIFT) & HW_PAGE_INDEX_MASK]; int tag = vpa >> HW_PAGE_INDEX_SHIFT;
if (tlbe[0].tag == (vpa & ~0xfff) && !(tlbe[0].flags & TLB_FLAG_INVALID)) PowerPC::tlb_entry *tlbe = PowerPC::ppcState.tlb[_Flag == FLAG_OPCODE][tag & HW_PAGE_INDEX_MASK];
if (tlbe[0].tag == tag && !(tlbe[0].flags & TLB_FLAG_INVALID))
{ {
// Check if C bit requires updating // Check if C bit requires updating
if (_Flag == FLAG_WRITE) if (_Flag == FLAG_WRITE)
@ -757,7 +729,7 @@ static __forceinline u32 LookupTLBPageAddress(const XCheckTLBFlag _Flag, const u
return 1; return 1;
} }
if (tlbe[1].tag == (vpa & ~0xfff) && !(tlbe[1].flags & TLB_FLAG_INVALID)) if (tlbe[1].tag == tag && !(tlbe[1].flags & TLB_FLAG_INVALID))
{ {
// Check if C bit requires updating // Check if C bit requires updating
if (_Flag == FLAG_WRITE) if (_Flag == FLAG_WRITE)
@ -797,7 +769,7 @@ static __forceinline void UpdateTLBEntry(const XCheckTLBFlag _Flag, UPTE2 PTE2,
tlbe[1].flags &= ~TLB_FLAG_MOST_RECENT; tlbe[1].flags &= ~TLB_FLAG_MOST_RECENT;
tlbe[0].paddr = PTE2.RPN << HW_PAGE_INDEX_SHIFT; tlbe[0].paddr = PTE2.RPN << HW_PAGE_INDEX_SHIFT;
tlbe[0].pte = PTE2.Hex; tlbe[0].pte = PTE2.Hex;
tlbe[0].tag = vpa & ~0xfff; tlbe[0].tag = vpa >> HW_PAGE_INDEX_SHIFT;
} }
else else
{ {
@ -805,7 +777,7 @@ static __forceinline void UpdateTLBEntry(const XCheckTLBFlag _Flag, UPTE2 PTE2,
tlbe[0].flags &= ~TLB_FLAG_MOST_RECENT; tlbe[0].flags &= ~TLB_FLAG_MOST_RECENT;
tlbe[1].paddr = PTE2.RPN << HW_PAGE_INDEX_SHIFT; tlbe[1].paddr = PTE2.RPN << HW_PAGE_INDEX_SHIFT;
tlbe[1].pte = PTE2.Hex; tlbe[1].pte = PTE2.Hex;
tlbe[1].tag = vpa & ~0xfff; tlbe[1].tag = vpa >> HW_PAGE_INDEX_SHIFT;
} }
} }
@ -952,7 +924,8 @@ static u32 TranslateBlockAddress(const u32 addr, const XCheckTLBFlag _Flag)
} }
// Translate effective address using BAT or PAT. Returns 0 if the address cannot be translated. // Translate effective address using BAT or PAT. Returns 0 if the address cannot be translated.
u32 TranslateAddress(const u32 _Address, const XCheckTLBFlag _Flag) template <const XCheckTLBFlag _Flag>
u32 TranslateAddress(const u32 _Address)
{ {
// Check MSR[IR] bit before translating instruction addresses. Rogue Leader clears IR and DR?? // Check MSR[IR] bit before translating instruction addresses. Rogue Leader clears IR and DR??
//if ((_Flag == FLAG_OPCODE) && !(MSR & (1 << (31 - 26)))) return _Address; //if ((_Flag == FLAG_OPCODE) && !(MSR & (1 << (31 - 26)))) return _Address;
@ -970,4 +943,9 @@ u32 TranslateAddress(const u32 _Address, const XCheckTLBFlag _Flag)
} }
return TranslatePageAddress(_Address, _Flag); return TranslatePageAddress(_Address, _Flag);
} }
template u32 TranslateAddress<Memory::FLAG_NO_EXCEPTION>(const u32 _Address);
template u32 TranslateAddress<Memory::FLAG_READ>(const u32 _Address);
template u32 TranslateAddress<Memory::FLAG_WRITE>(const u32 _Address);
template u32 TranslateAddress<Memory::FLAG_OPCODE>(const u32 _Address);
} // namespace } // namespace

View File

@ -211,7 +211,7 @@ namespace JitInterface
{ {
if (bMMU && !bFakeVMEM && (_Address & Memory::ADDR_MASK_MEM1)) if (bMMU && !bFakeVMEM && (_Address & Memory::ADDR_MASK_MEM1))
{ {
_Address = Memory::TranslateAddress(_Address, Memory::FLAG_OPCODE); _Address = Memory::TranslateAddress<Memory::FLAG_OPCODE>(_Address);
if (_Address == 0) if (_Address == 0)
{ {
return 0; return 0;

View File

@ -649,7 +649,7 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock *block, CodeBuffer *buffer, u32
bool virtualAddr = SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU && (address & JIT_ICACHE_VMEM_BIT); bool virtualAddr = SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU && (address & JIT_ICACHE_VMEM_BIT);
if (virtualAddr) if (virtualAddr)
{ {
if (!Memory::TranslateAddress(address, Memory::FLAG_NO_EXCEPTION)) if (!Memory::TranslateAddress<Memory::FLAG_NO_EXCEPTION>(address))
{ {
// Memory exception occurred during instruction fetch // Memory exception occurred during instruction fetch
block->m_memory_exception = true; block->m_memory_exception = true;