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/ARM64/Arm64Jit.h
Views: 1401
1
// Copyright (c) 2012- 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 "Common/CPUDetect.h"
21
#include "Common/ArmCommon.h"
22
#include "Common/Arm64Emitter.h"
23
#include "Core/MIPS/JitCommon/JitState.h"
24
#include "Core/MIPS/JitCommon/JitBlockCache.h"
25
#include "Core/MIPS/JitCommon/JitCommon.h"
26
#include "Core/MIPS/ARM64/Arm64RegCache.h"
27
#include "Core/MIPS/ARM64/Arm64RegCacheFPU.h"
28
#include "Core/MIPS/MIPSVFPUUtils.h"
29
30
#ifndef offsetof
31
#include "stddef.h"
32
#endif
33
34
namespace MIPSComp {
35
36
class Arm64Jit : public Arm64Gen::ARM64CodeBlock, public JitInterface, public MIPSFrontendInterface {
37
public:
38
Arm64Jit(MIPSState *mipsState);
39
virtual ~Arm64Jit();
40
41
void DoState(PointerWrap &p) override;
42
43
const JitOptions &GetJitOptions() { return jo; }
44
45
// Compiled ops should ignore delay slots
46
// the compiler will take care of them by itself
47
// OR NOT
48
void Comp_Generic(MIPSOpcode op) override;
49
50
void RunLoopUntil(u64 globalticks) override;
51
52
void Compile(u32 em_address) override; // Compiles a block at current MIPS PC
53
const u8 *DoJit(u32 em_address, JitBlock *b);
54
55
const u8 *GetCrashHandler() const override { return crashHandler; }
56
bool CodeInRange(const u8 *ptr) const override { return IsInSpace(ptr); }
57
bool DescribeCodePtr(const u8 *ptr, std::string &name) override;
58
MIPSOpcode GetOriginalOp(MIPSOpcode op) override;
59
60
void Comp_RunBlock(MIPSOpcode op) override;
61
void Comp_ReplacementFunc(MIPSOpcode op) override;
62
63
// Ops
64
void Comp_ITypeMem(MIPSOpcode op) override;
65
void Comp_StoreSync(MIPSOpcode op) override;
66
void Comp_Cache(MIPSOpcode op) override;
67
68
void Comp_RelBranch(MIPSOpcode op) override;
69
void Comp_RelBranchRI(MIPSOpcode op) override;
70
void Comp_FPUBranch(MIPSOpcode op) override;
71
void Comp_FPULS(MIPSOpcode op) override;
72
void Comp_FPUComp(MIPSOpcode op) override;
73
void Comp_Jump(MIPSOpcode op) override;
74
void Comp_JumpReg(MIPSOpcode op) override;
75
void Comp_Syscall(MIPSOpcode op) override;
76
void Comp_Break(MIPSOpcode op) override;
77
78
void Comp_IType(MIPSOpcode op) override;
79
void Comp_RType2(MIPSOpcode op) override;
80
void Comp_RType3(MIPSOpcode op) override;
81
void Comp_ShiftType(MIPSOpcode op) override;
82
void Comp_Allegrex(MIPSOpcode op) override;
83
void Comp_Allegrex2(MIPSOpcode op) override;
84
void Comp_VBranch(MIPSOpcode op) override;
85
void Comp_MulDivType(MIPSOpcode op) override;
86
void Comp_Special3(MIPSOpcode op) override;
87
88
void Comp_FPU3op(MIPSOpcode op) override;
89
void Comp_FPU2op(MIPSOpcode op) override;
90
void Comp_mxc1(MIPSOpcode op) override;
91
92
void Comp_DoNothing(MIPSOpcode op) override;
93
94
void Comp_SV(MIPSOpcode op) override;
95
void Comp_SVQ(MIPSOpcode op) override;
96
void Comp_VPFX(MIPSOpcode op) override;
97
void Comp_VVectorInit(MIPSOpcode op) override;
98
void Comp_VMatrixInit(MIPSOpcode op) override;
99
void Comp_VDot(MIPSOpcode op) override;
100
void Comp_VecDo3(MIPSOpcode op) override;
101
void Comp_VV2Op(MIPSOpcode op) override;
102
void Comp_Mftv(MIPSOpcode op) override;
103
void Comp_Vmfvc(MIPSOpcode op) override;
104
void Comp_Vmtvc(MIPSOpcode op) override;
105
void Comp_Vmmov(MIPSOpcode op) override;
106
void Comp_VScl(MIPSOpcode op) override;
107
void Comp_Vmmul(MIPSOpcode op) override;
108
void Comp_Vmscl(MIPSOpcode op) override;
109
void Comp_Vtfm(MIPSOpcode op) override;
110
void Comp_VHdp(MIPSOpcode op) override;
111
void Comp_VCrs(MIPSOpcode op) override;
112
void Comp_VDet(MIPSOpcode op) override;
113
void Comp_Vi2x(MIPSOpcode op) override;
114
void Comp_Vx2i(MIPSOpcode op) override;
115
void Comp_Vf2i(MIPSOpcode op) override;
116
void Comp_Vi2f(MIPSOpcode op) override;
117
void Comp_Vh2f(MIPSOpcode op) override;
118
void Comp_Vcst(MIPSOpcode op) override;
119
void Comp_Vhoriz(MIPSOpcode op) override;
120
void Comp_VRot(MIPSOpcode op) override;
121
void Comp_VIdt(MIPSOpcode op) override;
122
void Comp_Vcmp(MIPSOpcode op) override;
123
void Comp_Vcmov(MIPSOpcode op) override;
124
void Comp_Viim(MIPSOpcode op) override;
125
void Comp_Vfim(MIPSOpcode op) override;
126
void Comp_VCrossQuat(MIPSOpcode op) override;
127
void Comp_Vsgn(MIPSOpcode op) override;
128
void Comp_Vocp(MIPSOpcode op) override;
129
void Comp_ColorConv(MIPSOpcode op) override;
130
void Comp_Vbfy(MIPSOpcode op) override;
131
132
// Non-NEON: VPFX
133
134
// NEON implementations of the VFPU ops.
135
void CompNEON_SV(MIPSOpcode op);
136
void CompNEON_SVQ(MIPSOpcode op);
137
void CompNEON_VVectorInit(MIPSOpcode op);
138
void CompNEON_VMatrixInit(MIPSOpcode op);
139
void CompNEON_VDot(MIPSOpcode op);
140
void CompNEON_VecDo3(MIPSOpcode op);
141
void CompNEON_VV2Op(MIPSOpcode op);
142
void CompNEON_Mftv(MIPSOpcode op);
143
void CompNEON_Vmfvc(MIPSOpcode op);
144
void CompNEON_Vmtvc(MIPSOpcode op);
145
void CompNEON_Vmmov(MIPSOpcode op);
146
void CompNEON_VScl(MIPSOpcode op);
147
void CompNEON_Vmmul(MIPSOpcode op);
148
void CompNEON_Vmscl(MIPSOpcode op);
149
void CompNEON_Vtfm(MIPSOpcode op);
150
void CompNEON_VHdp(MIPSOpcode op);
151
void CompNEON_VCrs(MIPSOpcode op);
152
void CompNEON_VDet(MIPSOpcode op);
153
void CompNEON_Vi2x(MIPSOpcode op);
154
void CompNEON_Vx2i(MIPSOpcode op);
155
void CompNEON_Vf2i(MIPSOpcode op);
156
void CompNEON_Vi2f(MIPSOpcode op);
157
void CompNEON_Vh2f(MIPSOpcode op);
158
void CompNEON_Vcst(MIPSOpcode op);
159
void CompNEON_Vhoriz(MIPSOpcode op);
160
void CompNEON_VRot(MIPSOpcode op);
161
void CompNEON_VIdt(MIPSOpcode op);
162
void CompNEON_Vcmp(MIPSOpcode op);
163
void CompNEON_Vcmov(MIPSOpcode op);
164
void CompNEON_Viim(MIPSOpcode op);
165
void CompNEON_Vfim(MIPSOpcode op);
166
void CompNEON_VCrossQuat(MIPSOpcode op);
167
void CompNEON_Vsgn(MIPSOpcode op);
168
void CompNEON_Vocp(MIPSOpcode op);
169
void CompNEON_ColorConv(MIPSOpcode op);
170
void CompNEON_Vbfy(MIPSOpcode op);
171
172
int Replace_fabsf() override;
173
174
JitBlockCache *GetBlockCache() override { return &blocks; }
175
JitBlockCacheDebugInterface *GetBlockCacheDebugInterface() override { return &blocks; }
176
177
std::vector<u32> SaveAndClearEmuHackOps() override { return blocks.SaveAndClearEmuHackOps(); }
178
void RestoreSavedEmuHackOps(std::vector<u32> saved) override { blocks.RestoreSavedEmuHackOps(saved); }
179
180
void ClearCache() override;
181
void InvalidateCacheAt(u32 em_address, int length = 4) override;
182
void UpdateFCR31() override;
183
184
void EatPrefix() override { js.EatPrefix(); }
185
186
const u8 *GetDispatcher() const override {
187
return dispatcher;
188
}
189
bool IsAtDispatchFetch(const u8 *ptr) const override {
190
return ptr == dispatcherFetch;
191
}
192
193
void LinkBlock(u8 *exitPoint, const u8 *checkedEntry) override;
194
void UnlinkBlock(u8 *checkedEntry, u32 originalAddress) override;
195
196
private:
197
void GenerateFixedCode(const JitOptions &jo);
198
void FlushAll();
199
void FlushPrefixV();
200
201
u32 GetCompilerPC();
202
void CompileDelaySlot(int flags);
203
void EatInstruction(MIPSOpcode op);
204
void AddContinuedBlock(u32 dest);
205
MIPSOpcode GetOffsetInstruction(int offset);
206
207
void WriteDownCount(int offset = 0, bool updateFlags = true);
208
void WriteDownCountR(Arm64Gen::ARM64Reg reg, bool updateFlags = true);
209
void RestoreRoundingMode(bool force = false);
210
void ApplyRoundingMode(bool force = false);
211
void UpdateRoundingMode(u32 fcr31 = -1);
212
void MovFromPC(Arm64Gen::ARM64Reg r);
213
void MovToPC(Arm64Gen::ARM64Reg r);
214
215
bool ReplaceJalTo(u32 dest);
216
217
// Clobbers SCRATCH2.
218
void SaveStaticRegisters();
219
// Clobbers SCRATCH2.
220
void LoadStaticRegisters();
221
222
void WriteExit(u32 destination, int exit_num);
223
void WriteExitDestInR(Arm64Gen::ARM64Reg Reg);
224
void WriteSyscallExit();
225
bool CheckJitBreakpoint(u32 addr, int downcountOffset);
226
bool CheckMemoryBreakpoint(int instructionOffset = 0);
227
228
// Utility compilation functions
229
void BranchFPFlag(MIPSOpcode op, CCFlags cc, bool likely);
230
void BranchVFPUFlag(MIPSOpcode op, CCFlags cc, bool likely);
231
void BranchRSZeroComp(MIPSOpcode op, CCFlags cc, bool andLink, bool likely);
232
void BranchRSRTComp(MIPSOpcode op, CCFlags cc, bool likely);
233
234
// Utilities to reduce duplicated code
235
void CompImmLogic(MIPSGPReg rs, MIPSGPReg rt, u32 uimm, void (ARM64XEmitter::*arith)(Arm64Gen::ARM64Reg dst, Arm64Gen::ARM64Reg src, Arm64Gen::ARM64Reg src2), bool (ARM64XEmitter::*tryArithI2R)(Arm64Gen::ARM64Reg dst, Arm64Gen::ARM64Reg src, u64 val), u32 (*eval)(u32 a, u32 b));
236
void CompType3(MIPSGPReg rd, MIPSGPReg rs, MIPSGPReg rt, void (ARM64XEmitter::*arithOp2)(Arm64Gen::ARM64Reg dst, Arm64Gen::ARM64Reg rm, Arm64Gen::ARM64Reg rn), bool (ARM64XEmitter::*tryArithI2R)(Arm64Gen::ARM64Reg dst, Arm64Gen::ARM64Reg rm, u64 val), u32 (*eval)(u32 a, u32 b), bool symmetric = false);
237
void CompShiftImm(MIPSOpcode op, Arm64Gen::ShiftType shiftType, int sa);
238
void CompShiftVar(MIPSOpcode op, Arm64Gen::ShiftType shiftType);
239
void CompVrotShuffle(u8 *dregs, int imm, VectorSize sz, bool negSin);
240
241
void ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz);
242
void ApplyPrefixD(const u8 *vregs, VectorSize sz);
243
void GetVectorRegsPrefixS(u8 *regs, VectorSize sz, int vectorReg) {
244
_assert_(js.prefixSFlag & JitState::PREFIX_KNOWN);
245
GetVectorRegs(regs, sz, vectorReg);
246
ApplyPrefixST(regs, js.prefixS, sz);
247
}
248
void GetVectorRegsPrefixT(u8 *regs, VectorSize sz, int vectorReg) {
249
_assert_(js.prefixTFlag & JitState::PREFIX_KNOWN);
250
GetVectorRegs(regs, sz, vectorReg);
251
ApplyPrefixST(regs, js.prefixT, sz);
252
}
253
void GetVectorRegsPrefixD(u8 *regs, VectorSize sz, int vectorReg);
254
255
// Utils
256
void SetScratch1ToEffectiveAddress(MIPSGPReg rs, s16 offset);
257
std::vector<Arm64Gen::FixupBranch> SetScratch1ForSafeAddress(MIPSGPReg rs, s16 offset, Arm64Gen::ARM64Reg tempReg);
258
void Comp_ITypeMemLR(MIPSOpcode op, bool load);
259
260
JitBlockCache blocks;
261
JitOptions jo;
262
JitState js;
263
264
Arm64RegCache gpr;
265
Arm64RegCacheFPU fpr;
266
267
Arm64Gen::ARM64FloatEmitter fp;
268
269
MIPSState *mips_;
270
271
int dontLogBlocks;
272
int logBlocks;
273
274
public:
275
// Code pointers
276
const u8 *enterDispatcher;
277
278
const u8 *outerLoop;
279
const u8 *outerLoopPCInSCRATCH1;
280
const u8 *dispatcherCheckCoreState;
281
const u8 *dispatcherPCInSCRATCH1;
282
const u8 *dispatcher;
283
const u8 *dispatcherNoCheck;
284
const u8 *dispatcherFetch;
285
286
const u8 *saveStaticRegisters;
287
const u8 *loadStaticRegisters;
288
289
const u8 *restoreRoundingMode;
290
const u8 *applyRoundingMode;
291
const u8 *updateRoundingMode;
292
293
const u8 *crashHandler;
294
295
int jitStartOffset;
296
297
// Indexed by FPCR FZ:RN bits for convenience. Uses SCRATCH2.
298
const u8 *convertS0ToSCRATCH1[8];
299
};
300
301
} // namespace MIPSComp
302
303
304