|
|
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.