|
|
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 "debugui.h" ! 19: #include "evaluate.h" ! 20: #include "ioMem.h" ! 21: #include "m68000.h" ! 22: #include "nextMemory.h" ! 23: #include "video.h" ! 24: ! 25: ! 26: /* ------------------------------------------------------------------ ! 27: * TOS information ! 28: */ ! 29: #define OS_SYSBASE 0x4F2 ! 30: #define OS_HEADER_SIZE 0x30 ! 31: ! 32: #define COOKIE_JAR 0x5A0 ! 33: ! 34: #define BASEPAGE_SIZE 0x100 ! 35: ! 36: #define GEM_MAGIC 0x87654321 ! 37: #define GEM_MUPB_SIZE 0xC ! 38: ! 39: #define RESET_MAGIC 0x31415926 ! 40: #define RESET_VALID 0x426 ! 41: #define RESET_VECTOR 0x42A ! 42: ! 43: #define COUNTRY_SPAIN 4 ! 44: ! 45: /** ! 46: * DebugInfo_GetSysbase: set osversion to given argument. ! 47: * return sysbase address on success and zero on failure. ! 48: */ ! 49: static Uint32 DebugInfo_GetSysbase(Uint16 *osversion) ! 50: { ! 51: return 00; ! 52: } ! 53: ! 54: /** ! 55: * DebugInfo_CurrentBasepage: get currently running TOS program basepage ! 56: */ ! 57: static Uint32 DebugInfo_CurrentBasepage(void) ! 58: { ! 59: return 0; ! 60: } ! 61: ! 62: /** ! 63: * DebugInfo_Basepage: show TOS process basepage information ! 64: * at given address. ! 65: */ ! 66: static void DebugInfo_Basepage(Uint32 basepage) ! 67: { ! 68: } ! 69: ! 70: /** ! 71: * DebugInfo_OSHeader: display TOS OS Header ! 72: */ ! 73: static void DebugInfo_OSHeader(Uint32 dummy) ! 74: { ! 75: } ! 76: ! 77: ! 78: /* ------------------------------------------------------------------ ! 79: * Next HW information ! 80: */ ! 81: ! 82: /** ! 83: * DebugInfo_Rtc : display the Videl registers values. ! 84: */ ! 85: static void DebugInfo_Rtc(Uint32 dummy) ! 86: { ! 87: Screen_Draw(); ! 88: fprintf(stdout,"%s",get_rtc_ram_info()); ! 89: } ! 90: ! 91: /** ! 92: * DebugInfo_Crossbar : display the Crossbar registers values. ! 93: */ ! 94: static void DebugInfo_Crossbar(Uint32 dummy) ! 95: { ! 96: } ! 97: ! 98: ! 99: /* ------------------------------------------------------------------ ! 100: * CPU and DSP information wrappers ! 101: */ ! 102: ! 103: /** ! 104: * Helper to call debugcpu.c and debugdsp.c debugger commands ! 105: */ ! 106: static void DebugInfo_CallCommand(int (*func)(int, char* []), const char *command, Uint32 arg) ! 107: { ! 108: char cmdbuffer[16], argbuffer[12]; ! 109: char *argv[] = { cmdbuffer, NULL }; ! 110: int argc = 1; ! 111: ! 112: assert(strlen(command) < sizeof(cmdbuffer)); ! 113: strcpy(cmdbuffer, command); ! 114: if (arg) { ! 115: sprintf(argbuffer, "$%x", arg); ! 116: argv[argc++] = argbuffer; ! 117: } ! 118: func(argc, argv); ! 119: } ! 120: ! 121: static void DebugInfo_CpuRegister(Uint32 arg) ! 122: { ! 123: DebugInfo_CallCommand(DebugCpu_Register, "register", arg); ! 124: } ! 125: static void DebugInfo_CpuDisAsm(Uint32 arg) ! 126: { ! 127: DebugInfo_CallCommand(DebugCpu_DisAsm, "disasm", arg); ! 128: } ! 129: static void DebugInfo_CpuMemDump(Uint32 arg) ! 130: { ! 131: DebugInfo_CallCommand(DebugCpu_MemDump, "memdump", arg); ! 132: } ! 133: ! 134: #if ENABLE_DSP_EMU ! 135: ! 136: static void DebugInfo_DspRegister(Uint32 arg) ! 137: { ! 138: } ! 139: static void DebugInfo_DspDisAsm(Uint32 arg) ! 140: { ! 141: } ! 142: ! 143: static void DebugInfo_DspMemDump(Uint32 arg) ! 144: { ! 145: } ! 146: ! 147: /** ! 148: * Convert arguments to Uint32 arg suitable for DSP memdump callback ! 149: */ ! 150: static Uint32 DebugInfo_DspMemArgs(int argc, char *argv[]) ! 151: { ! 152: Uint32 value; ! 153: char space; ! 154: if (argc != 2) { ! 155: return 0; ! 156: } ! 157: space = toupper(argv[0][0]); ! 158: if ((space != 'X' && space != 'Y' && space != 'P') || argv[0][1]) { ! 159: fprintf(stderr, "ERROR: invalid DSP address space '%s'!\n", argv[0]); ! 160: return 0; ! 161: } ! 162: if (!Eval_Number(argv[1], &value) || value > 0xffff) { ! 163: fprintf(stderr, "ERROR: invalid DSP address '%s'!\n", argv[1]); ! 164: return 0; ! 165: } ! 166: return ((Uint32)space<<16) | value; ! 167: } ! 168: ! 169: #endif /* ENABLE_DSP_EMU */ ! 170: ! 171: ! 172: static void DebugInfo_RegAddr(Uint32 arg) ! 173: { ! 174: } ! 175: ! 176: /** ! 177: * Convert arguments to Uint32 arg suitable for RegAddr callback ! 178: */ ! 179: static Uint32 DebugInfo_RegAddrArgs(int argc, char *argv[]) ! 180: { ! 181: Uint32 value, *regaddr; ! 182: if (argc != 2) { ! 183: return 0; ! 184: } ! 185: ! 186: if (strcmp(argv[0], "disasm") == 0) { ! 187: value = 'D'; ! 188: } else if (strcmp(argv[0], "memdump") == 0) { ! 189: value = 'M'; ! 190: } else { ! 191: fprintf(stderr, "ERROR: regaddr operation can be only 'disasm' or 'memdump', not '%s'!\n", argv[0]); ! 192: return 0; ! 193: } ! 194: ! 195: if (strlen(argv[1]) != 2 || ! 196: (!DebugCpu_GetRegisterAddress(argv[1], ®addr) && ! 197: (toupper(argv[1][0]) != 'R' || !isdigit(argv[1][1]) || argv[1][2]))) { ! 198: /* not CPU register or Rx DSP register */ ! 199: fprintf(stderr, "ERROR: invalid address/data register '%s'!\n", argv[1]); ! 200: return 0; ! 201: } ! 202: ! 203: value |= argv[1][0] << 24; ! 204: value |= argv[1][1] << 16; ! 205: value &= 0xffff00ff; ! 206: return value; ! 207: } ! 208: ! 209: ! 210: /* ------------------------------------------------------------------ ! 211: * Debugger & readline TAB completion integration ! 212: */ ! 213: ! 214: /** ! 215: * Default information on entering the debugger ! 216: */ ! 217: static void DebugInfo_Default(Uint32 dummy) ! 218: { ! 219: int hbl, fcycles, lcycles; ! 220: Video_GetPosition(&fcycles, &hbl, &lcycles); ! 221: fprintf(stderr, "\nCPU=$%x, VBL=%d, FrameCycles=%d, HBL=%d, LineCycles=%d, DSP=", ! 222: M68000_GetPC(), 0, fcycles, hbl, lcycles); ! 223: fprintf(stderr, "N/A\n"); ! 224: } ! 225: ! 226: static const struct { ! 227: /* whether callback is used only for locking */ ! 228: bool lock; ! 229: const char *name; ! 230: void (*func)(Uint32 arg); ! 231: /* convert args in argv into single Uint32 for func */ ! 232: Uint32 (*args)(int argc, char *argv[]); ! 233: const char *info; ! 234: } infotable[] = { ! 235: { false,"basepage", DebugInfo_Basepage, NULL, "Show program basepage info at given <address>" }, ! 236: { false,"crossbar", DebugInfo_Crossbar, NULL, "Show Falcon crossbar HW register values" }, ! 237: { true, "default", DebugInfo_Default, NULL, "Show default debugger entry information" }, ! 238: { true, "disasm", DebugInfo_CpuDisAsm, NULL, "Disasm CPU from PC or given <address>" }, ! 239: #if ENABLE_DSP_EMU ! 240: { true, "dspdisasm", DebugInfo_DspDisAsm, NULL, "Disasm DSP from given <address>" }, ! 241: { true, "dspmemdump",DebugInfo_DspMemDump, DebugInfo_DspMemArgs, "Dump DSP memory from given <space> <address>" }, ! 242: { true, "dspregs", DebugInfo_DspRegister,NULL, "Show DSP register values" }, ! 243: #endif ! 244: { true, "memdump", DebugInfo_CpuMemDump, NULL, "Dump CPU memory from given <address>" }, ! 245: { false,"osheader", DebugInfo_OSHeader, NULL, "Show TOS OS header information" }, ! 246: { true, "regaddr", DebugInfo_RegAddr, DebugInfo_RegAddrArgs, "Show <disasm|memdump> from CPU/DSP address pointed by <register>" }, ! 247: { true, "registers", DebugInfo_CpuRegister,NULL, "Show CPU register values" }, ! 248: { false,"rtc", DebugInfo_Rtc, NULL, "Show Next's RTC registers" } ! 249: }; ! 250: ! 251: static int LockedFunction = 2; /* index for the "default" function */ ! 252: static Uint32 LockedArgument; ! 253: ! 254: /** ! 255: * Show selected debugger session information ! 256: * (when debugger is (again) entered) ! 257: */ ! 258: void DebugInfo_ShowSessionInfo(void) ! 259: { ! 260: infotable[LockedFunction].func(LockedArgument); ! 261: } ! 262: ! 263: ! 264: /** ! 265: * Readline match callback for info subcommand name completion. ! 266: * STATE = 0 -> different text from previous one. ! 267: * Return next match or NULL if no matches. ! 268: */ ! 269: static char *DebugInfo_Match(const char *text, int state, bool lock) ! 270: { ! 271: static int i, len; ! 272: const char *name; ! 273: ! 274: if (!state) { ! 275: /* first match */ ! 276: len = strlen(text); ! 277: i = 0; ! 278: } ! 279: /* next match */ ! 280: while (i++ < ARRAYSIZE(infotable)) { ! 281: if (!lock && infotable[i-1].lock) { ! 282: continue; ! 283: } ! 284: name = infotable[i-1].name; ! 285: if (strncmp(name, text, len) == 0) ! 286: return (strdup(name)); ! 287: } ! 288: return NULL; ! 289: } ! 290: char *DebugInfo_MatchLock(const char *text, int state) ! 291: { ! 292: return DebugInfo_Match(text, state, true); ! 293: } ! 294: char *DebugInfo_MatchInfo(const char *text, int state) ! 295: { ! 296: return DebugInfo_Match(text, state, false); ! 297: } ! 298: ! 299: ! 300: /** ! 301: * Show requested command information. ! 302: */ ! 303: int DebugInfo_Command(int nArgc, char *psArgs[]) ! 304: { ! 305: Uint32 value; ! 306: const char *cmd; ! 307: bool ok, lock; ! 308: int i, sub; ! 309: ! 310: sub = -1; ! 311: if (nArgc > 1) { ! 312: cmd = psArgs[1]; ! 313: /* which subcommand? */ ! 314: for (i = 0; i < ARRAYSIZE(infotable); i++) { ! 315: if (strcmp(cmd, infotable[i].name) == 0) { ! 316: sub = i; ! 317: break; ! 318: } ! 319: } ! 320: } ! 321: ! 322: if (infotable[sub].args) { ! 323: /* value needs callback specific conversion */ ! 324: value = infotable[sub].args(nArgc-2, psArgs+2); ! 325: ok = !!value; ! 326: } else { ! 327: if (nArgc > 2) { ! 328: /* value is normal number */ ! 329: ok = Eval_Number(psArgs[2], &value); ! 330: } else { ! 331: value = 0; ! 332: ok = true; ! 333: } ! 334: } ! 335: ! 336: lock = (strcmp(psArgs[0], "lock") == 0); ! 337: ! 338: if (sub < 0 || !ok) { ! 339: /* no subcommand or something wrong with value, show info */ ! 340: fprintf(stderr, "%s subcommands are:\n", psArgs[0]); ! 341: for (i = 0; i < ARRAYSIZE(infotable); i++) { ! 342: if (!lock && infotable[i].lock) { ! 343: continue; ! 344: } ! 345: fprintf(stderr, "- %s: %s\n", ! 346: infotable[i].name, infotable[i].info); ! 347: } ! 348: return DEBUGGER_CMDDONE; ! 349: } ! 350: ! 351: if (lock) { ! 352: /* lock given subcommand and value */ ! 353: LockedFunction = sub; ! 354: LockedArgument = value; ! 355: fprintf(stderr, "Locked %s output.\n", psArgs[1]); ! 356: } else { ! 357: /* do actual work */ ! 358: infotable[sub].func(value); ! 359: } ! 360: return DEBUGGER_CMDDONE; ! 361: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.