all repos — mgba @ 6fe1f44351b82f85210260ab2425f8aaecb774a4

mGBA Game Boy Advance Emulator

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}