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/ArmRegCache.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 "Core/MIPS/MIPS.h"
21
#include "ArmEmitter.h"
22
23
namespace ArmJitConstants {
24
25
const ArmGen::ARMReg JITBASEREG = ArmGen::R9;
26
const ArmGen::ARMReg CTXREG = ArmGen::R10;
27
const ArmGen::ARMReg MEMBASEREG = ArmGen::R11;
28
const ArmGen::ARMReg SCRATCHREG1 = ArmGen::R0;
29
const ArmGen::ARMReg SCRATCHREG2 = ArmGen::R14;
30
const ArmGen::ARMReg DOWNCOUNTREG = ArmGen::R7;
31
32
enum {
33
TOTAL_MAPPABLE_MIPSREGS = 36,
34
};
35
36
enum RegMIPSLoc {
37
ML_IMM,
38
ML_ARMREG,
39
// In an arm reg, but as a pre-adjusted pointer, not the actual reg.
40
ML_ARMREG_AS_PTR,
41
// In an arm reg, but also has a known immediate value.
42
ML_ARMREG_IMM,
43
ML_MEM,
44
};
45
46
// Initing is the default so the flag is reversed.
47
enum {
48
MAP_DIRTY = 1,
49
MAP_NOINIT = 2 | MAP_DIRTY,
50
};
51
52
}
53
54
namespace MIPSAnalyst {
55
struct AnalysisResults;
56
};
57
58
// R1 to R6: mapped MIPS regs
59
// R8 = flags (maybe we could do better here?)
60
// R9 = code pointers
61
// R10 = MIPS context
62
// R11 = base pointer
63
// R14 = scratch (actually LR)
64
65
66
typedef int MIPSReg;
67
68
struct RegARM {
69
MIPSGPReg mipsReg; // if -1, no mipsreg attached.
70
bool isDirty; // Should the register be written back?
71
};
72
73
struct RegMIPS {
74
// Where is this MIPS register?
75
ArmJitConstants::RegMIPSLoc loc;
76
// Data (both or only one may be used, depending on loc.)
77
u32 imm;
78
ArmGen::ARMReg reg; // reg index
79
bool spillLock; // if true, this register cannot be spilled.
80
// If loc == ML_MEM, it's back in its location in the CPU context struct.
81
};
82
83
namespace MIPSComp {
84
struct JitOptions;
85
struct JitState;
86
}
87
88
class ArmRegCache {
89
public:
90
ArmRegCache(MIPSState *mipsState, MIPSComp::JitState *js, MIPSComp::JitOptions *jo);
91
~ArmRegCache() {}
92
93
void Init(ArmGen::ARMXEmitter *emitter);
94
void Start(MIPSAnalyst::AnalysisResults &stats);
95
96
// Protect the arm register containing a MIPS register from spilling, to ensure that
97
// it's being kept allocated.
98
void SpillLock(MIPSGPReg reg, MIPSGPReg reg2 = MIPS_REG_INVALID, MIPSGPReg reg3 = MIPS_REG_INVALID, MIPSGPReg reg4 = MIPS_REG_INVALID);
99
void ReleaseSpillLock(MIPSGPReg reg);
100
void ReleaseSpillLocks();
101
102
void SetImm(MIPSGPReg reg, u32 immVal);
103
bool IsImm(MIPSGPReg reg) const;
104
u32 GetImm(MIPSGPReg reg) const;
105
// Optimally set a register to an imm value (possibly using another register.)
106
void SetRegImm(ArmGen::ARMReg reg, u32 imm);
107
108
// Returns an ARM register containing the requested MIPS register.
109
ArmGen::ARMReg MapReg(MIPSGPReg reg, int mapFlags = 0);
110
ArmGen::ARMReg MapRegAsPointer(MIPSGPReg reg); // read-only, non-dirty.
111
112
bool IsMapped(MIPSGPReg reg);
113
bool IsMappedAsPointer(MIPSGPReg reg);
114
115
void MapInIn(MIPSGPReg rd, MIPSGPReg rs);
116
void MapDirtyIn(MIPSGPReg rd, MIPSGPReg rs, bool avoidLoad = true);
117
void MapDirtyInIn(MIPSGPReg rd, MIPSGPReg rs, MIPSGPReg rt, bool avoidLoad = true);
118
void MapDirtyDirtyIn(MIPSGPReg rd1, MIPSGPReg rd2, MIPSGPReg rs, bool avoidLoad = true);
119
void MapDirtyDirtyInIn(MIPSGPReg rd1, MIPSGPReg rd2, MIPSGPReg rs, MIPSGPReg rt, bool avoidLoad = true);
120
void FlushArmReg(ArmGen::ARMReg r);
121
void FlushR(MIPSGPReg r);
122
void FlushBeforeCall();
123
void FlushAll();
124
void DiscardR(MIPSGPReg r);
125
126
ArmGen::ARMReg R(MIPSGPReg preg); // Returns a cached register, while checking that it's NOT mapped as a pointer
127
ArmGen::ARMReg RPtr(MIPSGPReg preg); // Returns a cached register, while checking that it's mapped as a pointer
128
129
void SetEmitter(ArmGen::ARMXEmitter *emitter) { emit_ = emitter; }
130
131
// For better log output only.
132
void SetCompilerPC(u32 compilerPC) { compilerPC_ = compilerPC; }
133
134
int GetMipsRegOffset(MIPSGPReg r);
135
136
private:
137
const ArmGen::ARMReg *GetMIPSAllocationOrder(int &count);
138
void MapRegTo(ArmGen::ARMReg reg, MIPSGPReg mipsReg, int mapFlags);
139
int FlushGetSequential(MIPSGPReg startMipsReg, bool allowFlushImm);
140
ArmGen::ARMReg FindBestToSpill(bool unusedOnly, bool *clobbered);
141
142
MIPSState *mips_;
143
ArmGen::ARMXEmitter *emit_;
144
MIPSComp::JitState *js_;
145
MIPSComp::JitOptions *jo_;
146
u32 compilerPC_;
147
148
enum {
149
NUM_ARMREG = 16,
150
NUM_MIPSREG = ArmJitConstants::TOTAL_MAPPABLE_MIPSREGS,
151
};
152
153
RegARM ar[NUM_ARMREG];
154
RegMIPS mr[NUM_MIPSREG];
155
};
156
157