mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-24 14:49:42 -06:00
Memmapfunctions: more refactoring and optimizations
Try to clean up some redundant code, simplify a few checks, and simplify page accesses.
This commit is contained in:
@ -91,37 +91,37 @@ u32 Read_Instruction(const u32 _Address);
|
|||||||
|
|
||||||
// For use by emulator
|
// For use by emulator
|
||||||
|
|
||||||
u8 Read_U8(const u32 _Address);
|
u8 Read_U8(const u32 address);
|
||||||
u16 Read_U16(const u32 _Address);
|
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(const u32 _Address, u32 _var);
|
u32 Read_S8_Val(const u32 address, u32 var);
|
||||||
u32 Read_U8_Val(const u32 _Address, u32 _var);
|
u32 Read_U8_Val(const u32 address, u32 var);
|
||||||
u32 Read_S16_Val(const u32 _Address, u32 _var);
|
u32 Read_S16_Val(const u32 address, u32 var);
|
||||||
u32 Read_U16_Val(const u32 _Address, u32 _var);
|
u32 Read_U16_Val(const u32 address, u32 var);
|
||||||
u32 Read_U32_Val(const u32 _Address, u32 _var);
|
u32 Read_U32_Val(const u32 address, u32 var);
|
||||||
u64 Read_U64_Val(const u32 _Address, u64 _var);
|
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);
|
||||||
double Read_F64(const u32 _Address);
|
double Read_F64(const u32 address);
|
||||||
|
|
||||||
// used by JIT. Return zero-extended 32bit values
|
// used by JIT. Return zero-extended 32bit values
|
||||||
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 _var, const u32 _Address);
|
void Write_U8(const u8 var, const u32 address);
|
||||||
void Write_U16(const u16 _var, const u32 _Address);
|
void Write_U16(const u16 var, const u32 address);
|
||||||
void Write_U32(const u32 _var, const u32 _Address);
|
void Write_U32(const u32 var, const u32 address);
|
||||||
void Write_U64(const u64 _var, const u32 _Address);
|
void Write_U64(const u64 var, const u32 address);
|
||||||
|
|
||||||
void Write_U16_Swap(const u16 _var, const u32 _Address);
|
void Write_U16_Swap(const u16 var, const u32 address);
|
||||||
void Write_U32_Swap(const u32 _var, const u32 _Address);
|
void Write_U32_Swap(const u32 var, const u32 address);
|
||||||
void Write_U64_Swap(const u64 _var, 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 _var, 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);
|
||||||
|
|
||||||
|
@ -129,28 +129,31 @@ translateaddress:
|
|||||||
_var = bswap((*(const T*)&m_pFakeVMEM[em_address & FAKEVMEM_MASK]));
|
_var = bswap((*(const T*)&m_pFakeVMEM[em_address & FAKEVMEM_MASK]));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MMU
|
// MMU: Do page table translation
|
||||||
|
u32 tlb_addr = TranslateAddress<flag>(em_address);
|
||||||
|
if (tlb_addr == 0)
|
||||||
|
{
|
||||||
|
if (flag == FLAG_READ)
|
||||||
|
GenerateDSIException(em_address, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 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))
|
// The alignment check isn't strictly necessary, but since this is a rare slow path, it provides a faster
|
||||||
|
// (1 instruction on x86) bailout.
|
||||||
|
if (sizeof(T) > 1 && (em_address & (sizeof(T) - 1)) && (em_address & (HW_PAGE_SIZE - 1)) > HW_PAGE_SIZE - sizeof(T))
|
||||||
{
|
{
|
||||||
// This could be unaligned down to the byte level... hopefully this is rare, so doing it this
|
// This could be unaligned down to the byte level... hopefully this is rare, so doing it this
|
||||||
// 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<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<flag>(em_address_next_page);
|
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)
|
||||||
{
|
GenerateDSIException(em_address_next_page, false);
|
||||||
u32 exception_addr = tlb_addr == 0 ? em_address : em_address_next_page;
|
|
||||||
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU)
|
|
||||||
PanicAlertT("Invalid Read at 0x%08x, PC = 0x%08x ", exception_addr, PC);
|
|
||||||
else
|
|
||||||
GenerateDSIException(exception_addr, false);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_var = 0;
|
_var = 0;
|
||||||
@ -158,37 +161,14 @@ translateaddress:
|
|||||||
{
|
{
|
||||||
if (addr == em_address_next_page)
|
if (addr == em_address_next_page)
|
||||||
tlb_addr = tlb_addr_next_page;
|
tlb_addr = tlb_addr_next_page;
|
||||||
_var <<= 8;
|
_var = (_var << 8) | Memory::base[tlb_addr];
|
||||||
if (m_pEXRAM && (tlb_addr & 0xF0000000) == 0x10000000)
|
|
||||||
_var |= m_pEXRAM[tlb_addr & EXRAM_MASK];
|
|
||||||
else
|
|
||||||
_var |= m_pRAM[tlb_addr & RAM_MASK];
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u32 tlb_addr = TranslateAddress<flag>(em_address);
|
// The easy case!
|
||||||
if (tlb_addr == 0)
|
_var = bswap(*(const T*)&Memory::base[tlb_addr]);
|
||||||
{
|
|
||||||
if (flag == FLAG_READ)
|
|
||||||
{
|
|
||||||
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU)
|
|
||||||
PanicAlertT("Invalid Read at 0x%08x, PC = 0x%08x ", em_address, PC);
|
|
||||||
else
|
|
||||||
GenerateDSIException(em_address, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -255,7 +235,7 @@ __forceinline void WriteToHardware(u32 em_address, const T data)
|
|||||||
*(T*)&m_pL1Cache[em_address & L1_CACHE_MASK] = bswap(data);
|
*(T*)&m_pL1Cache[em_address & L1_CACHE_MASK] = bswap(data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
translateaddress:
|
translateaddress:
|
||||||
if (bFakeVMEM && (segment == 0x7 || segment == 0x4))
|
if (bFakeVMEM && (segment == 0x7 || segment == 0x4))
|
||||||
@ -265,61 +245,40 @@ translateaddress:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MMU
|
// MMU: Do page table translation
|
||||||
|
u32 tlb_addr = TranslateAddress<flag>(em_address);
|
||||||
|
if (tlb_addr == 0)
|
||||||
|
{
|
||||||
|
if (flag == FLAG_WRITE)
|
||||||
|
GenerateDSIException(em_address, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 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 & (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<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<flag>(em_address_next_page);
|
u32 tlb_addr_next_page = TranslateAddress<flag>(em_address_next_page);
|
||||||
if (tlb_addr == 0 || tlb_addr_next_page == 0)
|
if (tlb_addr_next_page == 0)
|
||||||
{
|
{
|
||||||
if (flag == FLAG_WRITE)
|
if (flag == FLAG_WRITE)
|
||||||
{
|
GenerateDSIException(em_address_next_page, true);
|
||||||
u32 exception_addr = tlb_addr == 0 ? em_address : em_address_next_page;
|
|
||||||
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU)
|
|
||||||
PanicAlertT("Invalid Write to 0x%08x, PC = 0x%08x ", exception_addr, PC);
|
|
||||||
else
|
|
||||||
GenerateDSIException(exception_addr, true);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (u32 addr = em_address; addr < em_address + sizeof(T); addr++, tlb_addr++, val >>= 8)
|
for (u32 addr = em_address; addr < em_address + sizeof(T); addr++, tlb_addr++, val >>= 8)
|
||||||
{
|
{
|
||||||
if (addr == em_address_next_page)
|
if (addr == em_address_next_page)
|
||||||
tlb_addr = tlb_addr_next_page;
|
tlb_addr = tlb_addr_next_page;
|
||||||
if (m_pEXRAM && (tlb_addr & 0xF0000000) == 0x10000000)
|
Memory::base[tlb_addr] = (u8)val;
|
||||||
m_pEXRAM[tlb_addr & EXRAM_MASK] = (u8)val;
|
|
||||||
else
|
|
||||||
m_pRAM[tlb_addr & RAM_MASK] = (u8)val;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u32 tlb_addr = TranslateAddress<flag>(em_address);
|
// The easy case!
|
||||||
if (tlb_addr == 0)
|
*(T*)&Memory::base[tlb_addr] = bswap(data);
|
||||||
{
|
|
||||||
if (flag == FLAG_WRITE)
|
|
||||||
{
|
|
||||||
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU)
|
|
||||||
PanicAlertT("Invalid Write to 0x%08x, PC = 0x%08x ", em_address, PC);
|
|
||||||
else
|
|
||||||
GenerateDSIException(em_address, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -361,53 +320,51 @@ u32 Read_Opcode(u32 _Address)
|
|||||||
return PowerPC::ppcState.iCache.ReadInstruction(_Address);
|
return PowerPC::ppcState.iCache.ReadInstruction(_Address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __forceinline void Memcheck(u32 address, u32 var, bool write, int size)
|
||||||
|
{
|
||||||
#ifdef ENABLE_MEM_CHECK
|
#ifdef ENABLE_MEM_CHECK
|
||||||
#define MEMCHECK(write, size)\
|
TMemCheck *mc = PowerPC::memchecks.GetMemCheck(address);
|
||||||
{\
|
if (mc)
|
||||||
TMemCheck *mc = PowerPC::memchecks.GetMemCheck(_Address);\
|
{
|
||||||
if (mc)\
|
mc->numHits++;
|
||||||
{\
|
mc->Action(&PowerPC::debug_interface, var, address, write, size, PC);
|
||||||
mc->numHits++;\
|
}
|
||||||
mc->Action(&PowerPC::debug_interface, (u32)_var, _Address, write, size, PC);\
|
|
||||||
}\
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define MEMCHECK(write, size)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
u8 Read_U8(const u32 _Address)
|
|
||||||
{
|
|
||||||
u8 _var = 0;
|
|
||||||
ReadFromHardware<FLAG_READ, u8>(_var, _Address);
|
|
||||||
MEMCHECK(false, 1);
|
|
||||||
return (u8)_var;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 Read_U16(const u32 _Address)
|
u8 Read_U8(const u32 address)
|
||||||
{
|
{
|
||||||
u16 _var = 0;
|
u8 var = 0;
|
||||||
ReadFromHardware<FLAG_READ, u16>(_var, _Address);
|
ReadFromHardware<FLAG_READ, u8>(var, address);
|
||||||
MEMCHECK(false, 2);
|
Memcheck(address, var, false, 1);
|
||||||
return (u16)_var;
|
return (u8)var;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Read_U32(const u32 _Address)
|
u16 Read_U16(const u32 address)
|
||||||
{
|
{
|
||||||
u32 _var = 0;
|
u16 var = 0;
|
||||||
ReadFromHardware<FLAG_READ, u32>(_var, _Address);
|
ReadFromHardware<FLAG_READ, u16>(var, address);
|
||||||
MEMCHECK(false, 4);
|
Memcheck(address, var, false, 2);
|
||||||
return _var;
|
return (u16)var;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 Read_U64(const u32 _Address)
|
u32 Read_U32(const u32 address)
|
||||||
{
|
{
|
||||||
u64 _var = 0;
|
u32 var = 0;
|
||||||
ReadFromHardware<FLAG_READ, u64>(_var, _Address);
|
ReadFromHardware<FLAG_READ, u32>(var, address);
|
||||||
MEMCHECK(false, 8);
|
Memcheck(address, var, false, 4);
|
||||||
return _var;
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Read_F64(const u32 _Address)
|
u64 Read_U64(const u32 address)
|
||||||
|
{
|
||||||
|
u64 var = 0;
|
||||||
|
ReadFromHardware<FLAG_READ, u64>(var, address);
|
||||||
|
Memcheck(address, (u32)var, false, 8);
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Read_F64(const u32 address)
|
||||||
{
|
{
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
@ -415,11 +372,11 @@ double Read_F64(const u32 _Address)
|
|||||||
double d;
|
double d;
|
||||||
} cvt;
|
} cvt;
|
||||||
|
|
||||||
cvt.i = Read_U64(_Address);
|
cvt.i = Read_U64(address);
|
||||||
return cvt.d;
|
return cvt.d;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Read_F32(const u32 _Address)
|
float Read_F32(const u32 address)
|
||||||
{
|
{
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
@ -427,136 +384,136 @@ float Read_F32(const u32 _Address)
|
|||||||
float d;
|
float d;
|
||||||
} cvt;
|
} cvt;
|
||||||
|
|
||||||
cvt.i = Read_U32(_Address);
|
cvt.i = Read_U32(address);
|
||||||
return cvt.d;
|
return cvt.d;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Read_U8_Val(const u32 _Address, u32 _var)
|
u32 Read_U8_Val(const u32 address, u32 var)
|
||||||
{
|
{
|
||||||
ReadFromHardware<FLAG_READ, u8>(_var, _Address);
|
ReadFromHardware<FLAG_READ, u8>(var, address);
|
||||||
MEMCHECK(false, 1);
|
Memcheck(address, var, false, 1);
|
||||||
return _var;
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Read_S8_Val(const u32 _Address, u32 _var)
|
u32 Read_S8_Val(const u32 address, u32 var)
|
||||||
{
|
{
|
||||||
ReadFromHardware<FLAG_READ, s8>(_var, _Address);
|
ReadFromHardware<FLAG_READ, s8>(var, address);
|
||||||
MEMCHECK(false, 1);
|
Memcheck(address, var, false, 1);
|
||||||
return _var;
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Read_U16_Val(const u32 _Address, u32 _var)
|
u32 Read_U16_Val(const u32 address, u32 var)
|
||||||
{
|
{
|
||||||
ReadFromHardware<FLAG_READ, u16>(_var, _Address);
|
ReadFromHardware<FLAG_READ, u16>(var, address);
|
||||||
MEMCHECK(false, 2);
|
Memcheck(address, var, false, 2);
|
||||||
return _var;
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Read_S16_Val(const u32 _Address, u32 _var)
|
u32 Read_S16_Val(const u32 address, u32 var)
|
||||||
{
|
{
|
||||||
ReadFromHardware<FLAG_READ, s16>(_var, _Address);
|
ReadFromHardware<FLAG_READ, s16>(var, address);
|
||||||
MEMCHECK(false, 2);
|
Memcheck(address, var, false, 2);
|
||||||
return _var;
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Read_U32_Val(const u32 _Address, u32 _var)
|
u32 Read_U32_Val(const u32 address, u32 var)
|
||||||
{
|
{
|
||||||
ReadFromHardware<FLAG_READ, u32>(_var, _Address);
|
ReadFromHardware<FLAG_READ, u32>(var, address);
|
||||||
MEMCHECK(false, 4);
|
Memcheck(address, var, false, 4);
|
||||||
return _var;
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 Read_U64_Val(const u32 _Address, u64 _var)
|
u64 Read_U64_Val(const u32 address, u64 var)
|
||||||
{
|
{
|
||||||
ReadFromHardware<FLAG_READ, u64>(_var, _Address);
|
ReadFromHardware<FLAG_READ, u64>(var, address);
|
||||||
MEMCHECK(false, 8);
|
Memcheck(address, (u32)var, false, 8);
|
||||||
return _var;
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Read_U8_ZX(const u32 _Address)
|
u32 Read_U8_ZX(const u32 address)
|
||||||
{
|
{
|
||||||
return (u32)Read_U8(_Address);
|
return (u32)Read_U8(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Read_U16_ZX(const u32 _Address)
|
u32 Read_U16_ZX(const u32 address)
|
||||||
{
|
{
|
||||||
return (u32)Read_U16(_Address);
|
return (u32)Read_U16(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write_U8(const u8 _var, const u32 _Address)
|
void Write_U8(const u8 var, const u32 address)
|
||||||
{
|
{
|
||||||
MEMCHECK(true, 1);
|
Memcheck(address, var, true, 1);
|
||||||
WriteToHardware<FLAG_WRITE, u8>(_Address, _var);
|
WriteToHardware<FLAG_WRITE, u8>(address, var);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write_U16(const u16 _var, const u32 _Address)
|
void Write_U16(const u16 var, const u32 address)
|
||||||
{
|
{
|
||||||
MEMCHECK(true, 2);
|
Memcheck(address, var, true, 2);
|
||||||
WriteToHardware<FLAG_WRITE, u16>(_Address, _var);
|
WriteToHardware<FLAG_WRITE, u16>(address, var);
|
||||||
}
|
}
|
||||||
void Write_U16_Swap(const u16 _var, const u32 _Address)
|
void Write_U16_Swap(const u16 var, const u32 address)
|
||||||
{
|
{
|
||||||
MEMCHECK(true, 2);
|
Memcheck(address, var, true, 2);
|
||||||
Write_U16(Common::swap16(_var), _Address);
|
Write_U16(Common::swap16(var), address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Write_U32(const u32 _var, const u32 _Address)
|
void Write_U32(const u32 var, const u32 address)
|
||||||
{
|
{
|
||||||
MEMCHECK(true, 4);
|
Memcheck(address, var, true, 4);
|
||||||
WriteToHardware<FLAG_WRITE, u32>(_Address, _var);
|
WriteToHardware<FLAG_WRITE, u32>(address, var);
|
||||||
}
|
}
|
||||||
void Write_U32_Swap(const u32 _var, const u32 _Address)
|
void Write_U32_Swap(const u32 var, const u32 address)
|
||||||
{
|
{
|
||||||
MEMCHECK(true, 4);
|
Memcheck(address, var, true, 4);
|
||||||
Write_U32(Common::swap32(_var), _Address);
|
Write_U32(Common::swap32(var), address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write_U64(const u64 _var, const u32 _Address)
|
void Write_U64(const u64 var, const u32 address)
|
||||||
{
|
{
|
||||||
MEMCHECK(true, 8);
|
Memcheck(address, (u32)var, true, 8);
|
||||||
WriteToHardware<FLAG_WRITE, u64>(_Address, _var);
|
WriteToHardware<FLAG_WRITE, u64>(address, var);
|
||||||
}
|
}
|
||||||
void Write_U64_Swap(const u64 _var, const u32 _Address)
|
void Write_U64_Swap(const u64 var, const u32 address)
|
||||||
{
|
{
|
||||||
MEMCHECK(true, 8);
|
Memcheck(address, (u32)var, true, 8);
|
||||||
Write_U64(Common::swap64(_var), _Address);
|
Write_U64(Common::swap64(var), address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write_F64(const double _var, const u32 _Address)
|
void Write_F64(const double var, const u32 address)
|
||||||
{
|
{
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
u64 i;
|
u64 i;
|
||||||
double d;
|
double d;
|
||||||
} cvt;
|
} cvt;
|
||||||
cvt.d = _var;
|
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<FLAG_NO_EXCEPTION, u8>(_var, _Address);
|
ReadFromHardware<FLAG_NO_EXCEPTION, u8>(var, address);
|
||||||
return _var;
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
u32 ReadUnchecked_U32(const u32 _Address)
|
u32 ReadUnchecked_U32(const u32 address)
|
||||||
{
|
{
|
||||||
u32 _var = 0;
|
u32 var = 0;
|
||||||
ReadFromHardware<FLAG_NO_EXCEPTION, u32>(_var, _Address);
|
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 var, const u32 address)
|
||||||
{
|
{
|
||||||
WriteToHardware<FLAG_NO_EXCEPTION, u8>(_Address, _iValue);
|
WriteToHardware<FLAG_NO_EXCEPTION, u8>(address, var);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WriteUnchecked_U32(const u32 _iValue, const u32 _Address)
|
void WriteUnchecked_U32(const u32 var, const u32 address)
|
||||||
{
|
{
|
||||||
WriteToHardware<FLAG_NO_EXCEPTION, u32>(_Address, _iValue);
|
WriteToHardware<FLAG_NO_EXCEPTION, u32>(address, var);
|
||||||
}
|
}
|
||||||
|
|
||||||
// *********************************************************************************
|
// *********************************************************************************
|
||||||
@ -654,6 +611,13 @@ union UPTE2
|
|||||||
|
|
||||||
static void GenerateDSIException(u32 _EffectiveAddress, bool _bWrite)
|
static void GenerateDSIException(u32 _EffectiveAddress, bool _bWrite)
|
||||||
{
|
{
|
||||||
|
// DSI exceptions are only supported in MMU mode.
|
||||||
|
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU)
|
||||||
|
{
|
||||||
|
PanicAlertT("Invalid %s to 0x%08x, PC = 0x%08x ", _bWrite ? "Write to" : "Read from", _EffectiveAddress, PC);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (_bWrite)
|
if (_bWrite)
|
||||||
PowerPC::ppcState.spr[SPR_DSISR] = PPC_EXC_DSISR_PAGE | PPC_EXC_DSISR_STORE;
|
PowerPC::ppcState.spr[SPR_DSISR] = PPC_EXC_DSISR_PAGE | PPC_EXC_DSISR_STORE;
|
||||||
else
|
else
|
||||||
|
Reference in New Issue
Block a user