Merge pull request #1809 from magumagu/simplify-isi
JIT: simplify ISI handling.
This commit is contained in:
commit
b06a3fb144
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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<u8, JIT_ICACHEEX_SIZE> iCacheEx;
|
||||
std::array<u8, JIT_ICACHE_SIZE> 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
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue