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 <stdio.h>
rlm@1: #include <stdlib.h>
rlm@1: } // FIXME: should use c++ headers instead
rlm@1: 
rlm@1: #include <string.h>
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 ? <command> for command help", "[<command>]" },
rlm@1:   { "ba", debuggerBreakArm,   "Adds an ARM breakpoint", "<address>" },
rlm@1:   { "bd", debuggerBreakDelete,"Deletes a breakpoint", "<number>" },
rlm@1:   { "bl", debuggerBreakList,  "Lists breakpoints" },
rlm@1:   { "bpw", debuggerBreakWrite, "Break on write", "<address> <size>" },
rlm@1:   { "bpwc", debuggerBreakWriteClear, "Clear break on write", NULL },
rlm@1:   { "break", debuggerBreak,    "Adds a breakpoint on the given function", "<function>|<line>|<file:line>" },
rlm@1:   { "bt", debuggerBreakThumb, "Adds a THUMB breakpoint", "<address>" },
rlm@1:   { "c", debuggerContinue,    "Continues execution" , NULL },
rlm@1:   { "d", debuggerDisassemble, "Disassembles instructions", "[<address> [<number>]]" },
rlm@1:   { "da", debuggerDisassembleArm, "Disassembles ARM instructions", "[<address> [<number>]]" },
rlm@1:   { "dt", debuggerDisassembleThumb, "Disassembles THUMB instructions", "[<address> [<number>]]" },
rlm@1:   { "eb", debuggerEditByte,   "Modify memory location (byte)", "<address> <hex value>" },
rlm@1:   { "eh", debuggerEditHalfWord,"Modify memory location (half-word)","<address> <hex value>" },
rlm@1:   { "ew", debuggerEdit,       "Modify memory location (word)", "<address> <hex value" },
rlm@1:   { "h", debuggerHelp,        "Shows this help information. Type h <command> for command help", "[<command>]" },
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)", "<address>" },
rlm@1:   { "mh", debuggerMemoryHalfWord, "Shows memory contents (half-words)", "<address>"},
rlm@1:   { "mw", debuggerMemory,     "Shows memory contents (words)", "<address>" },
rlm@1:   { "n", debuggerNext,        "Executes the next instruction", "[<count>]" },
rlm@1:   { "print", debuggerPrint,   "Print the value of a expression (if known)", "[/x|/o|/d] <expression>" },
rlm@1:   { "q", debuggerQuit,        "Quits the emulator", NULL },
rlm@1:   { "r", debuggerRegisters,   "Shows ARM registers", NULL },
rlm@1:   { "radix", debuggerSetRadix,   "Sets the print radix", "<radix>" },
rlm@1:   { "symbols", debuggerSymbols, "List symbols", "[<symbol>]" },
rlm@1: #ifndef FINAL_VERSION
rlm@1:   { "trace", debuggerDebug,       "Sets the trace level", "<value>" },
rlm@1: #endif
rlm@1: #ifdef DEV_VERSION
rlm@1:   { "verbose", debuggerVerbose,     "Change verbose setting", "<value>" },
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<char *>("m");
rlm@1:   command[1]=buffer;
rlm@1:   command[2]=const_cast<char *>("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: }