diff --git a/Core/MIPS/IR/IRNativeCommon.cpp b/Core/MIPS/IR/IRNativeCommon.cpp index 80bde869e4..c1e872f843 100644 --- a/Core/MIPS/IR/IRNativeCommon.cpp +++ b/Core/MIPS/IR/IRNativeCommon.cpp @@ -656,6 +656,23 @@ static std::vector 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 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 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); diff --git a/Core/MIPS/JitCommon/JitProfiler.cpp b/Core/MIPS/JitCommon/JitProfiler.cpp index 39de74091a..930de027a4 100644 --- a/Core/MIPS/JitCommon/JitProfiler.cpp +++ b/Core/MIPS/JitCommon/JitProfiler.cpp @@ -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); } diff --git a/Core/MIPS/LoongArch64/LoongArch64Asm.cpp b/Core/MIPS/LoongArch64/LoongArch64Asm.cpp index 342f9bcc21..ecddc3e40f 100644 --- a/Core/MIPS/LoongArch64/LoongArch64Asm.cpp +++ b/Core/MIPS/LoongArch64/LoongArch64Asm.cpp @@ -246,4 +246,17 @@ void LoongArch64JitBackend::GenerateFixedCode(MIPSState *mipsState) { EndWrite(); } +void LoongArch64JitBackend::GetFixedCodeLabels(std::vector &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 diff --git a/Core/MIPS/LoongArch64/LoongArch64Jit.h b/Core/MIPS/LoongArch64/LoongArch64Jit.h index 97209065aa..eb95d79736 100644 --- a/Core/MIPS/LoongArch64/LoongArch64Jit.h +++ b/Core/MIPS/LoongArch64/LoongArch64Jit.h @@ -41,6 +41,8 @@ public: void InvalidateBlock(IRBlockCache *irBlockCache, int block_num) override; protected: + void GetFixedCodeLabels(std::vector &labels) const override; + const CodeBlockCommon &CodeBlock() const override { return *this; } diff --git a/Core/MIPS/RiscV/RiscVAsm.cpp b/Core/MIPS/RiscV/RiscVAsm.cpp index fe079366eb..3ab7f23154 100644 --- a/Core/MIPS/RiscV/RiscVAsm.cpp +++ b/Core/MIPS/RiscV/RiscVAsm.cpp @@ -259,4 +259,17 @@ void RiscVJitBackend::GenerateFixedCode(MIPSState *mipsState) { EndWrite(); } +void RiscVJitBackend::GetFixedCodeLabels(std::vector &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 diff --git a/Core/MIPS/RiscV/RiscVJit.h b/Core/MIPS/RiscV/RiscVJit.h index 7c96cfa562..b5d7b3bed9 100644 --- a/Core/MIPS/RiscV/RiscVJit.h +++ b/Core/MIPS/RiscV/RiscVJit.h @@ -41,6 +41,8 @@ public: void InvalidateBlock(IRBlockCache *irBlockCache, int block_num) override; protected: + void GetFixedCodeLabels(std::vector &labels) const override; + const CodeBlockCommon &CodeBlock() const override { return *this; } diff --git a/docs/debugging.md b/docs/debugging.md index d6a417babb..ef3a967d45 100644 --- a/docs/debugging.md +++ b/docs/debugging.md @@ -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