|
|
1.1 root 1: /*
2: Hatari - debugdsp.c
3:
1.1.1.5 root 4: This file is distributed under the GNU General Public License, version 2
5: or at your option any later version. Read the file gpl.txt for details.
1.1 root 6:
7: debugdsp.c - function needed for the DSP debugging tasks like memory
8: and register dumps.
9: */
10: const char DebugDsp_fileid[] = "Hatari debugdsp.c : " __DATE__ " " __TIME__;
11:
12: #include <stdio.h>
1.1.1.6 root 13: #include <ctype.h>
1.1.1.9 root 14: #include <limits.h>
1.1 root 15:
16: #include "config.h"
17:
18: #include "main.h"
19: #include "breakcond.h"
20: #include "configuration.h"
21: #include "debugui.h"
22: #include "debug_priv.h"
23: #include "debugdsp.h"
24: #include "dsp.h"
25: #include "evaluate.h"
1.1.1.3 root 26: #include "history.h"
1.1.1.4 root 27: #include "log.h"
1.1 root 28: #include "memorySnapShot.h"
1.1.1.2 root 29: #include "profile.h"
1.1 root 30: #include "str.h"
31: #include "symbols.h"
32:
33: static Uint16 dsp_disasm_addr; /* DSP disasm address */
34: static Uint16 dsp_memdump_addr; /* DSP memdump address */
35: static char dsp_mem_space = 'P'; /* X, Y, P */
36:
1.1.1.2 root 37: static bool bDspProfiling; /* Whether profiling is enabled */
1.1 root 38: static int nDspActiveCBs = 0; /* Amount of active conditional breakpoints */
39: static int nDspSteps = 0; /* Amount of steps for DSP single-stepping */
40:
41:
42: /**
43: * Readline match callback to list register names usable within debugger.
44: * STATE = 0 -> different text from previous one.
45: * Return next match or NULL if no matches.
46: */
47: static char *DebugDsp_MatchRegister(const char *text, int state)
48: {
1.1.1.6 root 49: static const char* regs[] = {
1.1 root 50: "a0", "a1", "a2", "b0", "b1", "b2", "la", "lc",
51: "m0", "m1", "m2", "m3", "m4", "m5", "m6", "m7",
52: "n0", "n1", "n2", "n3", "n4", "n5", "n6", "n7",
53: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
54: "omr", "pc", "sp", "sr", "ssh", "ssl",
55: "x0", "x1", "y0", "y1",
56: };
1.1.1.8 root 57: return DebugUI_MatchHelper(regs, ARRAY_SIZE(regs), text, state);
1.1 root 58: }
59:
60: /**
61: * Command: Dump or set a DSP register
62: */
63: int DebugDsp_Register(int nArgc, char *psArgs[])
64: {
65: char *assign;
66: Uint32 value;
67: char *arg;
68:
69: if (!bDspEnabled)
70: {
71: fprintf(stderr, "DSP isn't present or initialized.\n");
72: return DEBUGGER_CMDDONE;
73: }
74:
75: if (nArgc == 1)
76: {
77: /* No parameter - dump all registers */
1.1.1.8 root 78: DSP_DisasmRegisters(debugOutput);
79: fflush(debugOutput);
1.1 root 80: return DEBUGGER_CMDDONE;
81: }
82: arg = psArgs[1];
83:
84: assign = strchr(arg, '=');
85: if (!assign)
86: goto error_msg;
87:
88: *assign++ = '\0';
89: if (!Eval_Number(Str_Trim(assign), &value))
90: goto error_msg;
91:
92: if (DSP_Disasm_SetRegister(Str_Trim(arg), value))
93: return DEBUGGER_CMDDONE;
94:
95: error_msg:
96: fprintf(stderr,"\tError, usage: dr or dr xx=yyyy\n"
97: "\tWhere: xx=A0-A2, B0-B2, X0, X1, Y0, Y1, R0-R7,\n"
98: "\t N0-N7, M0-M7, LA, LC, PC, SR, SP, OMR, SSH, SSL\n");
99:
100: return DEBUGGER_CMDDONE;
101: }
102:
103:
104: /**
1.1.1.2 root 105: * Check whether given address matches any DSP symbol and whether
106: * there's profiling information available for it. If yes, show it.
1.1.1.9 root 107: *
108: * @return true if symbol was shown, false otherwise
1.1 root 109: */
1.1.1.9 root 110: static bool DebugDsp_ShowAddressInfo(Uint16 addr, FILE *fp)
1.1 root 111: {
1.1.1.9 root 112: const char *symbol = Symbols_GetByDspAddress(addr, SYMTYPE_ALL);
1.1 root 113: if (symbol)
1.1.1.9 root 114: {
1.1.1.8 root 115: fprintf(fp, "%s:\n", symbol);
1.1.1.9 root 116: return true;
117: }
118: return false;
1.1 root 119: }
120:
121:
122: /**
123: * DSP dissassemble - arg = starting address/range, or PC.
124: */
125: int DebugDsp_DisAsm(int nArgc, char *psArgs[])
126: {
127: Uint32 lower, upper;
128: Uint16 dsp_disasm_upper = 0;
1.1.1.9 root 129: int shown, lines = INT_MAX;
1.1 root 130:
131: if (!bDspEnabled)
132: {
133: fprintf(stderr, "DSP isn't present or initialized.\n");
134: return DEBUGGER_CMDDONE;
135: }
136:
137: if (nArgc > 1)
138: {
1.1.1.2 root 139: switch (Eval_Range(psArgs[1], &lower, &upper, true))
1.1 root 140: {
141: case -1:
142: /* invalid value(s) */
143: return DEBUGGER_CMDDONE;
144: case 0:
145: /* single value */
146: break;
147: case 1:
148: /* range */
149: if (upper > 0xFFFF)
150: {
151: fprintf(stderr,"Invalid address 0x%x!\n", upper);
152: return DEBUGGER_CMDDONE;
153: }
154: dsp_disasm_upper = upper;
155: break;
156: }
157:
158: if (lower > 0xFFFF)
159: {
160: fprintf(stderr,"Invalid address 0x%x!\n", lower);
161: return DEBUGGER_CMDDONE;
162: }
163: dsp_disasm_addr = lower;
164: }
165: else
166: {
167: /* continue */
168: if(!dsp_disasm_addr)
169: {
170: dsp_disasm_addr = DSP_GetPC();
171: }
172: }
173: if (!dsp_disasm_upper)
174: {
1.1.1.9 root 175: lines = DebugUI_GetPageLines(ConfigureParams.Debugger.nDisasmLines, 8);
176: dsp_disasm_upper = 0xFFFF;
1.1 root 177: }
1.1.1.8 root 178: fprintf(debugOutput, "DSP disasm 0x%hx-0x%hx:\n", dsp_disasm_addr, dsp_disasm_upper);
1.1.1.9 root 179: for (shown = 1; shown < lines && dsp_disasm_addr < dsp_disasm_upper; shown++) {
180: if (DebugDsp_ShowAddressInfo(dsp_disasm_addr, debugOutput))
181: shown++;
1.1.1.8 root 182: dsp_disasm_addr = DSP_DisasmAddress(debugOutput, dsp_disasm_addr, dsp_disasm_addr);
1.1 root 183: }
1.1.1.8 root 184: fflush(debugOutput);
1.1 root 185:
186: return DEBUGGER_CMDCONT;
187: }
188:
189:
190: /**
191: * Do a DSP memory dump, args = starting address or range.
192: * <x|y|p> <address>: dump from X, Y or P, starting from given address,
193: * e.g. "x 200" or "p 200-300"
194: */
195: int DebugDsp_MemDump(int nArgc, char *psArgs[])
196: {
197: Uint32 lower, upper;
198: Uint16 dsp_memdump_upper = 0;
1.1.1.6 root 199: char *range, space;
1.1 root 200:
201: if (!bDspEnabled)
202: {
203: fprintf(stderr, "DSP isn't present or initialized.\n");
204: return DEBUGGER_CMDDONE;
205: }
1.1.1.6 root 206:
207: switch (nArgc)
1.1 root 208: {
1.1.1.6 root 209: case 1:
210: break;
211: case 3: /* "x $200" */
212: space = psArgs[1][0];
213: range = psArgs[2];
214: break;
215: case 2: /* "x:$200" */
216: if (psArgs[1][1] == ':')
217: {
218: space = psArgs[1][0];
219: range = psArgs[1] + 2;
220: break;
221: }
1.1.1.10! root 222: /* fall through */
1.1.1.6 root 223: default:
224: return DebugUI_PrintCmdHelp(psArgs[0]);
1.1 root 225: }
226:
1.1.1.6 root 227: if (nArgc > 1)
1.1 root 228: {
1.1.1.6 root 229: space = toupper((unsigned char)space);
1.1 root 230: switch (space)
231: {
232: case 'X':
233: case 'Y':
234: case 'P':
235: break;
236: default:
237: fprintf(stderr,"Invalid DSP address space '%c'!\n", space);
238: return DEBUGGER_CMDDONE;
239: }
1.1.1.6 root 240: switch (Eval_Range(range, &lower, &upper, true))
1.1 root 241: {
242: case -1:
243: /* invalid value(s) */
244: return DEBUGGER_CMDDONE;
245: case 0:
246: /* single value */
247: break;
248: case 1:
249: /* range */
250: if (upper > 0xFFFF)
251: {
252: fprintf(stderr,"Invalid address 0x%x!\n", upper);
253: return DEBUGGER_CMDDONE;
254: }
255: dsp_memdump_upper = upper;
256: break;
257: }
258: if (lower > 0xFFFF)
259: {
260: fprintf(stderr,"Invalid address 0x%x!\n", lower);
261: return DEBUGGER_CMDDONE;
262: }
263: dsp_memdump_addr = lower;
264: dsp_mem_space = space;
1.1.1.6 root 265: }
1.1 root 266:
267: if (!dsp_memdump_upper)
268: {
1.1.1.9 root 269: int lines = DebugUI_GetPageLines(ConfigureParams.Debugger.nMemdumpLines, 8);
1.1 root 270: if ( dsp_memdump_addr < (0xFFFF - lines))
271: dsp_memdump_upper = dsp_memdump_addr + lines;
272: else
273: dsp_memdump_upper = 0xFFFF;
274: }
275:
1.1.1.8 root 276: fprintf(debugOutput, "DSP memdump from 0x%hx in '%c' address space:\n", dsp_memdump_addr, dsp_mem_space);
277: dsp_memdump_addr = DSP_DisasmMemory(debugOutput, dsp_memdump_addr, dsp_memdump_upper, dsp_mem_space);
278: fflush(debugOutput);
1.1 root 279:
280: return DEBUGGER_CMDCONT;
281: }
282:
283:
284: /**
285: * Command: Continue DSP emulation / single-stepping
286: */
287: static int DebugDsp_Continue(int nArgc, char *psArgv[])
288: {
289: int steps = 0;
290:
291: if (nArgc > 1)
292: {
293: steps = atoi(psArgv[1]);
294: }
295: if (steps <= 0)
296: {
297: nDspSteps = 0;
298: fprintf(stderr,"Returning to emulation...\n");
299: return DEBUGGER_END;
300: }
301: nDspSteps = steps;
302: fprintf(stderr,"Returning to emulation for %i DSP instructions...\n", steps);
303: return DEBUGGER_END;
304: }
305:
1.1.1.5 root 306: /**
307: * Command: Single-step DSP
308: */
309: static int DebugDsp_Step(int nArgc, char *psArgv[])
310: {
311: nDspSteps = 1;
312: return DEBUGGER_END;
313: }
314:
1.1.1.6 root 315:
316: /**
317: * Readline match callback to list next command opcode types.
318: * STATE = 0 -> different text from previous one.
319: * Return next match or NULL if no matches.
320: */
321: static char *DebugDsp_MatchNext(const char *text, int state)
322: {
323: static const char* ntypes[] = {
324: "branch", "exreturn", "return", "subcall", "subreturn"
325: };
1.1.1.8 root 326: return DebugUI_MatchHelper(ntypes, ARRAY_SIZE(ntypes), text, state);
1.1.1.6 root 327: }
328:
1.1.1.5 root 329: /**
330: * Command: Step DSP, but proceed through subroutines
331: * Does this by temporary conditional breakpoint
332: */
333: static int DebugDsp_Next(int nArgc, char *psArgv[])
334: {
1.1.1.6 root 335: char command[40];
336: if (nArgc > 1)
337: {
338: int optype;
339: if(strcmp(psArgv[1], "branch") == 0)
340: optype = CALL_BRANCH;
341: else if(strcmp(psArgv[1], "exreturn") == 0)
342: optype = CALL_EXCRETURN;
343: else if(strcmp(psArgv[1], "subcall") == 0)
344: optype = CALL_SUBROUTINE;
345: else if (strcmp(psArgv[1], "subreturn") == 0)
346: optype = CALL_SUBRETURN;
347: else if (strcmp(psArgv[1], "return") == 0)
348: optype = CALL_SUBRETURN | CALL_EXCRETURN;
349: else
350: {
351: fprintf(stderr, "Unrecognized opcode type given!\n");
352: return DEBUGGER_CMDDONE;
353: }
354: sprintf(command, "DspOpcodeType & $%x > 0 :once :quiet\n", optype);
355: }
356: else
357: {
358: Uint32 optype;
359: Uint16 nextpc;
360:
361: optype = DebugDsp_OpcodeType();
362: /* can this instruction be stepped normally? */
363: if (optype != CALL_SUBROUTINE && optype != CALL_EXCEPTION)
364: {
365: nDspSteps = 1;
366: return DEBUGGER_END;
367: }
368:
369: nextpc = DSP_GetNextPC(DSP_GetPC());
370: sprintf(command, "pc=$%x :once :quiet\n", nextpc);
371: }
372: /* use breakpoint, not steps */
1.1.1.5 root 373: if (BreakCond_Command(command, true)) {
1.1.1.6 root 374: nDspSteps = 0;
1.1.1.5 root 375: return DEBUGGER_END;
376: }
377: return DEBUGGER_CMDDONE;
378: }
379:
1.1.1.6 root 380: /* helper to get instruction type, slightly simpler
381: * version from one in profiledsp.c
382: */
383: Uint32 DebugDsp_OpcodeType(void)
384: {
385: const char *dummy;
386: Uint32 opcode;
387:
388: /* 24-bit instruction opcode */
389: opcode = DSP_ReadMemory(DSP_GetPC(), 'P', &dummy) & 0xFFFFFF;
390:
391: /* subroutine returns */
392: if (opcode == 0xC) { /* (just) RTS */
393: return CALL_SUBRETURN;
394: }
395: if (
396: /* unconditional subroutine calls */
397: (opcode & 0xFFF000) == 0xD0000 || /* JSR 00001101 0000aaaa aaaaaaaa */
398: (opcode & 0xFFC0FF) == 0xBC080 || /* JSR 00001011 11MMMRRR 10000000 */
399: /* conditional subroutine calls */
400: (opcode & 0xFF0000) == 0xF0000 || /* JSCC 00001111 CCCCaaaa aaaaaaaa */
401: (opcode & 0xFFC0F0) == 0xBC0A0 || /* JSCC 00001011 11MMMRRR 1010CCCC */
402: (opcode & 0xFFC0A0) == 0xB4080 || /* JSCLR 00001011 01MMMRRR 1S0bbbbb */
403: (opcode & 0xFFC0A0) == 0xB0080 || /* JSCLR 00001011 00aaaaaa 1S0bbbbb */
404: (opcode & 0xFFC0A0) == 0xB8080 || /* JSCLR 00001011 10pppppp 1S0bbbbb */
405: (opcode & 0xFFC0E0) == 0xBC000 || /* JSCLR 00001011 11DDDDDD 000bbbbb */
406: (opcode & 0xFFC0A0) == 0xB40A0 || /* JSSET 00001011 01MMMRRR 1S1bbbbb */
407: (opcode & 0xFFC0A0) == 0xB00A0 || /* JSSET 00001011 00aaaaaa 1S1bbbbb */
408: (opcode & 0xFFC0A0) == 0xB80A0 || /* JSSET 00001011 10pppppp 1S1bbbbb */
409: (opcode & 0xFFC0E0) == 0xBC020) { /* JSSET 00001011 11DDDDDD 001bbbbb */
410: return CALL_SUBROUTINE;
411: }
412: /* exception handler returns */
413: if (opcode == 0x4) { /* (just) RTI */
414: return CALL_EXCRETURN;
415: }
416: /* branches */
417: if ((opcode & 0xFFF000) == 0xC0000 || /* JMP 00001100 0000aaaa aaaaaaaa */
418: (opcode & 0xFFC0FF) == 0xAC080 || /* JMP 00001010 11MMMRRR 10000000 */
419: (opcode & 0xFF0000) == 0xE0000 || /* JCC 00001110 CCCCaaaa aaaaaaaa */
420: (opcode & 0xFFC0F0) == 0xAC0A0 || /* JCC 00001010 11MMMRRR 1010CCCC */
421: (opcode & 0xFFC0A0) == 0xA8080 || /* JCLR 00001010 10pppppp 1S0bbbbb */
422: (opcode & 0xFFC0A0) == 0xA4080 || /* JCLR 00001010 01MMMRRR 1S0bbbbb */
423: (opcode & 0xFFC0A0) == 0xA0080 || /* JCLR 00001010 00aaaaaa 1S0bbbbb */
424: (opcode & 0xFFC0E0) == 0xAC000 || /* JCLR 00001010 11dddddd 000bbbbb */
425: (opcode & 0xFFC0A0) == 0xA80A0 || /* JSET 00001010 10pppppp 1S1bbbbb */
426: (opcode & 0xFFC0A0) == 0xA40A0 || /* JSET 00001010 01MMMRRR 1S1bbbbb */
427: (opcode & 0xFFC0A0) == 0xA00A0 || /* JSET 00001010 00aaaaaa 1S1bbbbb */
428: (opcode & 0xFFC0E0) == 0xAC020 || /* JSET 00001010 11dddddd 001bbbbb */
429: (opcode & 0xFF00F0) == 0x600A0 || /* REP 00000110 iiiiiiii 1010hhhh */
430: (opcode & 0xFFC0FF) == 0x6C020 || /* REP 00000110 11dddddd 00100000 */
431: (opcode & 0xFFC0BF) == 0x64020 || /* REP 00000110 01MMMRRR 0s100000 */
432: (opcode & 0xFFC0BF) == 0x60020 || /* REP 00000110 00aaaaaa 0s100000 */
433: (opcode & 0xFF00F0) == 0x60080 || /* DO/ENDO 00000110 iiiiiiii 1000hhhh */
434: (opcode & 0xFFC0FF) == 0x6C000 || /* DO/ENDO 00000110 11DDDDDD 00000000 */
435: (opcode & 0xFFC0BF) == 0x64000 || /* DO/ENDO 00000110 01MMMRRR 0S000000 */
436: (opcode & 0xFFC0BF) == 0x60000) { /* DO/ENDO 00000110 00aaaaaa 0S000000 */
437: return CALL_BRANCH;
438: }
439: return CALL_UNKNOWN;
440: }
441:
1.1 root 442:
443: /**
1.1.1.2 root 444: * DSP wrapper for BreakAddr_Command().
1.1 root 445: */
446: static int DebugDsp_BreakAddr(int nArgc, char *psArgs[])
447: {
448: BreakAddr_Command(psArgs[1], true);
449: return DEBUGGER_CMDDONE;
450: }
451:
452: /**
1.1.1.2 root 453: * DSP wrapper for BreakCond_Command().
1.1 root 454: */
455: static int DebugDsp_BreakCond(int nArgc, char *psArgs[])
456: {
457: BreakCond_Command(psArgs[1], true);
458: return DEBUGGER_CMDDONE;
459: }
460:
1.1.1.2 root 461: /**
462: * DSP wrapper for Profile_Command().
463: */
464: static int DebugDsp_Profile(int nArgc, char *psArgs[])
465: {
1.1.1.5 root 466: return Profile_Command(nArgc, psArgs, true);
1.1.1.2 root 467: }
468:
1.1 root 469:
470: /**
1.1.1.6 root 471: * DSP instructions since continuing emulation
472: */
473: static Uint32 nDspInstructions;
474: Uint32 DebugDsp_InstrCount(void)
475: {
476: return nDspInstructions;
477: }
478:
479: /**
1.1 root 480: * This function is called after each DSP instruction when debugging is enabled.
481: */
482: void DebugDsp_Check(void)
483: {
1.1.1.6 root 484: nDspInstructions++;
1.1.1.2 root 485: if (bDspProfiling)
486: {
487: Profile_DspUpdate();
488: }
1.1.1.4 root 489: if (LOG_TRACE_LEVEL((TRACE_DSP_DISASM|TRACE_DSP_SYMBOLS)))
490: {
1.1.1.8 root 491: DebugDsp_ShowAddressInfo(DSP_GetPC(), TraceFile);
1.1.1.4 root 492: }
1.1 root 493: if (nDspActiveCBs)
494: {
495: if (BreakCond_MatchDsp())
1.1.1.5 root 496: {
1.1.1.3 root 497: DebugUI(REASON_DSP_BREAKPOINT);
1.1.1.5 root 498: /* make sure we don't decrease step count
499: * below, before even getting out of here
500: */
501: if (nDspSteps)
502: nDspSteps++;
503: }
1.1 root 504: }
505: if (nDspSteps)
506: {
1.1.1.5 root 507: nDspSteps--;
1.1 root 508: if (nDspSteps == 0)
1.1.1.3 root 509: DebugUI(REASON_DSP_STEPS);
510: }
1.1.1.5 root 511: if (History_TrackDsp())
1.1.1.3 root 512: {
513: History_AddDsp();
1.1 root 514: }
515: }
516:
517:
518: /**
519: * Should be called before returning back emulation to tell the DSP core
520: * to call us after each instruction if "real-time" debugging like
521: * breakpoints has been set.
522: */
523: void DebugDsp_SetDebugging(void)
524: {
1.1.1.2 root 525: bDspProfiling = Profile_DspStart();
1.1.1.7 root 526: nDspActiveCBs = BreakCond_DspBreakPointCount();
1.1.1.2 root 527:
1.1.1.5 root 528: if (nDspActiveCBs || nDspSteps || bDspProfiling || History_TrackDsp()
1.1.1.4 root 529: || LOG_TRACE_LEVEL((TRACE_DSP_DISASM|TRACE_DSP_SYMBOLS)))
1.1.1.6 root 530: {
1.1 root 531: DSP_SetDebugging(true);
1.1.1.6 root 532: nDspInstructions = 0;
533: }
1.1 root 534: else
535: DSP_SetDebugging(false);
536: }
537:
538:
539: static const dbgcommand_t dspcommands[] =
540: {
541: { NULL, NULL, "DSP commands", NULL, NULL, NULL, false },
542: { DebugDsp_BreakAddr, Symbols_MatchDspCodeAddress,
543: "dspaddress", "da",
544: "set DSP PC address breakpoints",
545: BreakAddr_Description,
546: true },
1.1.1.8 root 547: /* currently no DSP variables, so checks that DSP symbol addresses */
548: { DebugDsp_BreakCond, Symbols_MatchDspAddress,
1.1 root 549: "dspbreak", "db",
550: "set/remove/list conditional DSP breakpoints",
551: BreakCond_Description,
552: true },
553: { DebugDsp_DisAsm, Symbols_MatchDspCodeAddress,
554: "dspdisasm", "dd",
555: "disassemble DSP code",
556: "[<start address>[-<end address>]]\n"
557: "\tDisassemble from DSP-PC, otherwise at given address.",
558: false },
559: { DebugDsp_MemDump, Symbols_MatchDspDataAddress,
560: "dspmemdump", "dm",
561: "dump DSP memory",
562: "[<x|y|p> <start address>[-<end address>]]\n"
563: "\tdump DSP memory from given memory space and address, or\n"
564: "\tcontinue from previous address if not specified.",
565: false },
566: { Symbols_Command, NULL,
567: "dspsymbols", "",
568: "load DSP symbols & their addresses",
569: Symbols_Description,
570: false },
1.1.1.2 root 571: { DebugDsp_Profile, Profile_Match,
572: "dspprofile", "dp",
573: "profile DSP code",
574: Profile_Description,
575: false },
1.1 root 576: { DebugDsp_Register, DebugDsp_MatchRegister,
577: "dspreg", "dr",
578: "read/write DSP registers",
579: "[REG=value]"
580: "\tSet or dump contents of DSP registers.",
581: true },
1.1.1.5 root 582: { DebugDsp_Step, NULL,
583: "dspstep", "ds",
584: "single-step DSP",
585: "\n"
586: "\tExecute next DSP instruction (equals 'dc 1')",
587: false },
1.1.1.6 root 588: { DebugDsp_Next, DebugDsp_MatchNext,
1.1.1.5 root 589: "dspnext", "dn",
1.1.1.6 root 590: "step DSP through subroutine calls / to given instruction type",
591: "[instruction type]\n"
592: "\tSame as 'dspstep' command if there are no subroutine calls.\n"
593: "\tWhen there are, those calls are treated as one instruction.\n"
594: "\tIf argument is given, continues until instruction of given\n"
595: "\ttype is encountered.",
1.1.1.5 root 596: false },
1.1 root 597: { DebugDsp_Continue, NULL,
598: "dspcont", "dc",
599: "continue emulation / DSP single-stepping",
600: "[steps]\n"
601: "\tLeave debugger and continue emulation for <steps> DSP instructions\n"
602: "\tor forever if no steps have been specified.",
603: false }
604: };
605:
606:
607: /**
608: * Should be called when debugger is first entered to initialize
609: * DSP debugging variables.
610: *
611: * if you want disassembly or memdumping to start/continue from
612: * specific address, you can set them here. If disassembly
613: * address is zero, disassembling starts from PC.
614: *
615: * returns number of DSP commands and pointer to array of them.
616: */
617: int DebugDsp_Init(const dbgcommand_t **table)
618: {
619: dsp_disasm_addr = 0;
620: dsp_memdump_addr = 0;
621: dsp_mem_space = 'P';
622:
623: *table = dspcommands;
1.1.1.8 root 624: return ARRAY_SIZE(dspcommands);
1.1 root 625: }
626:
627: /**
628: * Should be called when debugger is re-entered to reset
629: * relevant DSP debugging variables.
630: */
631: void DebugDsp_InitSession(void)
632: {
633: dsp_disasm_addr = DSP_GetPC();
1.1.1.2 root 634: Profile_DspStop();
1.1 root 635: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.