all repos — mgba @ d61d9ef6a6132d6d890053a483b00da74a92f5e5

mGBA Game Boy Advance Emulator

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}