diff --git a/Source/Core/Core/Src/HW/MemmapFunctions.cpp b/Source/Core/Core/Src/HW/MemmapFunctions.cpp index b391eea975..7e3f78616d 100644 --- a/Source/Core/Core/Src/HW/MemmapFunctions.cpp +++ b/Source/Core/Core/Src/HW/MemmapFunctions.cpp @@ -265,6 +265,7 @@ inline void WriteToHardware(u32 em_address, const T data, u32 effective_address, ((em_address & 0xF0000000) == 0xC0000000) || ((em_address & 0xF0000000) == 0x00000000)) { + PowerPC::ppcState.iCache.InvalidateBlock(em_address); *(T*)&m_pRAM[em_address & RAM_MASK] = bswap(data); return; } @@ -272,6 +273,7 @@ inline void WriteToHardware(u32 em_address, const T data, u32 effective_address, ((em_address & 0xF0000000) == 0xD0000000) || ((em_address & 0xF0000000) == 0x10000000)) { + PowerPC::ppcState.iCache.InvalidateBlock(em_address); *(T*)&m_pEXRAM[em_address & EXRAM_MASK] = bswap(data); return; } @@ -284,6 +286,7 @@ inline void WriteToHardware(u32 em_address, const T data, u32 effective_address, (bFakeVMEM && ((em_address &0xF0000000) == 0x40000000))) { // fake VMEM + PowerPC::ppcState.iCache.InvalidateBlock(em_address); *(T*)&m_pFakeVMEM[em_address & FAKEVMEM_MASK] = bswap(data); } else diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp index 5d7cd28b20..1133f348e4 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp @@ -363,12 +363,23 @@ void Interpreter::dcbf(UGeckoInstruction _inst) { NPC = PC + 12; }*/ + // Invalidate the icache on dcbf + if (jit) + { + u32 address = Helper_Get_EA_X(_inst); + jit->GetBlockCache()->InvalidateICache(address & ~0x1f); + } } void Interpreter::dcbi(UGeckoInstruction _inst) { - // Removes a block from data cache. Since we don't emulate the data cache, we don't need to do anything. - // Seen used during initialization. + // Removes a block from data cache. Since we don't emulate the data cache, we don't need to do anything to the data cache + // However, we invalidate the icache on dcbi + if (jit) + { + u32 address = Helper_Get_EA_X(_inst); + jit->GetBlockCache()->InvalidateICache(address & ~0x1f); + } } void Interpreter::dcbst(UGeckoInstruction _inst) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp index 3d5efd80ae..f9fd3c4635 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp @@ -393,6 +393,7 @@ void STACKALIGN Jit64::Jit(u32 em_address) { ClearCache(); } + int block_num = blocks.AllocateBlock(em_address); JitBlock *b = blocks.GetBlock(block_num); blocks.FinalizeBlock(block_num, jo.enableBlocklink, DoJit(em_address, &code_buffer, b)); @@ -612,14 +613,14 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc #ifdef _M_IX86 if (js.compilerPC & JIT_ICACHE_VMEM_BIT) MOV(32, M((jit->GetBlockCache()->GetICacheVMEM() + (js.compilerPC & JIT_ICACHE_MASK))), Imm32(JIT_ICACHE_INVALID_WORD)); - else if (js.blockStart & JIT_ICACHE_EXRAM_BIT) + else if (js.compilerPC & JIT_ICACHE_EXRAM_BIT) MOV(32, M((jit->GetBlockCache()->GetICacheEx() + (js.compilerPC & JIT_ICACHEEX_MASK))), Imm32(JIT_ICACHE_INVALID_WORD)); else MOV(32, M((jit->GetBlockCache()->GetICache() + (js.compilerPC & JIT_ICACHE_MASK))), Imm32(JIT_ICACHE_INVALID_WORD)); #else if (js.compilerPC & JIT_ICACHE_VMEM_BIT) MOV(64, R(RAX), ImmPtr(jit->GetBlockCache()->GetICacheVMEM() + (js.compilerPC & JIT_ICACHE_MASK))); - else if (js.blockStart & JIT_ICACHE_EXRAM_BIT) + else if (js.compilerPC & JIT_ICACHE_EXRAM_BIT) MOV(64, R(RAX), ImmPtr(jit->GetBlockCache()->GetICacheEx() + (js.compilerPC & JIT_ICACHEEX_MASK))); else MOV(64, R(RAX), ImmPtr(jit->GetBlockCache()->GetICache() + (js.compilerPC & JIT_ICACHE_MASK))); diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp index 1632a76796..c366617dfa 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp @@ -210,12 +210,12 @@ static GekkoOPTemplate table31[] = {824, &Jit64::srawix}, //"srawix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}}, {24, &Jit64::slwx}, //"slwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}}, - {54, &Jit64::Default}, //"dcbst", OPTYPE_DCACHE, 0, 4}}, - {86, &Jit64::DoNothing}, //"dcbf", OPTYPE_DCACHE, 0, 4}}, - {246, &Jit64::Default}, //"dcbtst", OPTYPE_DCACHE, 0, 1}}, - {278, &Jit64::Default}, //"dcbt", OPTYPE_DCACHE, 0, 1}}, + {54, &Jit64::DoNothing}, //"dcbst", OPTYPE_DCACHE, 0, 4}}, + {86, &Jit64::Default}, //"dcbf", OPTYPE_DCACHE, 0, 4}}, + {246, &Jit64::DoNothing}, //"dcbtst", OPTYPE_DCACHE, 0, 1}}, + {278, &Jit64::DoNothing}, //"dcbt", OPTYPE_DCACHE, 0, 1}}, {470, &Jit64::Default}, //"dcbi", OPTYPE_DCACHE, 0, 4}}, - {758, &Jit64::Default}, //"dcba", OPTYPE_DCACHE, 0, 4}}, + {758, &Jit64::DoNothing}, //"dcba", OPTYPE_DCACHE, 0, 4}}, {1014, &Jit64::dcbz}, //"dcbz", OPTYPE_DCACHE, 0, 4}}, //load word diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp index 4110c37f96..75755de5cb 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp @@ -494,7 +494,7 @@ void JitIL::Trace() } #endif - NOTICE_LOG(DYNA_REC, "JITIL PC: %08x SRR0: %08x SRR1: %08x CRfast: %02x%02x%02x%02x%02x%02x%02x%02x FPSCR: %08x MSR: %08x LR: %08x %s %s", + DEBUG_LOG(DYNA_REC, "JITIL PC: %08x SRR0: %08x SRR1: %08x CRfast: %02x%02x%02x%02x%02x%02x%02x%02x FPSCR: %08x MSR: %08x LR: %08x %s %s", PC, SRR0, SRR1, PowerPC::ppcState.cr_fast[0], PowerPC::ppcState.cr_fast[1], PowerPC::ppcState.cr_fast[2], PowerPC::ppcState.cr_fast[3], PowerPC::ppcState.cr_fast[4], PowerPC::ppcState.cr_fast[5], PowerPC::ppcState.cr_fast[6], PowerPC::ppcState.cr_fast[7], PowerPC::ppcState.fpscr, PowerPC::ppcState.msr, PowerPC::ppcState.spr[8], regs, fregs); diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp index f34f100657..bcfea0a07b 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp @@ -212,12 +212,12 @@ static GekkoOPTemplate table31[] = {824, &JitIL::srawix}, //"srawix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}}, {24, &JitIL::slwx}, //"slwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}}, - {54, &JitIL::Default}, //"dcbst", OPTYPE_DCACHE, 0, 4}}, - {86, &JitIL::DoNothing}, //"dcbf", OPTYPE_DCACHE, 0, 4}}, - {246, &JitIL::Default}, //"dcbtst", OPTYPE_DCACHE, 0, 1}}, - {278, &JitIL::Default}, //"dcbt", OPTYPE_DCACHE, 0, 1}}, + {54, &JitIL::DoNothing}, //"dcbst", OPTYPE_DCACHE, 0, 4}}, + {86, &JitIL::Default}, //"dcbf", OPTYPE_DCACHE, 0, 4}}, + {246, &JitIL::DoNothing}, //"dcbtst", OPTYPE_DCACHE, 0, 1}}, + {278, &JitIL::DoNothing}, //"dcbt", OPTYPE_DCACHE, 0, 1}}, {470, &JitIL::Default}, //"dcbi", OPTYPE_DCACHE, 0, 4}}, - {758, &JitIL::Default}, //"dcba", OPTYPE_DCACHE, 0, 4}}, + {758, &JitIL::DoNothing}, //"dcba", OPTYPE_DCACHE, 0, 4}}, {1014, &JitIL::dcbz}, //"dcbz", OPTYPE_DCACHE, 0, 4}}, //load word {23, &JitIL::lXzx}, //"lwzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}}, diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp index 1ed997ce4c..deffa9586d 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp @@ -126,16 +126,16 @@ bool JitBlock::ContainsAddress(u32 em_address) // This clears the JIT cache. It's called from JitCache.cpp when the JIT cache // is full and when saving and loading states. void JitBlockCache::Clear() - { + { Core::DisplayMessage("Clearing code cache.", 3000); for (int i = 0; i < num_blocks; i++) { DestroyBlock(i, false); } links_to.clear(); - block_map.clear(); num_blocks = 0; memset(blockCodePointers, 0, sizeof(u8*)*MAX_NUM_BLOCKS); + ClearSafe(); } void JitBlockCache::ClearSafe() @@ -207,8 +207,9 @@ bool JitBlock::ContainsAddress(u32 em_address) blockCodePointers[block_num] = code_ptr; JitBlock &b = blocks[block_num]; b.originalFirstOpcode = Memory::Read_Opcode_JIT(b.originalAddress); + if ((b.originalAddress + b.originalSize) > code_high) + code_high = b.originalAddress + b.originalSize; Memory::Write_Opcode_JIT(b.originalAddress, (JIT_OPCODE << 26) | block_num); - block_map[std::make_pair(b.originalAddress + 4 * b.originalSize - 1, b.originalAddress)] = block_num; if (block_link) { for (int i = 0; i < 2; i++) @@ -355,79 +356,44 @@ bool JitBlock::ContainsAddress(u32 em_address) void JitBlockCache::DestroyBlock(int block_num, bool invalidate) { - if (block_num < 0 || block_num >= num_blocks) - { - PanicAlert("DestroyBlock: Invalid block number %d", block_num); - return; - } JitBlock &b = blocks[block_num]; if (b.invalid) { - if (invalidate) - PanicAlert("Invalidating invalid block %d", block_num); return; } b.invalid = true; #ifdef JIT_UNLIMITED_ICACHE - Memory::Write_Opcode_JIT(b.originalAddress, b.originalFirstOpcode?b.originalFirstOpcode:JIT_ICACHE_INVALID_WORD); + Memory::Write_Opcode_JIT(b.originalAddress, JIT_ICACHE_INVALID_WORD); #else if (Memory::ReadFast32(b.originalAddress) == block_num) Memory::WriteUnchecked_U32(b.originalFirstOpcode, b.originalAddress); #endif - - // We don't unlink blocks, we just send anyone who tries to run them back to the dispatcher. - // Not entirely ideal, but .. pretty good. - // Spurious entrances from previously linked blocks can only come through checkedEntry - XEmitter emit((u8 *)b.checkedEntry); - emit.MOV(32, M(&PC), Imm32(b.originalAddress)); - emit.JMP(jit->GetAsmRoutines()->dispatcher, true); - // this is not needed really - /* - emit.SetCodePtr((u8 *)blockCodePointers[blocknum]); - emit.MOV(32, M(&PC), Imm32(b.originalAddress)); - emit.JMP(asm_routines.dispatcher, true); - */ } void JitBlockCache::InvalidateICache(u32 address) - { + { address &= ~0x1f; - // destroy JIT blocks - // !! this works correctly under assumption that any two overlapping blocks end at the same address - std::map, u32>::iterator it1 = block_map.lower_bound(std::make_pair(address, 0)), it2 = it1, it; - while (it2 != block_map.end() && it2->first.second < address + 0x20) - { - DestroyBlock(it2->second, true); - it2++; - } - if (it1 != it2) - { - block_map.erase(it1, it2); - } - #ifdef JIT_UNLIMITED_ICACHE - // invalidate iCache. - // icbi can be called with any address, so we should check - if ((address & ~JIT_ICACHE_MASK) != 0x80000000 && (address & ~JIT_ICACHE_MASK) != 0x00000000 && - (address & ~JIT_ICACHE_MASK) != 0x7e000000 && // TLB area - (address & ~JIT_ICACHEEX_MASK) != 0x90000000 && (address & ~JIT_ICACHEEX_MASK) != 0x10000000) - { - return; - } if (address & JIT_ICACHE_VMEM_BIT) { u32 cacheaddr = address & JIT_ICACHE_MASK; + if (cacheaddr > (code_high & JIT_ICACHE_MASK)) + return; memset(iCacheVMEM + cacheaddr, JIT_ICACHE_INVALID_BYTE, 32); } else if (address & JIT_ICACHE_EXRAM_BIT) { u32 cacheaddr = address & JIT_ICACHEEX_MASK; + if (cacheaddr > (code_high & JIT_ICACHEEX_MASK)) + return; memset(iCacheEx + cacheaddr, JIT_ICACHE_INVALID_BYTE, 32); } else { u32 cacheaddr = address & JIT_ICACHE_MASK; + if (cacheaddr > (code_high & JIT_ICACHE_MASK)) + return; memset(iCache + cacheaddr, JIT_ICACHE_INVALID_BYTE, 32); } #endif diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h index 91d47a3d0e..e6862a747b 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h @@ -76,7 +76,6 @@ class JitBlockCache JitBlock *blocks; int num_blocks; std::multimap links_to; - std::map, u32> block_map; // (end_addr, start_addr) -> number #ifdef JIT_UNLIMITED_ICACHE u8 *iCache; u8 *iCacheEx; @@ -105,6 +104,7 @@ public: void Reset(); bool IsFull() const; + u32 code_high; // Code Cache JitBlock *GetBlock(int block_num); diff --git a/Source/Core/Core/Src/PowerPC/PPCCache.cpp b/Source/Core/Core/Src/PowerPC/PPCCache.cpp index 33ecc0ee88..7e45c9e1ab 100644 --- a/Source/Core/Core/Src/PowerPC/PPCCache.cpp +++ b/Source/Core/Core/Src/PowerPC/PPCCache.cpp @@ -82,8 +82,6 @@ namespace PowerPC void InstructionCache::Invalidate(u32 addr) { - if (jit) - jit->GetBlockCache()->InvalidateICache(addr); if (!HID0.ICE) return; // invalidates the whole set @@ -101,6 +99,14 @@ namespace PowerPC } #endif valid[set] = 0; + if (jit) + jit->GetBlockCache()->InvalidateICache(addr); + } + + void InstructionCache::InvalidateBlock(u32 addr) + { + if (jit) + jit->GetBlockCache()->InvalidateICache(addr); } u32 InstructionCache::ReadInstruction(u32 addr) diff --git a/Source/Core/Core/Src/PowerPC/PPCCache.h b/Source/Core/Core/Src/PowerPC/PPCCache.h index c2e428946c..76e1f47345 100644 --- a/Source/Core/Core/Src/PowerPC/PPCCache.h +++ b/Source/Core/Core/Src/PowerPC/PPCCache.h @@ -53,6 +53,7 @@ namespace PowerPC void Reset(); u32 ReadInstruction(u32 addr); void Invalidate(u32 addr); + void InvalidateBlock(u32 addr); }; }