mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-17 16:30:30 +02:00
RISC-V and LoongArch64 IR JITs: Name the fixed code routines, and profile on Linux
Both now list their routines (GetFixedCodeLabels), so the disassembly names jump targets and --jit-profile charges routine samples to the calling block. The profiler samples them on Linux, and its report disassembles their host code per instruction (RISC-V's in 2- and 4-byte steps). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
08b398bbd1
commit
d4a2cd3e43
7 files changed
+55
-2
No files matched your search
@@ -656,6 +656,23 @@ static std::vector<std::string> DisassembleHost(const u8 *p, int size, std::vect
|
||||
}
|
||||
#elif PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64)
|
||||
lines = DisassembleX86(p, size, &offsets);
|
||||
#elif PPSSPP_ARCH(RISCV64)
|
||||
for (int i = 0; i + 2 <= size; ) {
|
||||
// Compressed instructions are 2 bytes.
|
||||
const int len = (p[i] & 3) == 3 ? 4 : 2;
|
||||
if (i + len > size)
|
||||
break;
|
||||
std::vector<std::string> one = DisassembleRV64(p + i, len);
|
||||
lines.push_back(one.empty() ? "?" : one[0]);
|
||||
offsets.push_back(i);
|
||||
i += len;
|
||||
}
|
||||
#elif PPSSPP_ARCH(LOONGARCH64)
|
||||
for (int i = 0; i + 4 <= size; i += 4) {
|
||||
std::vector<std::string> one = DisassembleLA64(p + i, 4);
|
||||
lines.push_back(one.empty() ? "?" : one[0]);
|
||||
offsets.push_back(i);
|
||||
}
|
||||
#else
|
||||
lines.push_back("(no per-instruction disassembly for this host)");
|
||||
offsets.push_back(0);
|
||||
|
||||
@@ -117,7 +117,7 @@ std::string DescribeHostAddress(uintptr_t pc, uintptr_t *symbolStart) {
|
||||
return "";
|
||||
}
|
||||
|
||||
#elif !PPSSPP_PLATFORM(WINDOWS) && (PPSSPP_ARCH(AMD64) || PPSSPP_ARCH(ARM64) || PPSSPP_ARCH(ARM)) && (defined(__APPLE__) || defined(__linux__))
|
||||
#elif !PPSSPP_PLATFORM(WINDOWS) && (((PPSSPP_ARCH(AMD64) || PPSSPP_ARCH(ARM64) || PPSSPP_ARCH(ARM)) && (defined(__APPLE__) || defined(__linux__))) || ((PPSSPP_ARCH(RISCV64) || PPSSPP_ARCH(LOONGARCH64)) && defined(__linux__)))
|
||||
|
||||
static pthread_t g_target;
|
||||
static struct sigaction g_oldAction;
|
||||
@@ -140,6 +140,12 @@ static void SignalHandler(int, siginfo_t *, void *context) {
|
||||
#elif PPSSPP_ARCH(ARM)
|
||||
pc = (uintptr_t)uc->uc_mcontext.arm_pc;
|
||||
caller = (uintptr_t)uc->uc_mcontext.arm_lr;
|
||||
#elif PPSSPP_ARCH(RISCV64)
|
||||
pc = (uintptr_t)uc->uc_mcontext.__gregs[REG_PC];
|
||||
caller = (uintptr_t)uc->uc_mcontext.__gregs[REG_RA];
|
||||
#elif PPSSPP_ARCH(LOONGARCH64)
|
||||
pc = (uintptr_t)uc->uc_mcontext.__pc;
|
||||
caller = (uintptr_t)uc->uc_mcontext.__gregs[1]; // ra
|
||||
#endif
|
||||
Record(pc, caller);
|
||||
}
|
||||
|
||||
@@ -246,4 +246,17 @@ void LoongArch64JitBackend::GenerateFixedCode(MIPSState *mipsState) {
|
||||
EndWrite();
|
||||
}
|
||||
|
||||
void LoongArch64JitBackend::GetFixedCodeLabels(std::vector<IRNativeFixedCodeLabel> &labels) const {
|
||||
labels.push_back({ outerLoop_, "outerLoop", false });
|
||||
labels.push_back({ outerLoopPCInSCRATCH1_, "outerLoopPCInSCRATCH1", false });
|
||||
labels.push_back({ dispatcherCheckCoreState_, "dispatcherCheckCoreState", false });
|
||||
labels.push_back({ dispatcherPCInSCRATCH1_, "dispatcherPCInSCRATCH1", false });
|
||||
labels.push_back({ dispatcherNoCheck_, "dispatcherNoCheck", false });
|
||||
labels.push_back({ applyRoundingMode_, "applyRoundingMode", true });
|
||||
labels.push_back({ saveStaticRegisters_, "saveStaticRegisters", true });
|
||||
labels.push_back({ loadStaticRegisters_, "loadStaticRegisters", true });
|
||||
labels.push_back({ vfpuDot_, "vfpuDot", true });
|
||||
labels.push_back({ vfpuDotSpecial_, "vfpuDotSpecial", true });
|
||||
}
|
||||
|
||||
} // namespace MIPSComp
|
||||
@@ -41,6 +41,8 @@ public:
|
||||
void InvalidateBlock(IRBlockCache *irBlockCache, int block_num) override;
|
||||
|
||||
protected:
|
||||
void GetFixedCodeLabels(std::vector<IRNativeFixedCodeLabel> &labels) const override;
|
||||
|
||||
const CodeBlockCommon &CodeBlock() const override {
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -259,4 +259,17 @@ void RiscVJitBackend::GenerateFixedCode(MIPSState *mipsState) {
|
||||
EndWrite();
|
||||
}
|
||||
|
||||
void RiscVJitBackend::GetFixedCodeLabels(std::vector<IRNativeFixedCodeLabel> &labels) const {
|
||||
labels.push_back({ outerLoop_, "outerLoop", false });
|
||||
labels.push_back({ outerLoopPCInSCRATCH1_, "outerLoopPCInSCRATCH1", false });
|
||||
labels.push_back({ dispatcherCheckCoreState_, "dispatcherCheckCoreState", false });
|
||||
labels.push_back({ dispatcherPCInSCRATCH1_, "dispatcherPCInSCRATCH1", false });
|
||||
labels.push_back({ dispatcherNoCheck_, "dispatcherNoCheck", false });
|
||||
labels.push_back({ applyRoundingMode_, "applyRoundingMode", true });
|
||||
labels.push_back({ saveStaticRegisters_, "saveStaticRegisters", true });
|
||||
labels.push_back({ loadStaticRegisters_, "loadStaticRegisters", true });
|
||||
labels.push_back({ vfpuDot_, "vfpuDot", true });
|
||||
labels.push_back({ vfpuDotSpecial_, "vfpuDotSpecial", true });
|
||||
}
|
||||
|
||||
} // namespace MIPSComp
|
||||
@@ -41,6 +41,8 @@ public:
|
||||
void InvalidateBlock(IRBlockCache *irBlockCache, int block_num) override;
|
||||
|
||||
protected:
|
||||
void GetFixedCodeLabels(std::vector<IRNativeFixedCodeLabel> &labels) const override;
|
||||
|
||||
const CodeBlockCommon &CodeBlock() const override {
|
||||
return *this;
|
||||
}
|
||||
|
||||
+1
-1
@@ -266,7 +266,7 @@ goes away or clears its cache, appends a report to FILE:
|
||||
- the hot fixed-code routines, per instruction.
|
||||
|
||||
It costs nothing when off. The native JITs (macOS, Linux and Android by signal, Windows by
|
||||
`SuspendThread`) sample the host PC; the IR interpreter instead times every block, which used to be the
|
||||
`SuspendThread`; RISC-V and LoongArch on Linux only) sample the host PC; the IR interpreter instead times every block, which used to be the
|
||||
`IR_PROFILING` define. Short runs from a savestate include compiling everything after the load, which
|
||||
shows as emitter and IR pass functions; profile 20 emulated seconds or more to see the game itself.
|
||||
To compare two builds by where the time goes, profile one game at a time: several at once wait on each
|
||||
|
||||
Reference in new issue
Block a user