1 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
2 // Copyright (C) 1999-2003 Forgotten
3 // Copyright (C) 2004 Forgotten and the VBA development team
4 
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2, or(at your option)
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 
23 #include "GBA.h"
24 #include "Port.h"
25 #include "armdis.h"
26 #include "elf.h"
27 #include "exprNode.h"
28 
29 extern bool debugger;
30 extern int emulating;
31 
32 extern struct EmulatedSystem emulator;
33 
34 #define debuggerReadMemory(addr) \
35   READ32LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
36 
37 #define debuggerReadHalfWord(addr) \
38   READ16LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
39 
40 #define debuggerReadByte(addr) \
41   map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
42 
43 #define debuggerWriteMemory(addr, value) \
44   WRITE32LE(&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], value)
45 
46 #define debuggerWriteHalfWord(addr, value) \
47   WRITE16LE(&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], value)
48 
49 #define debuggerWriteByte(addr, value) \
50   map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] = (value)
51 
52 struct breakpointInfo {
53   u32 address;
54   u32 value;
55   int size;
56 };
57 
58 struct DebuggerCommand {
59   char *name;
60   void (*function)(int,char **);
61   char *help;
62   char *syntax;
63 };
64 
65 void debuggerContinueAfterBreakpoint();
66 
67 void debuggerHelp(int,char **);
68 void debuggerNext(int,char **);
69 void debuggerContinue(int, char **);
70 void debuggerRegisters(int, char **);
71 void debuggerBreak(int, char **);
72 void debuggerBreakDelete(int, char **);
73 void debuggerBreakList(int, char **);
74 void debuggerBreakArm(int, char **);
75 void debuggerBreakWriteClear(int, char **);
76 void debuggerBreakThumb(int, char **);
77 void debuggerBreakWrite(int, char **);
78 void debuggerDebug(int, char **);
79 void debuggerDisassemble(int, char **);
80 void debuggerDisassembleArm(int, char **);
81 void debuggerDisassembleThumb(int, char **);
82 void debuggerEditByte(int, char **);
83 void debuggerEditHalfWord(int, char **);
84 void debuggerEdit(int, char **);
85 void debuggerIo(int, char **);
86 void debuggerLocals(int, char **);
87 void debuggerMemoryByte(int, char **);
88 void debuggerMemoryHalfWord(int, char **);
89 void debuggerMemory(int, char **);
90 void debuggerPrint(int, char **);
91 void debuggerQuit(int, char **);
92 void debuggerSetRadix(int, char **);
93 void debuggerSymbols(int, char **);
94 void debuggerVerbose(int, char **);
95 void debuggerWhere(int, char **);
96 
97 DebuggerCommand debuggerCommands[] = {
98   { "?", debuggerHelp,        "Shows this help information. Type ? <command> for command help", "[<command>]" },
99   { "ba", debuggerBreakArm,   "Adds an ARM breakpoint", "<address>" },
100   { "bd", debuggerBreakDelete,"Deletes a breakpoint", "<number>" },
101   { "bl", debuggerBreakList,  "Lists breakpoints" },
102   { "bpw", debuggerBreakWrite, "Break on write", "<address> <size>" },
103   { "bpwc", debuggerBreakWriteClear, "Clear break on write", NULL },
104   { "break", debuggerBreak,    "Adds a breakpoint on the given function", "<function>|<line>|<file:line>" },
105   { "bt", debuggerBreakThumb, "Adds a THUMB breakpoint", "<address>" },
106   { "c", debuggerContinue,    "Continues execution" , NULL },
107   { "d", debuggerDisassemble, "Disassembles instructions", "[<address> [<number>]]" },
108   { "da", debuggerDisassembleArm, "Disassembles ARM instructions", "[<address> [<number>]]" },
109   { "dt", debuggerDisassembleThumb, "Disassembles THUMB instructions", "[<address> [<number>]]" },
110   { "eb", debuggerEditByte,   "Modify memory location (byte)", "<address> <hex value>" },
111   { "eh", debuggerEditHalfWord,"Modify memory location (half-word)","<address> <hex value>" },
112   { "ew", debuggerEdit,       "Modify memory location (word)", "<address> <hex value" },
113   { "h", debuggerHelp,        "Shows this help information. Type h <command> for command help", "[<command>]" },
114   { "io", debuggerIo,         "Show I/O registers status", "[video|video2|dma|timer|misc]" },
115   { "locals", debuggerLocals, "Shows local variables", NULL },
116   { "mb", debuggerMemoryByte, "Shows memory contents (bytes)", "<address>" },
117   { "mh", debuggerMemoryHalfWord, "Shows memory contents (half-words)", "<address>"},
118   { "mw", debuggerMemory,     "Shows memory contents (words)", "<address>" },
119   { "n", debuggerNext,        "Executes the next instruction", "[<count>]" },
120   { "print", debuggerPrint,   "Print the value of a expression (if known)", "[/x|/o|/d] <expression>" },
121   { "q", debuggerQuit,        "Quits the emulator", NULL },
122   { "r", debuggerRegisters,   "Shows ARM registers", NULL },
123   { "radix", debuggerSetRadix,   "Sets the print radix", "<radix>" },
124   { "symbols", debuggerSymbols, "List symbols", "[<symbol>]" },
125 #ifndef FINAL_VERSION
126   { "trace", debuggerDebug,       "Sets the trace level", "<value>" },
127 #endif
128 #ifdef DEV_VERSION
129   { "verbose", debuggerVerbose,     "Change verbose setting", "<value>" },
130 #endif
131   { "where", debuggerWhere,   "Shows call chain", NULL },
132   { NULL, NULL, NULL, NULL} // end marker
133 };
134 
135 breakpointInfo debuggerBreakpointList[100];
136 
137 int debuggerNumOfBreakpoints = 0;
138 bool debuggerAtBreakpoint = false;
139 int debuggerBreakpointNumber = 0;
140 int debuggerRadix = 0;
141 
debuggerApplyBreakpoint(u32 address,int num,int size)142 void debuggerApplyBreakpoint(u32 address, int num, int size)
143 {
144   if(size)
145     debuggerWriteMemory(address, (u32)(0xe1200070 |
146                                        (num & 0xf) |
147                                        ((num<<4)&0xf0)));
148   else
149     debuggerWriteHalfWord(address,
150                           (u16)(0xbe00 | num));
151 }
152 
debuggerDisableBreakpoints()153 void debuggerDisableBreakpoints()
154 {
155   for(int i = 0; i < debuggerNumOfBreakpoints; i++) {
156     if(debuggerBreakpointList[i].size)
157       debuggerWriteMemory(debuggerBreakpointList[i].address,
158                           debuggerBreakpointList[i].value);
159     else
160       debuggerWriteHalfWord(debuggerBreakpointList[i].address,
161                             debuggerBreakpointList[i].value);
162   }
163 }
164 
debuggerEnableBreakpoints(bool skipPC)165 void debuggerEnableBreakpoints(bool skipPC)
166 {
167   for(int i = 0; i < debuggerNumOfBreakpoints; i++) {
168     if(debuggerBreakpointList[i].address == armNextPC && skipPC)
169       continue;
170 
171     debuggerApplyBreakpoint(debuggerBreakpointList[i].address,
172                             i,
173                             debuggerBreakpointList[i].size);
174   }
175 }
176 
debuggerUsage(char * cmd)177 void debuggerUsage(char *cmd)
178 {
179   for(int i = 0; ; i++) {
180     if(debuggerCommands[i].name) {
181       if(!strcmp(debuggerCommands[i].name, cmd)) {
182         printf("%s %s\t%s\n",
183                debuggerCommands[i].name,
184                debuggerCommands[i].syntax ? debuggerCommands[i].syntax : "",
185                debuggerCommands[i].help);
186         break;
187       }
188     } else {
189       printf("Unrecognized command '%s'.", cmd);
190       break;
191     }
192   }
193 }
194 
debuggerPrintBaseType(Type * t,u32 value,u32 location,LocationType type,int bitSize,int bitOffset)195 void debuggerPrintBaseType(Type *t, u32 value, u32 location,
196                            LocationType type,
197                            int bitSize, int bitOffset)
198 {
199   if(bitSize) {
200     if(bitOffset)
201       value >>= ((t->size*8)-bitOffset-bitSize);
202     value &= (1 << bitSize)-1;
203   } else {
204     if(t->size == 2)
205       value &= 0xFFFF;
206     else if(t->size == 1)
207       value &= 0xFF;
208   }
209 
210   if(t->size == 8) {
211     u64 value = 0;
212     if(type == LOCATION_memory) {
213       value = debuggerReadMemory(location) |
214         ((u64)debuggerReadMemory(location+4)<<32);
215     } else if(type == LOCATION_register) {
216       value = reg[location].I | ((u64)reg[location+1].I << 32);
217     }
218     switch(t->encoding) {
219     case DW_ATE_signed:
220       switch(debuggerRadix) {
221       case 0:
222         printf("%lld", value);
223         break;
224       case 1:
225         printf("0x%llx", value);
226         break;
227       case 2:
228         printf("0%llo", value);
229         break;
230       }
231       break;
232     case DW_ATE_unsigned:
233       switch(debuggerRadix) {
234       case 0:
235         printf("%llu", value);
236         break;
237       case 1:
238         printf("0x%llx", value);
239         break;
240       case 2:
241         printf("0%llo", value);
242         break;
243       }
244       break;
245     default:
246       printf("Unknowing 64-bit encoding\n");
247     }
248     return;
249   }
250 
251   switch(t->encoding) {
252   case DW_ATE_boolean:
253     if(value)
254       printf("true");
255     else
256       printf("false");
257     break;
258   case DW_ATE_signed:
259     switch(debuggerRadix) {
260     case 0:
261       printf("%d", value);
262       break;
263     case 1:
264       printf("0x%x", value);
265       break;
266     case 2:
267       printf("0%o", value);
268       break;
269     }
270     break;
271   case DW_ATE_unsigned:
272   case DW_ATE_unsigned_char:
273     switch(debuggerRadix) {
274     case 0:
275       printf("%u", value);
276       break;
277     case 1:
278       printf("0x%x", value);
279       break;
280     case 2:
281       printf("0%o", value);
282       break;
283     }
284     break;
285   default:
286     printf("UNKNOWN BASE %d %08x", t->encoding, value);
287   }
288 }
289 
debuggerPrintType(Type * t)290 char *debuggerPrintType(Type *t)
291 {
292   char buffer[1024];
293   static char buffer2[1024];
294 
295   if(t->type == TYPE_pointer) {
296     if(t->pointer)
297       strcpy(buffer, debuggerPrintType(t->pointer));
298     else
299       strcpy(buffer, "void");
300     sprintf(buffer2, "%s *", buffer);
301     return buffer2;
302   } else if(t->type == TYPE_reference) {
303     strcpy(buffer, debuggerPrintType(t->pointer));
304     sprintf(buffer2, "%s &", buffer);
305     return buffer2;
306   }
307   return t->name;
308 }
309 
310 void debuggerPrintValueInternal(Function *, Type *, ELFBlock *, int, int, u32);
311 void debuggerPrintValueInternal(Function *f, Type *t,
312                                 int bitSize, int bitOffset,
313                                 u32 objLocation, LocationType type);
314 
debuggerGetValue(u32 location,LocationType type)315 u32 debuggerGetValue(u32 location, LocationType type)
316 {
317   switch(type) {
318   case LOCATION_memory:
319     return debuggerReadMemory(location);
320   case LOCATION_register:
321     return reg[location].I;
322   case LOCATION_value:
323     return location;
324   }
325   return 0;
326 }
327 
debuggerPrintPointer(Type * t,u32 value)328 void debuggerPrintPointer(Type *t, u32 value)
329 {
330   printf("(%s)0x%08x", debuggerPrintType(t), value);
331 }
332 
debuggerPrintReference(Type * t,u32 value)333 void debuggerPrintReference(Type *t, u32 value)
334 {
335   printf("(%s)0x%08x", debuggerPrintType(t), value);
336 }
337 
debuggerPrintFunction(Type * t,u32 value)338 void debuggerPrintFunction(Type *t, u32 value)
339 {
340   printf("(%s)0x%08x", debuggerPrintType(t), value);
341 }
342 
debuggerPrintArray(Type * t,u32 value)343 void debuggerPrintArray(Type *t, u32 value)
344 {
345   // todo
346   printf("(%s[])0x%08x", debuggerPrintType(t->array->type), value);
347 }
348 
debuggerPrintMember(Function * f,Member * m,u32 objLocation,u32 location)349 void debuggerPrintMember(Function *f,
350                          Member *m,
351                          u32 objLocation,
352                          u32 location)
353 {
354   int bitSize = m->bitSize;
355   if(bitSize) {
356     u32 value = 0;
357     int off = m->bitOffset;
358     int size = m->byteSize;
359     u32 v = 0;
360     if(size == 1)
361       v = debuggerReadByte(location);
362       else if(size == 2)
363         v = debuggerReadHalfWord(location);
364       else if(size == 4)
365         v = debuggerReadMemory(location);
366 
367       while(bitSize) {
368         int top = size*8 - off;
369         int bot = top - bitSize;
370         top--;
371         if(bot >= 0) {
372           value = (v >> (size*8 - bitSize - off)) & ((1 << bitSize)-1);
373           bitSize = 0;
374         } else {
375           value |= (v & ((1 << top)-1)) << (bitSize - top);
376           bitSize -= (top+1);
377           location -= size;
378           off = 0;
379           if(size == 1)
380             v = debuggerReadByte(location);
381           else if(size == 2)
382             v = debuggerReadHalfWord(location);
383           else
384             v = debuggerReadMemory(location);
385         }
386       }
387       debuggerPrintBaseType(m->type, value, location, LOCATION_memory,
388                             bitSize, 0);
389     } else {
390       debuggerPrintValueInternal(f, m->type, m->location, m->bitSize,
391                                  m->bitOffset, objLocation);
392     }
393 }
394 
debuggerPrintStructure(Function * f,Type * t,u32 objLocation)395 void debuggerPrintStructure(Function *f, Type *t, u32 objLocation)
396 {
397   printf("{");
398   int count = t->structure->memberCount;
399   int i = 0;
400   while(i < count) {
401     Member *m = &t->structure->members[i];
402     printf("%s=", m->name);
403     LocationType type;
404     u32 location = elfDecodeLocation(f, m->location, &type, objLocation);
405     debuggerPrintMember(f, m, objLocation, location);
406     i++;
407     if(i < count)
408       printf(",");
409   }
410   printf("}");
411 }
412 
debuggerPrintUnion(Function * f,Type * t,u32 objLocation)413 void debuggerPrintUnion(Function *f, Type *t, u32 objLocation)
414 {
415   // todo
416   printf("{");
417   int count = t->structure->memberCount;
418   int i = 0;
419   while(i < count) {
420     Member *m = &t->structure->members[i];
421     printf("%s=", m->name);
422     debuggerPrintMember(f, m, objLocation, 0);
423     i++;
424     if(i < count)
425       printf(",");
426   }
427   printf("}");
428 }
429 
debuggerPrintEnum(Type * t,u32 value)430 void debuggerPrintEnum(Type *t, u32 value)
431 {
432   int i;
433   for(i = 0; i < t->enumeration->count; i++) {
434     EnumMember *m = (EnumMember *)&t->enumeration->members[i];
435     if(value == m->value) {
436       printf(m->name);
437       return;
438     }
439   }
440   printf("(UNKNOWN VALUE) %d", value);
441 }
442 
debuggerPrintValueInternal(Function * f,Type * t,int bitSize,int bitOffset,u32 objLocation,LocationType type)443 void debuggerPrintValueInternal(Function *f, Type *t,
444                                 int bitSize, int bitOffset,
445                                 u32 objLocation, LocationType type)
446 {
447   u32 value = debuggerGetValue(objLocation, type);
448   if(!t) {
449     printf("void");
450     return;
451   }
452   switch(t->type) {
453   case TYPE_base:
454     debuggerPrintBaseType(t, value, objLocation, type, bitSize, bitOffset);
455     break;
456   case TYPE_pointer:
457     debuggerPrintPointer(t, value);
458     break;
459   case TYPE_reference:
460     debuggerPrintReference(t, value);
461     break;
462   case TYPE_function:
463     debuggerPrintFunction(t, value);
464     break;
465   case TYPE_array:
466     debuggerPrintArray(t, objLocation);
467     break;
468   case TYPE_struct:
469     debuggerPrintStructure(f, t, objLocation);
470     break;
471   case TYPE_union:
472     debuggerPrintUnion(f, t, objLocation);
473     break;
474   case TYPE_enum:
475     debuggerPrintEnum(t, value);
476     break;
477   default:
478     printf("%08x", value);
479     break;
480   }
481 }
482 
debuggerPrintValueInternal(Function * f,Type * t,ELFBlock * loc,int bitSize,int bitOffset,u32 objLocation)483 void debuggerPrintValueInternal(Function *f, Type *t, ELFBlock *loc,
484                                 int bitSize, int bitOffset, u32 objLocation)
485 {
486   LocationType type;
487   u32 location;
488   if(loc) {
489     if(objLocation)
490       location = elfDecodeLocation(f, loc, &type, objLocation);
491     else
492       location = elfDecodeLocation(f, loc,&type);
493   } else {
494     location = objLocation;
495     type = LOCATION_memory;
496   }
497 
498   debuggerPrintValueInternal(f, t, bitSize, bitOffset, location, type);
499 }
500 
debuggerPrintValue(Function * f,Object * o)501 void debuggerPrintValue(Function *f, Object *o)
502 {
503   debuggerPrintValueInternal(f, o->type, o->location, 0, 0, 0);
504 
505   printf("\n");
506 }
507 
debuggerSymbols(int argc,char ** argv)508 void debuggerSymbols(int argc, char **argv)
509 {
510   int i = 0;
511   u32 value;
512   u32 size;
513   int type;
514   bool match = false;
515   int matchSize = 0;
516   char *matchStr = NULL;
517 
518   if(argc == 2) {
519     match = true;
520     matchSize = strlen(argv[1]);
521     matchStr = argv[1];
522   }
523   printf("Symbol               Value    Size     Type   \n");
524   printf("-------------------- -------  -------- -------\n");
525   char *s = NULL;
526   while((s = elfGetSymbol(i, &value, &size, &type))) {
527     if(*s) {
528       if(match) {
529         if(strncmp(s, matchStr, matchSize) != 0) {
530           i++;
531           continue;
532         }
533       }
534       char *ts = "?";
535       switch(type) {
536       case 2:
537         ts = "ARM";
538         break;
539       case 0x0d:
540         ts = "THUMB";
541         break;
542       case 1:
543         ts = "DATA";
544         break;
545       }
546       printf("%-20s %08x %08x %-7s\n",
547              s, value, size, ts);
548     }
549     i++;
550   }
551 }
552 
debuggerSetRadix(int argc,char ** argv)553 void debuggerSetRadix(int argc, char **argv)
554 {
555   if(argc != 2)
556     debuggerUsage(argv[0]);
557   else {
558     int r = atoi(argv[1]);
559 
560     bool error = false;
561     switch(r) {
562     case 10:
563       debuggerRadix = 0;
564       break;
565     case 8:
566       debuggerRadix = 2;
567       break;
568     case 16:
569       debuggerRadix = 1;
570       break;
571     default:
572       error = true;
573       printf("Unknown radix %d. Valid values are 8, 10 and 16.\n", r);
574       break;
575     }
576     if(!error)
577       printf("Radix set to %d\n", r);
578   }
579 }
580 
debuggerPrint(int argc,char ** argv)581 void debuggerPrint(int argc, char **argv)
582 {
583   if(argc != 2 && argc != 3) {
584     debuggerUsage(argv[0]);
585   } else {
586     u32 pc = armNextPC;
587     Function *f = NULL;
588     CompileUnit *u = NULL;
589 
590     elfGetCurrentFunction(pc,
591                           &f, &u);
592 
593     int oldRadix = debuggerRadix;
594     if(argc == 3) {
595       if(argv[1][0] == '/') {
596         if(argv[1][1] == 'x')
597           debuggerRadix = 1;
598         else if(argv[1][1] == 'o')
599           debuggerRadix = 2;
600         else if(argv[1][1] == 'd')
601           debuggerRadix = 0;
602         else {
603           printf("Unknown format %c\n", argv[1][1]);
604           return;
605         }
606       } else {
607         printf("Unknown option %s\n", argv[1]);
608         return;
609       }
610     }
611 
612     char *s = argc == 2 ? argv[1] : argv[2];
613 
614     extern char *exprString;
615     extern int exprCol;
616     extern int yyparse();
617     exprString = s;
618     exprCol = 0;
619     if(!yyparse()) {
620       extern Node *result;
621       if(result->resolve(result, f, u)) {
622         if(result->member)
623           debuggerPrintMember(f,
624                               result->member,
625                               result->objLocation,
626                               result->location);
627         else
628           debuggerPrintValueInternal(f, result->type, 0, 0,
629                                      result->location,
630                                      result->locType);
631         printf("\n");
632       } else {
633         printf("Error resolving expression\n");
634       }
635     } else {
636       printf("Error parsing expression:\n");
637       printf("%s\n", s);
638       exprCol--;
639       for(int i = 0; i < exprCol; i++)
640         printf(" ");
641       printf("^\n");
642     }
643     extern void exprCleanBuffer();
644     exprCleanBuffer();
645     exprNodeCleanUp();
646     debuggerRadix = oldRadix;
647   }
648 }
649 
debuggerHelp(int n,char ** args)650 void debuggerHelp(int n, char **args)
651 {
652   if(n == 2) {
653     debuggerUsage(args[1]);
654   } else {
655     for(int i = 0; ; i++) {
656       if(debuggerCommands[i].name) {
657         printf("%s\t%s\n", debuggerCommands[i].name, debuggerCommands[i].help);
658       } else
659         break;
660     }
661   }
662 }
663 
debuggerDebug(int n,char ** args)664 void debuggerDebug(int n, char **args)
665 {
666   if(n == 2) {
667     int v = 0;
668     sscanf(args[1], "%d", &v);
669     systemDebug = v;
670     printf("Debug level set to %d\n", systemDebug);
671   } else
672     debuggerUsage("trace");
673 }
674 
debuggerVerbose(int n,char ** args)675 void debuggerVerbose(int n, char **args)
676 {
677   if(n == 2) {
678     int v = 0;
679     sscanf(args[1], "%d", &v);
680     systemVerbose = v;
681     printf("Verbose level set to %d\n", systemVerbose);
682   } else
683     debuggerUsage("verbose");
684 }
685 
debuggerWhere(int n,char ** args)686 void debuggerWhere(int n, char **args)
687 {
688   void elfPrintCallChain(u32);
689   elfPrintCallChain(armNextPC);
690 }
691 
debuggerLocals(int n,char ** args)692 void debuggerLocals(int n, char **args)
693 {
694   Function *f = NULL;
695   CompileUnit *u = NULL;
696   u32 pc = armNextPC;
697   if(elfGetCurrentFunction(pc,
698                            &f, &u)) {
699     Object *o = f->parameters;
700     while(o) {
701       printf("%s=", o->name);
702       debuggerPrintValue(f, o);
703       o = o->next;
704     }
705 
706     o = f->variables;
707     while(o) {
708       bool visible = o->startScope ? pc>=o->startScope : true;
709       if(visible)
710         visible = o->endScope ? pc < o->endScope : true;
711       if(visible) {
712         printf("%s=", o->name);
713         debuggerPrintValue(f, o);
714       }
715       o = o->next;
716     }
717   } else {
718     printf("No information for current address\n");
719   }
720 }
721 
debuggerNext(int n,char ** args)722 void debuggerNext(int n, char **args)
723 {
724   int count = 1;
725   if(n == 2) {
726     sscanf(args[1], "%d", &count);
727   }
728   for(int i = 0; i < count; i++) {
729     if(debuggerAtBreakpoint) {
730       debuggerContinueAfterBreakpoint();
731       debuggerEnableBreakpoints(false);
732     } else
733       emulator.emuMain(1);
734   }
735   debuggerDisableBreakpoints();
736   Function *f = NULL;
737   CompileUnit *u = NULL;
738   u32 a = armNextPC;
739   if(elfGetCurrentFunction(a, &f, &u)) {
740     char *file;
741     int line = elfFindLine(u, f, a, &file);
742 
743     printf("File %s, function %s, line %d\n", file, f->name,
744            line);
745   }
746   debuggerRegisters(0, NULL);
747 }
748 
debuggerContinue(int n,char ** args)749 void debuggerContinue(int n, char **args)
750 {
751   if(debuggerAtBreakpoint)
752     debuggerContinueAfterBreakpoint();
753   debuggerEnableBreakpoints(false);
754   debugger = false;
755 }
756 
debuggerSignal(int sig,int number)757 void debuggerSignal(int sig,int number)
758 {
759   switch(sig) {
760   case 4:
761     {
762       printf("Illegal instruction at %08x\n", armNextPC);
763       debugger = true;
764     }
765     break;
766   case 5:
767     {
768       printf("Breakpoint %d reached\n", number);
769       debugger = true;
770       debuggerAtBreakpoint = true;
771       debuggerBreakpointNumber = number;
772       debuggerDisableBreakpoints();
773 
774       Function *f = NULL;
775       CompileUnit *u = NULL;
776 
777       if(elfGetCurrentFunction(armNextPC, &f, &u)) {
778         char *file;
779         int line = elfFindLine(u,f,armNextPC,&file);
780         printf("File %s, function %s, line %d\n", file, f->name,
781                line);
782       }
783     }
784     break;
785   default:
786     printf("Unknown signal %d\n", sig);
787     break;
788   }
789 }
790 
debuggerBreakList(int,char **)791 void debuggerBreakList(int, char **)
792 {
793   printf("Num Address  Type  Symbol\n");
794   printf("--- -------- ----- ------\n");
795   for(int i = 0; i < debuggerNumOfBreakpoints; i++) {
796     printf("%3d %08x %s %s\n",i, debuggerBreakpointList[i].address,
797            debuggerBreakpointList[i].size ? "ARM" : "THUMB",
798            elfGetAddressSymbol(debuggerBreakpointList[i].address));
799   }
800 }
801 
debuggerBreakDelete(int n,char ** args)802 void debuggerBreakDelete(int n, char **args)
803 {
804   if(n == 2) {
805     int n = 0;
806     sscanf(args[1], "%d", &n);
807     printf("Deleting breakpoint %d (%d)\n", n, debuggerNumOfBreakpoints);
808     if(n >= 0 && n < debuggerNumOfBreakpoints) {
809       n++;
810       if(n < debuggerNumOfBreakpoints) {
811         for(int i = n; i < debuggerNumOfBreakpoints; i++) {
812           debuggerBreakpointList[i-1].address =
813             debuggerBreakpointList[i].address;
814           debuggerBreakpointList[i-1].value =
815             debuggerBreakpointList[i].value;
816           debuggerBreakpointList[i-1].size =
817             debuggerBreakpointList[i].size;
818         }
819       }
820       debuggerNumOfBreakpoints--;
821     }
822   } else
823     debuggerUsage("bd");
824 }
825 
debuggerBreak(int n,char ** args)826 void debuggerBreak(int n, char **args)
827 {
828   if(n == 2) {
829     u32 address = 0;
830     u32 value = 0;
831     int type = 0;
832     char *s = args[1];
833     char c = *s;
834     if(strchr(s, ':')) {
835       char *name = s;
836       char *l = strchr(s, ':');
837       *l++ = 0;
838       int line = atoi(l);
839 
840       u32 addr;
841       Function *f;
842       CompileUnit *u;
843 
844       if(elfFindLineInModule(&addr, name, line)) {
845         if(elfGetCurrentFunction(addr, &f, &u)) {
846           u32 addr2;
847           if(elfGetSymbolAddress(f->name, &addr2, &value, &type)) {
848             address = addr;
849           } else {
850             printf("Unable to get function symbol data\n");
851             return;
852           }
853         } else {
854           printf("Unable to find function for address\n");
855           return;
856         }
857       } else {
858         printf("Unable to find module or line\n");
859         return;
860       }
861     } else if(c >= '0' && c <= '9') {
862       int line = atoi(s);
863       Function *f;
864       CompileUnit *u;
865       u32 addr;
866 
867       if(elfGetCurrentFunction(armNextPC, &f, &u)) {
868         if(elfFindLineInUnit(&addr, u, line)) {
869           if(elfGetCurrentFunction(addr, &f, &u)) {
870             u32 addr2;
871             if(elfGetSymbolAddress(f->name, &addr2, &value, &type)) {
872               address = addr;
873             } else {
874               printf("Unable to get function symbol data\n");
875               return;
876             }
877           } else {
878             printf("Unable to find function for address\n");
879             return;
880           }
881         } else {
882           printf("Unable to find line\n");
883           return;
884         }
885       } else {
886         printf("Cannot find current function\n");
887         return;
888       }
889     } else {
890       if(!elfGetSymbolAddress(s, &address, &value, &type)) {
891         printf("Function %s not found\n", args[1]);
892         return;
893       }
894     }
895     if(type == 0x02 || type == 0x0d) {
896       int i = debuggerNumOfBreakpoints;
897       int size = 0;
898       if(type == 2)
899         size = 1;
900       debuggerBreakpointList[i].address = address;
901       debuggerBreakpointList[i].value = type == 0x02 ?
902         debuggerReadMemory(address) : debuggerReadHalfWord(address);
903       debuggerBreakpointList[i].size = size;
904       //      debuggerApplyBreakpoint(address, i, size);
905       debuggerNumOfBreakpoints++;
906       if(size)
907         printf("Added ARM breakpoint at %08x\n", address);
908       else
909         printf("Added THUMB breakpoint at %08x\n", address);
910     } else {
911       printf("%s is not a function symbol\n", args[1]);
912     }
913   } else
914     debuggerUsage("break");
915 }
916 
debuggerBreakThumb(int n,char ** args)917 void debuggerBreakThumb(int n, char **args)
918 {
919   if(n == 2) {
920     u32 address = 0;
921     sscanf(args[1],"%x", &address);
922     int i = debuggerNumOfBreakpoints;
923     debuggerBreakpointList[i].address = address;
924     debuggerBreakpointList[i].value = debuggerReadHalfWord(address);
925     debuggerBreakpointList[i].size = 0;
926     //    debuggerApplyBreakpoint(address, i, 0);
927     debuggerNumOfBreakpoints++;
928     printf("Added THUMB breakpoint at %08x\n", address);
929   } else
930     debuggerUsage("bt");
931 }
932 
debuggerBreakArm(int n,char ** args)933 void debuggerBreakArm(int n, char **args)
934 {
935   if(n == 2) {
936     u32 address = 0;
937     sscanf(args[1],"%x", &address);
938     int i = debuggerNumOfBreakpoints;
939     debuggerBreakpointList[i].address = address;
940     debuggerBreakpointList[i].value = debuggerReadMemory(address);
941     debuggerBreakpointList[i].size = 1;
942     //    debuggerApplyBreakpoint(address, i, 1);
943     debuggerNumOfBreakpoints++;
944     printf("Added ARM breakpoint at %08x\n", address);
945   } else
946     debuggerUsage("ba");
947 }
948 
debuggerBreakOnWrite(u32 * mem,u32 oldvalue,u32 value,int size)949 void debuggerBreakOnWrite(u32 *mem, u32 oldvalue, u32 value, int size)
950 {
951   u32 address = 0;
952   if(mem >= (u32*)&workRAM[0] && mem <= (u32*)&workRAM[0x3ffff])
953     address = 0x2000000 + (u32)((u8 *)mem - &workRAM[0]);
954   else
955     address = 0x3000000 + (u32)((u8 *)mem - &internalRAM[0]);
956 
957   if(size == 2)
958     printf("Breakpoint (on write) address %08x old:%08x new:%08x\n",
959            address, oldvalue, value);
960   else if(size == 1)
961     printf("Breakpoint (on write) address %08x old:%04x new:%04x\n",
962            address, (u16)oldvalue,(u16)value);
963   else
964     printf("Breakpoint (on write) address %08x old:%02x new:%02x\n",
965            address, (u8)oldvalue, (u8)value);
966   debugger = true;
967 }
968 
debuggerBreakWriteClear(int n,char ** args)969 void debuggerBreakWriteClear(int n, char **args)
970 {
971   memset(freezeWorkRAM, false, 0x40000);
972   memset(freezeInternalRAM, false, 0x8000);
973   printf("Cleared all break on write\n");
974 }
975 
debuggerBreakWrite(int n,char ** args)976 void debuggerBreakWrite(int n, char **args)
977 {
978   if(n == 3) {
979     if(cheatsNumber != 0) {
980       printf("Cheats are enabled. Cannot continue.\n");
981       return;
982     }
983     u32 address = 0;
984     sscanf(args[1], "%x", &address);
985     int n = 0;
986     sscanf(args[2], "%d", &n);
987 
988     if(address < 0x2000000 || address > 0x3007fff) {
989       printf("Invalid address: %08x\n", address);
990       return;
991     }
992 
993     if(address > 0x203ffff && address < 0x3000000) {
994       printf("Invalid address: %08x\n", address);
995       return;
996     }
997 
998     u32 final = address + n;
999 
1000     if(address < 0x2040000 && final > 0x2040000) {
1001       printf("Invalid byte count: %d\n", n);
1002       return;
1003     } else if(address < 0x3008000 && final > 0x3008000) {
1004       printf("Invalid byte count: %d\n", n);
1005       return;
1006     }
1007     printf("Added break on write at %08x for %d bytes\n", address, n);
1008     for(int i = 0; i < n; i++) {
1009       if((address >> 24) == 2)
1010         freezeWorkRAM[address & 0x3ffff] = true;
1011       else
1012         freezeInternalRAM[address & 0x7fff] = true;
1013       address++;
1014     }
1015   } else
1016     debuggerUsage("bpw");
1017 }
1018 
debuggerDisassembleArm(int n,char ** args)1019 void debuggerDisassembleArm(int n, char **args)
1020 {
1021   char buffer[80];
1022   u32 pc = reg[15].I;
1023   pc -= 4;
1024   int count = 20;
1025   if(n >= 2) {
1026     sscanf(args[1], "%x", &pc);
1027   }
1028   if(pc & 3) {
1029     printf("Misaligned address %08x\n", pc);
1030     pc &= 0xfffffffc;
1031   }
1032   if(n >= 3) {
1033     sscanf(args[2], "%d", &count);
1034   }
1035   int i = 0;
1036   int len = 0;
1037   char format[30];
1038   for(i = 0; i < count; i++) {
1039     int l = strlen(elfGetAddressSymbol(pc+4*i));
1040     if(l > len)
1041       len = l;
1042   }
1043   sprintf(format, "%%08x %%-%ds %%s\n", len);
1044   for(i = 0; i < count; i++) {
1045     u32 addr = pc;
1046     pc += disArm(pc, buffer, 2);
1047     printf(format, addr, elfGetAddressSymbol(addr), buffer);
1048   }
1049 }
1050 
debuggerDisassembleThumb(int n,char ** args)1051 void debuggerDisassembleThumb(int n, char **args)
1052 {
1053   char buffer[80];
1054   u32 pc = reg[15].I;
1055   pc -= 2;
1056   int count = 20;
1057   if(n >= 2) {
1058     sscanf(args[1], "%x", &pc);
1059   }
1060   if(pc & 1) {
1061     printf("Misaligned address %08x\n", pc);
1062     pc &= 0xfffffffe;
1063   }
1064   if(n >= 3) {
1065     sscanf(args[2], "%d", &count);
1066   }
1067 
1068   int i = 0;
1069   int len = 0;
1070   char format[30];
1071   for(i = 0; i < count; i++) {
1072     int l = strlen(elfGetAddressSymbol(pc+2*i));
1073     if(l > len)
1074       len = l;
1075   }
1076   sprintf(format, "%%08x %%-%ds %%s\n", len);
1077 
1078   for(i = 0; i < count; i++) {
1079     u32 addr = pc;
1080     pc += disThumb(pc, buffer, 2);
1081     printf(format, addr, elfGetAddressSymbol(addr), buffer);
1082   }
1083 }
1084 
debuggerDisassemble(int n,char ** args)1085 void debuggerDisassemble(int n, char **args)
1086 {
1087   if(armState)
1088     debuggerDisassembleArm(n, args);
1089   else
1090     debuggerDisassembleThumb(n, args);
1091 }
1092 
debuggerContinueAfterBreakpoint()1093 void debuggerContinueAfterBreakpoint()
1094 {
1095   printf("Continuing after breakpoint\n");
1096   debuggerEnableBreakpoints(true);
1097   emulator.emuMain(1);
1098   debuggerAtBreakpoint = false;
1099 }
1100 
debuggerRegisters(int,char **)1101 void debuggerRegisters(int, char **)
1102 {
1103   char *command[3];
1104   char buffer[10];
1105 
1106   printf("R00=%08x R04=%08x R08=%08x R12=%08x\n",
1107          reg[0].I, reg[4].I, reg[8].I, reg[12].I);
1108   printf("R01=%08x R05=%08x R09=%08x R13=%08x\n",
1109          reg[1].I, reg[5].I, reg[9].I, reg[13].I);
1110   printf("R02=%08x R06=%08x R10=%08x R14=%08x\n",
1111          reg[2].I, reg[6].I, reg[10].I, reg[14].I);
1112   printf("R03=%08x R07=%08x R11=%08x R15=%08x\n",
1113          reg[3].I, reg[7].I, reg[11].I, reg[15].I);
1114   printf("CPSR=%08x (%c%c%c%c%c%c%c Mode: %02x)\n",
1115          reg[16].I,
1116          (N_FLAG ? 'N' : '.'),
1117          (Z_FLAG ? 'Z' : '.'),
1118          (C_FLAG ? 'C' : '.'),
1119          (V_FLAG ? 'V' : '.'),
1120          (armIrqEnable ? '.' : 'I'),
1121          ((!(reg[16].I & 0x40)) ? '.' : 'F'),
1122          (armState ? '.' : 'T'),
1123          armMode);
1124   sprintf(buffer,"%08x", armState ? reg[15].I - 4 : reg[15].I - 2);
1125   command[0]="m";
1126   command[1]=buffer;
1127   command[2]="1";
1128   debuggerDisassemble(3, command);
1129 }
1130 
debuggerIoVideo()1131 void debuggerIoVideo()
1132 {
1133   printf("DISPCNT  = %04x\n", DISPCNT);
1134   printf("DISPSTAT = %04x\n", DISPSTAT);
1135   printf("VCOUNT   = %04x\n", VCOUNT);
1136   printf("BG0CNT   = %04x\n", BG0CNT);
1137   printf("BG1CNT   = %04x\n", BG1CNT);
1138   printf("BG2CNT   = %04x\n", BG2CNT);
1139   printf("BG3CNT   = %04x\n", BG3CNT);
1140   printf("WIN0H    = %04x\n", WIN0H);
1141   printf("WIN0V    = %04x\n", WIN0V);
1142   printf("WIN1H    = %04x\n", WIN1H);
1143   printf("WIN1V    = %04x\n", WIN1V);
1144   printf("WININ    = %04x\n", WININ);
1145   printf("WINOUT   = %04x\n", WINOUT);
1146   printf("MOSAIC   = %04x\n", MOSAIC);
1147   printf("BLDMOD   = %04x\n", BLDMOD);
1148   printf("COLEV    = %04x\n", COLEV);
1149   printf("COLY     = %04x\n", COLY);
1150 }
1151 
debuggerIoVideo2()1152 void debuggerIoVideo2()
1153 {
1154   printf("BG0HOFS  = %04x\n", BG0HOFS);
1155   printf("BG0VOFS  = %04x\n", BG0VOFS);
1156   printf("BG1HOFS  = %04x\n", BG1HOFS);
1157   printf("BG1VOFS  = %04x\n", BG1VOFS);
1158   printf("BG2HOFS  = %04x\n", BG2HOFS);
1159   printf("BG2VOFS  = %04x\n", BG2VOFS);
1160   printf("BG3HOFS  = %04x\n", BG3HOFS);
1161   printf("BG3VOFS  = %04x\n", BG3VOFS);
1162   printf("BG2PA    = %04x\n", BG2PA);
1163   printf("BG2PB    = %04x\n", BG2PB);
1164   printf("BG2PC    = %04x\n", BG2PC);
1165   printf("BG2PD    = %04x\n", BG2PD);
1166   printf("BG2X     = %08x\n", (BG2X_H<<16)|BG2X_L);
1167   printf("BG2Y     = %08x\n", (BG2Y_H<<16)|BG2Y_L);
1168   printf("BG3PA    = %04x\n", BG3PA);
1169   printf("BG3PB    = %04x\n", BG3PB);
1170   printf("BG3PC    = %04x\n", BG3PC);
1171   printf("BG3PD    = %04x\n", BG3PD);
1172   printf("BG3X     = %08x\n", (BG3X_H<<16)|BG3X_L);
1173   printf("BG3Y     = %08x\n", (BG3Y_H<<16)|BG3Y_L);
1174 }
1175 
debuggerIoDMA()1176 void debuggerIoDMA()
1177 {
1178   printf("DM0SAD   = %08x\n", (DM0SAD_H<<16)|DM0SAD_L);
1179   printf("DM0DAD   = %08x\n", (DM0DAD_H<<16)|DM0DAD_L);
1180   printf("DM0CNT   = %08x\n", (DM0CNT_H<<16)|DM0CNT_L);
1181   printf("DM1SAD   = %08x\n", (DM1SAD_H<<16)|DM1SAD_L);
1182   printf("DM1DAD   = %08x\n", (DM1DAD_H<<16)|DM1DAD_L);
1183   printf("DM1CNT   = %08x\n", (DM1CNT_H<<16)|DM1CNT_L);
1184   printf("DM2SAD   = %08x\n", (DM2SAD_H<<16)|DM2SAD_L);
1185   printf("DM2DAD   = %08x\n", (DM2DAD_H<<16)|DM2DAD_L);
1186   printf("DM2CNT   = %08x\n", (DM2CNT_H<<16)|DM2CNT_L);
1187   printf("DM3SAD   = %08x\n", (DM3SAD_H<<16)|DM3SAD_L);
1188   printf("DM3DAD   = %08x\n", (DM3DAD_H<<16)|DM3DAD_L);
1189   printf("DM3CNT   = %08x\n", (DM3CNT_H<<16)|DM3CNT_L);
1190 }
1191 
debuggerIoTimer()1192 void debuggerIoTimer()
1193 {
1194   printf("TM0D     = %04x\n", TM0D);
1195   printf("TM0CNT   = %04x\n", TM0CNT);
1196   printf("TM1D     = %04x\n", TM1D);
1197   printf("TM1CNT   = %04x\n", TM1CNT);
1198   printf("TM2D     = %04x\n", TM2D);
1199   printf("TM2CNT   = %04x\n", TM2CNT);
1200   printf("TM3D     = %04x\n", TM3D);
1201   printf("TM3CNT   = %04x\n", TM3CNT);
1202 }
1203 
debuggerIoMisc()1204 void debuggerIoMisc()
1205 {
1206   printf("P1       = %04x\n", P1);
1207   printf("IE       = %04x\n", IE);
1208   printf("IF       = %04x\n", IF);
1209   printf("IME      = %04x\n", IME);
1210 }
1211 
debuggerIo(int n,char ** args)1212 void debuggerIo(int n, char **args)
1213 {
1214   if(n == 1) {
1215     debuggerIoVideo();
1216     return;
1217   }
1218   if(!strcmp(args[1], "video"))
1219     debuggerIoVideo();
1220   else if(!strcmp(args[1], "video2"))
1221     debuggerIoVideo2();
1222   else if(!strcmp(args[1], "dma"))
1223     debuggerIoDMA();
1224   else if(!strcmp(args[1], "timer"))
1225     debuggerIoTimer();
1226   else if(!strcmp(args[1], "misc"))
1227     debuggerIoMisc();
1228   else printf("Unrecognized option %s\n", args[1]);
1229 }
1230 
debuggerEditByte(int n,char ** args)1231 void debuggerEditByte(int n, char **args)
1232 {
1233   if(n == 3) {
1234     u32 address;
1235     u32 byte;
1236     sscanf(args[1], "%x", &address);
1237     sscanf(args[2], "%x", &byte);
1238     debuggerWriteByte(address, (u8)byte);
1239   } else
1240     debuggerUsage("eb");
1241 }
1242 
debuggerEditHalfWord(int n,char ** args)1243 void debuggerEditHalfWord(int n, char **args)
1244 {
1245   if(n == 3) {
1246     u32 address;
1247     u32 byte;
1248     sscanf(args[1], "%x", &address);
1249     if(address & 1) {
1250       printf("Error: address must be half-word aligned\n");
1251       return;
1252     }
1253     sscanf(args[2], "%x", &byte);
1254     debuggerWriteHalfWord(address, (u16)byte);
1255   } else
1256     debuggerUsage("eh");
1257 }
1258 
debuggerEdit(int n,char ** args)1259 void debuggerEdit(int n, char **args)
1260 {
1261   if(n == 3) {
1262     u32 address;
1263     u32 byte;
1264     sscanf(args[1], "%x", &address);
1265     if(address & 3) {
1266       printf("Error: address must be word aligned\n");
1267       return;
1268     }
1269     sscanf(args[2], "%x", &byte);
1270     debuggerWriteMemory(address, (u32)byte);
1271   } else
1272     debuggerUsage("ew");
1273 }
1274 
1275 
1276 #define ASCII(c) (c) < 32 ? '.' : (c) > 127 ? '.' : (c)
1277 
debuggerMemoryByte(int n,char ** args)1278 void debuggerMemoryByte(int n, char **args)
1279 {
1280   if(n == 2) {
1281     u32 addr = 0;
1282     sscanf(args[1], "%x", &addr);
1283     for(int i_ = 0; i_ < 16; i_++) {
1284       int a = debuggerReadByte(addr);
1285       int b = debuggerReadByte(addr+1);
1286       int c = debuggerReadByte(addr+2);
1287       int d = debuggerReadByte(addr+3);
1288       int e = debuggerReadByte(addr+4);
1289       int f = debuggerReadByte(addr+5);
1290       int g = debuggerReadByte(addr+6);
1291       int h = debuggerReadByte(addr+7);
1292       int i = debuggerReadByte(addr+8);
1293       int j = debuggerReadByte(addr+9);
1294       int k = debuggerReadByte(addr+10);
1295       int l = debuggerReadByte(addr+11);
1296       int m = debuggerReadByte(addr+12);
1297       int n = debuggerReadByte(addr+13);
1298       int o = debuggerReadByte(addr+14);
1299       int p = debuggerReadByte(addr+15);
1300 
1301       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",
1302              addr,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,
1303              ASCII(a),ASCII(b),ASCII(c),ASCII(d),
1304              ASCII(e),ASCII(f),ASCII(g),ASCII(h),
1305              ASCII(i),ASCII(j),ASCII(k),ASCII(l),
1306              ASCII(m),ASCII(n),ASCII(o),ASCII(p));
1307       addr += 16;
1308     }
1309   } else
1310     debuggerUsage("mb");
1311 }
1312 
debuggerMemoryHalfWord(int n,char ** args)1313 void debuggerMemoryHalfWord(int n, char **args)
1314 {
1315   if(n == 2) {
1316     u32 addr = 0;
1317     sscanf(args[1], "%x", &addr);
1318     addr = addr & 0xfffffffe;
1319     for(int i_ = 0; i_ < 16; i_++) {
1320       int a = debuggerReadByte(addr);
1321       int b = debuggerReadByte(addr+1);
1322       int c = debuggerReadByte(addr+2);
1323       int d = debuggerReadByte(addr+3);
1324       int e = debuggerReadByte(addr+4);
1325       int f = debuggerReadByte(addr+5);
1326       int g = debuggerReadByte(addr+6);
1327       int h = debuggerReadByte(addr+7);
1328       int i = debuggerReadByte(addr+8);
1329       int j = debuggerReadByte(addr+9);
1330       int k = debuggerReadByte(addr+10);
1331       int l = debuggerReadByte(addr+11);
1332       int m = debuggerReadByte(addr+12);
1333       int n = debuggerReadByte(addr+13);
1334       int o = debuggerReadByte(addr+14);
1335       int p = debuggerReadByte(addr+15);
1336 
1337       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",
1338              addr,b,a,d,c,f,e,h,g,j,i,l,k,n,m,p,o,
1339              ASCII(a),ASCII(b),ASCII(c),ASCII(d),
1340              ASCII(e),ASCII(f),ASCII(g),ASCII(h),
1341              ASCII(i),ASCII(j),ASCII(k),ASCII(l),
1342              ASCII(m),ASCII(n),ASCII(o),ASCII(p));
1343       addr += 16;
1344     }
1345   } else
1346     debuggerUsage("mh");
1347 }
1348 
debuggerMemory(int n,char ** args)1349 void debuggerMemory(int n, char **args)
1350 {
1351   if(n == 2) {
1352     u32 addr = 0;
1353     sscanf(args[1], "%x", &addr);
1354     addr = addr & 0xfffffffc;
1355     for(int i_ = 0; i_ < 16; i_++) {
1356       int a = debuggerReadByte(addr);
1357       int b = debuggerReadByte(addr+1);
1358       int c = debuggerReadByte(addr+2);
1359       int d = debuggerReadByte(addr+3);
1360 
1361       int e = debuggerReadByte(addr+4);
1362       int f = debuggerReadByte(addr+5);
1363       int g = debuggerReadByte(addr+6);
1364       int h = debuggerReadByte(addr+7);
1365 
1366       int i = debuggerReadByte(addr+8);
1367       int j = debuggerReadByte(addr+9);
1368       int k = debuggerReadByte(addr+10);
1369       int l = debuggerReadByte(addr+11);
1370 
1371       int m = debuggerReadByte(addr+12);
1372       int n = debuggerReadByte(addr+13);
1373       int o = debuggerReadByte(addr+14);
1374       int p = debuggerReadByte(addr+15);
1375 
1376       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",
1377              addr,d,c,b,a,h,g,f,e,l,k,j,i,p,o,n,m,
1378              ASCII(a),ASCII(b),ASCII(c),ASCII(d),
1379              ASCII(e),ASCII(f),ASCII(g),ASCII(h),
1380              ASCII(i),ASCII(j),ASCII(k),ASCII(l),
1381              ASCII(m),ASCII(n),ASCII(o),ASCII(p));
1382       addr += 16;
1383     }
1384   } else
1385     debuggerUsage("mw");
1386 }
1387 
debuggerQuit(int,char **)1388 void debuggerQuit(int, char **)
1389 {
1390   char buffer[10];
1391   printf("Are you sure you want to quit (y/n)? ");
1392   fgets(buffer, sizeof(buffer), stdin);
1393 
1394   if(buffer[0] == 'y' || buffer[0] == 'Y') {
1395     debugger = false;
1396     emulating = false;
1397   }
1398 }
1399 
debuggerOutput(char * s,u32 addr)1400 void debuggerOutput(char *s, u32 addr)
1401 {
1402   if(s)
1403     printf(s);
1404   else {
1405     char c;
1406 
1407     c = debuggerReadByte(addr);
1408     addr++;
1409     while(c) {
1410       putchar(c);
1411       c = debuggerReadByte(addr);
1412       addr++;
1413     }
1414   }
1415 }
1416 
debuggerMain()1417 void debuggerMain()
1418 {
1419   char buffer[1024];
1420   char *commands[10];
1421   int commandCount = 0;
1422 
1423   if(emulator.emuUpdateCPSR)
1424     emulator.emuUpdateCPSR();
1425   debuggerRegisters(0, NULL);
1426 
1427   while(debugger) {
1428     systemSoundPause();
1429     printf("debugger> ");
1430     commandCount = 0;
1431     char *s = fgets(buffer, 1024, stdin);
1432 
1433     commands[0] = strtok(s, " \t\n");
1434     if(commands[0] == NULL)
1435       continue;
1436     commandCount++;
1437     while((s = strtok(NULL, " \t\n"))) {
1438       commands[commandCount++] = s;
1439       if(commandCount == 10)
1440         break;
1441     }
1442 
1443     for(int j = 0; ; j++) {
1444       if(debuggerCommands[j].name == NULL) {
1445         printf("Unrecognized command %s. Type h for help.\n", commands[0]);
1446         break;
1447       }
1448       if(!strcmp(commands[0], debuggerCommands[j].name)) {
1449         debuggerCommands[j].function(commandCount, commands);
1450         break;
1451       }
1452     }
1453   }
1454 }
1455