diff --git a/Source/Core/Core/Debugger/PPCDebugInterface.cpp b/Source/Core/Core/Debugger/PPCDebugInterface.cpp index ddc2fec12e..1434fdb5bd 100644 --- a/Source/Core/Core/Debugger/PPCDebugInterface.cpp +++ b/Source/Core/Core/Debugger/PPCDebugInterface.cpp @@ -28,7 +28,7 @@ std::string PPCDebugInterface::Disassemble(unsigned int address) if (!Memory::IsRAMAddress(address, true, true)) { if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU || !((address & JIT_ICACHE_VMEM_BIT) && - Memory::TranslateAddress(address, Memory::FLAG_NO_EXCEPTION))) + Memory::TranslateAddress(address))) { return "(No RAM here)"; } diff --git a/Source/Core/Core/HW/Memmap.h b/Source/Core/Core/HW/Memmap.h index 8a8b5b42e1..31e2e9979f 100644 --- a/Source/Core/Core/HW/Memmap.h +++ b/Source/Core/Core/HW/Memmap.h @@ -96,12 +96,12 @@ u16 Read_U16(const u32 _Address); u32 Read_U32(const u32 _Address); u64 Read_U64(const u32 _Address); -u32 Read_S8_Val(u32 address, u32 val); -u32 Read_U8_Val(u32 address, u32 val); -u32 Read_S16_Val(u32 address, u32 val); -u32 Read_U16_Val(u32 address, u32 val); -u32 Read_U32_Val(u32 address, u32 val); -u64 Read_U64_Val(u32 address, u64 val); +u32 Read_S8_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_U16_Val(const u32 _Address, u32 _var); +u32 Read_U32_Val(const u32 _Address, u32 _var); +u64 Read_U64_Val(const u32 _Address, u64 _var); // Useful helper functions, used by ARM JIT 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_U16_ZX(const u32 _Address); -void Write_U8(const u8 _Data, const u32 _Address); -void Write_U16(const u16 _Data, const u32 _Address); -void Write_U32(const u32 _Data, const u32 _Address); -void Write_U64(const u64 _Data, const u32 _Address); +void Write_U8(const u8 _var, const u32 _Address); +void Write_U16(const u16 _var, const u32 _Address); +void Write_U32(const u32 _var, const u32 _Address); +void Write_U64(const u64 _var, const u32 _Address); -void Write_U16_Swap(const u16 _Data, const u32 _Address); -void Write_U32_Swap(const u32 _Data, const u32 _Address); -void Write_U64_Swap(const u64 _Data, 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_U64_Swap(const u64 _var, const u32 _Address); // 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); @@ -142,7 +142,7 @@ enum XCheckTLBFlag FLAG_WRITE, FLAG_OPCODE, }; -u32 TranslateAddress(u32 _Address, XCheckTLBFlag _Flag); +template u32 TranslateAddress(const u32 _Address); void InvalidateTLBEntry(u32 _Address); extern u32 pagetable_base; extern u32 pagetable_hashmask; diff --git a/Source/Core/Core/HW/MemmapFunctions.cpp b/Source/Core/Core/HW/MemmapFunctions.cpp index 8db4be1920..a8e3e8be63 100644 --- a/Source/Core/Core/HW/MemmapFunctions.cpp +++ b/Source/Core/Core/HW/MemmapFunctions.cpp @@ -16,6 +16,7 @@ // https://github.com/dolphin-emu/dolphin #include "Common/Atomic.h" +#include "Common/BitSet.h" #include "Common/CommonTypes.h" #include "Core/ConfigManager.h" @@ -91,9 +92,14 @@ static u32 EFB_Read(const u32 addr) static void GenerateDSIException(u32 _EffectiveAddress, bool _bWrite); -template -__forceinline void ReadFromHardware(U &_var, const u32 em_address, Memory::XCheckTLBFlag flag) +template +__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). if ((em_address & 0xC8000000) == 0xC8000000) { @@ -102,30 +108,28 @@ __forceinline void ReadFromHardware(U &_var, const u32 em_address, Memory::XChec else _var = (T)mmio_mapping->Read::type>(em_address); } - else if (((em_address & 0xF0000000) == 0x80000000) || - ((em_address & 0xF0000000) == 0xC0000000) || - ((em_address & 0xF0000000) == 0x00000000)) + else if (segment == 0x8 || segment == 0xC || segment == 0x0) { _var = bswap((*(const T*)&m_pRAM[em_address & RAM_MASK])); } - else if (m_pEXRAM && (((em_address & 0xF0000000) == 0x90000000) || - ((em_address & 0xF0000000) == 0xD0000000) || - ((em_address & 0xF0000000) == 0x10000000))) + else if (m_pEXRAM && (segment == 0x9 || segment == 0xD || segment == 0x1)) { _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])); } - 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 { +translateaddress: + if (bFakeVMEM && (segment == 0x7 || segment == 0x4)) + { + // fake VMEM + _var = bswap((*(const T*)&m_pFakeVMEM[em_address & FAKEVMEM_MASK])); + return; + } + // MMU // Handle loads that cross page boundaries (ewwww) 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. // 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! - u32 tlb_addr = TranslateAddress(em_address, flag); + u32 tlb_addr = TranslateAddress(em_address); 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(em_address_next_page); if (tlb_addr == 0 || tlb_addr_next_page == 0) { if (flag == FLAG_READ) @@ -163,7 +167,7 @@ __forceinline void ReadFromHardware(U &_var, const u32 em_address, Memory::XChec } else { - u32 tlb_addr = TranslateAddress(em_address, flag); + u32 tlb_addr = TranslateAddress(em_address); if (tlb_addr == 0) { if (flag == FLAG_READ) @@ -190,9 +194,14 @@ __forceinline void ReadFromHardware(U &_var, const u32 em_address, Memory::XChec } -template -__forceinline void WriteToHardware(u32 em_address, const T data, Memory::XCheckTLBFlag flag) +template +__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 // reason we end up in this function: if ((em_address & 0xFFFFF000) == 0xCC008000) @@ -231,42 +240,40 @@ __forceinline void WriteToHardware(u32 em_address, const T data, Memory::XCheckT return; } } - else if (((em_address & 0xF0000000) == 0x80000000) || - ((em_address & 0xF0000000) == 0xC0000000) || - ((em_address & 0xF0000000) == 0x00000000)) + else if (segment == 0x8 || segment == 0xC || segment == 0x0) { *(T*)&m_pRAM[em_address & RAM_MASK] = bswap(data); return; } - else if (m_pEXRAM && (((em_address & 0xF0000000) == 0x90000000) || - ((em_address & 0xF0000000) == 0xD0000000) || - ((em_address & 0xF0000000) == 0x10000000))) + else if (m_pEXRAM && (segment == 0x9 || segment == 0xD || segment == 0x1)) { *(T*)&m_pEXRAM[em_address & EXRAM_MASK] = bswap(data); 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); return; } - else if ((bFakeVMEM && ((em_address &0xF0000000) == 0x70000000)) || - (bFakeVMEM && ((em_address &0xF0000000) == 0x40000000))) - { - // fake VMEM - *(T*)&m_pFakeVMEM[em_address & FAKEVMEM_MASK] = bswap(data); - } - else + else { +translateaddress: + if (bFakeVMEM && (segment == 0x7 || segment == 0x4)) + { + // fake VMEM + *(T*)&m_pFakeVMEM[em_address & FAKEVMEM_MASK] = bswap(data); + return; + } + // MMU // 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); // 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(em_address); 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(em_address_next_page); if (tlb_addr == 0 || tlb_addr_next_page == 0) { if (flag == FLAG_WRITE) @@ -291,7 +298,7 @@ __forceinline void WriteToHardware(u32 em_address, const T data, Memory::XCheckT } else { - u32 tlb_addr = TranslateAddress(em_address, flag); + u32 tlb_addr = TranslateAddress(em_address); if (tlb_addr == 0) { if (flag == FLAG_WRITE) @@ -339,7 +346,7 @@ u32 Read_Opcode(u32 _Address) (_Address & ADDR_MASK_MEM1)) { // TODO: Check for MSR instruction address translation flag before translating - u32 tlb_addr = Memory::TranslateAddress(_Address, FLAG_OPCODE); + u32 tlb_addr = TranslateAddress(_Address); if (tlb_addr == 0) { GenerateISIException(_Address); @@ -354,63 +361,49 @@ u32 Read_Opcode(u32 _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 _var = 0; - ReadFromHardware(_var, _Address, FLAG_READ); -#ifdef ENABLE_MEM_CHECK - TMemCheck *mc = PowerPC::memchecks.GetMemCheck(_Address); - if (mc) - { - mc->numHits++; - mc->Action(&PowerPC::debug_interface, _var, _Address, false, 1, PC); - } -#endif + ReadFromHardware(_var, _Address); + MEMCHECK(false, 1); return (u8)_var; } u16 Read_U16(const u32 _Address) { u16 _var = 0; - ReadFromHardware(_var, _Address, FLAG_READ); -#ifdef ENABLE_MEM_CHECK - TMemCheck *mc = PowerPC::memchecks.GetMemCheck(_Address); - if (mc) - { - mc->numHits++; - mc->Action(&PowerPC::debug_interface, _var, _Address, false, 2, PC); - } -#endif + ReadFromHardware(_var, _Address); + MEMCHECK(false, 2); return (u16)_var; } u32 Read_U32(const u32 _Address) { u32 _var = 0; - ReadFromHardware(_var, _Address, FLAG_READ); -#ifdef ENABLE_MEM_CHECK - TMemCheck *mc = PowerPC::memchecks.GetMemCheck(_Address); - if (mc) - { - mc->numHits++; - mc->Action(&PowerPC::debug_interface, _var, _Address, false, 4, PC); - } -#endif + ReadFromHardware(_var, _Address); + MEMCHECK(false, 4); return _var; } u64 Read_U64(const u32 _Address) { u64 _var = 0; - ReadFromHardware(_var, _Address, FLAG_READ); -#ifdef ENABLE_MEM_CHECK - TMemCheck *mc = PowerPC::memchecks.GetMemCheck(_Address); - if (mc) - { - mc->numHits++; - mc->Action(&PowerPC::debug_interface, (u32)_var, _Address, false, 8, PC); - } -#endif + ReadFromHardware(_var, _Address); + MEMCHECK(false, 8); return _var; } @@ -438,40 +431,46 @@ float Read_F32(const u32 _Address) return cvt.d; } -u32 Read_U8_Val(u32 address, u32 val) +u32 Read_U8_Val(const u32 _Address, u32 _var) { - ReadFromHardware(val, address, FLAG_READ); - return val; + ReadFromHardware(_var, _Address); + MEMCHECK(false, 1); + return _var; } -u32 Read_S8_Val(u32 address, u32 val) +u32 Read_S8_Val(const u32 _Address, u32 _var) { - ReadFromHardware(val, address, FLAG_READ); - return val; + ReadFromHardware(_var, _Address); + MEMCHECK(false, 1); + return _var; } -u32 Read_U16_Val(u32 address, u32 val) +u32 Read_U16_Val(const u32 _Address, u32 _var) { - ReadFromHardware(val, address, FLAG_READ); - return val; + ReadFromHardware(_var, _Address); + MEMCHECK(false, 2); + return _var; } -u32 Read_S16_Val(u32 address, u32 val) +u32 Read_S16_Val(const u32 _Address, u32 _var) { - ReadFromHardware(val, address, FLAG_READ); - return val; + ReadFromHardware(_var, _Address); + MEMCHECK(false, 2); + return _var; } -u32 Read_U32_Val(u32 address, u32 val) +u32 Read_U32_Val(const u32 _Address, u32 _var) { - ReadFromHardware(val, address, FLAG_READ); - return val; + ReadFromHardware(_var, _Address); + MEMCHECK(false, 4); + return _var; } -u64 Read_U64_Val(u32 address, u64 val) +u64 Read_U64_Val(const u32 _Address, u64 _var) { - ReadFromHardware(val, address, FLAG_READ); - return val; + ReadFromHardware(_var, _Address); + MEMCHECK(false, 8); + return _var; } u32 Read_U8_ZX(const u32 _Address) @@ -484,88 +483,60 @@ u32 Read_U16_ZX(const u32 _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 - TMemCheck *mc = PowerPC::memchecks.GetMemCheck(_Address); - if (mc) - { - mc->numHits++; - mc->Action(&PowerPC::debug_interface, _Data,_Address,true,1,PC); - } -#endif - WriteToHardware(_Address, _Data, FLAG_WRITE); + MEMCHECK(true, 1); + WriteToHardware(_Address, _var); +} + +void Write_U16(const u16 _var, const u32 _Address) +{ + MEMCHECK(true, 2); + WriteToHardware(_Address, _var); +} +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 - TMemCheck *mc = PowerPC::memchecks.GetMemCheck(_Address); - if (mc) - { - mc->numHits++; - mc->Action(&PowerPC::debug_interface, _Data,_Address,true,2,PC); - } -#endif - - WriteToHardware(_Address, _Data, FLAG_WRITE); + MEMCHECK(true, 4); + WriteToHardware(_Address, _var); } -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_U32(const u32 _Data, const u32 _Address) +void Write_U64(const u64 _var, const u32 _Address) { -#ifdef ENABLE_MEM_CHECK - TMemCheck *mc = PowerPC::memchecks.GetMemCheck(_Address); - if (mc) - { - mc->numHits++; - mc->Action(&PowerPC::debug_interface, _Data,_Address,true,4,PC); - } -#endif - WriteToHardware(_Address, _Data, FLAG_WRITE); + MEMCHECK(true, 8); + WriteToHardware(_Address, _var); } -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) -{ -#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(_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) +void Write_F64(const double _var, const u32 _Address) { union { u64 i; double d; } cvt; - cvt.d = _Data; + cvt.d = _var; Write_U64(cvt.i, _Address); } u8 ReadUnchecked_U8(const u32 _Address) { u8 _var = 0; - ReadFromHardware(_var, _Address, FLAG_NO_EXCEPTION); + ReadFromHardware(_var, _Address); return _var; } @@ -573,19 +544,19 @@ u8 ReadUnchecked_U8(const u32 _Address) u32 ReadUnchecked_U32(const u32 _Address) { u32 _var = 0; - ReadFromHardware(_var, _Address, FLAG_NO_EXCEPTION); + ReadFromHardware(_var, _Address); return _var; } void WriteUnchecked_U8(const u8 _iValue, const u32 _Address) { - WriteToHardware(_Address, _iValue, FLAG_NO_EXCEPTION); + WriteToHardware(_Address, _iValue); } void WriteUnchecked_U32(const u32 _iValue, const u32 _Address) { - WriteToHardware(_Address, _iValue, FLAG_NO_EXCEPTION); + WriteToHardware(_Address, _iValue); } // ********************************************************************************* @@ -731,8 +702,9 @@ void SDRUpdated() 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]; - if (tlbe[0].tag == (vpa & ~0xfff) && !(tlbe[0].flags & TLB_FLAG_INVALID)) + int tag = vpa >> HW_PAGE_INDEX_SHIFT; + 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 if (_Flag == FLAG_WRITE) @@ -757,7 +729,7 @@ static __forceinline u32 LookupTLBPageAddress(const XCheckTLBFlag _Flag, const u 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 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[0].paddr = PTE2.RPN << HW_PAGE_INDEX_SHIFT; tlbe[0].pte = PTE2.Hex; - tlbe[0].tag = vpa & ~0xfff; + tlbe[0].tag = vpa >> HW_PAGE_INDEX_SHIFT; } else { @@ -805,7 +777,7 @@ static __forceinline void UpdateTLBEntry(const XCheckTLBFlag _Flag, UPTE2 PTE2, tlbe[0].flags &= ~TLB_FLAG_MOST_RECENT; tlbe[1].paddr = PTE2.RPN << HW_PAGE_INDEX_SHIFT; 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. -u32 TranslateAddress(const u32 _Address, const XCheckTLBFlag _Flag) +template +u32 TranslateAddress(const u32 _Address) { // Check MSR[IR] bit before translating instruction addresses. Rogue Leader clears IR and DR?? //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); } + +template u32 TranslateAddress(const u32 _Address); +template u32 TranslateAddress(const u32 _Address); +template u32 TranslateAddress(const u32 _Address); +template u32 TranslateAddress(const u32 _Address); } // namespace diff --git a/Source/Core/Core/PowerPC/JitInterface.cpp b/Source/Core/Core/PowerPC/JitInterface.cpp index 86c17653d5..87cb0c6d43 100644 --- a/Source/Core/Core/PowerPC/JitInterface.cpp +++ b/Source/Core/Core/PowerPC/JitInterface.cpp @@ -211,7 +211,7 @@ namespace JitInterface { if (bMMU && !bFakeVMEM && (_Address & Memory::ADDR_MASK_MEM1)) { - _Address = Memory::TranslateAddress(_Address, Memory::FLAG_OPCODE); + _Address = Memory::TranslateAddress(_Address); if (_Address == 0) { return 0; diff --git a/Source/Core/Core/PowerPC/PPCAnalyst.cpp b/Source/Core/Core/PowerPC/PPCAnalyst.cpp index 1064e6af2e..5c6dd390c8 100644 --- a/Source/Core/Core/PowerPC/PPCAnalyst.cpp +++ b/Source/Core/Core/PowerPC/PPCAnalyst.cpp @@ -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); if (virtualAddr) { - if (!Memory::TranslateAddress(address, Memory::FLAG_NO_EXCEPTION)) + if (!Memory::TranslateAddress(address)) { // Memory exception occurred during instruction fetch block->m_memory_exception = true;