|
|
1.1 root 1: /*
2: Hatari - debuginfo.c
3:
4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
6:
7: debuginfo.c - functions needed to show info about the atari HW & OS
8: components and "lock" that info to be shown on entering the debugger.
9: */
10: const char DebugInfo_fileid[] = "Hatari debuginfo.c : " __DATE__ " " __TIME__;
11:
12: #include <stdio.h>
13: #include <assert.h>
14: #include "main.h"
15: #include "configuration.h"
16: #include "debugInfo.h"
17: #include "debugcpu.h"
18: #include "debugdsp.h"
19: #include "debugui.h"
20: #include "dsp.h"
21: #include "evaluate.h"
22: #include "ioMem.h"
23: #include "m68000.h"
24: #include "stMemory.h"
25: #include "tos.h"
26: #include "video.h"
27:
28:
29: /* ------------------------------------------------------------------
30: * TOS information
31: */
32: #define OS_SYSBASE 0x4F2
33: #define OS_HEADER_SIZE 0x30
34:
35: #define COOKIE_JAR 0x5A0
36:
37: #define BASEPAGE_SIZE 0x100
38:
39: #define GEM_MAGIC 0x87654321
40: #define GEM_MUPB_SIZE 0xC
41:
42: #define RESET_MAGIC 0x31415926
43: #define RESET_VALID 0x426
44: #define RESET_VECTOR 0x42A
45:
46: #define COUNTRY_SPAIN 4
47:
48: /**
49: * DebugInfo_GetSysbase: set osversion to given argument.
50: * return sysbase address on success and zero on failure.
51: */
52: static Uint32 DebugInfo_GetSysbase(Uint16 *osversion)
53: {
54: Uint32 sysbase = STMemory_ReadLong(OS_SYSBASE);
55:
56: if (!STMemory_ValidArea(sysbase, OS_HEADER_SIZE)) {
57: fprintf(stderr, "Invalid TOS base address!\n");
58: return 0;
59: }
60: if (sysbase != TosAddress || sysbase != STMemory_ReadLong(sysbase+0x08)) {
61: fprintf(stderr, "Sysbase and os_beg address in OS header mismatch!\n");
62: return 0;
63: }
64: *osversion = STMemory_ReadWord(sysbase+0x02);
65: return sysbase;
66: }
67:
68: /**
69: * DebugInfo_CurrentBasepage: get currently running TOS program basepage
70: */
71: static Uint32 DebugInfo_CurrentBasepage(void)
72: {
73: Uint32 basepage, sysbase;
74: Uint16 osversion, osconf;
75:
76: sysbase = DebugInfo_GetSysbase(&osversion);
77: if (!sysbase) {
78: return 0;
79: }
80: if (osversion >= 0x0102) {
81: basepage = STMemory_ReadLong(sysbase+0x28);
82: } else {
83: osconf = STMemory_ReadWord(sysbase+0x1C);
84: if((osconf>>1) == COUNTRY_SPAIN) {
85: basepage = 0x873C;
86: } else {
87: basepage = 0x602C;
88: }
89: }
90: if (STMemory_ValidArea(basepage, 4)) {
91: return STMemory_ReadLong(basepage);
92: }
93: fprintf(stderr, "Pointer 0x%06x to basepage address is invalid!\n", basepage);
94: return 0;
95: }
96:
97: /**
98: * DebugInfo_Basepage: show TOS process basepage information
99: * at given address.
100: */
101: static void DebugInfo_Basepage(Uint32 basepage)
102: {
103: Uint8 cmdlen;
104: Uint32 env;
105:
106: if (!basepage) {
107: /* default to current process basepage */
108: basepage = DebugInfo_CurrentBasepage();
109: if (!basepage) {
110: return;
111: }
112: }
113: fprintf(stderr, "Process basepage information:\n");
114: if (!STMemory_ValidArea(basepage, BASEPAGE_SIZE) ||
115: STMemory_ReadLong(basepage) != basepage) {
116: fprintf(stderr, "- address 0x%06x is invalid!\n", basepage);
117: return;
118: }
119: fprintf(stderr, "- TPA start : 0x%06x\n", STMemory_ReadLong(basepage));
120: fprintf(stderr, "- TPA end +1 : 0x%06x\n", STMemory_ReadLong(basepage+0x04));
121: fprintf(stderr, "- Text segment : 0x%06x\n", STMemory_ReadLong(basepage+0x08));
122: fprintf(stderr, "- Text size : 0x%x\n", STMemory_ReadLong(basepage+0x0C));
123: fprintf(stderr, "- Data segment : 0x%06x\n", STMemory_ReadLong(basepage+0x10));
124: fprintf(stderr, "- Data size : 0x%x\n", STMemory_ReadLong(basepage+0x14));
125: fprintf(stderr, "- BSS segment : 0x%06x\n", STMemory_ReadLong(basepage+0x18));
126: fprintf(stderr, "- BSS size : 0x%x\n", STMemory_ReadLong(basepage+0x1C));
127: fprintf(stderr, "- Process DTA : 0x%06x\n", STMemory_ReadLong(basepage+0x20));
128: fprintf(stderr, "- Parent basepage: 0x%06x\n", STMemory_ReadLong(basepage+0x24));
129:
130: env = STMemory_ReadLong(basepage+0x2C);
131: fprintf(stderr, "- Environment : 0x%06x\n", env);
132: if (STMemory_ValidArea(env, 4096)) {
133: Uint32 end = env + 4096;
134: while (env < end && *(STRam+env)) {
135: fprintf(stderr, "'%s'\n", STRam+env);
136: env += strlen((const char *)(STRam+env)) + 1;
137: }
138: }
139: cmdlen = STMemory_ReadByte(basepage+0x80);
140: fprintf(stderr, "- Command argslen: %d\n", cmdlen);
141: if (cmdlen) {
142: int offset = 0;
143: while (offset < cmdlen) {
144: fprintf(stderr, " '%s'", STRam+basepage+0x81+offset);
145: offset += strlen((const char *)(STRam+basepage+0x81+offset)) + 1;
146: }
147: fprintf(stderr, "\n");
148: }
149: }
150:
151: /**
152: * DebugInfo_OSHeader: display TOS OS Header
153: */
154: static void DebugInfo_OSHeader(Uint32 dummy)
155: {
156: Uint32 sysbase, gemblock, basepage;
157: Uint16 osversion, osconf;
158:
159: sysbase = DebugInfo_GetSysbase(&osversion);
160: if (!sysbase) {
161: return;
162: }
163: fprintf(stderr, "OS base addr : 0x%06x\n", sysbase);
164: fprintf(stderr, "OS RAM end+1 : 0x%06x\n", STMemory_ReadLong(sysbase+0x0C));
165: fprintf(stderr, "TOS version : 0x%x\n", osversion);
166:
167: fprintf(stderr, "Reset handler: 0x%06x\n", STMemory_ReadLong(sysbase+0x04));
168: fprintf(stderr, "Reset vector : 0x%06x\n", STMemory_ReadLong(RESET_VECTOR));
169: fprintf(stderr, "Reset valid : 0x%x (valid=0x%x)\n", STMemory_ReadLong(RESET_VALID), RESET_MAGIC);
170:
171: gemblock = STMemory_ReadLong(sysbase+0x14);
172: fprintf(stderr, "GEM Memory Usage Parameter Block:\n");
173: if (STMemory_ValidArea(gemblock, GEM_MUPB_SIZE)) {
174: fprintf(stderr, "- Block addr : 0x%06x\n", gemblock);
175: fprintf(stderr, "- GEM magic : 0x%x (valid=0x%x)\n", STMemory_ReadLong(gemblock), GEM_MAGIC);
176: fprintf(stderr, "- GEM entry : 0x%06x\n", STMemory_ReadLong(gemblock+4));
177: fprintf(stderr, "- GEM end : 0x%06x\n", STMemory_ReadLong(gemblock+8));
178: } else {
179: fprintf(stderr, "- is at INVALID 0x%06x address.\n", gemblock);
180: }
181:
182: fprintf(stderr, "OS date : 0x%x\n", STMemory_ReadLong(sysbase+0x14));
183: fprintf(stderr, "OS DOS date : 0x%x\n", STMemory_ReadLong(sysbase+0x1E));
184:
185: osconf = STMemory_ReadWord(sysbase+0x1C);
186: fprintf(stderr, "OS Conf bits : lang=%d, %s\n", osconf>>1, osconf&1 ? "PAL":"NTSC");
187: fprintf(stderr, "Cookie Jar : 0x%06x\n", STMemory_ReadLong(COOKIE_JAR));
188:
189: /* last 3 OS header fields are only available as of TOS 1.02 */
190: if (osversion >= 0x0102) {
191: fprintf(stderr, "Memory pool : 0x%06x\n", STMemory_ReadLong(sysbase+0x20));
192: fprintf(stderr, "Kbshift addr : 0x%06x\n", STMemory_ReadLong(sysbase+0x24));
193: } else {
194: /* TODO: GEMDOS memory pool address for TOS 1.0? */
195: fprintf(stderr, "Kbshift addr : 0x000E1B\n");
196: }
197: basepage = DebugInfo_CurrentBasepage();
198: if (basepage) {
199: fprintf(stderr, "Basepage : 0x%06x\n", basepage);
200: }
201: }
202:
203:
204: /* ------------------------------------------------------------------
205: * Falcon HW information
206: */
207:
208: /**
209: * DebugInfo_Videl : display the Videl registers values.
210: */
211: static void DebugInfo_Videl(Uint32 dummy)
212: {
213: if (ConfigureParams.System.nMachineType != MACHINE_FALCON) {
214: fprintf(stderr, "Not Falcon - no Videl!\n");
215: return;
216: }
217:
218: fprintf(stderr, "$FF8006 : monitor type : %02x\n", IoMem_ReadByte(0xff8006));
219: fprintf(stderr, "$FF820E : offset to next line : %04x\n", IoMem_ReadWord(0xff820e));
220: fprintf(stderr, "$FF8210 : VWRAP - line width : %04x\n", IoMem_ReadWord(0xff8210));
221: fprintf(stderr, "$FF8260 : ST shift mode : %02x\n", IoMem_ReadByte(0xff8260));
222: fprintf(stderr, "$FF8265 : Horizontal scroll register : %02x\n", IoMem_ReadByte(0xff8265));
223: fprintf(stderr, "$FF8266 : Falcon shift mode : %04x\n", IoMem_ReadWord(0xff8266));
224: fprintf(stderr, "\n");
225: fprintf(stderr, "$FF8280 : HHC - Horizontal Hold Counter : %04x\n", IoMem_ReadWord(0xff8280));
226: fprintf(stderr, "$FF8282 : HHT - Horizontal Hold Timer : %04x\n", IoMem_ReadWord(0xff8282));
227: fprintf(stderr, "$FF8284 : HBB - Horizontal Border Begin : %04x\n", IoMem_ReadWord(0xff8284));
228: fprintf(stderr, "$FF8286 : HBE - Horizontal Border End : %04x\n", IoMem_ReadWord(0xff8286));
229: fprintf(stderr, "$FF8288 : HDB - Horizontal Display Begin : %04x\n", IoMem_ReadWord(0xff8288));
230: fprintf(stderr, "$FF828A : HDE - Horizontal Display End : %04x\n", IoMem_ReadWord(0xff828a));
231: fprintf(stderr, "$FF828C : HSS - Horizontal SS : %04x\n", IoMem_ReadWord(0xff828c));
232: fprintf(stderr, "$FF828E : HFS - Horizontal FS : %04x\n", IoMem_ReadWord(0xff828e));
233: fprintf(stderr, "$FF8290 : HEE - Horizontal EE : %04x\n", IoMem_ReadWord(0xff8290));
234: fprintf(stderr, "\n");
235: fprintf(stderr, "$FF82A0 : VFC - Vertical Frequency Counter : %04x\n", IoMem_ReadWord(0xff82a0));
236: fprintf(stderr, "$FF82A2 : VFT - Vertical Frequency Timer : %04x\n", IoMem_ReadWord(0xff82a2));
237: fprintf(stderr, "$FF82A4 : VBB - Vertical Border Begin : %04x\n", IoMem_ReadWord(0xff82a4));
238: fprintf(stderr, "$FF82A6 : VBE - Vertical Border End : %04x\n", IoMem_ReadWord(0xff82a6));
239: fprintf(stderr, "$FF82A8 : VDB - Vertical Display Begin : %04x\n", IoMem_ReadWord(0xff82a8));
240: fprintf(stderr, "$FF82AA : VDE - Vertical Display End : %04x\n", IoMem_ReadWord(0xff82aa));
241: fprintf(stderr, "$FF82AC : VSS - Vertical SS : %04x\n", IoMem_ReadWord(0xff82ac));
242: fprintf(stderr, "\n");
243: fprintf(stderr, "$FF82C0 : VCO - Video control : %04x\n", IoMem_ReadWord(0xff82c0));
244: fprintf(stderr, "$FF82C2 : VMD - Video mode : %04x\n", IoMem_ReadWord(0xff82c2));
245: fprintf(stderr, "\n");
246: }
247:
248: /**
249: * DebugInfo_Crossbar : display the Crossbar registers values.
250: */
251: static void DebugInfo_Crossbar(Uint32 dummy)
252: {
253: char matrixDMA[5], matrixDAC[5], matrixDSP[5], matrixEXT[5];
254: char frqDMA[11], frqDAC[11], frqDSP[11], frqEXT[11];
255: char dataSize[15];
256:
257: if (ConfigureParams.System.nMachineType != MACHINE_FALCON) {
258: fprintf(stderr, "Not Falcon - no Crossbar!\n");
259: return;
260: }
261:
262: fprintf(stderr, "$FF8900 : Sound DMA control : %02x\n", IoMem_ReadByte(0xff8900));
263: fprintf(stderr, "$FF8901 : Sound DMA control : %02x\n", IoMem_ReadByte(0xff8901));
264: fprintf(stderr, "$FF8903 : Frame Start High : %02x\n", IoMem_ReadByte(0xff8903));
265: fprintf(stderr, "$FF8905 : Frame Start middle : %02x\n", IoMem_ReadByte(0xff8905));
266: fprintf(stderr, "$FF8907 : Frame Start low : %02x\n", IoMem_ReadByte(0xff8907));
267: fprintf(stderr, "$FF8909 : Frame Count High : %02x\n", IoMem_ReadByte(0xff8909));
268: fprintf(stderr, "$FF890B : Frame Count middle : %02x\n", IoMem_ReadByte(0xff890b));
269: fprintf(stderr, "$FF890D : Frame Count low : %02x\n", IoMem_ReadByte(0xff890d));
270: fprintf(stderr, "$FF890f : Frame End High : %02x\n", IoMem_ReadByte(0xff890f));
271: fprintf(stderr, "$FF8911 : Frame End middle : %02x\n", IoMem_ReadByte(0xff8911));
272: fprintf(stderr, "$FF8913 : Frame End low : %02x\n", IoMem_ReadByte(0xff8913));
273: fprintf(stderr, "\n");
274: fprintf(stderr, "$FF8920 : Sound Mode Control : %02x\n", IoMem_ReadByte(0xff8920));
275: fprintf(stderr, "$FF8921 : Sound Mode Control : %02x\n", IoMem_ReadByte(0xff8921));
276: fprintf(stderr, "$FF8930 : DMA Crossbar Input Select Controller : %04x\n", IoMem_ReadWord(0xff8930));
277: fprintf(stderr, "$FF8932 : DMA Crossbar Output Select Controller : %04x\n", IoMem_ReadWord(0xff8932));
278: fprintf(stderr, "\n");
279: fprintf(stderr, "$FF8934 : External Sync Frequency Divider : %02x\n", IoMem_ReadByte(0xff8934));
280: fprintf(stderr, "$FF8935 : Internal Sync Frequency Divider : %02x\n", IoMem_ReadByte(0xff8935));
281: fprintf(stderr, "$FF8936 : Record Track select : %02x\n", IoMem_ReadByte(0xff8936));
282: fprintf(stderr, "$FF8937 : Codec Input Source : %02x\n", IoMem_ReadByte(0xff8937));
283: fprintf(stderr, "$FF8938 : Codec ADC Input : %02x\n", IoMem_ReadByte(0xff8938));
284: fprintf(stderr, "$FF8939 : Gain Settings Per Channel : %02x\n", IoMem_ReadByte(0xff8939));
285: fprintf(stderr, "$FF893A : Attenuation Settings Per Channel : %02x\n", IoMem_ReadByte(0xff893a));
286: fprintf(stderr, "$FF893C : Codec Status : %04x\n", IoMem_ReadWord(0xff893c));
287: fprintf(stderr, "$FF8940 : GPIO Data Direction : %04x\n", IoMem_ReadWord(0xff8940));
288: fprintf(stderr, "$FF8942 : GPIO Data : %04x\n", IoMem_ReadWord(0xff8942));
289: fprintf(stderr, "\n");
290:
291: /* DAC connexion */
292: switch ((IoMem_ReadWord(0xff8932) >> 13) & 3) {
293: case 0 : strcpy(matrixDAC, "OOXO"); break;
294: case 1 : strcpy(matrixDAC, "OXOO"); break;
295: case 2 : strcpy(matrixDAC, "XOOO"); break;
296: case 3 : strcpy(matrixDAC, "OOOX"); break;
297: }
298:
299: /* DMA connexion */
300: switch ((IoMem_ReadWord(0xff8932) >> 1) & 3) {
301: case 0 : strcpy(matrixDMA, "OOXO"); break;
302: case 1 : strcpy(matrixDMA, "OXOO"); break;
303: case 2 : strcpy(matrixDMA, "XOOO"); break;
304: case 3 : strcpy(matrixDMA, "OOOX"); break;
305: }
306:
307: /* DSP connexion */
308: switch ((IoMem_ReadWord(0xff8932) >> 5) & 3) {
309: case 0 : strcpy(matrixDSP, "OOXO"); break;
310: case 1 : strcpy(matrixDSP, "OXOO"); break;
311: case 2 : strcpy(matrixDSP, "XOOO"); break;
312: case 3 : strcpy(matrixDSP, "OOOX"); break;
313: }
314:
315: /* External input connexion */
316: switch ((IoMem_ReadWord(0xff8932) >> 9) & 3) {
317: case 0 : strcpy(matrixEXT, "OOXO"); break;
318: case 1 : strcpy(matrixEXT, "OXOO"); break;
319: case 2 : strcpy(matrixEXT, "XOOO"); break;
320: case 3 : strcpy(matrixEXT, "OOOX"); break;
321: }
322:
323: /* HandShake mode test */
324: if ((IoMem_ReadWord(0xff8932) & 7) == 2) {
325: matrixDMA[1] = 'H';
326: }
327:
328: /* HandShake mode test */
329: if ((IoMem_ReadWord(0xff8932) & 0xf) == 2) {
330: matrixDSP[2] = 'H';
331: }
332:
333: /* DSP Frequency */
334: if ((IoMem_ReadByte(0xff8935) & 0xf) == 0) {
335: strcpy(frqDSP, "(STe Freq)");
336: }else {
337: switch ((IoMem_ReadWord(0xff8930) >> 5) & 0x3) {
338: case 0: strcpy(frqDSP, " (25 Mhz) "); break;
339: case 1: strcpy(frqDSP, "(External)"); break;
340: case 2: strcpy(frqDSP, " (32 Mhz) "); break;
341: default: strcpy(frqDSP, "undefined "); break;break;
342: }
343: }
344:
345: /* DMA Frequency */
346: if ((IoMem_ReadByte(0xff8935) & 0xf) == 0) {
347: strcpy(frqDMA, "(STe Freq)");
348: }else {
349: switch ((IoMem_ReadWord(0xff8930) >> 1) & 0x3) {
350: case 0: strcpy(frqDMA, " (25 Mhz) "); break;
351: case 1: strcpy(frqDMA, "(External)"); break;
352: case 2: strcpy(frqDMA, " (32 Mhz) "); break;
353: default: strcpy(frqDMA, "undefined "); break;break;
354: }
355: }
356:
357: /* External Frequency */
358: if ((IoMem_ReadByte(0xff8935) & 0xf) == 0) {
359: strcpy(frqEXT, "(STe Freq)");
360: }else {
361: switch ((IoMem_ReadWord(0xff8930) >> 9) & 0x3) {
362: case 0: strcpy(frqEXT, " (25 Mhz) "); break;
363: case 1: strcpy(frqEXT, "(External)"); break;
364: case 2: strcpy(frqEXT, " (32 Mhz) "); break;
365: default: strcpy(frqEXT, "undefined "); break;break;
366: }
367: }
368:
369: /* DAC Frequency */
370: if ((IoMem_ReadByte(0xff8935) & 0xf) == 0) {
371: strcpy(frqDAC, "(STe Freq)");
372: }else {
373: strcpy(frqDAC, " (25 Mhz) ");
374: }
375:
376: /* data size */
377: switch ((IoMem_ReadByte(0xff8921) >> 6) & 0x3) {
378: case 0: strcpy (dataSize, "8 bits stereo"); break;
379: case 1: strcpy (dataSize, "16 bits stereo"); break;
380: case 2: strcpy (dataSize, "8 bits mono"); break;
381: default: strcpy (dataSize, "undefined"); break;
382: }
383:
384: /* Display the crossbar Matrix */
385: fprintf(stderr, " INPUT\n");
386: fprintf(stderr, "External Imp ---%c------%c------%c------%c\n", matrixDAC[0], matrixDMA[0], matrixDSP[0], matrixEXT[0]);
387: fprintf(stderr, "%s | | | | O = no connexion\n", frqEXT);
388: fprintf(stderr, " | | | | X = connexion\n");
389: fprintf(stderr, "Dsp Transmit ---%c------%c------%c------%c H = Handshake connexion\n", matrixDAC[1], matrixDMA[1], matrixDSP[1], matrixEXT[1]);
390: fprintf(stderr, "%s | | | |\n", frqDSP);
391: fprintf(stderr, " | | | | %s\n", dataSize);
392: fprintf(stderr, "DMA PlayBack ---%c------%c------%c------%c\n", matrixDAC[2], matrixDMA[2], matrixDSP[2], matrixEXT[2]);
393: fprintf(stderr, "%s | | | |\n", frqDMA);
394: fprintf(stderr, " | | | |\n");
395: fprintf(stderr, "ADC ---%c------%c------%c------%c\n", matrixDAC[3], matrixDMA[3], matrixDSP[3], matrixEXT[3]);
396: fprintf(stderr, "%s | | | |\n", frqDAC);
397: fprintf(stderr, " DAC DMA DSP External OUTPUT\n");
398: fprintf(stderr, " Record Record Out\n");
399: fprintf(stderr, "\n");
400: }
401:
402:
403: /* ------------------------------------------------------------------
404: * CPU and DSP information wrappers
405: */
406:
407: /**
408: * Helper to call debugcpu.c and debugdsp.c debugger commands
409: */
410: static void DebugInfo_CallCommand(int (*func)(int, char* []), const char *command, Uint32 arg)
411: {
412: char cmdbuffer[16], argbuffer[12];
413: char *argv[] = { cmdbuffer, NULL };
414: int argc = 1;
415:
416: assert(strlen(command) < sizeof(cmdbuffer));
417: strcpy(cmdbuffer, command);
418: if (arg) {
419: sprintf(argbuffer, "$%x", arg);
420: argv[argc++] = argbuffer;
421: }
422: func(argc, argv);
423: }
424:
425: static void DebugInfo_CpuRegister(Uint32 arg)
426: {
427: DebugInfo_CallCommand(DebugCpu_Register, "register", arg);
428: }
429: static void DebugInfo_CpuDisAsm(Uint32 arg)
430: {
431: DebugInfo_CallCommand(DebugCpu_DisAsm, "disasm", arg);
432: }
433: static void DebugInfo_CpuMemDump(Uint32 arg)
434: {
435: DebugInfo_CallCommand(DebugCpu_MemDump, "memdump", arg);
436: }
437:
438: #if ENABLE_DSP_EMU
439:
440: static void DebugInfo_DspRegister(Uint32 arg)
441: {
442: DebugInfo_CallCommand(DebugDsp_Register, "dspreg", arg);
443: }
444: static void DebugInfo_DspDisAsm(Uint32 arg)
445: {
446: DebugInfo_CallCommand(DebugDsp_DisAsm, "dspdisasm", arg);
447: }
448:
449: static void DebugInfo_DspMemDump(Uint32 arg)
450: {
451: char cmdbuf[] = "dspmemdump";
452: char addrbuf[6], spacebuf[2] = "X";
453: char *argv[] = { cmdbuf, spacebuf, addrbuf };
454: spacebuf[0] = (arg>>16)&0xff;
455: sprintf(addrbuf, "$%x", (Uint16)(arg&0xffff));
456: DebugDsp_MemDump(3, argv);
457: }
458:
459: /**
460: * Convert arguments to Uint32 arg suitable for DSP memdump callback
461: */
462: static Uint32 DebugInfo_DspMemArgs(int argc, char *argv[])
463: {
464: Uint32 value;
465: char space;
466: if (argc != 2) {
467: return 0;
468: }
469: space = toupper(argv[0][0]);
470: if ((space != 'X' && space != 'Y' && space != 'P') || argv[0][1]) {
471: fprintf(stderr, "ERROR: invalid DSP address space '%s'!\n", argv[0]);
472: return 0;
473: }
474: if (!Eval_Number(argv[1], &value) || value > 0xffff) {
475: fprintf(stderr, "ERROR: invalid DSP address '%s'!\n", argv[1]);
476: return 0;
477: }
478: return ((Uint32)space<<16) | value;
479: }
480:
481: #endif /* ENABLE_DSP_EMU */
482:
483:
484: static void DebugInfo_RegAddr(Uint32 arg)
485: {
486: bool forDsp;
487: char regname[3];
488: Uint32 *regvalue, mask;
489: char cmdbuf[12], addrbuf[6];
490: char *argv[] = { cmdbuf, addrbuf };
491:
492: regname[0] = (arg>>24)&0xff;
493: regname[1] = (arg>>16)&0xff;
494: regname[2] = '\0';
495:
496: if (DebugCpu_GetRegisterAddress(regname, ®value)) {
497: mask = 0xffffffff;
498: forDsp = false;
499: } else {
500: if (!DSP_GetRegisterAddress(regname, ®value, &mask)) {
501: fprintf(stderr, "ERROR: invalid address/data register '%s'!\n", regname);
502: return;
503: }
504: forDsp = true;
505: }
506: sprintf(addrbuf, "$%x", *regvalue & mask);
507:
508: if ((arg & 0xff) == 'D') {
509: strcpy(cmdbuf, "disasm");
510: if (forDsp) {
511: #if ENABLE_DSP_EMU
512: DebugDsp_DisAsm(2, argv);
513: #endif
514: } else {
515: DebugCpu_DisAsm(2, argv);
516: }
517: } else {
518: strcpy(cmdbuf, "memdump");
519: if (forDsp) {
520: #if ENABLE_DSP_EMU
521: DebugDsp_MemDump(2, argv);
522: #endif
523: } else {
524: DebugCpu_MemDump(2, argv);
525: }
526: }
527: }
528:
529: /**
530: * Convert arguments to Uint32 arg suitable for RegAddr callback
531: */
532: static Uint32 DebugInfo_RegAddrArgs(int argc, char *argv[])
533: {
534: Uint32 value, *regaddr;
535: if (argc != 2) {
536: return 0;
537: }
538:
539: if (strcmp(argv[0], "disasm") == 0) {
540: value = 'D';
541: } else if (strcmp(argv[0], "memdump") == 0) {
542: value = 'M';
543: } else {
544: fprintf(stderr, "ERROR: regaddr operation can be only 'disasm' or 'memdump', not '%s'!\n", argv[0]);
545: return 0;
546: }
547:
548: if (strlen(argv[1]) != 2 ||
549: (!DebugCpu_GetRegisterAddress(argv[1], ®addr) &&
550: (toupper(argv[1][0]) != 'R' || !isdigit(argv[1][1]) || argv[1][2]))) {
551: /* not CPU register or Rx DSP register */
552: fprintf(stderr, "ERROR: invalid address/data register '%s'!\n", argv[1]);
553: return 0;
554: }
555:
556: value |= argv[1][0] << 24;
557: value |= argv[1][1] << 16;
558: value &= 0xffff00ff;
559: return value;
560: }
561:
562:
563: /* ------------------------------------------------------------------
564: * Debugger & readline TAB completion integration
565: */
566:
567: /**
568: * Default information on entering the debugger
569: */
570: static void DebugInfo_Default(Uint32 dummy)
571: {
572: int hbl, fcycles, lcycles;
573: Video_GetPosition(&fcycles, &hbl, &lcycles);
574: fprintf(stderr, "\nCPU=$%x, VBL=%d, FrameCycles=%d, HBL=%d, LineCycles=%d, DSP=",
575: M68000_GetPC(), nVBLs, fcycles, hbl, lcycles);
576: if (bDspEnabled)
577: fprintf(stderr, "$%x\n", DSP_GetPC());
578: else
579: fprintf(stderr, "N/A\n");
580: }
581:
582: static const struct {
583: /* whether callback is used only for locking */
584: bool lock;
585: const char *name;
586: void (*func)(Uint32 arg);
587: /* convert args in argv into single Uint32 for func */
588: Uint32 (*args)(int argc, char *argv[]);
589: const char *info;
590: } infotable[] = {
591: { false,"basepage", DebugInfo_Basepage, NULL, "Show program basepage info at given <address>" },
592: { false,"crossbar", DebugInfo_Crossbar, NULL, "Show Falcon crossbar HW register values" },
593: { true, "default", DebugInfo_Default, NULL, "Show default debugger entry information" },
594: { true, "disasm", DebugInfo_CpuDisAsm, NULL, "Disasm CPU from PC or given <address>" },
595: #if ENABLE_DSP_EMU
596: { true, "dspdisasm", DebugInfo_DspDisAsm, NULL, "Disasm DSP from given <address>" },
597: { true, "dspmemdump",DebugInfo_DspMemDump, DebugInfo_DspMemArgs, "Dump DSP memory from given <space> <address>" },
598: { true, "dspregs", DebugInfo_DspRegister,NULL, "Show DSP register values" },
599: #endif
600: { true, "memdump", DebugInfo_CpuMemDump, NULL, "Dump CPU memory from given <address>" },
601: { false,"osheader", DebugInfo_OSHeader, NULL, "Show TOS OS header information" },
602: { true, "regaddr", DebugInfo_RegAddr, DebugInfo_RegAddrArgs, "Show <disasm|memdump> from CPU/DSP address pointed by <register>" },
603: { true, "registers", DebugInfo_CpuRegister,NULL, "Show CPU register values" },
604: { false,"videl", DebugInfo_Videl, NULL, "Show Falcon Videl HW register values" }
605: };
606:
607: static int LockedFunction = 2; /* index for the "default" function */
608: static Uint32 LockedArgument;
609:
610: /**
611: * Show selected debugger session information
612: * (when debugger is (again) entered)
613: */
614: void DebugInfo_ShowSessionInfo(void)
615: {
616: infotable[LockedFunction].func(LockedArgument);
617: }
618:
619:
620: /**
621: * Readline match callback for info subcommand name completion.
622: * STATE = 0 -> different text from previous one.
623: * Return next match or NULL if no matches.
624: */
625: static char *DebugInfo_Match(const char *text, int state, bool lock)
626: {
627: static int i, len;
628: const char *name;
629:
630: if (!state) {
631: /* first match */
632: len = strlen(text);
633: i = 0;
634: }
635: /* next match */
636: while (i++ < ARRAYSIZE(infotable)) {
637: if (!lock && infotable[i-1].lock) {
638: continue;
639: }
640: name = infotable[i-1].name;
641: if (strncmp(name, text, len) == 0)
642: return (strdup(name));
643: }
644: return NULL;
645: }
646: char *DebugInfo_MatchLock(const char *text, int state)
647: {
648: return DebugInfo_Match(text, state, true);
649: }
650: char *DebugInfo_MatchInfo(const char *text, int state)
651: {
652: return DebugInfo_Match(text, state, false);
653: }
654:
655:
656: /**
657: * Show requested command information.
658: */
659: int DebugInfo_Command(int nArgc, char *psArgs[])
660: {
661: Uint32 value;
662: const char *cmd;
663: bool ok, lock;
664: int i, sub;
665:
666: sub = -1;
667: if (nArgc > 1) {
668: cmd = psArgs[1];
669: /* which subcommand? */
670: for (i = 0; i < ARRAYSIZE(infotable); i++) {
671: if (strcmp(cmd, infotable[i].name) == 0) {
672: sub = i;
673: break;
674: }
675: }
676: }
677:
678: if (infotable[sub].args) {
679: /* value needs callback specific conversion */
680: value = infotable[sub].args(nArgc-2, psArgs+2);
681: ok = !!value;
682: } else {
683: if (nArgc > 2) {
684: /* value is normal number */
685: ok = Eval_Number(psArgs[2], &value);
686: } else {
687: value = 0;
688: ok = true;
689: }
690: }
691:
692: lock = (strcmp(psArgs[0], "lock") == 0);
693:
694: if (sub < 0 || !ok) {
695: /* no subcommand or something wrong with value, show info */
696: fprintf(stderr, "%s subcommands are:\n", psArgs[0]);
697: for (i = 0; i < ARRAYSIZE(infotable); i++) {
698: if (!lock && infotable[i].lock) {
699: continue;
700: }
701: fprintf(stderr, "- %s: %s\n",
702: infotable[i].name, infotable[i].info);
703: }
704: return DEBUGGER_CMDDONE;
705: }
706:
707: if (lock) {
708: /* lock given subcommand and value */
709: LockedFunction = sub;
710: LockedArgument = value;
711: fprintf(stderr, "Locked %s output.\n", psArgs[1]);
712: } else {
713: /* do actual work */
714: infotable[sub].func(value);
715: }
716: return DEBUGGER_CMDDONE;
717: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.