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/ARM/ArmJit.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/ArmEmitter.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/ARM/ArmRegCache.h"
27
#include "Core/MIPS/ARM/ArmRegCacheFPU.h"
28
#include "Core/MIPS/MIPSVFPUUtils.h"
29
30
#ifndef offsetof
31
#include "stddef.h"
32
#endif
33
34
namespace MIPSComp {
35
36
class ArmJit : public ArmGen::ARMXCodeBlock, public JitInterface, public MIPSFrontendInterface {
37
public:
38
ArmJit(MIPSState *mipsState);
39
virtual ~ArmJit();
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
54
const u8 *GetCrashHandler() const override { return crashHandler; }
55
bool CodeInRange(const u8 *ptr) const override { return IsInSpace(ptr); }
56
bool DescribeCodePtr(const u8 *ptr, std::string &name) override;
57
MIPSOpcode GetOriginalOp(MIPSOpcode op) override;
58
59
void Comp_RunBlock(MIPSOpcode op) override;
60
void Comp_ReplacementFunc(MIPSOpcode op) override;
61
62
// Ops
63
void Comp_ITypeMem(MIPSOpcode op) override;
64
void Comp_StoreSync(MIPSOpcode op) override;
65
void Comp_Cache(MIPSOpcode op) override;
66
67
void Comp_RelBranch(MIPSOpcode op) override;
68
void Comp_RelBranchRI(MIPSOpcode op) override;
69
void Comp_FPUBranch(MIPSOpcode op) override;
70
void Comp_FPULS(MIPSOpcode op) override;
71
void Comp_FPUComp(MIPSOpcode op) override;
72
void Comp_Jump(MIPSOpcode op) override;
73
void Comp_JumpReg(MIPSOpcode op) override;
74
void Comp_Syscall(MIPSOpcode op) override;
75
void Comp_Break(MIPSOpcode op) override;
76
77
void Comp_IType(MIPSOpcode op) override;
78
void Comp_RType2(MIPSOpcode op) override;
79
void Comp_RType3(MIPSOpcode op) override;
80
void Comp_ShiftType(MIPSOpcode op) override;
81
void Comp_Allegrex(MIPSOpcode op) override;
82
void Comp_Allegrex2(MIPSOpcode op) override;
83
void Comp_VBranch(MIPSOpcode op) override;
84
void Comp_MulDivType(MIPSOpcode op) override;
85
void Comp_Special3(MIPSOpcode op) override;
86
87
void Comp_FPU3op(MIPSOpcode op) override;
88
void Comp_FPU2op(MIPSOpcode op) override;
89
void Comp_mxc1(MIPSOpcode op) override;
90
91
void Comp_DoNothing(MIPSOpcode op) override;
92
93
void Comp_SV(MIPSOpcode op) override;
94
void Comp_SVQ(MIPSOpcode op) override;
95
void Comp_VPFX(MIPSOpcode op) override;
96
void Comp_VVectorInit(MIPSOpcode op) override;
97
void Comp_VMatrixInit(MIPSOpcode op) override;
98
void Comp_VDot(MIPSOpcode op) override;
99
void Comp_VecDo3(MIPSOpcode op) override;
100
void Comp_VV2Op(MIPSOpcode op) override;
101
void Comp_Mftv(MIPSOpcode op) override;
102
void Comp_Vmfvc(MIPSOpcode op) override;
103
void Comp_Vmtvc(MIPSOpcode op) override;
104
void Comp_Vmmov(MIPSOpcode op) override;
105
void Comp_VScl(MIPSOpcode op) override;
106
void Comp_Vmmul(MIPSOpcode op) override;
107
void Comp_Vmscl(MIPSOpcode op) override;
108
void Comp_Vtfm(MIPSOpcode op) override;
109
void Comp_VHdp(MIPSOpcode op) override;
110
void Comp_VCrs(MIPSOpcode op) override;
111
void Comp_VDet(MIPSOpcode op) override;
112
void Comp_Vi2x(MIPSOpcode op) override;
113
void Comp_Vx2i(MIPSOpcode op) override;
114
void Comp_Vf2i(MIPSOpcode op) override;
115
void Comp_Vi2f(MIPSOpcode op) override;
116
void Comp_Vh2f(MIPSOpcode op) override;
117
void Comp_Vcst(MIPSOpcode op) override;
118
void Comp_Vhoriz(MIPSOpcode op) override;
119
void Comp_VRot(MIPSOpcode op) override;
120
void Comp_VIdt(MIPSOpcode op) override;
121
void Comp_Vcmp(MIPSOpcode op) override;
122
void Comp_Vcmov(MIPSOpcode op) override;
123
void Comp_Viim(MIPSOpcode op) override;
124
void Comp_Vfim(MIPSOpcode op) override;
125
void Comp_VCrossQuat(MIPSOpcode op) override;
126
void Comp_Vsgn(MIPSOpcode op) override;
127
void Comp_Vocp(MIPSOpcode op) override;
128
void Comp_ColorConv(MIPSOpcode op) override;
129
void Comp_Vbfy(MIPSOpcode op) override;
130
131
// Non-NEON: VPFX
132
133
// NEON implementations of the VFPU ops.
134
void CompNEON_SV(MIPSOpcode op);
135
void CompNEON_SVQ(MIPSOpcode op);
136
void CompNEON_VVectorInit(MIPSOpcode op);
137
void CompNEON_VMatrixInit(MIPSOpcode op);
138
void CompNEON_VDot(MIPSOpcode op);
139
void CompNEON_VecDo3(MIPSOpcode op);
140
void CompNEON_VV2Op(MIPSOpcode op);
141
void CompNEON_Mftv(MIPSOpcode op);
142
void CompNEON_Vmfvc(MIPSOpcode op);
143
void CompNEON_Vmtvc(MIPSOpcode op);
144
void CompNEON_Vmmov(MIPSOpcode op);
145
void CompNEON_VScl(MIPSOpcode op);
146
void CompNEON_Vmmul(MIPSOpcode op);
147
void CompNEON_Vmscl(MIPSOpcode op);
148
void CompNEON_Vtfm(MIPSOpcode op);
149
void CompNEON_VHdp(MIPSOpcode op);
150
void CompNEON_VCrs(MIPSOpcode op);
151
void CompNEON_VDet(MIPSOpcode op);
152
void CompNEON_Vi2x(MIPSOpcode op);
153
void CompNEON_Vx2i(MIPSOpcode op);
154
void CompNEON_Vf2i(MIPSOpcode op);
155
void CompNEON_Vi2f(MIPSOpcode op);
156
void CompNEON_Vh2f(MIPSOpcode op);
157
void CompNEON_Vcst(MIPSOpcode op);
158
void CompNEON_Vhoriz(MIPSOpcode op);
159
void CompNEON_VRot(MIPSOpcode op);
160
void CompNEON_VIdt(MIPSOpcode op);
161
void CompNEON_Vcmp(MIPSOpcode op);
162
void CompNEON_Vcmov(MIPSOpcode op);
163
void CompNEON_Viim(MIPSOpcode op);
164
void CompNEON_Vfim(MIPSOpcode op);
165
void CompNEON_VCrossQuat(MIPSOpcode op);
166
void CompNEON_Vsgn(MIPSOpcode op);
167
void CompNEON_Vocp(MIPSOpcode op);
168
void CompNEON_ColorConv(MIPSOpcode op);
169
void CompNEON_Vbfy(MIPSOpcode op);
170
171
int Replace_fabsf() override;
172
173
JitBlockCache *GetBlockCache() override { return &blocks; }
174
JitBlockCacheDebugInterface *GetBlockCacheDebugInterface() override { return &blocks; }
175
176
std::vector<u32> SaveAndClearEmuHackOps() override { return blocks.SaveAndClearEmuHackOps(); }
177
void RestoreSavedEmuHackOps(std::vector<u32> saved) override { blocks.RestoreSavedEmuHackOps(saved); }
178
179
void ClearCache() override;
180
void InvalidateCacheAt(u32 em_address, int length = 4) override;
181
void UpdateFCR31() override;
182
183
void EatPrefix() override { js.EatPrefix(); }
184
185
const u8 *GetDispatcher() const override {
186
return dispatcher;
187
}
188
bool IsAtDispatchFetch(const u8 *ptr) const override {
189
return ptr == dispatcherFetch;
190
}
191
192
void LinkBlock(u8 *exitPoint, const u8 *checkedEntry) override;
193
void UnlinkBlock(u8 *checkedEntry, u32 originalAddress) override;
194
195
private:
196
const u8 *DoJit(u32 em_address, JitBlock *b);
197
198
void GenerateFixedCode();
199
void FlushAll();
200
void FlushPrefixV();
201
202
u32 GetCompilerPC();
203
void CompileDelaySlot(int flags);
204
void EatInstruction(MIPSOpcode op);
205
void AddContinuedBlock(u32 dest);
206
MIPSOpcode GetOffsetInstruction(int offset);
207
208
void WriteDownCount(int offset = 0);
209
void WriteDownCountR(ArmGen::ARMReg reg);
210
void RestoreRoundingMode(bool force = false);
211
void ApplyRoundingMode(bool force = false);
212
void UpdateRoundingMode(u32 fcr31 = -1);
213
void MovFromPC(ArmGen::ARMReg r);
214
void MovToPC(ArmGen::ARMReg r);
215
216
bool ReplaceJalTo(u32 dest);
217
218
void SaveDowncount();
219
void RestoreDowncount();
220
221
void WriteExit(u32 destination, int exit_num);
222
void WriteExitDestInR(ArmGen::ARMReg Reg);
223
void WriteSyscallExit();
224
bool CheckJitBreakpoint(u32 addr, int downcountOffset);
225
bool CheckMemoryBreakpoint(int instructionOffset = 0);
226
227
// Utility compilation functions
228
void BranchFPFlag(MIPSOpcode op, CCFlags cc, bool likely);
229
void BranchVFPUFlag(MIPSOpcode op, CCFlags cc, bool likely);
230
void BranchRSZeroComp(MIPSOpcode op, CCFlags cc, bool andLink, bool likely);
231
void BranchRSRTComp(MIPSOpcode op, CCFlags cc, bool likely);
232
233
// Utilities to reduce duplicated code
234
void CompImmLogic(MIPSGPReg rs, MIPSGPReg rt, u32 uimm, void (ARMXEmitter::*arith)(ArmGen::ARMReg dst, ArmGen::ARMReg src, ArmGen::Operand2 op2), bool (ARMXEmitter::*tryArithI2R)(ArmGen::ARMReg dst, ArmGen::ARMReg src, u32 val), u32 (*eval)(u32 a, u32 b));
235
void CompType3(MIPSGPReg rd, MIPSGPReg rs, MIPSGPReg rt, void (ARMXEmitter::*arithOp2)(ArmGen::ARMReg dst, ArmGen::ARMReg rm, ArmGen::Operand2 rn), bool (ARMXEmitter::*tryArithI2R)(ArmGen::ARMReg dst, ArmGen::ARMReg rm, u32 val), u32 (*eval)(u32 a, u32 b), bool symmetric = false);
236
237
void CompShiftImm(MIPSOpcode op, ArmGen::ShiftType shiftType, int sa);
238
void CompShiftVar(MIPSOpcode op, ArmGen::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
256
// For NEON mappings, it will be easier to deal directly in ARM registers.
257
258
ArmGen::ARMReg NEONMapPrefixST(int vfpuReg, VectorSize sz, u32 prefix, int mapFlags);
259
ArmGen::ARMReg NEONMapPrefixS(int vfpuReg, VectorSize sz, int mapFlags) {
260
return NEONMapPrefixST(vfpuReg, sz, js.prefixS, mapFlags);
261
}
262
ArmGen::ARMReg NEONMapPrefixT(int vfpuReg, VectorSize sz, int mapFlags) {
263
return NEONMapPrefixST(vfpuReg, sz, js.prefixT, mapFlags);
264
}
265
266
struct DestARMReg {
267
ArmGen::ARMReg rd;
268
ArmGen::ARMReg backingRd;
269
VectorSize sz;
270
271
operator ArmGen::ARMReg() const { return rd; }
272
};
273
274
struct MappedRegs {
275
ArmGen::ARMReg vs;
276
ArmGen::ARMReg vt;
277
DestARMReg vd;
278
bool overlap;
279
};
280
281
MappedRegs NEONMapDirtyInIn(MIPSOpcode op, VectorSize dsize, VectorSize ssize, VectorSize tsize, bool applyPrefixes = true);
282
MappedRegs NEONMapInIn(MIPSOpcode op, VectorSize ssize, VectorSize tsize, bool applyPrefixes = true);
283
MappedRegs NEONMapDirtyIn(MIPSOpcode op, VectorSize dsize, VectorSize ssize, bool applyPrefixes = true);
284
285
DestARMReg NEONMapPrefixD(int vfpuReg, VectorSize sz, int mapFlags);
286
void NEONApplyPrefixD(DestARMReg dest);
287
288
// NEON utils
289
void NEONMaskToSize(ArmGen::ARMReg vs, VectorSize sz);
290
void NEONTranspose4x4(ArmGen::ARMReg cols[4]);
291
292
// Utils
293
void SetR0ToEffectiveAddress(MIPSGPReg rs, s16 offset);
294
void SetCCAndR0ForSafeAddress(MIPSGPReg rs, s16 offset, ArmGen::ARMReg tempReg, bool reverse = false);
295
void Comp_ITypeMemLR(MIPSOpcode op, bool load);
296
297
JitBlockCache blocks;
298
JitOptions jo;
299
JitState js;
300
301
ArmRegCache gpr;
302
ArmRegCacheFPU fpr;
303
304
MIPSState *mips_;
305
306
int dontLogBlocks;
307
int logBlocks;
308
309
public:
310
// Code pointers
311
const u8 *enterDispatcher;
312
313
const u8 *outerLoop;
314
const u8 *outerLoopPCInR0;
315
const u8 *dispatcherCheckCoreState;
316
const u8 *dispatcherPCInR0;
317
const u8 *dispatcher;
318
const u8 *dispatcherFetch;
319
const u8 *dispatcherNoCheck;
320
321
const u8 *restoreRoundingMode;
322
const u8 *applyRoundingMode;
323
324
const u8 *crashHandler;
325
};
326
327
} // namespace MIPSComp
328
329
330