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