src/lr35902/debugger/cli-debugger.c (view raw)
1/* Copyright (c) 2013-2016 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include <mgba/internal/lr35902/debugger/cli-debugger.h>
7
8#include <mgba/core/core.h>
9#include <mgba/internal/debugger/cli-debugger.h>
10#include <mgba/internal/lr35902/decoder.h>
11#include <mgba/internal/lr35902/lr35902.h>
12
13static void _printStatus(struct CLIDebuggerSystem*);
14
15static void _disassemble(struct CLIDebuggerSystem* debugger, struct CLIDebugVector* dv);
16static uint16_t _printLine(struct CLIDebugger* debugger, uint16_t address, int segment);
17
18static struct CLIDebuggerCommandSummary _lr35902Commands[] = {
19 { 0, 0, 0, 0 }
20};
21
22static inline void _printFlags(struct CLIDebuggerBackend* be, union FlagRegister f) {
23 be->printf(be, "[%c%c%c%c]\n",
24 f.z ? 'Z' : '-',
25 f.n ? 'N' : '-',
26 f.h ? 'H' : '-',
27 f.c ? 'C' : '-');
28}
29
30static void _disassemble(struct CLIDebuggerSystem* debugger, struct CLIDebugVector* dv) {
31 struct LR35902Core* cpu = debugger->p->d.core->cpu;
32
33 uint16_t address;
34 int segment = -1;
35 size_t size;
36 if (!dv || dv->type != CLIDV_INT_TYPE) {
37 address = cpu->pc;
38 } else {
39 address = dv->intValue;
40 segment = dv->segmentValue;
41 dv = dv->next;
42 }
43
44 if (!dv || dv->type != CLIDV_INT_TYPE) {
45 size = 1;
46 } else {
47 size = dv->intValue;
48 dv = dv->next; // TODO: Check for excess args
49 }
50
51 size_t i;
52 for (i = 0; i < size; ++i) {
53 address = _printLine(debugger->p, address, segment);
54 }
55}
56
57static inline uint16_t _printLine(struct CLIDebugger* debugger, uint16_t address, int segment) {
58 struct CLIDebuggerBackend* be = debugger->backend;
59 struct LR35902InstructionInfo info = {0};
60 char disassembly[48];
61 char* disPtr = disassembly;
62 if (segment >= 0) {
63 be->printf(be, "%02X:", segment);
64 }
65 be->printf(be, "%04X: ", address);
66 uint8_t instruction;
67 size_t bytesRemaining = 1;
68 for (bytesRemaining = 1; bytesRemaining; --bytesRemaining) {
69 instruction = debugger->d.core->rawRead8(debugger->d.core, address, segment);
70 disPtr += snprintf(disPtr, sizeof(disassembly) - (disPtr - disassembly), "%02X", instruction);
71 ++address;
72 bytesRemaining += LR35902Decode(instruction, &info);
73 };
74 disPtr[0] = '\t';
75 ++disPtr;
76 LR35902Disassemble(&info, disPtr, sizeof(disassembly) - (disPtr - disassembly));
77 be->printf(be, "%s\n", disassembly);
78 return address;
79}
80
81static void _printStatus(struct CLIDebuggerSystem* debugger) {
82 struct CLIDebuggerBackend* be = debugger->p->backend;
83 struct LR35902Core* cpu = debugger->p->d.core->cpu;
84 be->printf(be, "A: %02X F: %02X (AF: %04X)\n", cpu->a, cpu->f.packed, cpu->af);
85 be->printf(be, "B: %02X C: %02X (BC: %04X)\n", cpu->b, cpu->c, cpu->bc);
86 be->printf(be, "D: %02X E: %02X (DE: %04X)\n", cpu->d, cpu->e, cpu->de);
87 be->printf(be, "H: %02X L: %02X (HL: %04X)\n", cpu->h, cpu->l, cpu->hl);
88 be->printf(be, "PC: %04X SP: %04X\n", cpu->pc, cpu->sp);
89 _printFlags(be, cpu->f);
90 _printLine(debugger->p, cpu->pc, cpu->memory.currentSegment(cpu, cpu->pc));
91}
92
93static uint32_t _lookupPlatformIdentifier(struct CLIDebuggerSystem* debugger, const char* name, struct CLIDebugVector* dv) {
94 struct LR35902Core* cpu = debugger->p->d.core->cpu;
95 if (strcmp(name, "a") == 0) {
96 return cpu->a;
97 }
98 if (strcmp(name, "b") == 0) {
99 return cpu->b;
100 }
101 if (strcmp(name, "c") == 0) {
102 return cpu->c;
103 }
104 if (strcmp(name, "d") == 0) {
105 return cpu->d;
106 }
107 if (strcmp(name, "e") == 0) {
108 return cpu->e;
109 }
110 if (strcmp(name, "h") == 0) {
111 return cpu->h;
112 }
113 if (strcmp(name, "l") == 0) {
114 return cpu->l;
115 }
116 if (strcmp(name, "bc") == 0) {
117 return cpu->bc;
118 }
119 if (strcmp(name, "de") == 0) {
120 return cpu->de;
121 }
122 if (strcmp(name, "hl") == 0) {
123 return cpu->hl;
124 }
125 if (strcmp(name, "af") == 0) {
126 return cpu->af;
127 }
128 if (strcmp(name, "pc") == 0) {
129 return cpu->pc;
130 }
131 if (strcmp(name, "sp") == 0) {
132 return cpu->sp;
133 }
134 if (strcmp(name, "f") == 0) {
135 return cpu->f.packed;
136 }
137 dv->type = CLIDV_ERROR_TYPE;
138 return 0;
139}
140
141void LR35902CLIDebuggerCreate(struct CLIDebuggerSystem* debugger) {
142 debugger->printStatus = _printStatus;
143 debugger->disassemble = _disassemble;
144 debugger->lookupPlatformIdentifier = _lookupPlatformIdentifier;
145 debugger->platformName = "GB-Z80";
146 debugger->platformCommands = _lr35902Commands;
147}