[AArch64] Implement block profiling.
This is time based block profiling unlike the ARMv7 core. I would like to add cycle counter based block profiling like the ARMv7 core, but it first requires writing a kernel module to enable the counters to userland applications
This commit is contained in:
parent
12493c332c
commit
eb94e742f1
|
@ -4,8 +4,10 @@
|
||||||
|
|
||||||
#include "Common/Arm64Emitter.h"
|
#include "Common/Arm64Emitter.h"
|
||||||
#include "Common/Common.h"
|
#include "Common/Common.h"
|
||||||
|
#include "Common/PerformanceCounter.h"
|
||||||
|
|
||||||
#include "Core/PatchEngine.h"
|
#include "Core/PatchEngine.h"
|
||||||
|
#include "Core/PowerPC/Profiler.h"
|
||||||
#include "Core/PowerPC/JitArm64/Jit.h"
|
#include "Core/PowerPC/JitArm64/Jit.h"
|
||||||
#include "Core/PowerPC/JitArm64/JitArm64_RegCache.h"
|
#include "Core/PowerPC/JitArm64/JitArm64_RegCache.h"
|
||||||
#include "Core/PowerPC/JitArm64/JitArm64_Tables.h"
|
#include "Core/PowerPC/JitArm64/JitArm64_Tables.h"
|
||||||
|
@ -106,6 +108,9 @@ void JitArm64::WriteExit(u32 destination)
|
||||||
{
|
{
|
||||||
DoDownCount();
|
DoDownCount();
|
||||||
|
|
||||||
|
if (Profiler::g_ProfileBlocks)
|
||||||
|
EndTimeProfile(js.curBlock);
|
||||||
|
|
||||||
//If nobody has taken care of this yet (this can be removed when all branches are done)
|
//If nobody has taken care of this yet (this can be removed when all branches are done)
|
||||||
JitBlock *b = js.curBlock;
|
JitBlock *b = js.curBlock;
|
||||||
JitBlock::LinkData linkData;
|
JitBlock::LinkData linkData;
|
||||||
|
@ -140,6 +145,10 @@ void JitArm64::WriteExceptionExit(ARM64Reg dest)
|
||||||
STR(INDEX_UNSIGNED, dest, X29, PPCSTATE_OFF(npc));
|
STR(INDEX_UNSIGNED, dest, X29, PPCSTATE_OFF(npc));
|
||||||
gpr.Unlock(dest);
|
gpr.Unlock(dest);
|
||||||
DoDownCount();
|
DoDownCount();
|
||||||
|
|
||||||
|
if (Profiler::g_ProfileBlocks)
|
||||||
|
EndTimeProfile(js.curBlock);
|
||||||
|
|
||||||
MOVI2R(EncodeRegTo64(dest), (u64)&PowerPC::CheckExceptions);
|
MOVI2R(EncodeRegTo64(dest), (u64)&PowerPC::CheckExceptions);
|
||||||
BLR(EncodeRegTo64(dest));
|
BLR(EncodeRegTo64(dest));
|
||||||
LDR(INDEX_UNSIGNED, dest, X29, PPCSTATE_OFF(npc));
|
LDR(INDEX_UNSIGNED, dest, X29, PPCSTATE_OFF(npc));
|
||||||
|
@ -153,6 +162,9 @@ void JitArm64::WriteExceptionExit()
|
||||||
{
|
{
|
||||||
DoDownCount();
|
DoDownCount();
|
||||||
|
|
||||||
|
if (Profiler::g_ProfileBlocks)
|
||||||
|
EndTimeProfile(js.curBlock);
|
||||||
|
|
||||||
ARM64Reg WA = gpr.GetReg();
|
ARM64Reg WA = gpr.GetReg();
|
||||||
ARM64Reg XA = EncodeRegTo64(WA);
|
ARM64Reg XA = EncodeRegTo64(WA);
|
||||||
LDR(INDEX_UNSIGNED, WA, X29, PPCSTATE_OFF(pc));
|
LDR(INDEX_UNSIGNED, WA, X29, PPCSTATE_OFF(pc));
|
||||||
|
@ -173,6 +185,10 @@ void JitArm64::WriteExitDestInR(ARM64Reg Reg)
|
||||||
STR(INDEX_UNSIGNED, Reg, X29, PPCSTATE_OFF(pc));
|
STR(INDEX_UNSIGNED, Reg, X29, PPCSTATE_OFF(pc));
|
||||||
gpr.Unlock(Reg);
|
gpr.Unlock(Reg);
|
||||||
DoDownCount();
|
DoDownCount();
|
||||||
|
|
||||||
|
if (Profiler::g_ProfileBlocks)
|
||||||
|
EndTimeProfile(js.curBlock);
|
||||||
|
|
||||||
MOVI2R(EncodeRegTo64(Reg), (u64)asm_routines.dispatcher);
|
MOVI2R(EncodeRegTo64(Reg), (u64)asm_routines.dispatcher);
|
||||||
BR(EncodeRegTo64(Reg));
|
BR(EncodeRegTo64(Reg));
|
||||||
}
|
}
|
||||||
|
@ -185,6 +201,32 @@ void JitArm64::DumpCode(const u8* start, const u8* end)
|
||||||
WARN_LOG(DYNA_REC, "Code dump from %p to %p:\n%s", start, end, output.c_str());
|
WARN_LOG(DYNA_REC, "Code dump from %p to %p:\n%s", start, end, output.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JitArm64::BeginTimeProfile(JitBlock* b)
|
||||||
|
{
|
||||||
|
b->ticCounter = 0;
|
||||||
|
b->ticStart = 0;
|
||||||
|
b->ticStop = 0;
|
||||||
|
|
||||||
|
MOVI2R(X1, (u64)QueryPerformanceCounter);
|
||||||
|
MOVI2R(X0, (u64)&b->ticStart);
|
||||||
|
BLR(X1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitArm64::EndTimeProfile(JitBlock* b)
|
||||||
|
{
|
||||||
|
MOVI2R(X1, (u64)QueryPerformanceCounter);
|
||||||
|
MOVI2R(X0, (u64)&b->ticStop);
|
||||||
|
BLR(X1);
|
||||||
|
|
||||||
|
MOVI2R(X0, (u64)&b->ticStart);
|
||||||
|
LDR(INDEX_UNSIGNED, X1, X0, 0); // Start
|
||||||
|
LDR(INDEX_UNSIGNED, X2, X0, 8); // Stop
|
||||||
|
LDR(INDEX_UNSIGNED, X3, X0, 16); // Counter
|
||||||
|
SUB(X2, X2, X1);
|
||||||
|
ADD(X3, X3, X2);
|
||||||
|
STR(INDEX_UNSIGNED, X3, X0, 16);
|
||||||
|
}
|
||||||
|
|
||||||
void JitArm64::Run()
|
void JitArm64::Run()
|
||||||
{
|
{
|
||||||
CompiledCode pExecAddr = (CompiledCode)asm_routines.enterCode;
|
CompiledCode pExecAddr = (CompiledCode)asm_routines.enterCode;
|
||||||
|
@ -256,6 +298,21 @@ const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
|
||||||
SetJumpTarget(bail);
|
SetJumpTarget(bail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Conditionally add profiling code.
|
||||||
|
if (Profiler::g_ProfileBlocks)
|
||||||
|
{
|
||||||
|
ARM64Reg WA = gpr.GetReg();
|
||||||
|
ARM64Reg WB = gpr.GetReg();
|
||||||
|
ARM64Reg XA = EncodeRegTo64(WA);
|
||||||
|
ARM64Reg XB = EncodeRegTo64(WB);
|
||||||
|
MOVI2R(XA, (u64)&b->runCount);
|
||||||
|
LDR(INDEX_UNSIGNED, XB, XA, 0);
|
||||||
|
ADD(XB, XB, 1);
|
||||||
|
STR(INDEX_UNSIGNED, XB, XA, 0);
|
||||||
|
gpr.Unlock(WA, WB);
|
||||||
|
// get start tic
|
||||||
|
BeginTimeProfile(b);
|
||||||
|
}
|
||||||
const u8 *normalEntry = GetCodePtr();
|
const u8 *normalEntry = GetCodePtr();
|
||||||
b->normalEntry = normalEntry;
|
b->normalEntry = normalEntry;
|
||||||
|
|
||||||
|
|
|
@ -200,6 +200,10 @@ private:
|
||||||
|
|
||||||
void DoDownCount();
|
void DoDownCount();
|
||||||
|
|
||||||
|
// Profiling
|
||||||
|
void BeginTimeProfile(JitBlock* b);
|
||||||
|
void EndTimeProfile(JitBlock* b);
|
||||||
|
|
||||||
// Exits
|
// Exits
|
||||||
void WriteExit(u32 destination);
|
void WriteExit(u32 destination);
|
||||||
void WriteExceptionExit(Arm64Gen::ARM64Reg dest);
|
void WriteExceptionExit(Arm64Gen::ARM64Reg dest);
|
||||||
|
|
Loading…
Reference in New Issue