Merge pull request #1809 from magumagu/simplify-isi

JIT: simplify ISI handling.
This commit is contained in:
skidau 2015-01-04 20:31:16 +11:00
commit b06a3fb144
9 changed files with 51 additions and 80 deletions

View File

@ -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)
{

View File

@ -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();

View File

@ -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));

View File

@ -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);

View File

@ -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();

View File

@ -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)
{

View File

@ -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

View File

@ -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[] = {

View File

@ -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);