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/MIPSAnalyst.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 <string>
21
#include <vector>
22
23
#include "Common/CommonTypes.h"
24
#include "Common/File/Path.h"
25
#include "Core/MIPS/MIPS.h"
26
27
class DebugInterface;
28
29
namespace MIPSAnalyst
30
{
31
const int MIPS_NUM_GPRS = 32;
32
33
struct RegisterAnalysisResults {
34
bool used;
35
int firstRead;
36
int lastRead;
37
int firstWrite;
38
int lastWrite;
39
int firstReadAsAddr;
40
int lastReadAsAddr;
41
42
int readCount;
43
int writeCount;
44
int readAsAddrCount;
45
46
int TotalReadCount() const { return readCount + readAsAddrCount; }
47
int FirstRead() const { return firstReadAsAddr < firstRead ? firstReadAsAddr : firstRead; }
48
int LastRead() const { return lastReadAsAddr > lastRead ? lastReadAsAddr : lastRead; }
49
50
void MarkRead(u32 addr) {
51
if (firstRead == -1)
52
firstRead = addr;
53
lastRead = addr;
54
readCount++;
55
used = true;
56
}
57
58
void MarkReadAsAddr(u32 addr) {
59
if (firstReadAsAddr == -1)
60
firstReadAsAddr = addr;
61
lastReadAsAddr = addr;
62
readAsAddrCount++;
63
used = true;
64
}
65
66
void MarkWrite(u32 addr) {
67
if (firstWrite == -1)
68
firstWrite = addr;
69
lastWrite = addr;
70
writeCount++;
71
used = true;
72
}
73
};
74
75
struct AnalysisResults {
76
RegisterAnalysisResults r[MIPS_NUM_GPRS];
77
};
78
79
AnalysisResults Analyze(u32 address);
80
81
// This tells us if the reg is used within intrs of addr (also includes likely delay slots.)
82
bool IsRegisterUsed(MIPSGPReg reg, u32 addr, int instrs);
83
// This tells us if the reg is clobbered within intrs of addr (e.g. it is surely not used.)
84
bool IsRegisterClobbered(MIPSGPReg reg, u32 addr, int instrs);
85
86
struct AnalyzedFunction {
87
u32 start;
88
u32 end;
89
u64 hash;
90
u32 size;
91
bool isStraightLeaf;
92
bool hasHash;
93
bool usesVFPU;
94
bool foundInSymbolMap;
95
char name[64];
96
};
97
98
struct ReplacementTableEntry;
99
100
void Reset();
101
102
bool IsRegisterUsed(u32 reg, u32 addr);
103
// This will not only create a database of "AnalyzedFunction" structs, it also
104
// will insert all the functions it finds into the symbol map, if insertSymbols is true.
105
106
// If we have loaded symbols from the elf, we'll register functions as they are touched
107
// so that we don't just dump them all in the cache.
108
void RegisterFunction(u32 startAddr, u32 size, const char *name);
109
// Returns new insertSymbols value for FinalizeScan().
110
bool ScanForFunctions(u32 startAddr, u32 endAddr, bool insertSymbols);
111
void FinalizeScan(bool insertSymbols);
112
void ForgetFunctions(u32 startAddr, u32 endAddr);
113
void PrecompileFunctions();
114
void PrecompileFunction(u32 startAddr, u32 length);
115
116
void SetHashMapFilename(const std::string& filename = "");
117
void LoadBuiltinHashMap();
118
void LoadHashMap(const Path &filename);
119
void StoreHashMap(Path filename = Path());
120
121
const char *LookupHash(u64 hash, u32 funcSize);
122
void ReplaceFunctions();
123
124
void UpdateHashMap();
125
void ApplyHashMap();
126
127
std::vector<MIPSGPReg> GetInputRegs(MIPSOpcode op);
128
std::vector<MIPSGPReg> GetOutputRegs(MIPSOpcode op);
129
130
MIPSGPReg GetOutGPReg(MIPSOpcode op);
131
bool ReadsFromGPReg(MIPSOpcode op, MIPSGPReg reg);
132
bool IsDelaySlotNiceReg(MIPSOpcode branchOp, MIPSOpcode op, MIPSGPReg reg1, MIPSGPReg reg2 = MIPS_REG_ZERO);
133
bool IsDelaySlotNiceVFPU(MIPSOpcode branchOp, MIPSOpcode op);
134
bool IsDelaySlotNiceFPU(MIPSOpcode branchOp, MIPSOpcode op);
135
bool IsSyscall(MIPSOpcode op);
136
137
bool OpWouldChangeMemory(u32 pc, u32 addr, u32 size);
138
int OpMemoryAccessSize(u32 pc);
139
bool IsOpMemoryWrite(u32 pc);
140
bool OpHasDelaySlot(u32 pc);
141
142
typedef struct {
143
DebugInterface* cpu;
144
u32 opcodeAddress;
145
MIPSOpcode encodedOpcode;
146
147
// shared between branches and conditional moves
148
bool isConditional;
149
bool conditionMet;
150
151
// branches
152
u32 branchTarget;
153
bool isBranch;
154
bool isLinkedBranch;
155
bool isLikelyBranch;
156
bool isBranchToRegister;
157
int branchRegisterNum;
158
159
// data access
160
bool isDataAccess;
161
int dataSize;
162
u32 dataAddress;
163
164
bool hasRelevantAddress;
165
u32 relevantAddress;
166
} MipsOpcodeInfo;
167
168
MipsOpcodeInfo GetOpcodeInfo(DebugInterface* cpu, u32 address);
169
170
} // namespace MIPSAnalyst
171
172