Adds support to the new PPCAnalyst to the ARM JIT cores.
ArmJit32 supports OPTION_CONDITIONAL_CONTINUE with this.
This commit is contained in:
parent
da2ed2e17d
commit
ad167e7b52
|
@ -40,6 +40,11 @@ void JitArm::Init()
|
|||
fpr.Init(this);
|
||||
jo.enableBlocklink = true;
|
||||
jo.optimizeGatherPipe = true;
|
||||
|
||||
code_block.m_stats = &js.st;
|
||||
code_block.m_gpa = &js.gpa;
|
||||
code_block.m_fpa = &js.fpa;
|
||||
analyser.SetOption(PPCAnalyst::PPCAnalyser::OPTION_CONDITIONAL_CONTINUE);
|
||||
}
|
||||
|
||||
void JitArm::ClearCache()
|
||||
|
@ -250,27 +255,27 @@ void JitArm::Trace()
|
|||
void JitArm::PrintDebug(UGeckoInstruction inst, u32 level)
|
||||
{
|
||||
if (level > 0)
|
||||
printf("Start: %08x OP '%s' Info\n", (u32)GetCodePtr(), PPCTables::GetInstructionName(inst));
|
||||
WARN_LOG(DYNA_REC, "Start: %08x OP '%s' Info", (u32)GetCodePtr(), PPCTables::GetInstructionName(inst));
|
||||
if (level > 1)
|
||||
{
|
||||
GekkoOPInfo* Info = GetOpInfo(inst.hex);
|
||||
printf("\tOuts\n");
|
||||
WARN_LOG(DYNA_REC, "\tOuts");
|
||||
if (Info->flags & FL_OUT_A)
|
||||
printf("\t-OUT_A: %x\n", inst.RA);
|
||||
WARN_LOG(DYNA_REC, "\t-OUT_A: %x", inst.RA);
|
||||
if (Info->flags & FL_OUT_D)
|
||||
printf("\t-OUT_D: %x\n", inst.RD);
|
||||
printf("\tIns\n");
|
||||
WARN_LOG(DYNA_REC, "\t-OUT_D: %x", inst.RD);
|
||||
WARN_LOG(DYNA_REC, "\tIns");
|
||||
// A, AO, B, C, S
|
||||
if (Info->flags & FL_IN_A)
|
||||
printf("\t-IN_A: %x\n", inst.RA);
|
||||
WARN_LOG(DYNA_REC, "\t-IN_A: %x", inst.RA);
|
||||
if (Info->flags & FL_IN_A0)
|
||||
printf("\t-IN_A0: %x\n", inst.RA);
|
||||
WARN_LOG(DYNA_REC, "\t-IN_A0: %x", inst.RA);
|
||||
if (Info->flags & FL_IN_B)
|
||||
printf("\t-IN_B: %x\n", inst.RB);
|
||||
WARN_LOG(DYNA_REC, "\t-IN_B: %x", inst.RB);
|
||||
if (Info->flags & FL_IN_C)
|
||||
printf("\t-IN_C: %x\n", inst.RC);
|
||||
WARN_LOG(DYNA_REC, "\t-IN_C: %x", inst.RC);
|
||||
if (Info->flags & FL_IN_S)
|
||||
printf("\t-IN_S: %x\n", inst.RS);
|
||||
WARN_LOG(DYNA_REC, "\t-IN_S: %x", inst.RS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -298,14 +303,10 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
|
|||
// Memory exception on instruction fetch
|
||||
bool memory_exception = false;
|
||||
|
||||
// A broken block is a block that does not end in a branch
|
||||
bool broken_block = false;
|
||||
|
||||
if (Core::g_CoreStartupParameter.bEnableDebugging)
|
||||
{
|
||||
// Comment out the following to disable breakpoints (speed-up)
|
||||
blockSize = 1;
|
||||
broken_block = true;
|
||||
Trace();
|
||||
}
|
||||
|
||||
|
@ -324,8 +325,6 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
int size = 0;
|
||||
js.isLastInstruction = false;
|
||||
js.blockStart = em_address;
|
||||
js.fifoBytesThisBlock = 0;
|
||||
|
@ -333,17 +332,12 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
|
|||
js.block_flags = 0;
|
||||
js.cancel = false;
|
||||
|
||||
u32 nextPC = em_address;
|
||||
// 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 = em_address;
|
||||
u32 merged_addresses[32];
|
||||
const int capacity_of_merged_addresses = sizeof(merged_addresses) / sizeof(merged_addresses[0]);
|
||||
int size_of_merged_addresses = 0;
|
||||
if (!memory_exception)
|
||||
{
|
||||
// If there is a memory exception inside a block (broken_block==true), compile up to that instruction.
|
||||
nextPC = PPCAnalyst::Flatten(em_address, &size, &js.st, &js.gpa, &js.fpa, broken_block, code_buf, blockSize, merged_addresses, capacity_of_merged_addresses, size_of_merged_addresses);
|
||||
}
|
||||
nextPC = analyser.Analyse(em_address, &code_block, code_buf, blockSize);
|
||||
|
||||
PPCAnalyst::CodeOp *ops = code_buf->codebuffer;
|
||||
|
||||
const u8 *start = GetCodePtr();
|
||||
|
@ -398,20 +392,21 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
|
|||
gpr.Start(js.gpa);
|
||||
fpr.Start(js.fpa);
|
||||
js.downcountAmount = 0;
|
||||
|
||||
if (!Core::g_CoreStartupParameter.bEnableDebugging)
|
||||
{
|
||||
for (int i = 0; i < size_of_merged_addresses; ++i)
|
||||
{
|
||||
const u32 address = merged_addresses[i];
|
||||
js.downcountAmount += PatchEngine::GetSpeedhackCycles(address);
|
||||
}
|
||||
}
|
||||
js.downcountAmount += PatchEngine::GetSpeedhackCycles(em_address);
|
||||
|
||||
js.skipnext = false;
|
||||
js.blockSize = size;
|
||||
js.blockSize = code_block.m_instructions;
|
||||
js.compilerPC = nextPC;
|
||||
|
||||
const int DEBUG_OUTPUT = 0;
|
||||
|
||||
if (DEBUG_OUTPUT)
|
||||
WARN_LOG(DYNA_REC, "-------0x%08x-------", em_address);
|
||||
|
||||
// Translate instructions
|
||||
for (int i = 0; i < (int)size; i++)
|
||||
for (u32 i = 0; i < code_block.m_instructions; i++)
|
||||
{
|
||||
js.compilerPC = ops[i].address;
|
||||
js.op = &ops[i];
|
||||
|
@ -419,7 +414,7 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
|
|||
const GekkoOPInfo *opinfo = ops[i].opinfo;
|
||||
js.downcountAmount += opinfo->numCycles;
|
||||
|
||||
if (i == (int)size - 1)
|
||||
if (i == (code_block.m_instructions - 1))
|
||||
{
|
||||
// WARNING - cmp->branch merging will screw this up.
|
||||
js.isLastInstruction = true;
|
||||
|
@ -468,7 +463,7 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
|
|||
}
|
||||
if (!ops[i].skip)
|
||||
{
|
||||
PrintDebug(ops[i].inst, 0);
|
||||
PrintDebug(ops[i].inst, DEBUG_OUTPUT);
|
||||
if (js.memcheck && (opinfo->flags & FL_USE_FPU))
|
||||
{
|
||||
// Don't do this yet
|
||||
|
@ -485,7 +480,7 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
|
|||
}
|
||||
if (memory_exception)
|
||||
BKPT(0x500);
|
||||
if (broken_block)
|
||||
if (code_block.m_broken)
|
||||
{
|
||||
printf("Broken Block going to 0x%08x\n", nextPC);
|
||||
WriteExit(nextPC);
|
||||
|
@ -493,7 +488,7 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
|
|||
|
||||
b->flags = js.block_flags;
|
||||
b->codeSize = (u32)(GetCodePtr() - normalEntry);
|
||||
b->originalSize = size;
|
||||
b->originalSize = code_block.m_instructions;
|
||||
FlushIcache();
|
||||
return start;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ private:
|
|||
ArmFPRCache fpr;
|
||||
|
||||
PPCAnalyst::CodeBuffer code_buffer;
|
||||
|
||||
void DoDownCount();
|
||||
|
||||
void PrintDebug(UGeckoInstruction inst, u32 level);
|
||||
|
|
|
@ -149,7 +149,6 @@ void JitArm::bcx(UGeckoInstruction inst)
|
|||
INSTRUCTION_START
|
||||
JITDISABLE(bJITBranchOff)
|
||||
// USES_CR
|
||||
_assert_msg_(DYNA_REC, js.isLastInstruction, "bcx not last instruction of block");
|
||||
|
||||
gpr.Flush();
|
||||
fpr.Flush();
|
||||
|
@ -203,7 +202,8 @@ void JitArm::bcx(UGeckoInstruction inst)
|
|||
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0)
|
||||
SetJumpTarget( pCTRDontBranch );
|
||||
|
||||
WriteExit(js.compilerPC + 4);
|
||||
if (!analyser.HasOption(PPCAnalyst::PPCAnalyser::OPTION_CONDITIONAL_CONTINUE))
|
||||
WriteExit(js.compilerPC + 4);
|
||||
}
|
||||
void JitArm::bcctrx(UGeckoInstruction inst)
|
||||
{
|
||||
|
@ -265,25 +265,16 @@ void JitArm::bcctrx(UGeckoInstruction inst)
|
|||
WriteExitDestInR(rA);
|
||||
|
||||
SetJumpTarget(b);
|
||||
WriteExit(js.compilerPC + 4);
|
||||
|
||||
if (!analyser.HasOption(PPCAnalyst::PPCAnalyser::OPTION_CONDITIONAL_CONTINUE))
|
||||
WriteExit(js.compilerPC + 4);
|
||||
}
|
||||
}
|
||||
void JitArm::bclrx(UGeckoInstruction inst)
|
||||
{
|
||||
INSTRUCTION_START
|
||||
JITDISABLE(bJITBranchOff)
|
||||
if (!js.isLastInstruction &&
|
||||
(inst.BO & (1 << 4)) && (inst.BO & (1 << 2))) {
|
||||
if (inst.LK)
|
||||
{
|
||||
ARMReg rA = gpr.GetReg(false);
|
||||
u32 Jumpto = js.compilerPC + 4;
|
||||
MOVI2R(rA, Jumpto);
|
||||
STR(rA, R9, PPCSTATE_OFF(spr[SPR_LR]));
|
||||
// ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
gpr.Flush();
|
||||
fpr.Flush();
|
||||
|
||||
|
@ -342,5 +333,7 @@ void JitArm::bclrx(UGeckoInstruction inst)
|
|||
SetJumpTarget( pConditionDontBranch );
|
||||
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0)
|
||||
SetJumpTarget( pCTRDontBranch );
|
||||
WriteExit(js.compilerPC + 4);
|
||||
|
||||
if (!analyser.HasOption(PPCAnalyst::PPCAnalyser::OPTION_CONDITIONAL_CONTINUE))
|
||||
WriteExit(js.compilerPC + 4);
|
||||
}
|
||||
|
|
|
@ -1014,7 +1014,9 @@ void JitArm::twx(UGeckoInstruction inst)
|
|||
SetJumpTarget(exit3);
|
||||
SetJumpTarget(exit4);
|
||||
SetJumpTarget(exit5);
|
||||
WriteExit(js.compilerPC + 4);
|
||||
|
||||
if (!analyser.HasOption(PPCAnalyst::PPCAnalyser::OPTION_CONDITIONAL_CONTINUE))
|
||||
WriteExit(js.compilerPC + 4);
|
||||
|
||||
gpr.Unlock(RA, RB);
|
||||
}
|
||||
|
|
|
@ -34,6 +34,10 @@ void JitArmIL::Init()
|
|||
AllocCodeSpace(CODE_SIZE);
|
||||
blocks.Init();
|
||||
asm_routines.Init();
|
||||
|
||||
code_block.m_stats = &js.st;
|
||||
code_block.m_gpa = &js.gpa;
|
||||
code_block.m_fpa = &js.fpa;
|
||||
}
|
||||
|
||||
void JitArmIL::ClearCache()
|
||||
|
@ -202,14 +206,10 @@ const u8* JitArmIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
|
|||
// Memory exception on instruction fetch
|
||||
bool memory_exception = false;
|
||||
|
||||
// A broken block is a block that does not end in a branch
|
||||
bool broken_block = false;
|
||||
|
||||
if (Core::g_CoreStartupParameter.bEnableDebugging)
|
||||
{
|
||||
// Comment out the following to disable breakpoints (speed-up)
|
||||
blockSize = 1;
|
||||
broken_block = true;
|
||||
}
|
||||
|
||||
if (em_address == 0)
|
||||
|
@ -228,7 +228,6 @@ const u8* JitArmIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
|
|||
}
|
||||
|
||||
|
||||
int size = 0;
|
||||
js.isLastInstruction = false;
|
||||
js.blockStart = em_address;
|
||||
js.fifoBytesThisBlock = 0;
|
||||
|
@ -236,17 +235,12 @@ const u8* JitArmIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
|
|||
js.block_flags = 0;
|
||||
js.cancel = false;
|
||||
|
||||
u32 nextPC = em_address;
|
||||
// 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 = em_address;
|
||||
u32 merged_addresses[32];
|
||||
const int capacity_of_merged_addresses = sizeof(merged_addresses) / sizeof(merged_addresses[0]);
|
||||
int size_of_merged_addresses = 0;
|
||||
if (!memory_exception)
|
||||
{
|
||||
// If there is a memory exception inside a block (broken_block==true), compile up to that instruction.
|
||||
nextPC = PPCAnalyst::Flatten(em_address, &size, &js.st, &js.gpa, &js.fpa, broken_block, code_buf, blockSize, merged_addresses, capacity_of_merged_addresses, size_of_merged_addresses);
|
||||
}
|
||||
nextPC = analyser.Analyse(em_address, &code_block, code_buf, blockSize);
|
||||
|
||||
PPCAnalyst::CodeOp *ops = code_buf->codebuffer;
|
||||
|
||||
const u8 *start = GetCodePtr();
|
||||
|
@ -271,7 +265,7 @@ const u8* JitArmIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
|
|||
u64 codeHash = -1;
|
||||
{
|
||||
// For profiling and IR Writer
|
||||
for (int i = 0; i < (int)size; i++)
|
||||
for (u32 i = 0; i < code_block.m_instructions; i++)
|
||||
{
|
||||
const u64 inst = ops[i].inst.hex;
|
||||
// Ported from boost::hash
|
||||
|
@ -289,19 +283,13 @@ const u8* JitArmIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
|
|||
|
||||
js.downcountAmount = 0;
|
||||
if (!Core::g_CoreStartupParameter.bEnableDebugging)
|
||||
{
|
||||
for (int i = 0; i < size_of_merged_addresses; ++i)
|
||||
{
|
||||
const u32 address = merged_addresses[i];
|
||||
js.downcountAmount += PatchEngine::GetSpeedhackCycles(address);
|
||||
}
|
||||
}
|
||||
js.downcountAmount += PatchEngine::GetSpeedhackCycles(em_address);
|
||||
|
||||
js.skipnext = false;
|
||||
js.blockSize = size;
|
||||
js.blockSize = code_block.m_instructions;
|
||||
js.compilerPC = nextPC;
|
||||
// Translate instructions
|
||||
for (int i = 0; i < (int)size; i++)
|
||||
for (u32 i = 0; i < code_block.m_instructions; i++)
|
||||
{
|
||||
js.compilerPC = ops[i].address;
|
||||
js.op = &ops[i];
|
||||
|
@ -309,7 +297,7 @@ const u8* JitArmIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
|
|||
const GekkoOPInfo *opinfo = ops[i].opinfo;
|
||||
js.downcountAmount += opinfo->numCycles;
|
||||
|
||||
if (i == (int)size - 1)
|
||||
if (i == (code_block.m_instructions - 1))
|
||||
{
|
||||
// WARNING - cmp->branch merging will screw this up.
|
||||
js.isLastInstruction = true;
|
||||
|
@ -348,21 +336,19 @@ const u8* JitArmIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
|
|||
}
|
||||
if (memory_exception)
|
||||
BKPT(0x500);
|
||||
if (broken_block)
|
||||
|
||||
if (code_block.m_broken)
|
||||
{
|
||||
printf("Broken Block going to 0x%08x\n", nextPC);
|
||||
WriteExit(nextPC);
|
||||
}
|
||||
|
||||
// Perform actual code generation
|
||||
|
||||
WriteCode(nextPC);
|
||||
b->flags = js.block_flags;
|
||||
b->codeSize = (u32)(GetCodePtr() - normalEntry);
|
||||
b->originalSize = size;
|
||||
b->originalSize = code_block.m_instructions;;
|
||||
|
||||
{
|
||||
}
|
||||
FlushIcache();
|
||||
return start;
|
||||
|
||||
|
|
|
@ -83,6 +83,9 @@ protected:
|
|||
std::unordered_set<u32> fifoWriteAddresses;
|
||||
};
|
||||
|
||||
PPCAnalyst::CodeBlock code_block;
|
||||
PPCAnalyst::PPCAnalyser analyser;
|
||||
|
||||
public:
|
||||
// This should probably be removed from public:
|
||||
JitOptions jo;
|
||||
|
|
Loading…
Reference in New Issue