CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/Core/MIPS/IR/IRNativeCommon.h
Views: 1401
1
// Copyright (c) 2023- PPSSPP Project.
2
3
// This program is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, version 2.0 or later versions.
6
7
// This program is distributed in the hope that it will be useful,
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
// GNU General Public License 2.0 for more details.
11
12
// A copy of the GPL 2.0 should have been included with the program.
13
// If not, see http://www.gnu.org/licenses/
14
15
// Official git repository and contact information can be found at
16
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17
18
#pragma once
19
20
#include <unordered_map>
21
#include "Core/MIPS/IR/IRJit.h"
22
#include "Core/MIPS/JitCommon/JitBlockCache.h"
23
24
namespace MIPSComp {
25
26
typedef void (*IRNativeFuncNoArg)();
27
28
enum class IRProfilerStatus : int32_t {
29
NOT_RUNNING,
30
IN_JIT,
31
TIMER_ADVANCE,
32
COMPILING,
33
MATH_HELPER,
34
REPLACEMENT,
35
SYSCALL,
36
INTERPRET,
37
IR_INTERPRET,
38
};
39
40
struct IRNativeHooks {
41
IRNativeFuncNoArg enterDispatcher = nullptr;
42
43
const uint8_t *dispatcher = nullptr;
44
const uint8_t *dispatchFetch = nullptr;
45
const uint8_t *crashHandler = nullptr;
46
47
uint32_t *profilerPC = nullptr;
48
IRProfilerStatus *profilerStatus = nullptr;
49
};
50
51
struct IRNativeBlockExit {
52
int offset;
53
int len;
54
uint32_t dest;
55
};
56
57
struct IRNativeBlock {
58
int checkedOffset = 0;
59
std::vector<IRNativeBlockExit> exits;
60
};
61
62
class IRNativeBackend {
63
public:
64
IRNativeBackend(IRBlockCache &blocks);
65
virtual ~IRNativeBackend();
66
67
void CompileIRInst(IRInst inst);
68
69
virtual bool DescribeCodePtr(const u8 *ptr, std::string &name) const;
70
bool CodeInRange(const u8 *ptr) const;
71
int OffsetFromCodePtr(const u8 *ptr);
72
73
virtual void GenerateFixedCode(MIPSState *mipsState) = 0;
74
virtual bool CompileBlock(IRBlockCache *irBlockCache, int block_num, bool preload) = 0;
75
virtual void ClearAllBlocks() = 0;
76
virtual void InvalidateBlock(IRBlockCache *irBlockCache, int block_num) = 0;
77
void FinalizeBlock(IRBlockCache *irBlockCache, int block_num, const JitOptions &jo);
78
79
virtual void UpdateFCR31(MIPSState *mipsState) {}
80
81
const IRNativeHooks &GetNativeHooks() const {
82
return hooks_;
83
}
84
85
const IRNativeBlock *GetNativeBlock(int block_num) const;
86
void SetBlockCheckedOffset(int block_num, int offset);
87
88
virtual const CodeBlockCommon &CodeBlock() const = 0;
89
90
protected:
91
virtual void CompIR_Arith(IRInst inst) = 0;
92
virtual void CompIR_Assign(IRInst inst) = 0;
93
virtual void CompIR_Basic(IRInst inst) = 0;
94
virtual void CompIR_Bits(IRInst inst) = 0;
95
virtual void CompIR_Breakpoint(IRInst inst) = 0;
96
virtual void CompIR_Compare(IRInst inst) = 0;
97
virtual void CompIR_CondAssign(IRInst inst) = 0;
98
virtual void CompIR_CondStore(IRInst inst) = 0;
99
virtual void CompIR_Div(IRInst inst) = 0;
100
virtual void CompIR_Exit(IRInst inst) = 0;
101
virtual void CompIR_ExitIf(IRInst inst) = 0;
102
virtual void CompIR_FArith(IRInst inst) = 0;
103
virtual void CompIR_FAssign(IRInst inst) = 0;
104
virtual void CompIR_FCompare(IRInst inst) = 0;
105
virtual void CompIR_FCondAssign(IRInst inst) = 0;
106
virtual void CompIR_FCvt(IRInst inst) = 0;
107
virtual void CompIR_FLoad(IRInst inst) = 0;
108
virtual void CompIR_FRound(IRInst inst) = 0;
109
virtual void CompIR_FSat(IRInst inst) = 0;
110
virtual void CompIR_FSpecial(IRInst inst) = 0;
111
virtual void CompIR_FStore(IRInst inst) = 0;
112
virtual void CompIR_Generic(IRInst inst) = 0;
113
virtual void CompIR_HiLo(IRInst inst) = 0;
114
virtual void CompIR_Interpret(IRInst inst) = 0;
115
virtual void CompIR_Load(IRInst inst) = 0;
116
virtual void CompIR_LoadShift(IRInst inst) = 0;
117
virtual void CompIR_Logic(IRInst inst) = 0;
118
virtual void CompIR_Mult(IRInst inst) = 0;
119
virtual void CompIR_RoundingMode(IRInst inst) = 0;
120
virtual void CompIR_Shift(IRInst inst) = 0;
121
virtual void CompIR_Store(IRInst inst) = 0;
122
virtual void CompIR_StoreShift(IRInst inst) = 0;
123
virtual void CompIR_System(IRInst inst) = 0;
124
virtual void CompIR_Transfer(IRInst inst) = 0;
125
virtual void CompIR_VecArith(IRInst inst) = 0;
126
virtual void CompIR_VecAssign(IRInst inst) = 0;
127
virtual void CompIR_VecClamp(IRInst inst) = 0;
128
virtual void CompIR_VecHoriz(IRInst inst) = 0;
129
virtual void CompIR_VecLoad(IRInst inst) = 0;
130
virtual void CompIR_VecPack(IRInst inst) = 0;
131
virtual void CompIR_VecStore(IRInst inst) = 0;
132
virtual void CompIR_ValidateAddress(IRInst inst) = 0;
133
134
virtual void OverwriteExit(int srcOffset, int len, int block_num) = 0;
135
136
// Returns true when debugging statistics should be compiled in.
137
bool DebugStatsEnabled() const;
138
bool DebugProfilerEnabled() const;
139
140
// Callback (compile when DebugStatsEnabled()) to log a base interpreter hit.
141
// Call the func returned by MIPSGetInterpretFunc(op) directly for interpret.
142
static void NotifyMIPSInterpret(const char *name);
143
144
// Callback to log AND perform a base interpreter op. Alternative to NotifyMIPSInterpret().
145
static void DoMIPSInst(uint32_t op);
146
147
// Callback to log AND perform an IR interpreter inst. Returns 0 or a PC to jump to.
148
static uint32_t DoIRInst(uint64_t inst);
149
150
static int ReportBadAddress(uint32_t addr, uint32_t alignment, uint32_t isWrite);
151
152
void AddLinkableExit(int block_num, uint32_t pc, int exitStartOffset, int exitLen);
153
void EraseAllLinks(int block_num);
154
155
IRNativeHooks hooks_;
156
IRBlockCache &blocks_;
157
std::vector<IRNativeBlock> nativeBlocks_;
158
std::unordered_multimap<uint32_t, int> linksTo_;
159
};
160
161
class IRNativeBlockCacheDebugInterface : public JitBlockCacheDebugInterface {
162
public:
163
IRNativeBlockCacheDebugInterface(const MIPSComp::IRBlockCache &irBlocks);
164
void Init(const IRNativeBackend *backend);
165
int GetNumBlocks() const override;
166
int GetBlockNumberFromStartAddress(u32 em_address, bool realBlocksOnly = true) const override;
167
JitBlockDebugInfo GetBlockDebugInfo(int blockNum) const override;
168
JitBlockMeta GetBlockMeta(int blockNum) const override;
169
JitBlockProfileStats GetBlockProfileStats(int blockNum) const override;
170
void ComputeStats(BlockCacheStats &bcStats) const override;
171
bool IsValidBlock(int blockNum) const override;
172
173
private:
174
void GetBlockCodeRange(int blockNum, int *startOffset, int *size) const;
175
176
const MIPSComp::IRBlockCache &irBlocks_;
177
const CodeBlockCommon *codeBlock_ = nullptr;
178
const IRNativeBackend *backend_ = nullptr;
179
};
180
181
class IRNativeJit : public IRJit {
182
public:
183
IRNativeJit(MIPSState *mipsState);
184
185
void RunLoopUntil(u64 globalticks) override;
186
187
void ClearCache() override;
188
189
bool DescribeCodePtr(const u8 *ptr, std::string &name) override;
190
bool CodeInRange(const u8 *ptr) const override;
191
bool IsAtDispatchFetch(const u8 *ptr) const override;
192
const u8 *GetDispatcher() const override;
193
const u8 *GetCrashHandler() const override;
194
195
void UpdateFCR31() override;
196
197
JitBlockCacheDebugInterface *GetBlockCacheDebugInterface() override;
198
199
protected:
200
void Init(IRNativeBackend &backend);
201
bool CompileNativeBlock(IRBlockCache *irBlockCache, int block_num, bool preload) override;
202
void FinalizeNativeBlock(IRBlockCache *irBlockCache, int block_num) override;
203
204
IRNativeBackend *backend_ = nullptr;
205
IRNativeHooks hooks_;
206
IRNativeBlockCacheDebugInterface debugInterface_;
207
};
208
209
} // namespace MIPSComp
210
211