Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Core/MIPS/MIPSDebugInterface.cpp
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
#include <string>
19
#include <cstring>
20
21
#ifndef _MSC_VER
22
#include <strings.h>
23
#endif
24
25
#include "Common/StringUtils.h"
26
#include "Core/CoreTiming.h"
27
#include "Core/Debugger/Breakpoints.h"
28
#include "Core/Debugger/SymbolMap.h"
29
#include "Core/Debugger/DebugInterface.h"
30
#include "Core/MIPS/MIPSDebugInterface.h"
31
#include "Core/MIPS/MIPSVFPUUtils.h"
32
#include "Core/HLE/sceKernelThread.h"
33
#include "Core/MemMap.h"
34
#include "Core/MIPS/MIPSTables.h"
35
#include "Core/Core.h"
36
#include "Core/System.h"
37
38
enum ReferenceIndexType {
39
REF_INDEX_PC = 32,
40
REF_INDEX_HI = 33,
41
REF_INDEX_LO = 34,
42
REF_INDEX_FPU = 0x1000,
43
REF_INDEX_FPU_INT = 0x2000,
44
REF_INDEX_VFPU = 0x4000,
45
REF_INDEX_VFPU_INT = 0x8000,
46
REF_INDEX_IS_FLOAT = REF_INDEX_FPU | REF_INDEX_VFPU,
47
REF_INDEX_HLE = 0x10000,
48
REF_INDEX_THREAD = REF_INDEX_HLE | 0,
49
REF_INDEX_MODULE = REF_INDEX_HLE | 1,
50
REF_INDEX_USEC = REF_INDEX_HLE | 2,
51
REF_INDEX_TICKS = REF_INDEX_HLE | 3,
52
};
53
54
55
class MipsExpressionFunctions : public IExpressionFunctions {
56
public:
57
MipsExpressionFunctions(const DebugInterface *_cpu): cpu(_cpu) {}
58
59
bool parseReference(char* str, uint32_t& referenceIndex) override
60
{
61
for (int i = 0; i < 32; i++)
62
{
63
char reg[8];
64
snprintf(reg, sizeof(reg), "r%d", i);
65
66
if (strcasecmp(str, reg) == 0 || strcasecmp(str, MIPSDebugInterface::GetRegName(0, i).c_str()) == 0)
67
{
68
referenceIndex = i;
69
return true;
70
}
71
else if (strcasecmp(str, MIPSDebugInterface::GetRegName(1, i).c_str()) == 0)
72
{
73
referenceIndex = REF_INDEX_FPU | i;
74
return true;
75
}
76
77
snprintf(reg, sizeof(reg), "fi%d", i);
78
if (strcasecmp(str, reg) == 0)
79
{
80
referenceIndex = REF_INDEX_FPU_INT | i;
81
return true;
82
}
83
}
84
85
for (int i = 0; i < 128; i++)
86
{
87
if (strcasecmp(str, MIPSDebugInterface::GetRegName(2, i).c_str()) == 0)
88
{
89
referenceIndex = REF_INDEX_VFPU | i;
90
return true;
91
}
92
93
char reg[8];
94
snprintf(reg, sizeof(reg), "vi%d", i);
95
if (strcasecmp(str, reg) == 0)
96
{
97
referenceIndex = REF_INDEX_VFPU_INT | i;
98
return true;
99
}
100
}
101
102
if (strcasecmp(str, "pc") == 0)
103
{
104
referenceIndex = REF_INDEX_PC;
105
return true;
106
}
107
108
if (strcasecmp(str, "hi") == 0)
109
{
110
referenceIndex = REF_INDEX_HI;
111
return true;
112
}
113
114
if (strcasecmp(str, "lo") == 0)
115
{
116
referenceIndex = REF_INDEX_LO;
117
return true;
118
}
119
120
if (strcasecmp(str, "threadid") == 0) {
121
referenceIndex = REF_INDEX_THREAD;
122
return true;
123
}
124
if (strcasecmp(str, "moduleid") == 0) {
125
referenceIndex = REF_INDEX_MODULE;
126
return true;
127
}
128
if (strcasecmp(str, "usec") == 0) {
129
referenceIndex = REF_INDEX_USEC;
130
return true;
131
}
132
if (strcasecmp(str, "ticks") == 0) {
133
referenceIndex = REF_INDEX_TICKS;
134
return true;
135
}
136
137
return false;
138
}
139
140
bool parseSymbol(char* str, uint32_t& symbolValue) override
141
{
142
return g_symbolMap->GetLabelValue(str,symbolValue);
143
}
144
145
uint32_t getReferenceValue(uint32_t referenceIndex) override
146
{
147
if (referenceIndex < 32)
148
return cpu->GetRegValue(0, referenceIndex);
149
if (referenceIndex == REF_INDEX_PC)
150
return cpu->GetPC();
151
if (referenceIndex == REF_INDEX_HI)
152
return cpu->GetHi();
153
if (referenceIndex == REF_INDEX_LO)
154
return cpu->GetLo();
155
if (referenceIndex == REF_INDEX_THREAD)
156
return __KernelGetCurThread();
157
if (referenceIndex == REF_INDEX_MODULE)
158
return __KernelGetCurThreadModuleId();
159
if (referenceIndex == REF_INDEX_USEC)
160
return (uint32_t)CoreTiming::GetGlobalTimeUs(); // Loses information
161
if (referenceIndex == REF_INDEX_TICKS)
162
return (uint32_t)CoreTiming::GetTicks();
163
if ((referenceIndex & ~(REF_INDEX_FPU | REF_INDEX_FPU_INT)) < 32)
164
return cpu->GetRegValue(1, referenceIndex & ~(REF_INDEX_FPU | REF_INDEX_FPU_INT));
165
if ((referenceIndex & ~(REF_INDEX_VFPU | REF_INDEX_VFPU_INT)) < 128)
166
return cpu->GetRegValue(2, referenceIndex & ~(REF_INDEX_VFPU | REF_INDEX_VFPU_INT));
167
return -1;
168
}
169
170
ExpressionType getReferenceType(uint32_t referenceIndex) override {
171
if (referenceIndex & REF_INDEX_IS_FLOAT) {
172
return EXPR_TYPE_FLOAT;
173
}
174
return EXPR_TYPE_UINT;
175
}
176
177
bool getMemoryValue(uint32_t address, int size, uint32_t& dest, std::string *error) override {
178
// We allow, but ignore, bad access.
179
// If we didn't, log/condition statements that reference registers couldn't be configured.
180
uint32_t valid = Memory::ValidSize(address, size);
181
uint8_t buf[4]{};
182
if (valid != 0)
183
memcpy(buf, Memory::GetPointerUnchecked(address), valid);
184
185
switch (size) {
186
case 1:
187
dest = buf[0];
188
return true;
189
case 2:
190
dest = (buf[1] << 8) | buf[0];
191
return true;
192
case 4:
193
dest = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
194
return true;
195
}
196
197
*error = StringFromFormat("Unexpected memory access size %d", size);
198
return false;
199
}
200
201
private:
202
const DebugInterface *cpu;
203
};
204
205
unsigned int MIPSDebugInterface::readMemory(unsigned int address) {
206
if (Memory::IsValidRange(address, 4))
207
return Memory::ReadUnchecked_Instruction(address).encoding;
208
return 0;
209
}
210
211
bool MIPSDebugInterface::isAlive()
212
{
213
return PSP_GetBootState() == BootState::Complete && coreState != CORE_RUNTIME_ERROR && coreState != CORE_POWERDOWN;
214
}
215
216
bool MIPSDebugInterface::isBreakpoint(unsigned int address)
217
{
218
return g_breakpoints.IsAddressBreakPoint(address);
219
}
220
221
void MIPSDebugInterface::setBreakpoint(unsigned int address) {
222
g_breakpoints.AddBreakPoint(address);
223
}
224
225
void MIPSDebugInterface::clearBreakpoint(unsigned int address) {
226
g_breakpoints.RemoveBreakPoint(address);
227
}
228
229
void MIPSDebugInterface::clearAllBreakpoints() {}
230
231
void MIPSDebugInterface::toggleBreakpoint(unsigned int address) {
232
if (g_breakpoints.IsAddressBreakPoint(address)) {
233
g_breakpoints.RemoveBreakPoint(address);
234
} else {
235
g_breakpoints.AddBreakPoint(address);
236
}
237
}
238
239
int MIPSDebugInterface::getColor(unsigned int address, bool darkMode) const {
240
uint32_t colors[6] = { 0xFFe0FFFF, 0xFFFFe0e0, 0xFFe8e8FF, 0xFFFFe0FF, 0xFFe0FFe0, 0xFFFFFFe0 };
241
uint32_t colorsDark[6] = { 0xFF301010, 0xFF103030, 0xFF403010, 0xFF103000, 0xFF301030, 0xFF101030 };
242
243
int n = g_symbolMap->GetFunctionNum(address);
244
if (n == -1) {
245
return darkMode ? 0xFF101010 : 0xFFFFFFFF;
246
} else if (darkMode) {
247
return colorsDark[n % ARRAY_SIZE(colorsDark)];
248
} else {
249
return colors[n % ARRAY_SIZE(colors)];
250
}
251
}
252
253
std::string MIPSDebugInterface::getDescription(unsigned int address) {
254
return g_symbolMap->GetDescription(address);
255
}
256
257
std::string MIPSDebugInterface::GetRegName(int cat, int index) {
258
static const char * const regName[32] = {
259
"zero", "at", "v0", "v1",
260
"a0", "a1", "a2", "a3",
261
"t0", "t1", "t2", "t3",
262
"t4", "t5", "t6", "t7",
263
"s0", "s1", "s2", "s3",
264
"s4", "s5", "s6", "s7",
265
"t8", "t9", "k0", "k1",
266
"gp", "sp", "fp", "ra"
267
};
268
static const char * const fpRegName[32] = {
269
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
270
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
271
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
272
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
273
};
274
275
if (cat == 0 && (unsigned)index < ARRAY_SIZE(regName)) {
276
return regName[index];
277
} else if (cat == 1 && (unsigned)index < ARRAY_SIZE(fpRegName)) {
278
return fpRegName[index];
279
} else if (cat == 2) {
280
return GetVectorNotation(index, V_Single);
281
}
282
return "???";
283
}
284
285
bool initExpression(const DebugInterface *debug, const char* exp, PostfixExpression& dest) {
286
MipsExpressionFunctions funcs(debug);
287
return initPostfixExpression(exp, &funcs, dest);
288
}
289
290
bool parseExpression(const DebugInterface *debug, PostfixExpression& exp, u32& dest) {
291
MipsExpressionFunctions funcs(debug);
292
return parsePostfixExpression(exp, &funcs, dest);
293
}
294
295
void DisAsm(u32 pc, char *out, size_t outSize) {
296
if (Memory::IsValidAddress(pc))
297
MIPSDisAsm(Memory::Read_Opcode_JIT(pc), pc, out, outSize);
298
else
299
truncate_cpy(out, outSize, "-");
300
}
301
302