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