diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 0837d7697d..99fea369f8 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -500,14 +500,7 @@ void 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)); -} - -const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlock *b) -{ - int blockSize = code_buf->GetSize(); + int blockSize = code_buffer.GetSize(); if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging) { @@ -532,6 +525,26 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc } } + // Analyze the block, collect all instructions it is made of (including inlining, + // if that is enabled), reorder instructions for optimal performance, and join joinable instructions. + u32 nextPC = analyzer.Analyze(em_address, &code_block, &code_buffer, blockSize); + + if (code_block.m_memory_exception) + { + // Address of instruction could not be translated + NPC = nextPC; + PowerPC::ppcState.Exceptions |= EXCEPTION_ISI; + PowerPC::CheckExceptions(); + return; + } + + 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, nextPC)); +} + +const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlock *b, u32 nextPC) +{ js.firstFPInstructionFound = false; js.isLastInstruction = false; js.blockStart = em_address; @@ -540,10 +553,6 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc jit->js.numLoadStoreInst = 0; jit->js.numFloatingPointInst = 0; - // Analyze the block, collect all instructions it is made of (including inlining, - // if that is enabled), reorder instructions for optimal performance, and join joinable instructions. - u32 nextPC = analyzer.Analyze(em_address, &code_block, code_buf, blockSize); - PPCAnalyst::CodeOp *ops = code_buf->codebuffer; const u8 *start = AlignCode4(); // TODO: Test if this or AlignCode16 make a difference from GetCodePtr @@ -594,7 +603,6 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc js.skipnext = false; js.carryFlagSet = false; js.carryFlagInverted = false; - js.compilerPC = nextPC; // Translate instructions for (u32 i = 0; i < code_block.m_num_instructions; i++) { @@ -812,20 +820,6 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc } } - if (code_block.m_memory_exception) - { - b->memoryException = true; - // Address of instruction could not be translated - MOV(32, PPCSTATE(npc), Imm32(js.compilerPC)); - - OR(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_ISI)); - - // Remove the invalid instruction from the icache, forcing a recompile - MOV(64, R(RSCRATCH), ImmPtr(jit->GetBlockCache()->GetICachePtr(js.compilerPC))); - MOV(32,MatR(RSCRATCH),Imm32(JIT_ICACHE_INVALID_WORD)); - - WriteExceptionExit(); - } if (code_block.m_broken) { diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.h b/Source/Core/Core/PowerPC/Jit64/Jit.h index 6b919d1cd3..48b8e5ada3 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/PowerPC/Jit64/Jit.h @@ -71,7 +71,7 @@ public: // Jit! void Jit(u32 em_address) override; - const u8* DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buffer, JitBlock *b); + const u8* DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buffer, JitBlock *b, u32 nextPC); BitSet32 CallerSavedRegistersInUse(); diff --git a/Source/Core/Core/PowerPC/Jit64IL/IR_X86.cpp b/Source/Core/Core/PowerPC/Jit64IL/IR_X86.cpp index 3936121148..5131edd8c6 100644 --- a/Source/Core/Core/PowerPC/Jit64IL/IR_X86.cpp +++ b/Source/Core/Core/PowerPC/Jit64IL/IR_X86.cpp @@ -791,7 +791,6 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) case ShortIdleLoop: case FPExceptionCheck: case DSIExceptionCheck: - case ISIException: case ExtExceptionCheck: case BreakPointCheck: case Int3: @@ -2242,20 +2241,6 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) Jit->SetJumpTarget(noMemException); break; } - case ISIException: - { - unsigned InstLoc = ibuild->GetImmValue(getOp1(I)); - - // Address of instruction could not be translated - Jit->MOV(32, PPCSTATE(npc), Imm32(InstLoc)); - Jit->OR(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_ISI)); - - // Remove the invalid instruction from the icache, forcing a recompile - Jit->MOV(64, R(RSCRATCH), ImmPtr(jit->GetBlockCache()->GetICachePtr(InstLoc))); - Jit->MOV(32, MatR(RSCRATCH), Imm32(JIT_ICACHE_INVALID_WORD)); - Jit->WriteExceptionExit(); - break; - } case ExtExceptionCheck: { unsigned InstLoc = ibuild->GetImmValue(getOp1(I)); diff --git a/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp b/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp index ce55c6176e..45f910eca0 100644 --- a/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp +++ b/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp @@ -489,14 +489,8 @@ void JitIL::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)); -} -const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlock *b) -{ - int blockSize = code_buf->GetSize(); + int blockSize = code_buffer.GetSize(); if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging) { @@ -517,6 +511,26 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc } } + // Analyze the block, collect all instructions it is made of (including inlining, + // if that is enabled), reorder instructions for optimal performance, and join joinable instructions. + u32 nextPC = analyzer.Analyze(em_address, &code_block, &code_buffer, blockSize); + + if (code_block.m_memory_exception) + { + // Address of instruction could not be translated + NPC = nextPC; + PowerPC::ppcState.Exceptions |= EXCEPTION_ISI; + PowerPC::CheckExceptions(); + return; + } + + 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, nextPC)); +} + +const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlock *b, u32 nextPC) +{ js.isLastInstruction = false; js.blockStart = em_address; js.fifoBytesThisBlock = 0; @@ -524,10 +538,6 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc jit->js.numLoadStoreInst = 0; jit->js.numFloatingPointInst = 0; - // Analyze the block, collect all instructions it is made of (including inlining, - // if that is enabled), reorder instructions for optimal performance, and join joinable instructions. - u32 nextPC = analyzer.Analyze(em_address, &code_block, code_buf, blockSize); - PPCAnalyst::CodeOp *ops = code_buf->codebuffer; const u8 *start = AlignCode4(); // TODO: Test if this or AlignCode16 make a difference from GetCodePtr @@ -681,12 +691,6 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc } } - if (code_block.m_memory_exception) - { - b->memoryException = true; - ibuild.EmitISIException(ibuild.EmitIntConst(em_address)); - } - // Perform actual code generation WriteCode(nextPC); diff --git a/Source/Core/Core/PowerPC/Jit64IL/JitIL.h b/Source/Core/Core/PowerPC/Jit64IL/JitIL.h index bb3cce01bd..d846c7af10 100644 --- a/Source/Core/Core/PowerPC/Jit64IL/JitIL.h +++ b/Source/Core/Core/PowerPC/Jit64IL/JitIL.h @@ -54,7 +54,7 @@ public: // Jit! void Jit(u32 em_address) override; - const u8* DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buffer, JitBlock *b); + const u8* DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buffer, JitBlock *b, u32 nextPC); void Trace(); diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp index cbf65bd137..a3aee33ed4 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp @@ -110,7 +110,6 @@ using namespace Gen; { JitBlock &b = blocks[num_blocks]; b.invalid = false; - b.memoryException = false; b.originalAddress = em_address; b.linkData.clear(); num_blocks++; //commit the current block @@ -132,11 +131,7 @@ using namespace Gen; block_map[std::make_pair(pAddr + 4 * b.originalSize - 1, pAddr)] = block_num; - // Blocks where a memory exception (ISI) occurred in the instruction fetch have to - // execute the ISI handler as the next instruction. These blocks cannot be - // linked to other blocks. The block will be recompiled after the ISI is handled - // and so we do not link other blocks to it either. - if (block_link && !b.memoryException) + if (block_link) { for (const auto& e : b.linkData) { diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.h b/Source/Core/Core/PowerPC/JitCommon/JitCache.h index fe85195745..5b38cb6a82 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.h +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.h @@ -42,7 +42,6 @@ struct JitBlock int runCount; // for profiling. bool invalid; - bool memoryException; struct LinkData { @@ -121,6 +120,9 @@ class JitBaseBlockCache void LinkBlock(int i); void UnlinkBlock(int i); + u32* GetICachePtr(u32 addr); + void DestroyBlock(int block_num, bool invalidate); + // Virtual for overloaded virtual void WriteLinkBlock(u8* location, const u8* address) = 0; virtual void WriteDestroyBlock(const u8* location, u32 address) = 0; @@ -148,17 +150,13 @@ public: std::array iCacheEx; std::array iCacheVMEM; - u32* GetICachePtr(u32 addr); - // Fast way to get a block. Only works on the first ppc instruction of a block. int GetBlockNumberFromStartAddress(u32 em_address); - u32 GetOriginalFirstOp(int block_num); CompiledCode GetCompiledCodeFromBlock(int block_num); // DOES NOT WORK CORRECTLY WITH INLINING void InvalidateICache(u32 address, const u32 length, bool forced); - void DestroyBlock(int block_num, bool invalidate); }; // x86 BlockCache diff --git a/Source/Core/Core/PowerPC/JitILCommon/IR.cpp b/Source/Core/Core/PowerPC/JitILCommon/IR.cpp index bc8220a040..811c8854b6 100644 --- a/Source/Core/Core/PowerPC/JitILCommon/IR.cpp +++ b/Source/Core/Core/PowerPC/JitILCommon/IR.cpp @@ -1476,7 +1476,7 @@ static const std::string opcodeNames[] = { "FResult_End", "StorePaired", "StoreSingle", "StoreDouble", "StoreFReg", "FDCmpCR", "CInt16", "CInt32", "SystemCall", "RFIExit", "InterpreterBranch", "IdleBranch", "ShortIdleLoop", - "FPExceptionCheckStart", "FPExceptionCheckEnd", "ISIException", "ExtExceptionCheck", + "FPExceptionCheckStart", "FPExceptionCheckEnd", "ExtExceptionCheck", "Tramp", "BlockStart", "BlockEnd", "Int3", }; static const unsigned alwaysUsedList[] = { @@ -1485,7 +1485,7 @@ static const unsigned alwaysUsedList[] = { Store16, Store32, StoreSingle, StoreDouble, StorePaired, StoreFReg, FDCmpCR, BlockStart, BlockEnd, IdleBranch, BranchCond, BranchUncond, ShortIdleLoop, SystemCall, InterpreterBranch, RFIExit, FPExceptionCheck, - DSIExceptionCheck, ISIException, ExtExceptionCheck, BreakPointCheck, + DSIExceptionCheck, ExtExceptionCheck, BreakPointCheck, Int3, Tramp, Nop }; static const unsigned extra8RegList[] = { diff --git a/Source/Core/Core/PowerPC/JitILCommon/IR.h b/Source/Core/Core/PowerPC/JitILCommon/IR.h index baac14e052..43b1ddf93a 100644 --- a/Source/Core/Core/PowerPC/JitILCommon/IR.h +++ b/Source/Core/Core/PowerPC/JitILCommon/IR.h @@ -166,7 +166,7 @@ enum Opcode // used for exception checking, at least until someone // has a better idea of integrating it FPExceptionCheck, DSIExceptionCheck, - ISIException, ExtExceptionCheck, BreakPointCheck, + ExtExceptionCheck, BreakPointCheck, // "Opcode" representing a register too far away to // reference directly; this is a size optimization Tramp, @@ -551,11 +551,6 @@ public: return EmitUOp(DSIExceptionCheck, pc); } - InstLoc EmitISIException(InstLoc dest) - { - return EmitUOp(ISIException, dest); - } - InstLoc EmitExtExceptionCheck(InstLoc pc) { return EmitUOp(ExtExceptionCheck, pc);