rlm@1: // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. rlm@1: // Copyright (C) 1999-2003 Forgotten rlm@1: // Copyright (C) 2004 Forgotten and the VBA development team rlm@1: rlm@1: // This program is free software; you can redistribute it and/or modify rlm@1: // it under the terms of the GNU General Public License as published by rlm@1: // the Free Software Foundation; either version 2, or(at your option) rlm@1: // any later version. rlm@1: // rlm@1: // This program is distributed in the hope that it will be useful, rlm@1: // but WITHOUT ANY WARRANTY; without even the implied warranty of rlm@1: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the rlm@1: // GNU General Public License for more details. rlm@1: // rlm@1: // You should have received a copy of the GNU General Public License rlm@1: // along with this program; if not, write to the Free Software Foundation, rlm@1: // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. rlm@1: rlm@1: extern "C" { rlm@1: #include rlm@1: #include rlm@1: } // FIXME: should use c++ headers instead rlm@1: rlm@1: #include rlm@1: rlm@1: #include "Port.h" rlm@1: #include "gba/GBA.h" rlm@1: #include "gba/GBAGlobals.h" rlm@1: #include "gba/GBACheats.h" rlm@1: #include "gba/armdis.h" rlm@1: #include "gba/elf.h" rlm@1: #include "common/System.h" rlm@1: #include "exprNode.h" rlm@1: rlm@1: extern bool debugger; rlm@1: extern int emulating; rlm@1: rlm@1: extern struct EmulatedSystem theEmulator; rlm@1: rlm@1: #define debuggerReadMemory(addr) \ rlm@1: READ32LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) rlm@1: rlm@1: #define debuggerReadHalfWord(addr) \ rlm@1: READ16LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) rlm@1: rlm@1: #define debuggerReadByte(addr) \ rlm@1: map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] rlm@1: rlm@1: #define debuggerWriteMemory(addr, value) \ rlm@1: WRITE32LE(&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], value) rlm@1: rlm@1: #define debuggerWriteHalfWord(addr, value) \ rlm@1: WRITE16LE(&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], value) rlm@1: rlm@1: #define debuggerWriteByte(addr, value) \ rlm@1: map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] = (value) rlm@1: rlm@1: struct breakpointInfo { rlm@1: u32 address; rlm@1: u32 value; rlm@1: int size; rlm@1: }; rlm@1: rlm@1: struct DebuggerCommand { rlm@1: const char *name; rlm@1: void (*function)(int,char **); rlm@1: const char *help; rlm@1: const char *syntax; rlm@1: }; rlm@1: rlm@1: void debuggerContinueAfterBreakpoint(); rlm@1: rlm@1: void debuggerHelp(int,char **); rlm@1: void debuggerNext(int,char **); rlm@1: void debuggerContinue(int, char **); rlm@1: void debuggerRegisters(int, char **); rlm@1: void debuggerBreak(int, char **); rlm@1: void debuggerBreakDelete(int, char **); rlm@1: void debuggerBreakList(int, char **); rlm@1: void debuggerBreakArm(int, char **); rlm@1: void debuggerBreakWriteClear(int, char **); rlm@1: void debuggerBreakThumb(int, char **); rlm@1: void debuggerBreakWrite(int, char **); rlm@1: void debuggerDebug(int, char **); rlm@1: void debuggerDisassemble(int, char **); rlm@1: void debuggerDisassembleArm(int, char **); rlm@1: void debuggerDisassembleThumb(int, char **); rlm@1: void debuggerEditByte(int, char **); rlm@1: void debuggerEditHalfWord(int, char **); rlm@1: void debuggerEdit(int, char **); rlm@1: void debuggerIo(int, char **); rlm@1: void debuggerLocals(int, char **); rlm@1: void debuggerMemoryByte(int, char **); rlm@1: void debuggerMemoryHalfWord(int, char **); rlm@1: void debuggerMemory(int, char **); rlm@1: void debuggerPrint(int, char **); rlm@1: void debuggerQuit(int, char **); rlm@1: void debuggerSetRadix(int, char **); rlm@1: void debuggerSymbols(int, char **); rlm@1: void debuggerVerbose(int, char **); rlm@1: void debuggerWhere(int, char **); rlm@1: rlm@1: DebuggerCommand debuggerCommands[] = { rlm@1: { "?", debuggerHelp, "Shows this help information. Type ? for command help", "[]" }, rlm@1: { "ba", debuggerBreakArm, "Adds an ARM breakpoint", "
" }, rlm@1: { "bd", debuggerBreakDelete,"Deletes a breakpoint", "" }, rlm@1: { "bl", debuggerBreakList, "Lists breakpoints" }, rlm@1: { "bpw", debuggerBreakWrite, "Break on write", "
" }, rlm@1: { "bpwc", debuggerBreakWriteClear, "Clear break on write", NULL }, rlm@1: { "break", debuggerBreak, "Adds a breakpoint on the given function", "||" }, rlm@1: { "bt", debuggerBreakThumb, "Adds a THUMB breakpoint", "
" }, rlm@1: { "c", debuggerContinue, "Continues execution" , NULL }, rlm@1: { "d", debuggerDisassemble, "Disassembles instructions", "[
[]]" }, rlm@1: { "da", debuggerDisassembleArm, "Disassembles ARM instructions", "[
[]]" }, rlm@1: { "dt", debuggerDisassembleThumb, "Disassembles THUMB instructions", "[
[]]" }, rlm@1: { "eb", debuggerEditByte, "Modify memory location (byte)", "
" }, rlm@1: { "eh", debuggerEditHalfWord,"Modify memory location (half-word)","
" }, rlm@1: { "ew", debuggerEdit, "Modify memory location (word)", "
for command help", "[]" }, rlm@1: { "io", debuggerIo, "Show I/O registers status", "[video|video2|dma|timer|misc]" }, rlm@1: { "locals", debuggerLocals, "Shows local variables", NULL }, rlm@1: { "mb", debuggerMemoryByte, "Shows memory contents (bytes)", "
" }, rlm@1: { "mh", debuggerMemoryHalfWord, "Shows memory contents (half-words)", "
"}, rlm@1: { "mw", debuggerMemory, "Shows memory contents (words)", "
" }, rlm@1: { "n", debuggerNext, "Executes the next instruction", "[]" }, rlm@1: { "print", debuggerPrint, "Print the value of a expression (if known)", "[/x|/o|/d] " }, rlm@1: { "q", debuggerQuit, "Quits the emulator", NULL }, rlm@1: { "r", debuggerRegisters, "Shows ARM registers", NULL }, rlm@1: { "radix", debuggerSetRadix, "Sets the print radix", "" }, rlm@1: { "symbols", debuggerSymbols, "List symbols", "[]" }, rlm@1: #ifndef FINAL_VERSION rlm@1: { "trace", debuggerDebug, "Sets the trace level", "" }, rlm@1: #endif rlm@1: #ifdef DEV_VERSION rlm@1: { "verbose", debuggerVerbose, "Change verbose setting", "" }, rlm@1: #endif rlm@1: { "where", debuggerWhere, "Shows call chain", NULL }, rlm@1: { NULL, NULL, NULL, NULL} // end marker rlm@1: }; rlm@1: rlm@1: breakpointInfo debuggerBreakpointList[100]; rlm@1: rlm@1: int debuggerNumOfBreakpoints = 0; rlm@1: bool debuggerAtBreakpoint = false; rlm@1: int debuggerBreakpointNumber = 0; rlm@1: int debuggerRadix = 0; rlm@1: rlm@1: void debuggerApplyBreakpoint(u32 address, int num, int size) rlm@1: { rlm@1: if(size) rlm@1: debuggerWriteMemory(address, (u32)(0xe1200070 | rlm@1: (num & 0xf) | rlm@1: ((num<<4)&0xf0))); rlm@1: else rlm@1: debuggerWriteHalfWord(address, rlm@1: (u16)(0xbe00 | num)); rlm@1: } rlm@1: rlm@1: void debuggerDisableBreakpoints() rlm@1: { rlm@1: for(int i = 0; i < debuggerNumOfBreakpoints; i++) { rlm@1: if(debuggerBreakpointList[i].size) rlm@1: debuggerWriteMemory(debuggerBreakpointList[i].address, rlm@1: debuggerBreakpointList[i].value); rlm@1: else rlm@1: debuggerWriteHalfWord(debuggerBreakpointList[i].address, rlm@1: debuggerBreakpointList[i].value); rlm@1: } rlm@1: } rlm@1: rlm@1: void debuggerEnableBreakpoints(bool skipPC) rlm@1: { rlm@1: for(int i = 0; i < debuggerNumOfBreakpoints; i++) { rlm@1: if(debuggerBreakpointList[i].address == armNextPC && skipPC) rlm@1: continue; rlm@1: rlm@1: debuggerApplyBreakpoint(debuggerBreakpointList[i].address, rlm@1: i, rlm@1: debuggerBreakpointList[i].size); rlm@1: } rlm@1: } rlm@1: rlm@1: void debuggerUsage(const char *cmd) rlm@1: { rlm@1: for(int i = 0; ; i++) { rlm@1: if(debuggerCommands[i].name) { rlm@1: if(!strcmp(debuggerCommands[i].name, cmd)) { rlm@1: printf("%s %s\t%s\n", rlm@1: debuggerCommands[i].name, rlm@1: debuggerCommands[i].syntax ? debuggerCommands[i].syntax : "", rlm@1: debuggerCommands[i].help); rlm@1: break; rlm@1: } rlm@1: } else { rlm@1: printf("Unrecognized command '%s'.", cmd); rlm@1: break; rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: void debuggerPrintBaseType(Type *t, u32 value, u32 location, rlm@1: LocationType type, rlm@1: int bitSize, int bitOffset) rlm@1: { rlm@1: if(bitSize) { rlm@1: if(bitOffset) rlm@1: value >>= ((t->size*8)-bitOffset-bitSize); rlm@1: value &= (1 << bitSize)-1; rlm@1: } else { rlm@1: if(t->size == 2) rlm@1: value &= 0xFFFF; rlm@1: else if(t->size == 1) rlm@1: value &= 0xFF; rlm@1: } rlm@1: rlm@1: if(t->size == 8) { rlm@1: u64 value = 0; rlm@1: if(type == LOCATION_memory) { rlm@1: value = debuggerReadMemory(location) | rlm@1: ((u64)debuggerReadMemory(location+4)<<32); rlm@1: } else if(type == LOCATION_register) { rlm@1: value = reg[location].I | ((u64)reg[location+1].I << 32); rlm@1: } rlm@1: switch(t->encoding) { rlm@1: case DW_ATE_signed: rlm@1: switch(debuggerRadix) { rlm@1: case 0: rlm@1: printf("%lld", value); rlm@1: break; rlm@1: case 1: rlm@1: printf("0x%llx", value); rlm@1: break; rlm@1: case 2: rlm@1: printf("0%llo", value); rlm@1: break; rlm@1: } rlm@1: break; rlm@1: case DW_ATE_unsigned: rlm@1: switch(debuggerRadix) { rlm@1: case 0: rlm@1: printf("%llu", value); rlm@1: break; rlm@1: case 1: rlm@1: printf("0x%llx", value); rlm@1: break; rlm@1: case 2: rlm@1: printf("0%llo", value); rlm@1: break; rlm@1: } rlm@1: break; rlm@1: default: rlm@1: printf("Unknowing 64-bit encoding\n"); rlm@1: } rlm@1: return; rlm@1: } rlm@1: rlm@1: switch(t->encoding) { rlm@1: case DW_ATE_boolean: rlm@1: if(value) rlm@1: printf("true"); rlm@1: else rlm@1: printf("false"); rlm@1: break; rlm@1: case DW_ATE_signed: rlm@1: switch(debuggerRadix) { rlm@1: case 0: rlm@1: printf("%d", value); rlm@1: break; rlm@1: case 1: rlm@1: printf("0x%x", value); rlm@1: break; rlm@1: case 2: rlm@1: printf("0%o", value); rlm@1: break; rlm@1: } rlm@1: break; rlm@1: case DW_ATE_unsigned: rlm@1: case DW_ATE_unsigned_char: rlm@1: switch(debuggerRadix) { rlm@1: case 0: rlm@1: printf("%u", value); rlm@1: break; rlm@1: case 1: rlm@1: printf("0x%x", value); rlm@1: break; rlm@1: case 2: rlm@1: printf("0%o", value); rlm@1: break; rlm@1: } rlm@1: break; rlm@1: default: rlm@1: printf("UNKNOWN BASE %d %08x", t->encoding, value); rlm@1: } rlm@1: } rlm@1: rlm@1: char *debuggerPrintType(Type *t) rlm@1: { rlm@1: char buffer[1024]; rlm@1: static char buffer2[1024]; rlm@1: rlm@1: if(t->type == TYPE_pointer) { rlm@1: if(t->pointer) rlm@1: strcpy(buffer, debuggerPrintType(t->pointer)); rlm@1: else rlm@1: strcpy(buffer, "void"); rlm@1: sprintf(buffer2, "%s *", buffer); rlm@1: return buffer2; rlm@1: } else if(t->type == TYPE_reference) { rlm@1: strcpy(buffer, debuggerPrintType(t->pointer)); rlm@1: sprintf(buffer2, "%s &", buffer); rlm@1: return buffer2; rlm@1: } rlm@1: return t->name; rlm@1: } rlm@1: rlm@1: void debuggerPrintValueInternal(Function *, Type *, ELFBlock *, int, int, u32); rlm@1: void debuggerPrintValueInternal(Function *f, Type *t, rlm@1: int bitSize, int bitOffset, rlm@1: u32 objLocation, LocationType type); rlm@1: rlm@1: u32 debuggerGetValue(u32 location, LocationType type) rlm@1: { rlm@1: switch(type) { rlm@1: case LOCATION_memory: rlm@1: return debuggerReadMemory(location); rlm@1: case LOCATION_register: rlm@1: return reg[location].I; rlm@1: case LOCATION_value: rlm@1: return location; rlm@1: } rlm@1: return 0; rlm@1: } rlm@1: rlm@1: void debuggerPrintPointer(Type *t, u32 value) rlm@1: { rlm@1: printf("(%s)0x%08x", debuggerPrintType(t), value); rlm@1: } rlm@1: rlm@1: void debuggerPrintReference(Type *t, u32 value) rlm@1: { rlm@1: printf("(%s)0x%08x", debuggerPrintType(t), value); rlm@1: } rlm@1: rlm@1: void debuggerPrintFunction(Type *t, u32 value) rlm@1: { rlm@1: printf("(%s)0x%08x", debuggerPrintType(t), value); rlm@1: } rlm@1: rlm@1: void debuggerPrintArray(Type *t, u32 value) rlm@1: { rlm@1: // todo rlm@1: printf("(%s[])0x%08x", debuggerPrintType(t->array->type), value); rlm@1: } rlm@1: rlm@1: void debuggerPrintMember(Function *f, rlm@1: Member *m, rlm@1: u32 objLocation, rlm@1: u32 location) rlm@1: { rlm@1: int bitSize = m->bitSize; rlm@1: if(bitSize) { rlm@1: u32 value = 0; rlm@1: int off = m->bitOffset; rlm@1: int size = m->byteSize; rlm@1: u32 v = 0; rlm@1: if(size == 1) rlm@1: v = debuggerReadByte(location); rlm@1: else if(size == 2) rlm@1: v = debuggerReadHalfWord(location); rlm@1: else if(size == 4) rlm@1: v = debuggerReadMemory(location); rlm@1: rlm@1: while(bitSize) { rlm@1: int top = size*8 - off; rlm@1: int bot = top - bitSize; rlm@1: top--; rlm@1: if(bot >= 0) { rlm@1: value = (v >> (size*8 - bitSize - off)) & ((1 << bitSize)-1); rlm@1: bitSize = 0; rlm@1: } else { rlm@1: value |= (v & ((1 << top)-1)) << (bitSize - top); rlm@1: bitSize -= (top+1); rlm@1: location -= size; rlm@1: off = 0; rlm@1: if(size == 1) rlm@1: v = debuggerReadByte(location); rlm@1: else if(size == 2) rlm@1: v = debuggerReadHalfWord(location); rlm@1: else rlm@1: v = debuggerReadMemory(location); rlm@1: } rlm@1: } rlm@1: debuggerPrintBaseType(m->type, value, location, LOCATION_memory, rlm@1: bitSize, 0); rlm@1: } else { rlm@1: debuggerPrintValueInternal(f, m->type, m->location, m->bitSize, rlm@1: m->bitOffset, objLocation); rlm@1: } rlm@1: } rlm@1: rlm@1: void debuggerPrintStructure(Function *f, Type *t, u32 objLocation) rlm@1: { rlm@1: printf("{"); rlm@1: int count = t->structure->memberCount; rlm@1: int i = 0; rlm@1: while(i < count) { rlm@1: Member *m = &t->structure->members[i]; rlm@1: printf("%s=", m->name); rlm@1: LocationType type; rlm@1: u32 location = elfDecodeLocation(f, m->location, &type, objLocation); rlm@1: debuggerPrintMember(f, m, objLocation, location); rlm@1: i++; rlm@1: if(i < count) rlm@1: printf(","); rlm@1: } rlm@1: printf("}"); rlm@1: } rlm@1: rlm@1: void debuggerPrintUnion(Function *f, Type *t, u32 objLocation) rlm@1: { rlm@1: // todo rlm@1: printf("{"); rlm@1: int count = t->structure->memberCount; rlm@1: int i = 0; rlm@1: while(i < count) { rlm@1: Member *m = &t->structure->members[i]; rlm@1: printf("%s=", m->name); rlm@1: debuggerPrintMember(f, m, objLocation, 0); rlm@1: i++; rlm@1: if(i < count) rlm@1: printf(","); rlm@1: } rlm@1: printf("}"); rlm@1: } rlm@1: rlm@1: void debuggerPrintEnum(Type *t, u32 value) rlm@1: { rlm@1: int i; rlm@1: for(i = 0; i < t->enumeration->count; i++) { rlm@1: EnumMember *m = (EnumMember *)&t->enumeration->members[i]; rlm@1: if(value == m->value) { rlm@1: puts(m->name); rlm@1: return; rlm@1: } rlm@1: } rlm@1: printf("(UNKNOWN VALUE) %d", value); rlm@1: } rlm@1: rlm@1: void debuggerPrintValueInternal(Function *f, Type *t, rlm@1: int bitSize, int bitOffset, rlm@1: u32 objLocation, LocationType type) rlm@1: { rlm@1: u32 value = debuggerGetValue(objLocation, type); rlm@1: if(!t) { rlm@1: printf("void"); rlm@1: return; rlm@1: } rlm@1: switch(t->type) { rlm@1: case TYPE_base: rlm@1: debuggerPrintBaseType(t, value, objLocation, type, bitSize, bitOffset); rlm@1: break; rlm@1: case TYPE_pointer: rlm@1: debuggerPrintPointer(t, value); rlm@1: break; rlm@1: case TYPE_reference: rlm@1: debuggerPrintReference(t, value); rlm@1: break; rlm@1: case TYPE_function: rlm@1: debuggerPrintFunction(t, value); rlm@1: break; rlm@1: case TYPE_array: rlm@1: debuggerPrintArray(t, objLocation); rlm@1: break; rlm@1: case TYPE_struct: rlm@1: debuggerPrintStructure(f, t, objLocation); rlm@1: break; rlm@1: case TYPE_union: rlm@1: debuggerPrintUnion(f, t, objLocation); rlm@1: break; rlm@1: case TYPE_enum: rlm@1: debuggerPrintEnum(t, value); rlm@1: break; rlm@1: default: rlm@1: printf("%08x", value); rlm@1: break; rlm@1: } rlm@1: } rlm@1: rlm@1: void debuggerPrintValueInternal(Function *f, Type *t, ELFBlock *loc, rlm@1: int bitSize, int bitOffset, u32 objLocation) rlm@1: { rlm@1: LocationType type; rlm@1: u32 location; rlm@1: if(loc) { rlm@1: if(objLocation) rlm@1: location = elfDecodeLocation(f, loc, &type, objLocation); rlm@1: else rlm@1: location = elfDecodeLocation(f, loc,&type); rlm@1: } else { rlm@1: location = objLocation; rlm@1: type = LOCATION_memory; rlm@1: } rlm@1: rlm@1: debuggerPrintValueInternal(f, t, bitSize, bitOffset, location, type); rlm@1: } rlm@1: rlm@1: void debuggerPrintValue(Function *f, Object *o) rlm@1: { rlm@1: debuggerPrintValueInternal(f, o->type, o->location, 0, 0, 0); rlm@1: rlm@1: printf("\n"); rlm@1: } rlm@1: rlm@1: void debuggerSymbols(int argc, char **argv) rlm@1: { rlm@1: int i = 0; rlm@1: u32 value; rlm@1: u32 size; rlm@1: int type; rlm@1: bool match = false; rlm@1: int matchSize = 0; rlm@1: char *matchStr = NULL; rlm@1: rlm@1: if(argc == 2) { rlm@1: match = true; rlm@1: matchSize = strlen(argv[1]); rlm@1: matchStr = argv[1]; rlm@1: } rlm@1: printf("Symbol Value Size Type \n"); rlm@1: printf("-------------------- ------- -------- -------\n"); rlm@1: char *s = NULL; rlm@1: while((s = elfGetSymbol(i, &value, &size, &type))) { rlm@1: if(*s) { rlm@1: if(match) { rlm@1: if(strncmp(s, matchStr, matchSize) != 0) { rlm@1: i++; rlm@1: continue; rlm@1: } rlm@1: } rlm@1: const char *ts = "?"; rlm@1: switch(type) { rlm@1: case 2: rlm@1: ts = "ARM"; rlm@1: break; rlm@1: case 0x0d: rlm@1: ts = "THUMB"; rlm@1: break; rlm@1: case 1: rlm@1: ts = "DATA"; rlm@1: break; rlm@1: } rlm@1: printf("%-20s %08x %08x %-7s\n", rlm@1: s, value, size, ts); rlm@1: } rlm@1: i++; rlm@1: } rlm@1: } rlm@1: rlm@1: void debuggerSetRadix(int argc, char **argv) rlm@1: { rlm@1: if(argc != 2) rlm@1: debuggerUsage(argv[0]); rlm@1: else { rlm@1: int r = atoi(argv[1]); rlm@1: rlm@1: bool error = false; rlm@1: switch(r) { rlm@1: case 10: rlm@1: debuggerRadix = 0; rlm@1: break; rlm@1: case 8: rlm@1: debuggerRadix = 2; rlm@1: break; rlm@1: case 16: rlm@1: debuggerRadix = 1; rlm@1: break; rlm@1: default: rlm@1: error = true; rlm@1: printf("Unknown radix %d. Valid values are 8, 10 and 16.\n", r); rlm@1: break; rlm@1: } rlm@1: if(!error) rlm@1: printf("Radix set to %d\n", r); rlm@1: } rlm@1: } rlm@1: rlm@1: void debuggerPrint(int argc, char **argv) rlm@1: { rlm@1: if(argc != 2 && argc != 3) { rlm@1: debuggerUsage(argv[0]); rlm@1: } else { rlm@1: u32 pc = armNextPC; rlm@1: Function *f = NULL; rlm@1: CompileUnit *u = NULL; rlm@1: rlm@1: elfGetCurrentFunction(pc, rlm@1: &f, &u); rlm@1: rlm@1: int oldRadix = debuggerRadix; rlm@1: if(argc == 3) { rlm@1: if(argv[1][0] == '/') { rlm@1: if(argv[1][1] == 'x') rlm@1: debuggerRadix = 1; rlm@1: else if(argv[1][1] == 'o') rlm@1: debuggerRadix = 2; rlm@1: else if(argv[1][1] == 'd') rlm@1: debuggerRadix = 0; rlm@1: else { rlm@1: printf("Unknown format %c\n", argv[1][1]); rlm@1: return; rlm@1: } rlm@1: } else { rlm@1: printf("Unknown option %s\n", argv[1]); rlm@1: return; rlm@1: } rlm@1: } rlm@1: rlm@1: char *s = argc == 2 ? argv[1] : argv[2]; rlm@1: rlm@1: extern char *exprString; rlm@1: extern int exprCol; rlm@1: extern int yyparse(); rlm@1: exprString = s; rlm@1: exprCol = 0; rlm@1: if(!yyparse()) { rlm@1: extern Node *result; rlm@1: if(result->resolve(result, f, u)) { rlm@1: if(result->member) rlm@1: debuggerPrintMember(f, rlm@1: result->member, rlm@1: result->objLocation, rlm@1: result->location); rlm@1: else rlm@1: debuggerPrintValueInternal(f, result->type, 0, 0, rlm@1: result->location, rlm@1: result->locType); rlm@1: printf("\n"); rlm@1: } else { rlm@1: printf("Error resolving expression\n"); rlm@1: } rlm@1: } else { rlm@1: printf("Error parsing expression:\n"); rlm@1: printf("%s\n", s); rlm@1: exprCol--; rlm@1: for(int i = 0; i < exprCol; i++) rlm@1: printf(" "); rlm@1: printf("^\n"); rlm@1: } rlm@1: extern void exprCleanBuffer(); rlm@1: exprCleanBuffer(); rlm@1: exprNodeCleanUp(); rlm@1: debuggerRadix = oldRadix; rlm@1: } rlm@1: } rlm@1: rlm@1: void debuggerHelp(int n, char **args) rlm@1: { rlm@1: if(n == 2) { rlm@1: debuggerUsage(args[1]); rlm@1: } else { rlm@1: for(int i = 0; ; i++) { rlm@1: if(debuggerCommands[i].name) { rlm@1: printf("%s\t%s\n", debuggerCommands[i].name, debuggerCommands[i].help); rlm@1: } else rlm@1: break; rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: void debuggerDebug(int n, char **args) rlm@1: { rlm@1: if(n == 2) { rlm@1: int v = 0; rlm@1: sscanf(args[1], "%d", &v); rlm@1: systemDebug = v; rlm@1: printf("Debug level set to %d\n", systemDebug); rlm@1: } else rlm@1: debuggerUsage("trace"); rlm@1: } rlm@1: rlm@1: void debuggerVerbose(int n, char **args) rlm@1: { rlm@1: if(n == 2) { rlm@1: int v = 0; rlm@1: sscanf(args[1], "%d", &v); rlm@1: systemVerbose = v; rlm@1: printf("Verbose level set to %d\n", systemVerbose); rlm@1: } else rlm@1: debuggerUsage("verbose"); rlm@1: } rlm@1: rlm@1: void debuggerWhere(int n, char **args) rlm@1: { rlm@1: void elfPrintCallChain(u32); rlm@1: elfPrintCallChain(armNextPC); rlm@1: } rlm@1: rlm@1: void debuggerLocals(int n, char **args) rlm@1: { rlm@1: Function *f = NULL; rlm@1: CompileUnit *u = NULL; rlm@1: u32 pc = armNextPC; rlm@1: if(elfGetCurrentFunction(pc, rlm@1: &f, &u)) { rlm@1: Object *o = f->parameters; rlm@1: while(o) { rlm@1: printf("%s=", o->name); rlm@1: debuggerPrintValue(f, o); rlm@1: o = o->next; rlm@1: } rlm@1: rlm@1: o = f->variables; rlm@1: while(o) { rlm@1: bool visible = o->startScope ? pc>=o->startScope : true; rlm@1: if(visible) rlm@1: visible = o->endScope ? pc < o->endScope : true; rlm@1: if(visible) { rlm@1: printf("%s=", o->name); rlm@1: debuggerPrintValue(f, o); rlm@1: } rlm@1: o = o->next; rlm@1: } rlm@1: } else { rlm@1: printf("No information for current address\n"); rlm@1: } rlm@1: } rlm@1: rlm@1: void debuggerNext(int n, char **args) rlm@1: { rlm@1: int count = 1; rlm@1: if(n == 2) { rlm@1: sscanf(args[1], "%d", &count); rlm@1: } rlm@1: for(int i = 0; i < count; i++) { rlm@1: if(debuggerAtBreakpoint) { rlm@1: debuggerContinueAfterBreakpoint(); rlm@1: debuggerEnableBreakpoints(false); rlm@1: } else rlm@1: theEmulator.emuMain(1); rlm@1: } rlm@1: debuggerDisableBreakpoints(); rlm@1: Function *f = NULL; rlm@1: CompileUnit *u = NULL; rlm@1: u32 a = armNextPC; rlm@1: if(elfGetCurrentFunction(a, &f, &u)) { rlm@1: char *file; rlm@1: int line = elfFindLine(u, f, a, &file); rlm@1: rlm@1: printf("File %s, function %s, line %d\n", file, f->name, rlm@1: line); rlm@1: } rlm@1: debuggerRegisters(0, NULL); rlm@1: } rlm@1: rlm@1: void debuggerContinue(int n, char **args) rlm@1: { rlm@1: if(debuggerAtBreakpoint) rlm@1: debuggerContinueAfterBreakpoint(); rlm@1: debuggerEnableBreakpoints(false); rlm@1: debugger = false; rlm@1: } rlm@1: rlm@1: void debuggerSignal(int sig,int number) rlm@1: { rlm@1: switch(sig) { rlm@1: case 4: rlm@1: { rlm@1: printf("Illegal instruction at %08x\n", armNextPC); rlm@1: debugger = true; rlm@1: } rlm@1: break; rlm@1: case 5: rlm@1: { rlm@1: printf("Breakpoint %d reached\n", number); rlm@1: debugger = true; rlm@1: debuggerAtBreakpoint = true; rlm@1: debuggerBreakpointNumber = number; rlm@1: debuggerDisableBreakpoints(); rlm@1: rlm@1: Function *f = NULL; rlm@1: CompileUnit *u = NULL; rlm@1: rlm@1: if(elfGetCurrentFunction(armNextPC, &f, &u)) { rlm@1: char *file; rlm@1: int line = elfFindLine(u,f,armNextPC,&file); rlm@1: printf("File %s, function %s, line %d\n", file, f->name, rlm@1: line); rlm@1: } rlm@1: } rlm@1: break; rlm@1: default: rlm@1: printf("Unknown signal %d\n", sig); rlm@1: break; rlm@1: } rlm@1: } rlm@1: rlm@1: void debuggerBreakList(int, char **) rlm@1: { rlm@1: printf("Num Address Type Symbol\n"); rlm@1: printf("--- -------- ----- ------\n"); rlm@1: for(int i = 0; i < debuggerNumOfBreakpoints; i++) { rlm@1: printf("%3d %08x %s %s\n",i, debuggerBreakpointList[i].address, rlm@1: debuggerBreakpointList[i].size ? "ARM" : "THUMB", rlm@1: elfGetAddressSymbol(debuggerBreakpointList[i].address)); rlm@1: } rlm@1: } rlm@1: rlm@1: void debuggerBreakDelete(int n, char **args) rlm@1: { rlm@1: if(n == 2) { rlm@1: int n = 0; rlm@1: sscanf(args[1], "%d", &n); rlm@1: printf("Deleting breakpoint %d (%d)\n", n, debuggerNumOfBreakpoints); rlm@1: if(n >= 0 && n < debuggerNumOfBreakpoints) { rlm@1: n++; rlm@1: if(n < debuggerNumOfBreakpoints) { rlm@1: for(int i = n; i < debuggerNumOfBreakpoints; i++) { rlm@1: debuggerBreakpointList[i-1].address = rlm@1: debuggerBreakpointList[i].address; rlm@1: debuggerBreakpointList[i-1].value = rlm@1: debuggerBreakpointList[i].value; rlm@1: debuggerBreakpointList[i-1].size = rlm@1: debuggerBreakpointList[i].size; rlm@1: } rlm@1: } rlm@1: debuggerNumOfBreakpoints--; rlm@1: } rlm@1: } else rlm@1: debuggerUsage("bd"); rlm@1: } rlm@1: rlm@1: void debuggerBreak(int n, char **args) rlm@1: { rlm@1: if(n == 2) { rlm@1: u32 address = 0; rlm@1: u32 value = 0; rlm@1: int type = 0; rlm@1: char *s = args[1]; rlm@1: char c = *s; rlm@1: if(strchr(s, ':')) { rlm@1: char *name = s; rlm@1: char *l = strchr(s, ':'); rlm@1: *l++ = 0; rlm@1: int line = atoi(l); rlm@1: rlm@1: u32 addr; rlm@1: Function *f; rlm@1: CompileUnit *u; rlm@1: rlm@1: if(elfFindLineInModule(&addr, name, line)) { rlm@1: if(elfGetCurrentFunction(addr, &f, &u)) { rlm@1: u32 addr2; rlm@1: if(elfGetSymbolAddress(f->name, &addr2, &value, &type)) { rlm@1: address = addr; rlm@1: } else { rlm@1: printf("Unable to get function symbol data\n"); rlm@1: return; rlm@1: } rlm@1: } else { rlm@1: printf("Unable to find function for address\n"); rlm@1: return; rlm@1: } rlm@1: } else { rlm@1: printf("Unable to find module or line\n"); rlm@1: return; rlm@1: } rlm@1: } else if(c >= '0' && c <= '9') { rlm@1: int line = atoi(s); rlm@1: Function *f; rlm@1: CompileUnit *u; rlm@1: u32 addr; rlm@1: rlm@1: if(elfGetCurrentFunction(armNextPC, &f, &u)) { rlm@1: if(elfFindLineInUnit(&addr, u, line)) { rlm@1: if(elfGetCurrentFunction(addr, &f, &u)) { rlm@1: u32 addr2; rlm@1: if(elfGetSymbolAddress(f->name, &addr2, &value, &type)) { rlm@1: address = addr; rlm@1: } else { rlm@1: printf("Unable to get function symbol data\n"); rlm@1: return; rlm@1: } rlm@1: } else { rlm@1: printf("Unable to find function for address\n"); rlm@1: return; rlm@1: } rlm@1: } else { rlm@1: printf("Unable to find line\n"); rlm@1: return; rlm@1: } rlm@1: } else { rlm@1: printf("Cannot find current function\n"); rlm@1: return; rlm@1: } rlm@1: } else { rlm@1: if(!elfGetSymbolAddress(s, &address, &value, &type)) { rlm@1: printf("Function %s not found\n", args[1]); rlm@1: return; rlm@1: } rlm@1: } rlm@1: if(type == 0x02 || type == 0x0d) { rlm@1: int i = debuggerNumOfBreakpoints; rlm@1: int size = 0; rlm@1: if(type == 2) rlm@1: size = 1; rlm@1: debuggerBreakpointList[i].address = address; rlm@1: debuggerBreakpointList[i].value = type == 0x02 ? rlm@1: debuggerReadMemory(address) : debuggerReadHalfWord(address); rlm@1: debuggerBreakpointList[i].size = size; rlm@1: // debuggerApplyBreakpoint(address, i, size); rlm@1: debuggerNumOfBreakpoints++; rlm@1: if(size) rlm@1: printf("Added ARM breakpoint at %08x\n", address); rlm@1: else rlm@1: printf("Added THUMB breakpoint at %08x\n", address); rlm@1: } else { rlm@1: printf("%s is not a function symbol\n", args[1]); rlm@1: } rlm@1: } else rlm@1: debuggerUsage("break"); rlm@1: } rlm@1: rlm@1: void debuggerBreakThumb(int n, char **args) rlm@1: { rlm@1: if(n == 2) { rlm@1: u32 address = 0; rlm@1: sscanf(args[1],"%x", &address); rlm@1: int i = debuggerNumOfBreakpoints; rlm@1: debuggerBreakpointList[i].address = address; rlm@1: debuggerBreakpointList[i].value = debuggerReadHalfWord(address); rlm@1: debuggerBreakpointList[i].size = 0; rlm@1: // debuggerApplyBreakpoint(address, i, 0); rlm@1: debuggerNumOfBreakpoints++; rlm@1: printf("Added THUMB breakpoint at %08x\n", address); rlm@1: } else rlm@1: debuggerUsage("bt"); rlm@1: } rlm@1: rlm@1: void debuggerBreakArm(int n, char **args) rlm@1: { rlm@1: if(n == 2) { rlm@1: u32 address = 0; rlm@1: sscanf(args[1],"%x", &address); rlm@1: int i = debuggerNumOfBreakpoints; rlm@1: debuggerBreakpointList[i].address = address; rlm@1: debuggerBreakpointList[i].value = debuggerReadMemory(address); rlm@1: debuggerBreakpointList[i].size = 1; rlm@1: // debuggerApplyBreakpoint(address, i, 1); rlm@1: debuggerNumOfBreakpoints++; rlm@1: printf("Added ARM breakpoint at %08x\n", address); rlm@1: } else rlm@1: debuggerUsage("ba"); rlm@1: } rlm@1: rlm@1: void debuggerBreakOnWrite(u32 *mem, u32 oldvalue, u32 value, int size) rlm@1: { rlm@1: u32 address = 0; rlm@1: if(mem >= (u32*)&workRAM[0] && mem <= (u32*)&workRAM[0x3ffff]) rlm@1: address = 0x2000000 + ((u64)mem - (u64)&workRAM[0]); rlm@1: else rlm@1: address = 0x3000000 + ((u64)mem - (u64)&internalRAM[0]); rlm@1: rlm@1: if(size == 2) rlm@1: printf("Breakpoint (on write) address %08x old:%08x new:%08x\n", rlm@1: address, oldvalue, value); rlm@1: else if(size == 1) rlm@1: printf("Breakpoint (on write) address %08x old:%04x new:%04x\n", rlm@1: address, (u16)oldvalue,(u16)value); rlm@1: else rlm@1: printf("Breakpoint (on write) address %08x old:%02x new:%02x\n", rlm@1: address, (u8)oldvalue, (u8)value); rlm@1: debugger = true; rlm@1: } rlm@1: rlm@1: void debuggerBreakWriteClear(int n, char **args) rlm@1: { rlm@1: memset(freezeWorkRAM, false, 0x40000); rlm@1: memset(freezeInternalRAM, false, 0x8000); rlm@1: printf("Cleared all break on write\n"); rlm@1: } rlm@1: rlm@1: void debuggerBreakWrite(int n, char **args) rlm@1: { rlm@1: if(n == 3) { rlm@1: if(cheatsNumber != 0) { rlm@1: printf("Cheats are enabled. Cannot continue.\n"); rlm@1: return; rlm@1: } rlm@1: u32 address = 0; rlm@1: sscanf(args[1], "%x", &address); rlm@1: int n = 0; rlm@1: sscanf(args[2], "%d", &n); rlm@1: rlm@1: if(address < 0x2000000 || address > 0x3007fff) { rlm@1: printf("Invalid address: %08x\n", address); rlm@1: return; rlm@1: } rlm@1: rlm@1: if(address > 0x203ffff && address < 0x3000000) { rlm@1: printf("Invalid address: %08x\n", address); rlm@1: return; rlm@1: } rlm@1: rlm@1: u32 final = address + n; rlm@1: rlm@1: if(address < 0x2040000 && final > 0x2040000) { rlm@1: printf("Invalid byte count: %d\n", n); rlm@1: return; rlm@1: } else if(address < 0x3008000 && final > 0x3008000) { rlm@1: printf("Invalid byte count: %d\n", n); rlm@1: return; rlm@1: } rlm@1: printf("Added break on write at %08x for %d bytes\n", address, n); rlm@1: for(int i = 0; i < n; i++) { rlm@1: if((address >> 24) == 2) rlm@1: freezeWorkRAM[address & 0x3ffff] = true; rlm@1: else rlm@1: freezeInternalRAM[address & 0x7fff] = true; rlm@1: address++; rlm@1: } rlm@1: } else rlm@1: debuggerUsage("bpw"); rlm@1: } rlm@1: rlm@1: void debuggerDisassembleArm(int n, char **args) rlm@1: { rlm@1: char buffer[80]; rlm@1: u32 pc = reg[15].I; rlm@1: pc -= 4; rlm@1: int count = 20; rlm@1: if(n >= 2) { rlm@1: sscanf(args[1], "%x", &pc); rlm@1: } rlm@1: if(pc & 3) { rlm@1: printf("Misaligned address %08x\n", pc); rlm@1: pc &= 0xfffffffc; rlm@1: } rlm@1: if(n >= 3) { rlm@1: sscanf(args[2], "%d", &count); rlm@1: } rlm@1: int i = 0; rlm@1: int len = 0; rlm@1: char format[30]; rlm@1: for(i = 0; i < count; i++) { rlm@1: int l = strlen(elfGetAddressSymbol(pc+4*i)); rlm@1: if(l > len) rlm@1: len = l; rlm@1: } rlm@1: sprintf(format, "%%08x %%-%ds %%s\n", len); rlm@1: for(i = 0; i < count; i++) { rlm@1: u32 addr = pc; rlm@1: pc += disArm(pc, buffer, 2); rlm@1: printf(format, addr, elfGetAddressSymbol(addr), buffer); rlm@1: } rlm@1: } rlm@1: rlm@1: void debuggerDisassembleThumb(int n, char **args) rlm@1: { rlm@1: char buffer[80]; rlm@1: u32 pc = reg[15].I; rlm@1: pc -= 2; rlm@1: int count = 20; rlm@1: if(n >= 2) { rlm@1: sscanf(args[1], "%x", &pc); rlm@1: } rlm@1: if(pc & 1) { rlm@1: printf("Misaligned address %08x\n", pc); rlm@1: pc &= 0xfffffffe; rlm@1: } rlm@1: if(n >= 3) { rlm@1: sscanf(args[2], "%d", &count); rlm@1: } rlm@1: rlm@1: int i = 0; rlm@1: int len = 0; rlm@1: char format[30]; rlm@1: for(i = 0; i < count; i++) { rlm@1: int l = strlen(elfGetAddressSymbol(pc+2*i)); rlm@1: if(l > len) rlm@1: len = l; rlm@1: } rlm@1: sprintf(format, "%%08x %%-%ds %%s\n", len); rlm@1: rlm@1: for(i = 0; i < count; i++) { rlm@1: u32 addr = pc; rlm@1: pc += disThumb(pc, buffer, 2); rlm@1: printf(format, addr, elfGetAddressSymbol(addr), buffer); rlm@1: } rlm@1: } rlm@1: rlm@1: void debuggerDisassemble(int n, char **args) rlm@1: { rlm@1: if(armState) rlm@1: debuggerDisassembleArm(n, args); rlm@1: else rlm@1: debuggerDisassembleThumb(n, args); rlm@1: } rlm@1: rlm@1: void debuggerContinueAfterBreakpoint() rlm@1: { rlm@1: printf("Continuing after breakpoint\n"); rlm@1: debuggerEnableBreakpoints(true); rlm@1: theEmulator.emuMain(1); rlm@1: debuggerAtBreakpoint = false; rlm@1: } rlm@1: rlm@1: void debuggerRegisters(int, char **) rlm@1: { rlm@1: char *command[3]; rlm@1: char buffer[10]; rlm@1: rlm@1: printf("R00=%08x R04=%08x R08=%08x R12=%08x\n", rlm@1: reg[0].I, reg[4].I, reg[8].I, reg[12].I); rlm@1: printf("R01=%08x R05=%08x R09=%08x R13=%08x\n", rlm@1: reg[1].I, reg[5].I, reg[9].I, reg[13].I); rlm@1: printf("R02=%08x R06=%08x R10=%08x R14=%08x\n", rlm@1: reg[2].I, reg[6].I, reg[10].I, reg[14].I); rlm@1: printf("R03=%08x R07=%08x R11=%08x R15=%08x\n", rlm@1: reg[3].I, reg[7].I, reg[11].I, reg[15].I); rlm@1: printf("CPSR=%08x (%c%c%c%c%c%c%c Mode: %02x)\n", rlm@1: reg[16].I, rlm@1: (N_FLAG ? 'N' : '.'), rlm@1: (Z_FLAG ? 'Z' : '.'), rlm@1: (C_FLAG ? 'C' : '.'), rlm@1: (V_FLAG ? 'V' : '.'), rlm@1: (armIrqEnable ? '.' : 'I'), rlm@1: ((!(reg[16].I & 0x40)) ? '.' : 'F'), rlm@1: (armState ? '.' : 'T'), rlm@1: armMode); rlm@1: sprintf(buffer,"%08x", armState ? reg[15].I - 4 : reg[15].I - 2); rlm@1: command[0]=const_cast("m"); rlm@1: command[1]=buffer; rlm@1: command[2]=const_cast("1"); rlm@1: debuggerDisassemble(3, command); rlm@1: } rlm@1: rlm@1: void debuggerIoVideo() rlm@1: { rlm@1: printf("DISPCNT = %04x\n", DISPCNT); rlm@1: printf("DISPSTAT = %04x\n", DISPSTAT); rlm@1: printf("VCOUNT = %04x\n", VCOUNT); rlm@1: printf("BG0CNT = %04x\n", BG0CNT); rlm@1: printf("BG1CNT = %04x\n", BG1CNT); rlm@1: printf("BG2CNT = %04x\n", BG2CNT); rlm@1: printf("BG3CNT = %04x\n", BG3CNT); rlm@1: printf("WIN0H = %04x\n", WIN0H); rlm@1: printf("WIN0V = %04x\n", WIN0V); rlm@1: printf("WIN1H = %04x\n", WIN1H); rlm@1: printf("WIN1V = %04x\n", WIN1V); rlm@1: printf("WININ = %04x\n", WININ); rlm@1: printf("WINOUT = %04x\n", WINOUT); rlm@1: printf("MOSAIC = %04x\n", MOSAIC); rlm@1: printf("BLDMOD = %04x\n", BLDMOD); rlm@1: printf("COLEV = %04x\n", COLEV); rlm@1: printf("COLY = %04x\n", COLY); rlm@1: } rlm@1: rlm@1: void debuggerIoVideo2() rlm@1: { rlm@1: printf("BG0HOFS = %04x\n", BG0HOFS); rlm@1: printf("BG0VOFS = %04x\n", BG0VOFS); rlm@1: printf("BG1HOFS = %04x\n", BG1HOFS); rlm@1: printf("BG1VOFS = %04x\n", BG1VOFS); rlm@1: printf("BG2HOFS = %04x\n", BG2HOFS); rlm@1: printf("BG2VOFS = %04x\n", BG2VOFS); rlm@1: printf("BG3HOFS = %04x\n", BG3HOFS); rlm@1: printf("BG3VOFS = %04x\n", BG3VOFS); rlm@1: printf("BG2PA = %04x\n", BG2PA); rlm@1: printf("BG2PB = %04x\n", BG2PB); rlm@1: printf("BG2PC = %04x\n", BG2PC); rlm@1: printf("BG2PD = %04x\n", BG2PD); rlm@1: printf("BG2X = %08x\n", (BG2X_H<<16)|BG2X_L); rlm@1: printf("BG2Y = %08x\n", (BG2Y_H<<16)|BG2Y_L); rlm@1: printf("BG3PA = %04x\n", BG3PA); rlm@1: printf("BG3PB = %04x\n", BG3PB); rlm@1: printf("BG3PC = %04x\n", BG3PC); rlm@1: printf("BG3PD = %04x\n", BG3PD); rlm@1: printf("BG3X = %08x\n", (BG3X_H<<16)|BG3X_L); rlm@1: printf("BG3Y = %08x\n", (BG3Y_H<<16)|BG3Y_L); rlm@1: } rlm@1: rlm@1: void debuggerIoDMA() rlm@1: { rlm@1: printf("DM0SAD = %08x\n", (DM0SAD_H<<16)|DM0SAD_L); rlm@1: printf("DM0DAD = %08x\n", (DM0DAD_H<<16)|DM0DAD_L); rlm@1: printf("DM0CNT = %08x\n", (DM0CNT_H<<16)|DM0CNT_L); rlm@1: printf("DM1SAD = %08x\n", (DM1SAD_H<<16)|DM1SAD_L); rlm@1: printf("DM1DAD = %08x\n", (DM1DAD_H<<16)|DM1DAD_L); rlm@1: printf("DM1CNT = %08x\n", (DM1CNT_H<<16)|DM1CNT_L); rlm@1: printf("DM2SAD = %08x\n", (DM2SAD_H<<16)|DM2SAD_L); rlm@1: printf("DM2DAD = %08x\n", (DM2DAD_H<<16)|DM2DAD_L); rlm@1: printf("DM2CNT = %08x\n", (DM2CNT_H<<16)|DM2CNT_L); rlm@1: printf("DM3SAD = %08x\n", (DM3SAD_H<<16)|DM3SAD_L); rlm@1: printf("DM3DAD = %08x\n", (DM3DAD_H<<16)|DM3DAD_L); rlm@1: printf("DM3CNT = %08x\n", (DM3CNT_H<<16)|DM3CNT_L); rlm@1: } rlm@1: rlm@1: void debuggerIoTimer() rlm@1: { rlm@1: printf("TM0D = %04x\n", TM0D); rlm@1: printf("TM0CNT = %04x\n", TM0CNT); rlm@1: printf("TM1D = %04x\n", TM1D); rlm@1: printf("TM1CNT = %04x\n", TM1CNT); rlm@1: printf("TM2D = %04x\n", TM2D); rlm@1: printf("TM2CNT = %04x\n", TM2CNT); rlm@1: printf("TM3D = %04x\n", TM3D); rlm@1: printf("TM3CNT = %04x\n", TM3CNT); rlm@1: } rlm@1: rlm@1: void debuggerIoMisc() rlm@1: { rlm@1: printf("P1 = %04x\n", P1); rlm@1: printf("IE = %04x\n", IE); rlm@1: printf("IF = %04x\n", IF); rlm@1: printf("IME = %04x\n", IME); rlm@1: } rlm@1: rlm@1: void debuggerIo(int n, char **args) rlm@1: { rlm@1: if(n == 1) { rlm@1: debuggerIoVideo(); rlm@1: return; rlm@1: } rlm@1: if(!strcmp(args[1], "video")) rlm@1: debuggerIoVideo(); rlm@1: else if(!strcmp(args[1], "video2")) rlm@1: debuggerIoVideo2(); rlm@1: else if(!strcmp(args[1], "dma")) rlm@1: debuggerIoDMA(); rlm@1: else if(!strcmp(args[1], "timer")) rlm@1: debuggerIoTimer(); rlm@1: else if(!strcmp(args[1], "misc")) rlm@1: debuggerIoMisc(); rlm@1: else printf("Unrecognized option %s\n", args[1]); rlm@1: } rlm@1: rlm@1: void debuggerEditByte(int n, char **args) rlm@1: { rlm@1: if(n == 3) { rlm@1: u32 address; rlm@1: u32 byte; rlm@1: sscanf(args[1], "%x", &address); rlm@1: sscanf(args[2], "%x", &byte); rlm@1: debuggerWriteByte(address, (u8)byte); rlm@1: } else rlm@1: debuggerUsage("eb"); rlm@1: } rlm@1: rlm@1: void debuggerEditHalfWord(int n, char **args) rlm@1: { rlm@1: if(n == 3) { rlm@1: u32 address; rlm@1: u32 byte; rlm@1: sscanf(args[1], "%x", &address); rlm@1: if(address & 1) { rlm@1: printf("Error: address must be half-word aligned\n"); rlm@1: return; rlm@1: } rlm@1: sscanf(args[2], "%x", &byte); rlm@1: debuggerWriteHalfWord(address, (u16)byte); rlm@1: } else rlm@1: debuggerUsage("eh"); rlm@1: } rlm@1: rlm@1: void debuggerEdit(int n, char **args) rlm@1: { rlm@1: if(n == 3) { rlm@1: u32 address; rlm@1: u32 byte; rlm@1: sscanf(args[1], "%x", &address); rlm@1: if(address & 3) { rlm@1: printf("Error: address must be word aligned\n"); rlm@1: return; rlm@1: } rlm@1: sscanf(args[2], "%x", &byte); rlm@1: debuggerWriteMemory(address, (u32)byte); rlm@1: } else rlm@1: debuggerUsage("ew"); rlm@1: } rlm@1: rlm@1: rlm@1: #define ASCII(c) (c) < 32 ? '.' : (c) > 127 ? '.' : (c) rlm@1: rlm@1: void debuggerMemoryByte(int n, char **args) rlm@1: { rlm@1: if(n == 2) { rlm@1: u32 addr = 0; rlm@1: sscanf(args[1], "%x", &addr); rlm@1: for(int ii = 0; ii < 16; ii++) { rlm@1: int a = debuggerReadByte(addr); rlm@1: int b = debuggerReadByte(addr+1); rlm@1: int c = debuggerReadByte(addr+2); rlm@1: int d = debuggerReadByte(addr+3); rlm@1: int e = debuggerReadByte(addr+4); rlm@1: int f = debuggerReadByte(addr+5); rlm@1: int g = debuggerReadByte(addr+6); rlm@1: int h = debuggerReadByte(addr+7); rlm@1: int i = debuggerReadByte(addr+8); rlm@1: int j = debuggerReadByte(addr+9); rlm@1: int k = debuggerReadByte(addr+10); rlm@1: int l = debuggerReadByte(addr+11); rlm@1: int m = debuggerReadByte(addr+12); rlm@1: int n = debuggerReadByte(addr+13); rlm@1: int o = debuggerReadByte(addr+14); rlm@1: int p = debuggerReadByte(addr+15); rlm@1: rlm@1: printf("%08x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", rlm@1: addr,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p, rlm@1: ASCII(a),ASCII(b),ASCII(c),ASCII(d), rlm@1: ASCII(e),ASCII(f),ASCII(g),ASCII(h), rlm@1: ASCII(i),ASCII(j),ASCII(k),ASCII(l), rlm@1: ASCII(m),ASCII(n),ASCII(o),ASCII(p)); rlm@1: addr += 16; rlm@1: } rlm@1: } else rlm@1: debuggerUsage("mb"); rlm@1: } rlm@1: rlm@1: void debuggerMemoryHalfWord(int n, char **args) rlm@1: { rlm@1: if(n == 2) { rlm@1: u32 addr = 0; rlm@1: sscanf(args[1], "%x", &addr); rlm@1: addr = addr & 0xfffffffe; rlm@1: for(int ii = 0; ii < 16; ii++) { rlm@1: int a = debuggerReadByte(addr); rlm@1: int b = debuggerReadByte(addr+1); rlm@1: int c = debuggerReadByte(addr+2); rlm@1: int d = debuggerReadByte(addr+3); rlm@1: int e = debuggerReadByte(addr+4); rlm@1: int f = debuggerReadByte(addr+5); rlm@1: int g = debuggerReadByte(addr+6); rlm@1: int h = debuggerReadByte(addr+7); rlm@1: int i = debuggerReadByte(addr+8); rlm@1: int j = debuggerReadByte(addr+9); rlm@1: int k = debuggerReadByte(addr+10); rlm@1: int l = debuggerReadByte(addr+11); rlm@1: int m = debuggerReadByte(addr+12); rlm@1: int n = debuggerReadByte(addr+13); rlm@1: int o = debuggerReadByte(addr+14); rlm@1: int p = debuggerReadByte(addr+15); rlm@1: rlm@1: printf("%08x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", rlm@1: addr,b,a,d,c,f,e,h,g,j,i,l,k,n,m,p,o, rlm@1: ASCII(a),ASCII(b),ASCII(c),ASCII(d), rlm@1: ASCII(e),ASCII(f),ASCII(g),ASCII(h), rlm@1: ASCII(i),ASCII(j),ASCII(k),ASCII(l), rlm@1: ASCII(m),ASCII(n),ASCII(o),ASCII(p)); rlm@1: addr += 16; rlm@1: } rlm@1: } else rlm@1: debuggerUsage("mh"); rlm@1: } rlm@1: rlm@1: void debuggerMemory(int n, char **args) rlm@1: { rlm@1: if(n == 2) { rlm@1: u32 addr = 0; rlm@1: sscanf(args[1], "%x", &addr); rlm@1: addr = addr & 0xfffffffc; rlm@1: for(int ii = 0; ii < 16; ii++) { rlm@1: int a = debuggerReadByte(addr); rlm@1: int b = debuggerReadByte(addr+1); rlm@1: int c = debuggerReadByte(addr+2); rlm@1: int d = debuggerReadByte(addr+3); rlm@1: rlm@1: int e = debuggerReadByte(addr+4); rlm@1: int f = debuggerReadByte(addr+5); rlm@1: int g = debuggerReadByte(addr+6); rlm@1: int h = debuggerReadByte(addr+7); rlm@1: rlm@1: int i = debuggerReadByte(addr+8); rlm@1: int j = debuggerReadByte(addr+9); rlm@1: int k = debuggerReadByte(addr+10); rlm@1: int l = debuggerReadByte(addr+11); rlm@1: rlm@1: int m = debuggerReadByte(addr+12); rlm@1: int n = debuggerReadByte(addr+13); rlm@1: int o = debuggerReadByte(addr+14); rlm@1: int p = debuggerReadByte(addr+15); rlm@1: rlm@1: printf("%08x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", rlm@1: addr,d,c,b,a,h,g,f,e,l,k,j,i,p,o,n,m, rlm@1: ASCII(a),ASCII(b),ASCII(c),ASCII(d), rlm@1: ASCII(e),ASCII(f),ASCII(g),ASCII(h), rlm@1: ASCII(i),ASCII(j),ASCII(k),ASCII(l), rlm@1: ASCII(m),ASCII(n),ASCII(o),ASCII(p)); rlm@1: addr += 16; rlm@1: } rlm@1: } else rlm@1: debuggerUsage("mw"); rlm@1: } rlm@1: rlm@1: void debuggerQuit(int, char **) rlm@1: { rlm@1: char buffer[10]; rlm@1: printf("Are you sure you want to quit (y/n)? "); rlm@1: fgets(buffer, 1024, stdin); rlm@1: rlm@1: if(buffer[0] == 'y' || buffer[0] == 'Y') { rlm@1: debugger = false; rlm@1: emulating = false; rlm@1: } rlm@1: } rlm@1: rlm@1: void debuggerOutput(char *s, u32 addr) rlm@1: { rlm@1: if(s) rlm@1: puts(s); rlm@1: else { rlm@1: char c; rlm@1: rlm@1: c = debuggerReadByte(addr); rlm@1: addr++; rlm@1: while(c) { rlm@1: putchar(c); rlm@1: c = debuggerReadByte(addr); rlm@1: addr++; rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: void debuggerMain() rlm@1: { rlm@1: char buffer[1024]; rlm@1: char *commands[10]; rlm@1: int commandCount = 0; rlm@1: rlm@1: if(theEmulator.emuUpdateCPSR) rlm@1: theEmulator.emuUpdateCPSR(); rlm@1: debuggerRegisters(0, NULL); rlm@1: rlm@1: while(debugger) { rlm@1: systemSoundPause(); rlm@1: printf("debugger> "); rlm@1: commandCount = 0; rlm@1: char *s = fgets(buffer, 1024, stdin); rlm@1: rlm@1: commands[0] = strtok(s, " \t\n"); rlm@1: if(commands[0] == NULL) rlm@1: continue; rlm@1: commandCount++; rlm@1: while((s = strtok(NULL, " \t\n"))) { rlm@1: commands[commandCount++] = s; rlm@1: if(commandCount == 10) rlm@1: break; rlm@1: } rlm@1: rlm@1: for(int j = 0; ; j++) { rlm@1: if(debuggerCommands[j].name == NULL) { rlm@1: printf("Unrecognized command %s. Type h for help.\n", commands[0]); rlm@1: break; rlm@1: } rlm@1: if(!strcmp(commands[0], debuggerCommands[j].name)) { rlm@1: debuggerCommands[j].function(commandCount, commands); rlm@1: break; rlm@1: } rlm@1: } rlm@1: } rlm@1: }