src/sm83/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/sm83/debugger/cli-debugger.h>
7
8#include <mgba/core/core.h>
9#include <mgba/core/timing.h>
10#include <mgba/internal/debugger/cli-debugger.h>
11#include <mgba/internal/sm83/decoder.h>
12#include <mgba/internal/sm83/debugger/debugger.h>
13#include <mgba/internal/sm83/sm83.h>
14
15static void _printStatus(struct CLIDebuggerSystem*);
16
17static void _disassemble(struct CLIDebuggerSystem* debugger, struct CLIDebugVector* dv);
18static uint16_t _printLine(struct CLIDebugger* debugger, uint16_t address, int segment);
19
20static struct CLIDebuggerCommandSummary _sm83Commands[] = {
21 { 0, 0, 0, 0 }
22};
23
24static inline void _printFlags(struct CLIDebuggerBackend* be, union FlagRegister f) {
25 be->printf(be, "F: [%c%c%c%c]\n",
26 f.z ? 'Z' : '-',
27 f.n ? 'N' : '-',
28 f.h ? 'H' : '-',
29 f.c ? 'C' : '-');
30}
31
32static void _disassemble(struct CLIDebuggerSystem* debugger, struct CLIDebugVector* dv) {
33 struct SM83Core* cpu = debugger->p->d.core->cpu;
34
35 uint16_t address;
36 int segment = -1;
37 size_t size;
38 if (!dv || dv->type != CLIDV_INT_TYPE) {
39 address = cpu->pc;
40 } else {
41 address = dv->intValue;
42 segment = dv->segmentValue;
43 dv = dv->next;
44 }
45
46 if (!dv || dv->type != CLIDV_INT_TYPE) {
47 size = 1;
48 } else {
49 size = dv->intValue;
50 // TODO: Check for excess args
51 }
52
53 size_t i;
54 for (i = 0; i < size; ++i) {
55 address = _printLine(debugger->p, address, segment);
56 }
57}
58
59static inline uint16_t _printLine(struct CLIDebugger* debugger, uint16_t address, int segment) {
60 struct CLIDebuggerBackend* be = debugger->backend;
61 struct SM83InstructionInfo info = {{0}, 0};
62 char disassembly[48];
63 char* disPtr = disassembly;
64 if (segment >= 0) {
65 be->printf(be, "%02X:", segment);
66 }
67 be->printf(be, "%04X: ", address);
68 uint8_t instruction;
69 size_t bytesRemaining = 1;
70 for (bytesRemaining = 1; bytesRemaining; --bytesRemaining) {
71 instruction = debugger->d.core->rawRead8(debugger->d.core, address, segment);
72 disPtr += snprintf(disPtr, sizeof(disassembly) - (disPtr - disassembly), "%02X", instruction);
73 ++address;
74 bytesRemaining += SM83Decode(instruction, &info);
75 };
76 disPtr[0] = '\t';
77 ++disPtr;
78 SM83Disassemble(&info, address, disPtr, sizeof(disassembly) - (disPtr - disassembly));
79 be->printf(be, "%s\n", disassembly);
80 return address;
81}
82
83static void _printStatus(struct CLIDebuggerSystem* debugger) {
84 struct CLIDebuggerBackend* be = debugger->p->backend;
85 struct SM83Core* cpu = debugger->p->d.core->cpu;
86 be->printf(be, "A: %02X F: %02X (AF: %04X)\n", cpu->a, cpu->f.packed, cpu->af);
87 be->printf(be, "B: %02X C: %02X (BC: %04X)\n", cpu->b, cpu->c, cpu->bc);
88 be->printf(be, "D: %02X E: %02X (DE: %04X)\n", cpu->d, cpu->e, cpu->de);
89 be->printf(be, "H: %02X L: %02X (HL: %04X)\n", cpu->h, cpu->l, cpu->hl);
90 be->printf(be, "PC: %04X SP: %04X\n", cpu->pc, cpu->sp);
91 _printFlags(be, cpu->f);
92 be->printf(be, "T-cycle: %" PRIu64 "\n", mTimingGlobalTime(debugger->p->d.core->timing));
93
94 struct SM83Debugger* platDebugger = (struct SM83Debugger*) debugger->p->d.platform;
95 size_t i;
96 for (i = 0; platDebugger->segments[i].name; ++i) {
97 be->printf(be, "%s%s: %02X", i ? " " : "", platDebugger->segments[i].name, cpu->memory.currentSegment(cpu, platDebugger->segments[i].start));
98 }
99 if (i) {
100 be->printf(be, "\n");
101 }
102 if (platDebugger->printStatus) {
103 platDebugger->printStatus(debugger);
104 }
105 _printLine(debugger->p, cpu->pc, cpu->memory.currentSegment(cpu, cpu->pc));
106}
107
108void SM83CLIDebuggerCreate(struct CLIDebuggerSystem* debugger) {
109 debugger->printStatus = _printStatus;
110 debugger->disassemble = _disassemble;
111 debugger->platformName = "SM83";
112 debugger->platformCommands = _sm83Commands;
113 debugger->platformCommandAliases = NULL;
114}