mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 17:45:11 +02:00
213 lines
7.0 KiB
C++
213 lines
7.0 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 "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;
|
|
|
|
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_VecClamp(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;
|
|
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;
|
|
|
|
IRNativeBackend *backend_ = nullptr;
|
|
IRNativeHooks hooks_;
|
|
IRNativeBlockCacheDebugInterface debugInterface_;
|
|
};
|
|
|
|
} // namespace MIPSComp
|