mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-17 16:30:30 +02:00
FakeJit was the native JIT for architectures without one, but the config already forces those onto the IR interpreter, so CreateNativeJit() now returns that instead. The vertex decoder fallback no longer needs FakeEmitter. JitBlockCache was the block cache of the pre-IR JITs. Its header keeps the debug interface types the IR block caches use. Also removes the JitInterface link hooks only it called, and the JitState fields tied to it. This fixes a null dereference in the ImDebugger memory section, which read GetBlockCache(), always null with the IR JITs. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
217 lines
7.3 KiB
C++
217 lines
7.3 KiB
C++
// Copyright (c) 2023- PPSSPP Project.
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, version 2.0 or later versions.
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License 2.0 for more details.
|
|
|
|
// A copy of the GPL 2.0 should have been included with the program.
|
|
// If not, see http://www.gnu.org/licenses/
|
|
|
|
// Official git repository and contact information can be found at
|
|
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
|
|
|
#pragma once
|
|
|
|
#include <unordered_map>
|
|
|
|
#include "Common/CodeBlock.h"
|
|
#include "Core/MIPS/IR/IRJit.h"
|
|
#include "Core/MIPS/JitCommon/JitBlockCache.h"
|
|
|
|
namespace MIPSComp {
|
|
|
|
typedef void (*IRNativeFuncNoArg)();
|
|
|
|
enum class IRProfilerStatus : int32_t {
|
|
NOT_RUNNING,
|
|
IN_JIT,
|
|
TIMER_ADVANCE,
|
|
COMPILING,
|
|
MATH_HELPER,
|
|
REPLACEMENT,
|
|
SYSCALL,
|
|
INTERPRET,
|
|
IR_INTERPRET,
|
|
};
|
|
|
|
struct IRNativeHooks {
|
|
IRNativeFuncNoArg enterDispatcher = nullptr;
|
|
|
|
const uint8_t *dispatcher = nullptr;
|
|
const uint8_t *dispatchFetch = nullptr;
|
|
const uint8_t *crashHandler = nullptr;
|
|
// The dispatcher's compile path, where a replacement hook's block shadow entry goes.
|
|
const uint8_t *blockShadowHook = nullptr;
|
|
|
|
uint32_t *profilerPC = nullptr;
|
|
IRProfilerStatus *profilerStatus = nullptr;
|
|
};
|
|
|
|
struct IRNativeBlockExit {
|
|
int offset;
|
|
int len;
|
|
uint32_t dest;
|
|
};
|
|
|
|
struct IRNativeBlock {
|
|
int checkedOffset = 0;
|
|
std::vector<IRNativeBlockExit> exits;
|
|
};
|
|
|
|
class IRNativeBackend {
|
|
public:
|
|
IRNativeBackend(IRBlockCache &blocks);
|
|
virtual ~IRNativeBackend();
|
|
|
|
void CompileIRInst(IRInst inst);
|
|
|
|
virtual bool DescribeCodePtr(const u8 *ptr, std::string &name) const;
|
|
bool CodeInRange(const u8 *ptr) const;
|
|
int OffsetFromCodePtr(const u8 *ptr);
|
|
|
|
virtual void GenerateFixedCode(MIPSState *mipsState) = 0;
|
|
virtual bool CompileBlock(IRBlockCache *irBlockCache, int block_num) = 0;
|
|
virtual void ClearAllBlocks() = 0;
|
|
virtual void InvalidateBlock(IRBlockCache *irBlockCache, int block_num) = 0;
|
|
void FinalizeBlock(IRBlockCache *irBlockCache, int block_num, const JitOptions &jo);
|
|
|
|
virtual void UpdateFCR31(MIPSState *mipsState) {}
|
|
|
|
const IRNativeHooks &GetNativeHooks() const {
|
|
return hooks_;
|
|
}
|
|
|
|
const IRNativeBlock *GetNativeBlock(int block_num) const;
|
|
void SetBlockCheckedOffset(int block_num, int offset);
|
|
|
|
virtual const CodeBlockCommon &CodeBlock() const = 0;
|
|
|
|
protected:
|
|
virtual void CompIR_Arith(IRInst inst) = 0;
|
|
virtual void CompIR_Assign(IRInst inst) = 0;
|
|
virtual void CompIR_Basic(IRInst inst) = 0;
|
|
virtual void CompIR_Bits(IRInst inst) = 0;
|
|
virtual void CompIR_Breakpoint(IRInst inst) = 0;
|
|
virtual void CompIR_Compare(IRInst inst) = 0;
|
|
virtual void CompIR_CondAssign(IRInst inst) = 0;
|
|
virtual void CompIR_CondStore(IRInst inst) = 0;
|
|
virtual void CompIR_Div(IRInst inst) = 0;
|
|
virtual void CompIR_Exit(IRInst inst) = 0;
|
|
virtual void CompIR_ExitIf(IRInst inst) = 0;
|
|
virtual void CompIR_FArith(IRInst inst) = 0;
|
|
virtual void CompIR_FAssign(IRInst inst) = 0;
|
|
virtual void CompIR_FCompare(IRInst inst) = 0;
|
|
virtual void CompIR_FCondAssign(IRInst inst) = 0;
|
|
virtual void CompIR_FCvt(IRInst inst) = 0;
|
|
virtual void CompIR_FLoad(IRInst inst) = 0;
|
|
virtual void CompIR_FRound(IRInst inst) = 0;
|
|
virtual void CompIR_FSat(IRInst inst) = 0;
|
|
virtual void CompIR_FSpecial(IRInst inst) = 0;
|
|
virtual void CompIR_FStore(IRInst inst) = 0;
|
|
virtual void CompIR_Generic(IRInst inst) = 0;
|
|
virtual void CompIR_HiLo(IRInst inst) = 0;
|
|
virtual void CompIR_Interpret(IRInst inst) = 0;
|
|
virtual void CompIR_Load(IRInst inst) = 0;
|
|
virtual void CompIR_LoadShift(IRInst inst) = 0;
|
|
virtual void CompIR_Logic(IRInst inst) = 0;
|
|
virtual void CompIR_Mult(IRInst inst) = 0;
|
|
virtual void CompIR_RoundingMode(IRInst inst) = 0;
|
|
virtual void CompIR_Shift(IRInst inst) = 0;
|
|
virtual void CompIR_Store(IRInst inst) = 0;
|
|
virtual void CompIR_StoreShift(IRInst inst) = 0;
|
|
virtual void CompIR_System(IRInst inst) = 0;
|
|
virtual void CompIR_Transfer(IRInst inst) = 0;
|
|
virtual void CompIR_VecArith(IRInst inst) = 0;
|
|
virtual void CompIR_VecAssign(IRInst inst) = 0;
|
|
virtual void CompIR_VecHoriz(IRInst inst) = 0;
|
|
virtual void CompIR_VecLoad(IRInst inst) = 0;
|
|
virtual void CompIR_VecPack(IRInst inst) = 0;
|
|
virtual void CompIR_VecStore(IRInst inst) = 0;
|
|
virtual void CompIR_ValidateAddress(IRInst inst) = 0;
|
|
|
|
virtual void OverwriteExit(int srcOffset, int len, int block_num) = 0;
|
|
|
|
// Returns true when debugging statistics should be compiled in.
|
|
bool DebugStatsEnabled() const;
|
|
bool DebugProfilerEnabled() const;
|
|
|
|
// Callback (compile when DebugStatsEnabled()) to log a base interpreter hit.
|
|
// Call the func returned by MIPSGetInterpretFunc(op) directly for interpret.
|
|
static void NotifyMIPSInterpret(const char *name);
|
|
|
|
// Callback to log AND perform a base interpreter op. Alternative to NotifyMIPSInterpret().
|
|
static void DoMIPSInst(uint32_t op);
|
|
|
|
// Callback to log AND perform an IR interpreter inst. Returns 0 or a PC to jump to.
|
|
static uint32_t DoIRInst(uint64_t inst);
|
|
|
|
static int ReportBadAddress(uint32_t addr, uint32_t alignment, uint32_t isWrite);
|
|
|
|
void AddLinkableExit(int block_num, uint32_t pc, int exitStartOffset, int exitLen);
|
|
void EraseAllLinks(int block_num);
|
|
|
|
IRNativeHooks hooks_;
|
|
IRBlockCache &blocks_;
|
|
std::vector<IRNativeBlock> nativeBlocks_;
|
|
std::unordered_multimap<uint32_t, int> linksTo_;
|
|
};
|
|
|
|
class IRNativeBlockCacheDebugInterface : public JitBlockCacheDebugInterface {
|
|
public:
|
|
IRNativeBlockCacheDebugInterface(const MIPSComp::IRBlockCache &irBlocks);
|
|
void Init(const IRNativeBackend *backend);
|
|
int GetNumBlocks() const override;
|
|
int GetBlockNumberFromStartAddress(u32 em_address) const override;
|
|
JitBlockDebugInfo GetBlockDebugInfo(int blockNum) const override;
|
|
JitBlockMeta GetBlockMeta(int blockNum) const override;
|
|
JitBlockProfileStats GetBlockProfileStats(int blockNum) const override;
|
|
void ComputeStats(BlockCacheStats &bcStats) const override;
|
|
bool IsValidBlock(int blockNum) const override;
|
|
|
|
private:
|
|
void GetBlockCodeRange(int blockNum, int *startOffset, int *size) const;
|
|
|
|
const MIPSComp::IRBlockCache &irBlocks_;
|
|
const CodeBlockCommon *codeBlock_ = nullptr;
|
|
const IRNativeBackend *backend_ = nullptr;
|
|
};
|
|
|
|
class IRNativeJit : public IRJit {
|
|
public:
|
|
IRNativeJit(MIPSState *mipsState);
|
|
|
|
void RunLoopUntil(u64 globalticks) override;
|
|
|
|
void ClearCache() override;
|
|
|
|
bool DescribeCodePtr(const u8 *ptr, std::string &name) override;
|
|
bool CodeInRange(const u8 *ptr) const override;
|
|
bool IsAtDispatchFetch(const u8 *ptr) const override;
|
|
u32 GetBlockShadowHookValue() const override;
|
|
const u8 *GetDispatcher() const override;
|
|
const u8 *GetCrashHandler() const override;
|
|
|
|
void UpdateFCR31() override;
|
|
|
|
JitBlockCacheDebugInterface *GetBlockCacheDebugInterface() override;
|
|
|
|
const u8 *GetCodeBase() const override;
|
|
|
|
protected:
|
|
void Init(IRNativeBackend &backend);
|
|
bool CompileNativeBlock(IRBlockCache *irBlockCache, int block_num) override;
|
|
void FinalizeNativeBlock(IRBlockCache *irBlockCache, int block_num) override;
|
|
void InvalidateNativeBlock(IRBlockCache *irBlockCache, int block_num) override;
|
|
|
|
IRNativeBackend *backend_ = nullptr;
|
|
IRNativeHooks hooks_;
|
|
IRNativeBlockCacheDebugInterface debugInterface_;
|
|
};
|
|
|
|
} // namespace MIPSComp
|