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