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