Annotation of hatari/src/debug/debugInfo.c, revision 1.1.1.10

1.1       root        1: /*
                      2:   Hatari - debuginfo.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:   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>
1.1.1.6   root       14: #include <ctype.h>
                     15: 
1.1       root       16: #include "main.h"
1.1.1.4   root       17: #include "bios.h"
1.1.1.5   root       18: #include "blitter.h"
1.1       root       19: #include "configuration.h"
1.1.1.6   root       20: #include "crossbar.h"
1.1       root       21: #include "debugInfo.h"
                     22: #include "debugcpu.h"
                     23: #include "debugdsp.h"
                     24: #include "debugui.h"
1.1.1.5   root       25: #include "debug_priv.h"
1.1       root       26: #include "dsp.h"
                     27: #include "evaluate.h"
1.1.1.2   root       28: #include "file.h"
                     29: #include "gemdos.h"
1.1.1.3   root       30: #include "history.h"
1.1       root       31: #include "ioMem.h"
                     32: #include "m68000.h"
1.1.1.6   root       33: #include "psg.h"
1.1       root       34: #include "stMemory.h"
                     35: #include "tos.h"
1.1.1.2   root       36: #include "screen.h"
                     37: #include "vdi.h"
1.1       root       38: #include "video.h"
1.1.1.6   root       39: #include "videl.h"
1.1.1.4   root       40: #include "xbios.h"
1.1.1.6   root       41: #include "newcpu.h"
                     42: #include "68kDisass.h"
1.1       root       43: 
                     44: /* ------------------------------------------------------------------
                     45:  * TOS information
                     46:  */
                     47: #define OS_SYSBASE 0x4F2
                     48: #define OS_HEADER_SIZE 0x30
                     49: 
1.1.1.7   root       50: #define OS_PHYSTOP 0x42E
1.1       root       51: #define COOKIE_JAR 0x5A0
                     52: 
                     53: #define BASEPAGE_SIZE 0x100
                     54: 
                     55: #define GEM_MAGIC 0x87654321
                     56: #define GEM_MUPB_SIZE 0xC
                     57: 
                     58: #define RESET_MAGIC 0x31415926
                     59: #define RESET_VALID 0x426
                     60: #define RESET_VECTOR 0x42A
                     61: 
                     62: #define COUNTRY_SPAIN 4
                     63: 
1.1.1.2   root       64: 
1.1       root       65: /**
1.1.1.5   root       66:  * DebugInfo_GetSysbase: get and validate system base
1.1.1.7   root       67:  * If warnings is set, output warnings if no valid system base
1.1.1.5   root       68:  * return on success sysbase address (+ set rombase), on failure return zero
1.1       root       69:  */
1.1.1.7   root       70: static Uint32 DebugInfo_GetSysbase(Uint32 *rombase, bool warnings)
1.1       root       71: {
                     72:        Uint32 sysbase = STMemory_ReadLong(OS_SYSBASE);
                     73: 
1.1.1.7   root       74:        if ( !STMemory_CheckAreaType (sysbase, OS_HEADER_SIZE, ABFLAG_RAM | ABFLAG_ROM ) ) {
                     75:                if (warnings) {
                     76:                        fprintf(stderr, "Invalid TOS sysbase RAM address (0x%x)!\n", sysbase);
                     77:                }
1.1       root       78:                return 0;
                     79:        }
1.1.1.5   root       80:        /* under TOS, sysbase = os_beg = TosAddress, but not under MiNT -> use os_beg */
                     81:        *rombase = STMemory_ReadLong(sysbase+0x08);
1.1.1.7   root       82:        if ( !STMemory_CheckAreaType (*rombase, OS_HEADER_SIZE, ABFLAG_RAM | ABFLAG_ROM ) ) {
                     83:                if (warnings) {
                     84:                        fprintf(stderr, "Invalid TOS sysbase ROM address (0x%x)!\n", *rombase);
                     85:                }
1.1.1.10! root       86:                *rombase = 0;
1.1.1.5   root       87:        }
                     88:        if (*rombase != TosAddress) {
1.1.1.7   root       89:                if (warnings) {
                     90:                        fprintf(stderr, "os_beg (0x%x) != TOS address (0x%x), header in RAM not set up yet?\n",
                     91:                                *rombase, TosAddress);
                     92:                }
1.1       root       93:        }
                     94:        return sysbase;
                     95: }
                     96: 
                     97: /**
1.1.1.5   root       98:  * DebugInfo_CurrentBasepage: get and validate currently running program basepage.
                     99:  * if given sysbase is zero, use system sysbase.
1.1.1.7   root      100:  * If warnings is set, output warnings if no valid basepage
                    101:  * return on success basepage address, on failure return zero
1.1       root      102:  */
1.1.1.7   root      103: static Uint32 DebugInfo_CurrentBasepage(Uint32 sysbase, bool warnings)
1.1       root      104: {
1.1.1.5   root      105:        Uint32 basepage;
1.1       root      106:        Uint16 osversion, osconf;
                    107: 
                    108:        if (!sysbase) {
1.1.1.5   root      109:                Uint32 rombase;
1.1.1.7   root      110:                sysbase = DebugInfo_GetSysbase(&rombase, warnings);
1.1.1.5   root      111:                if (!sysbase) {
                    112:                        return 0;
                    113:                }
1.1       root      114:        }
1.1.1.5   root      115:        osversion = STMemory_ReadWord(sysbase+0x02);
1.1       root      116:        if (osversion >= 0x0102) {
                    117:                basepage = STMemory_ReadLong(sysbase+0x28);
                    118:        } else {
                    119:                osconf = STMemory_ReadWord(sysbase+0x1C);
                    120:                if((osconf>>1) == COUNTRY_SPAIN) {
                    121:                        basepage = 0x873C;
                    122:                } else {
                    123:                        basepage = 0x602C;
                    124:                }
                    125:        }
1.1.1.7   root      126:        if ( STMemory_CheckAreaType ( basepage, 4, ABFLAG_RAM ) ) {
1.1       root      127:                return STMemory_ReadLong(basepage);
                    128:        }
1.1.1.7   root      129:        if (warnings) {
                    130:                fprintf(stderr, "Pointer 0x%06x to basepage address is invalid!\n", basepage);
                    131:        }
1.1       root      132:        return 0;
                    133: }
                    134: 
1.1.1.2   root      135: 
                    136: /**
1.1.1.5   root      137:  * GetBasepageValue: return basepage value at given offset in
1.1.1.2   root      138:  * TOS process basepage or zero if that is missing/invalid.
                    139:  */
1.1.1.5   root      140: static Uint32 GetBasepageValue(unsigned offset)
1.1.1.2   root      141: {
1.1.1.7   root      142:        Uint32 basepage = DebugInfo_CurrentBasepage(0, false);
1.1.1.2   root      143:        if (!basepage) {
                    144:                return 0;
                    145:        }
1.1.1.7   root      146:        if ( !STMemory_CheckAreaType ( basepage, BASEPAGE_SIZE, ABFLAG_RAM ) ||
1.1.1.2   root      147:            STMemory_ReadLong(basepage) != basepage) {
                    148:                return 0;
                    149:        }
                    150:        return STMemory_ReadLong(basepage+offset);
                    151: }
                    152: 
                    153: /**
1.1.1.9   root      154:  * DebugInfo_DTA: if no DTA address given, get one from current
                    155:  * basepage and ask GEMDOS to show its info.
                    156:  */
                    157: static void DebugInfo_DTA(FILE *fp, Uint32 dta_addr)
                    158: {
                    159:        if (!dta_addr) {
                    160:                dta_addr = GetBasepageValue(0x20);
                    161:                if (!dta_addr) {
                    162:                        fprintf(fp, "ERROR: no valid basepage!\n");
                    163:                        return;
                    164:                }
                    165:        }
                    166:        GemDOS_InfoDTA(fp, dta_addr);
                    167: }
                    168: 
                    169: /**
1.1.1.2   root      170:  * DebugInfo_GetTEXT: return current program TEXT segment address
                    171:  * or zero if basepage missing/invalid.  For virtual debugger variable.
                    172:  */
                    173: Uint32 DebugInfo_GetTEXT(void)
                    174: {
1.1.1.5   root      175:        return GetBasepageValue(0x08);
                    176: }
                    177: /**
1.1.1.9   root      178:  * DebugInfo_GetTEXTEnd: return address following current program TEXT segment
1.1.1.5   root      179:  * or zero if basepage missing/invalid.  For virtual debugger variable.
                    180:  */
                    181: Uint32 DebugInfo_GetTEXTEnd(void)
                    182: {
                    183:        Uint32 addr = GetBasepageValue(0x08);
                    184:        if (addr) {
1.1.1.9   root      185:                return addr + GetBasepageValue(0x0C);
1.1.1.5   root      186:        }
                    187:        return 0;
1.1.1.2   root      188: }
                    189: /**
                    190:  * DebugInfo_GetDATA: return current program DATA segment address
                    191:  * or zero if basepage missing/invalid.  For virtual debugger variable.
                    192:  */
                    193: Uint32 DebugInfo_GetDATA(void)
                    194: {
1.1.1.5   root      195:        return GetBasepageValue(0x010);
1.1.1.2   root      196: }
                    197: /**
                    198:  * DebugInfo_GetBSS: return current program BSS segment address
                    199:  * or zero if basepage missing/invalid.  For virtual debugger variable.
                    200:  */
                    201: Uint32 DebugInfo_GetBSS(void)
                    202: {
1.1.1.5   root      203:        return GetBasepageValue(0x18);
1.1.1.2   root      204: }
1.1.1.7   root      205: /**
                    206:  * DebugInfo_GetBASEPAGE: return current basepage address.
                    207:  */
                    208: Uint32 DebugInfo_GetBASEPAGE(void)
                    209: {
                    210:        return DebugInfo_CurrentBasepage(0, false);
                    211: }
                    212: 
1.1.1.2   root      213: 
1.1.1.7   root      214: /**
                    215:  * output nil-terminated string from any Atari memory type
                    216:  */
                    217: static Uint32 print_mem_str(Uint32 addr, Uint32 end)
                    218: {
                    219:        Uint8 chr;
                    220:        while (addr < end && (chr = STMemory_ReadByte(addr++))) {
                    221:                fputc(chr, stderr);
                    222:        }
                    223:        return addr;
                    224: }
1.1.1.2   root      225: 
1.1       root      226: /**
                    227:  * DebugInfo_Basepage: show TOS process basepage information
                    228:  * at given address.
                    229:  */
1.1.1.7   root      230: static void DebugInfo_Basepage(FILE *fp, Uint32 basepage)
1.1       root      231: {
                    232:        Uint8 cmdlen;
1.1.1.7   root      233:        Uint32 addr;
1.1       root      234: 
                    235:        if (!basepage) {
                    236:                /* default to current process basepage */
1.1.1.7   root      237:                basepage = DebugInfo_CurrentBasepage(0, true);
1.1       root      238:                if (!basepage) {
                    239:                        return;
                    240:                }
                    241:        }
1.1.1.7   root      242:        fprintf(fp, "Process basepage (0x%x) information:\n", basepage);
                    243:        if ( !STMemory_CheckAreaType ( basepage, BASEPAGE_SIZE, ABFLAG_RAM ) ||
1.1       root      244:            STMemory_ReadLong(basepage) != basepage) {
1.1.1.7   root      245:                fprintf(fp, "- address 0x%06x is invalid!\n", basepage);
1.1       root      246:                return;
                    247:        }
1.1.1.7   root      248:        fprintf(fp, "- TPA start      : 0x%06x\n", STMemory_ReadLong(basepage));
                    249:        fprintf(fp, "- TPA end +1     : 0x%06x\n", STMemory_ReadLong(basepage+0x04));
                    250:        fprintf(fp, "- Text segment   : 0x%06x\n", STMemory_ReadLong(basepage+0x08));
                    251:        fprintf(fp, "- Text size      : 0x%x\n",   STMemory_ReadLong(basepage+0x0C));
                    252:        fprintf(fp, "- Data segment   : 0x%06x\n", STMemory_ReadLong(basepage+0x10));
                    253:        fprintf(fp, "- Data size      : 0x%x\n",   STMemory_ReadLong(basepage+0x14));
                    254:        fprintf(fp, "- BSS segment    : 0x%06x\n", STMemory_ReadLong(basepage+0x18));
                    255:        fprintf(fp, "- BSS size       : 0x%x\n",   STMemory_ReadLong(basepage+0x1C));
                    256:        fprintf(fp, "- Process DTA    : 0x%06x\n", STMemory_ReadLong(basepage+0x20));
                    257:        fprintf(fp, "- Parent basepage: 0x%06x\n", STMemory_ReadLong(basepage+0x24));
                    258: 
                    259:        addr = STMemory_ReadLong(basepage+0x2C);
                    260:        fprintf(fp, "- Environment    : 0x%06x\n", addr);
                    261:        if ( STMemory_CheckAreaType ( addr, 4096, ABFLAG_RAM ) ) {
                    262:                Uint32 end = addr + 4096;
                    263:                while (addr < end && STMemory_ReadByte(addr)) {
                    264:                        fprintf(fp, "  '");
                    265:                        addr = print_mem_str(addr, end);
                    266:                        addr = print_mem_str(addr, end);
                    267:                        fprintf(fp, "'\n");
                    268:                }
                    269:        }
                    270:        addr = basepage+0x80;
                    271:        cmdlen = STMemory_ReadByte(addr++);
                    272:        fprintf(fp, "- Command argslen: %d (at 0x%06x)\n", cmdlen, addr);
1.1       root      273:        if (cmdlen) {
1.1.1.7   root      274:                Uint32 end = addr + cmdlen;
                    275:                fprintf(fp, "  '");
                    276:                for (;;) {
                    277:                        addr = print_mem_str(addr, end);
                    278:                        if (addr >= end) {
                    279:                                break;
                    280:                        }
                    281:                        fputc(' ', fp);
1.1       root      282:                }
1.1.1.7   root      283:                fprintf(fp, "'\n");
1.1       root      284:        }
                    285: }
                    286: 
1.1.1.7   root      287: 
1.1       root      288: /**
1.1.1.5   root      289:  * DebugInfo_PrintOSHeader: output OS Header information
1.1       root      290:  */
1.1.1.7   root      291: static void DebugInfo_PrintOSHeader(FILE *fp, Uint32 sysbase)
1.1       root      292: {
1.1.1.5   root      293:        Uint32 gemblock, basepage;
1.1.1.7   root      294:        Uint16 osversion, datespec, osconf, langbits;
1.1.1.2   root      295:        const char *lang;
                    296:        static const char langs[][3] = {
                    297:                "us", "de", "fr", "uk", "es", "it", "se", "ch" /* fr */, "ch" /* de */,
                    298:                "tr", "fi", "no", "dk", "sa", "nl", "cs", "hu"
                    299:        };
1.1       root      300: 
1.1.1.7   root      301:        /* first more technical info */
                    302: 
1.1.1.5   root      303:        osversion = STMemory_ReadWord(sysbase+0x02);
1.1.1.7   root      304:        fprintf(fp, "OS base addr : 0x%06x\n", sysbase);
                    305:        fprintf(fp, "OS RAM end+1 : 0x%06x\n", STMemory_ReadLong(sysbase+0x0C));
                    306: 
                    307:        fprintf(fp, "Reset handler: 0x%06x\n", STMemory_ReadLong(sysbase+0x04));
                    308:        fprintf(fp, "Reset vector : 0x%06x\n", STMemory_ReadLong(RESET_VECTOR));
                    309:        fprintf(fp, "Reset valid  : 0x%x (valid=0x%x)\n", STMemory_ReadLong(RESET_VALID), RESET_MAGIC);
1.1       root      310: 
                    311:        gemblock = STMemory_ReadLong(sysbase+0x14);
1.1.1.7   root      312:        fprintf(fp, "GEM Memory Usage Parameter Block:\n");
                    313:        if ( STMemory_CheckAreaType ( gemblock, GEM_MUPB_SIZE, ABFLAG_RAM | ABFLAG_ROM ) ) {
                    314:                fprintf(fp, "- Block addr : 0x%06x\n", gemblock);
                    315:                fprintf(fp, "- GEM magic  : 0x%x (valid=0x%x)\n", STMemory_ReadLong(gemblock), GEM_MAGIC);
                    316:                fprintf(fp, "- GEM entry  : 0x%06x\n", STMemory_ReadLong(gemblock+4));
                    317:                fprintf(fp, "- GEM end    : 0x%06x\n", STMemory_ReadLong(gemblock+8));
                    318:        } else {
                    319:                fprintf(fp, "- is at INVALID 0x%06x address.\n", gemblock);
                    320:        }
                    321: 
                    322:        if (osversion >= 0x0102) {
                    323:                /* last 3 OS header fields are only available as of TOS 1.02 */
                    324:                fprintf(fp, "Memory pool  : 0x%06x\n", STMemory_ReadLong(sysbase+0x20));
                    325:                fprintf(fp, "Kbshift addr : 0x%06x\n", STMemory_ReadLong(sysbase+0x24));
1.1       root      326:        } else {
1.1.1.7   root      327:                /* TOS 1.0 */
                    328:                fprintf(fp, "Memory pool  : 0x0056FA\n");
                    329:                fprintf(fp, "Kbshift addr : 0x000E1B\n");
                    330:        }
                    331:        basepage = DebugInfo_CurrentBasepage(sysbase, true);
                    332:        if (basepage) {
                    333:                fprintf(fp, "Basepage     : 0x%06x\n", basepage);
1.1       root      334:        }
                    335: 
1.1.1.7   root      336:        /* and then basic TOS information */
                    337: 
                    338:        fputs("\n", fp);
                    339:        fprintf(fp, "TOS version  : 0x%x%s\n", osversion, bIsEmuTOS ? " (EmuTOS)" : "");
                    340:        /* Bits: 0-4 = day (1-31), 5-8 = month (1-12), 9-15 = years (since 1980) */
                    341:        datespec = STMemory_ReadWord(sysbase+0x1E);
                    342:        fprintf(fp, "Build date   : %04d-%02d-%02d\n", (datespec >> 9) + 1980,
                    343:               (datespec & 0x1E0) >> 5, datespec & 0x1f);
1.1       root      344: 
                    345:        osconf = STMemory_ReadWord(sysbase+0x1C);
1.1.1.2   root      346:        langbits = osconf >> 1;
                    347:        if (langbits == 127) {
                    348:                lang = "all";
1.1.1.8   root      349:        } else if (langbits < ARRAY_SIZE(langs)) {
1.1.1.2   root      350:                lang = langs[langbits];
                    351:        } else {
                    352:                lang = "unknown";
                    353:        }
1.1.1.7   root      354:        fprintf(fp, "OS config    : %s, %s (0x%x)\n", lang, osconf&1 ? "PAL":"NTSC", osconf);
                    355:        fprintf(fp, "Phystop      : %d KB\n", (STMemory_ReadLong(OS_PHYSTOP) + 511) / 1024);
1.1       root      356: }
                    357: 
1.1.1.5   root      358: /**
                    359:  * DebugInfo_OSHeader: display TOS OS Header and RAM one
                    360:  * if their addresses differ
                    361:  */
1.1.1.7   root      362: static void DebugInfo_OSHeader(FILE *fp, Uint32 dummy)
1.1.1.5   root      363: {
                    364:        Uint32 sysbase, rombase;
                    365: 
1.1.1.10! root      366:        sysbase = DebugInfo_GetSysbase(&rombase, true);
1.1.1.5   root      367:        if (!sysbase) {
                    368:                return;
                    369:        }
1.1.1.7   root      370:        fprintf(fp, "OS header information:\n");
                    371:        DebugInfo_PrintOSHeader(fp, sysbase);
1.1.1.10! root      372:        if (sysbase != rombase && rombase) {
1.1.1.7   root      373:                fprintf(fp, "\nROM TOS OS header information:\n");
                    374:                DebugInfo_PrintOSHeader(fp, rombase);
1.1.1.5   root      375:                return;
                    376:        }
                    377: }
1.1       root      378: 
1.1.1.2   root      379: /**
                    380:  * DebugInfo_Cookiejar: display TOS Cookiejar content
                    381:  */
1.1.1.7   root      382: static void DebugInfo_Cookiejar(FILE *fp, Uint32 dummy)
1.1.1.2   root      383: {
                    384:        int items;
                    385: 
                    386:        Uint32 jar = STMemory_ReadLong(COOKIE_JAR);
                    387:        if (!jar) {
1.1.1.7   root      388:                fprintf(fp, "Cookiejar is empty.\n");
1.1.1.2   root      389:                return;
                    390:        }
                    391: 
1.1.1.7   root      392:        fprintf(fp, "Cookiejar contents:\n");
1.1.1.2   root      393:        items = 0;
1.1.1.7   root      394:        while ( STMemory_CheckAreaType (jar, 8, ABFLAG_RAM ) && STMemory_ReadLong(jar)) {
                    395:                fprintf(fp, "%c%c%c%c = 0x%08x\n",
                    396:                        STMemory_ReadByte(jar+0), STMemory_ReadByte(jar+1),
                    397:                        STMemory_ReadByte(jar+2), STMemory_ReadByte(jar+3),
1.1.1.2   root      398:                        STMemory_ReadLong(jar+4));
                    399:                jar += 8;
                    400:                items++;
                    401:        }
1.1.1.7   root      402:        fprintf(fp, "%d items at 0x%06x.\n", items, STMemory_ReadLong(COOKIE_JAR));
1.1.1.2   root      403: }
                    404: 
                    405: 
1.1       root      406: /* ------------------------------------------------------------------
                    407:  * CPU and DSP information wrappers
                    408:  */
                    409: 
                    410: /**
                    411:  * Helper to call debugcpu.c and debugdsp.c debugger commands
                    412:  */
                    413: static void DebugInfo_CallCommand(int (*func)(int, char* []), const char *command, Uint32 arg)
                    414: {
                    415:        char cmdbuffer[16], argbuffer[12];
                    416:        char *argv[] = { cmdbuffer, NULL };
                    417:        int argc = 1;
                    418: 
                    419:        assert(strlen(command) < sizeof(cmdbuffer));
                    420:        strcpy(cmdbuffer, command);
                    421:        if (arg) {
                    422:                sprintf(argbuffer, "$%x", arg);
                    423:                argv[argc++] = argbuffer;
                    424:        }
                    425:        func(argc, argv);
                    426: }
                    427: 
1.1.1.7   root      428: static void DebugInfo_CpuRegister(FILE *fp, Uint32 arg)
1.1       root      429: {
                    430:        DebugInfo_CallCommand(DebugCpu_Register, "register", arg);
                    431: }
1.1.1.7   root      432: static void DebugInfo_CpuDisAsm(FILE *fp, Uint32 arg)
1.1       root      433: {
                    434:        DebugInfo_CallCommand(DebugCpu_DisAsm, "disasm", arg);
                    435: }
1.1.1.7   root      436: static void DebugInfo_CpuMemDump(FILE *fp, Uint32 arg)
1.1       root      437: {
                    438:        DebugInfo_CallCommand(DebugCpu_MemDump, "memdump", arg);
                    439: }
                    440: 
                    441: #if ENABLE_DSP_EMU
                    442: 
1.1.1.7   root      443: static void DebugInfo_DspRegister(FILE *fp, Uint32 arg)
1.1       root      444: {
                    445:        DebugInfo_CallCommand(DebugDsp_Register, "dspreg", arg);
                    446: }
1.1.1.7   root      447: static void DebugInfo_DspDisAsm(FILE *fp, Uint32 arg)
1.1       root      448: {
                    449:        DebugInfo_CallCommand(DebugDsp_DisAsm, "dspdisasm", arg);
                    450: }
                    451: 
1.1.1.7   root      452: static void DebugInfo_DspMemDump(FILE *fp, Uint32 arg)
1.1       root      453: {
                    454:        char cmdbuf[] = "dspmemdump";
                    455:        char addrbuf[6], spacebuf[2] = "X";
                    456:        char *argv[] = { cmdbuf, spacebuf, addrbuf };
                    457:        spacebuf[0] = (arg>>16)&0xff;
                    458:        sprintf(addrbuf, "$%x", (Uint16)(arg&0xffff));
                    459:        DebugDsp_MemDump(3, argv);
                    460: }
                    461: 
                    462: /**
                    463:  * Convert arguments to Uint32 arg suitable for DSP memdump callback
                    464:  */
                    465: static Uint32 DebugInfo_DspMemArgs(int argc, char *argv[])
                    466: {
                    467:        Uint32 value;
                    468:        char space;
                    469:        if (argc != 2) {
                    470:                return 0;
                    471:        }
1.1.1.6   root      472:        space = toupper((unsigned char)argv[0][0]);
1.1       root      473:        if ((space != 'X' && space != 'Y' && space != 'P') || argv[0][1]) {
                    474:                fprintf(stderr, "ERROR: invalid DSP address space '%s'!\n", argv[0]);
                    475:                return 0;
                    476:        }
                    477:        if (!Eval_Number(argv[1], &value) || value > 0xffff) {
                    478:                fprintf(stderr, "ERROR: invalid DSP address '%s'!\n", argv[1]);
                    479:                return 0;
                    480:        }
                    481:        return ((Uint32)space<<16) | value;
                    482: }
                    483: 
                    484: #endif  /* ENABLE_DSP_EMU */
                    485: 
                    486: 
1.1.1.7   root      487: static void DebugInfo_RegAddr(FILE *fp, Uint32 arg)
1.1       root      488: {
                    489:        bool forDsp;
                    490:        char regname[3];
1.1.1.5   root      491:        Uint32 *reg32, regvalue, mask;
1.1       root      492:        char cmdbuf[12], addrbuf[6];
                    493:        char *argv[] = { cmdbuf, addrbuf };
                    494:        
                    495:        regname[0] = (arg>>24)&0xff;
                    496:        regname[1] = (arg>>16)&0xff;
                    497:        regname[2] = '\0';
                    498: 
1.1.1.5   root      499:        if (DebugCpu_GetRegisterAddress(regname, &reg32)) {
                    500:                regvalue = *reg32;
1.1       root      501:                mask = 0xffffffff;
                    502:                forDsp = false;
                    503:        } else {
1.1.1.5   root      504:                int regsize = DSP_GetRegisterAddress(regname, &reg32, &mask);
                    505:                switch (regsize) {
                    506:                        /* currently regaddr supports only 32-bit Rx regs, but maybe later... */
                    507:                case 16:
                    508:                        regvalue = *((Uint16*)reg32);
                    509:                        break;
                    510:                case 32:
                    511:                        regvalue = *reg32;
                    512:                        break;
                    513:                default:
1.1       root      514:                        fprintf(stderr, "ERROR: invalid address/data register '%s'!\n", regname);
                    515:                        return;
                    516:                }
                    517:                forDsp = true;
                    518:        }
1.1.1.5   root      519:                sprintf(addrbuf, "$%x", regvalue & mask);
1.1       root      520: 
                    521:        if ((arg & 0xff) == 'D') {
                    522:                if (forDsp) {
                    523: #if ENABLE_DSP_EMU
1.1.1.5   root      524:                        strcpy(cmdbuf, "dd");
1.1       root      525:                        DebugDsp_DisAsm(2, argv);
                    526: #endif
                    527:                } else {
1.1.1.5   root      528:                        strcpy(cmdbuf, "d");
1.1       root      529:                        DebugCpu_DisAsm(2, argv);
                    530:                }
                    531:        } else {
                    532:                if (forDsp) {
                    533: #if ENABLE_DSP_EMU
1.1.1.5   root      534:                        /* use "Y" address space */
                    535:                        char cmd[] = "dm"; char space[] = "y";
                    536:                        char *dargv[] = { cmd, space, addrbuf };
                    537:                        DebugDsp_MemDump(3, dargv);
1.1       root      538: #endif
                    539:                } else {
1.1.1.5   root      540:                        strcpy(cmdbuf, "m");
1.1       root      541:                        DebugCpu_MemDump(2, argv);
                    542:                }
                    543:        }
                    544: }
                    545: 
                    546: /**
                    547:  * Convert arguments to Uint32 arg suitable for RegAddr callback
                    548:  */
                    549: static Uint32 DebugInfo_RegAddrArgs(int argc, char *argv[])
                    550: {
                    551:        Uint32 value, *regaddr;
                    552:        if (argc != 2) {
                    553:                return 0;
                    554:        }
                    555: 
                    556:        if (strcmp(argv[0], "disasm") == 0) {
                    557:                value = 'D';
                    558:        } else if (strcmp(argv[0], "memdump") == 0) {
                    559:                value = 'M';
                    560:        } else {
                    561:                fprintf(stderr, "ERROR: regaddr operation can be only 'disasm' or 'memdump', not '%s'!\n", argv[0]);
                    562:                return 0;
                    563:        }
                    564: 
                    565:        if (strlen(argv[1]) != 2 ||
                    566:            (!DebugCpu_GetRegisterAddress(argv[1], &regaddr) &&
1.1.1.6   root      567:             (toupper((unsigned char)argv[1][0]) != 'R'
                    568:              || !isdigit((unsigned char)argv[1][1]) || argv[1][2]))) {
1.1       root      569:                /* not CPU register or Rx DSP register */
                    570:                fprintf(stderr, "ERROR: invalid address/data register '%s'!\n", argv[1]);
                    571:                return 0;
                    572:        }
                    573:        
                    574:        value |= argv[1][0] << 24;
                    575:        value |= argv[1][1] << 16;
                    576:        value &= 0xffff00ff;
                    577:        return value;
                    578: }
                    579: 
                    580: 
                    581: /* ------------------------------------------------------------------
1.1.1.2   root      582:  * wrappers for command to parse debugger input file
                    583:  */
                    584: 
                    585: /* file name to be given before calling the Parse function,
                    586:  * needs to be set separately as it's a host pointer which
                    587:  * can be 64-bit i.e. may not fit into Uint32.
                    588:  */
                    589: static char *parse_filename;
                    590: 
                    591: /**
                    592:  * Parse and exec commands in the previously given debugger input file
                    593:  */
1.1.1.7   root      594: static void DebugInfo_FileParse(FILE *fp, Uint32 dummy)
1.1.1.2   root      595: {
                    596:        if (parse_filename) {
1.1.1.5   root      597:                DebugUI_ParseFile(parse_filename, true);
1.1.1.2   root      598:        } else {
                    599:                fputs("ERROR: debugger input file name to parse isn't set!\n", stderr);
                    600:        }
                    601: }
                    602: 
                    603: /**
                    604:  * Set which input file to parse.
                    605:  * Return true if file exists, false on error
                    606:  */
                    607: static Uint32 DebugInfo_FileArgs(int argc, char *argv[])
                    608: {
                    609:        if (argc != 1) {
                    610:                return false;
                    611:        }
                    612:        if (!File_Exists(argv[0])) {
                    613:                fprintf(stderr, "ERROR: given file '%s' doesn't exist!\n", argv[0]);
                    614:                return false;
                    615:        }
                    616:        if (parse_filename) {
                    617:                free(parse_filename);
                    618:        }
                    619:        parse_filename = strdup(argv[0]);
                    620:        return true;
                    621: }
                    622: 
                    623: 
                    624: /* ------------------------------------------------------------------
1.1       root      625:  * Debugger & readline TAB completion integration
                    626:  */
                    627: 
                    628: /**
                    629:  * Default information on entering the debugger
                    630:  */
1.1.1.7   root      631: static void DebugInfo_Default(FILE *fp, Uint32 dummy)
1.1       root      632: {
                    633:        int hbl, fcycles, lcycles;
1.1.1.6   root      634:         uaecptr nextpc, pc = M68000_GetPC();
1.1       root      635:        Video_GetPosition(&fcycles, &hbl, &lcycles);
1.1.1.6   root      636: 
1.1.1.7   root      637:        fprintf(fp, "\nCPU=$%x, VBL=%d, FrameCycles=%d, HBL=%d, LineCycles=%d, DSP=",
1.1.1.6   root      638:                pc, nVBLs, fcycles, hbl, lcycles);
1.1       root      639:        if (bDspEnabled)
1.1.1.7   root      640:                fprintf(fp, "$%x\n", DSP_GetPC());
1.1       root      641:        else
1.1.1.7   root      642:                fprintf(fp, "N/A\n");
1.1.1.6   root      643: 
1.1.1.7   root      644:        Disasm(fp, pc, &nextpc, 1);
1.1       root      645: }
                    646: 
                    647: static const struct {
1.1.1.2   root      648:        /* if overlaps with other functionality, list only for lock command */
1.1       root      649:        bool lock;
                    650:        const char *name;
1.1.1.7   root      651:        void (*func)(FILE *fp, Uint32 arg);
1.1       root      652:        /* convert args in argv into single Uint32 for func */
                    653:        Uint32 (*args)(int argc, char *argv[]);
                    654:        const char *info;
                    655: } infotable[] = {
1.1.1.2   root      656:        { false,"aes",       AES_Info,             NULL, "Show AES vector contents (with <value>, show opcodes)" },
1.1.1.6   root      657:        { false,"basepage",  DebugInfo_Basepage,   NULL, "Show program basepage contents at given <address>" },
1.1.1.4   root      658:        { false,"bios",      Bios_Info,            NULL, "Show BIOS opcodes" },
1.1.1.6   root      659:        { false,"blitter",   Blitter_Info,         NULL, "Show Blitter register contents" },
1.1.1.2   root      660:        { false,"cookiejar", DebugInfo_Cookiejar,  NULL, "Show TOS Cookiejar contents" },
1.1.1.6   root      661:        { false,"crossbar",  Crossbar_Info,        NULL, "Show Falcon Crossbar register contents" },
1.1       root      662:        { true, "default",   DebugInfo_Default,    NULL, "Show default debugger entry information" },
                    663:        { true, "disasm",    DebugInfo_CpuDisAsm,  NULL, "Disasm CPU from PC or given <address>" },
                    664: #if ENABLE_DSP_EMU
1.1.1.5   root      665:        { false, "dsp",      DSP_Info,             NULL, "Show misc. DSP core info (stack etc)" },
1.1       root      666:        { true, "dspdisasm", DebugInfo_DspDisAsm,  NULL, "Disasm DSP from given <address>" },
                    667:        { true, "dspmemdump",DebugInfo_DspMemDump, DebugInfo_DspMemArgs, "Dump DSP memory from given <space> <address>" },
1.1.1.6   root      668:        { true, "dspregs",   DebugInfo_DspRegister,NULL, "Show DSP register contents" },
1.1       root      669: #endif
1.1.1.9   root      670:        { false, "dta",      DebugInfo_DTA,       NULL, "Show current [or given] DTA information" },
1.1.1.2   root      671:        { true, "file",      DebugInfo_FileParse, DebugInfo_FileArgs, "Parse commands from given debugger input <file>" },
1.1.1.6   root      672:        { false,"gemdos",    GemDOS_Info,          NULL, "Show GEMDOS HDD emu information (with <value>, show opcodes)" },
1.1.1.3   root      673:        { true, "history",   History_Show,         NULL, "Show history of last <count> instructions" },
1.1       root      674:        { true, "memdump",   DebugInfo_CpuMemDump, NULL, "Dump CPU memory from given <address>" },
1.1.1.6   root      675:        { false,"osheader",  DebugInfo_OSHeader,   NULL, "Show TOS OS header contents" },
1.1       root      676:        { true, "regaddr",   DebugInfo_RegAddr, DebugInfo_RegAddrArgs, "Show <disasm|memdump> from CPU/DSP address pointed by <register>" },
1.1.1.6   root      677:        { true, "registers", DebugInfo_CpuRegister,NULL, "Show CPU register contents" },
1.1.1.2   root      678:        { false,"vdi",       VDI_Info,             NULL, "Show VDI vector contents (with <value>, show opcodes)" },
1.1.1.6   root      679:        { false,"videl",     Videl_Info,           NULL, "Show Falcon Videl register contents" },
                    680:        { false,"video",     Video_Info,           NULL, "Show Video information" },
                    681:        { false,"xbios",     XBios_Info,           NULL, "Show XBIOS opcodes" },
                    682:        { false,"ym",        PSG_Info,             NULL, "Show YM-2149 register contents" },
1.1       root      683: };
                    684: 
1.1.1.5   root      685: static int LockedFunction = 6; /* index for the "default" function */
1.1       root      686: static Uint32 LockedArgument;
                    687: 
                    688: /**
                    689:  * Show selected debugger session information
                    690:  * (when debugger is (again) entered)
                    691:  */
                    692: void DebugInfo_ShowSessionInfo(void)
                    693: {
1.1.1.7   root      694:        infotable[LockedFunction].func(stderr, LockedArgument);
1.1       root      695: }
                    696: 
                    697: 
                    698: /**
                    699:  * Readline match callback for info subcommand name completion.
                    700:  * STATE = 0 -> different text from previous one.
                    701:  * Return next match or NULL if no matches.
                    702:  */
                    703: static char *DebugInfo_Match(const char *text, int state, bool lock)
                    704: {
                    705:        static int i, len;
                    706:        const char *name;
                    707:        
                    708:        if (!state) {
                    709:                /* first match */
                    710:                len = strlen(text);
                    711:                i = 0;
                    712:        }
                    713:        /* next match */
1.1.1.8   root      714:        while (i++ < ARRAY_SIZE(infotable)) {
1.1       root      715:                if (!lock && infotable[i-1].lock) {
                    716:                        continue;
                    717:                }
                    718:                name = infotable[i-1].name;
                    719:                if (strncmp(name, text, len) == 0)
                    720:                        return (strdup(name));
                    721:        }
                    722:        return NULL;
                    723: }
                    724: char *DebugInfo_MatchLock(const char *text, int state)
                    725: {
                    726:        return DebugInfo_Match(text, state, true);
                    727: }
                    728: char *DebugInfo_MatchInfo(const char *text, int state)
                    729: {
                    730:        return DebugInfo_Match(text, state, false);
                    731: }
                    732: 
                    733: 
                    734: /**
                    735:  * Show requested command information.
                    736:  */
                    737: int DebugInfo_Command(int nArgc, char *psArgs[])
                    738: {
                    739:        Uint32 value;
                    740:        const char *cmd;
                    741:        bool ok, lock;
                    742:        int i, sub;
                    743: 
                    744:        sub = -1;
                    745:        if (nArgc > 1) {
                    746:                cmd = psArgs[1];                
                    747:                /* which subcommand? */
1.1.1.8   root      748:                for (i = 0; i < ARRAY_SIZE(infotable); i++) {
1.1       root      749:                        if (strcmp(cmd, infotable[i].name) == 0) {
                    750:                                sub = i;
                    751:                                break;
                    752:                        }
                    753:                }
                    754:        }
                    755: 
1.1.1.5   root      756:        if (sub >= 0 && infotable[sub].args) {
1.1       root      757:                /* value needs callback specific conversion */
                    758:                value = infotable[sub].args(nArgc-2, psArgs+2);
                    759:                ok = !!value;
                    760:        } else {
                    761:                if (nArgc > 2) {
                    762:                        /* value is normal number */
                    763:                        ok = Eval_Number(psArgs[2], &value);
                    764:                } else {
                    765:                        value = 0;
                    766:                        ok = true;
                    767:                }
                    768:        }
                    769: 
                    770:        lock = (strcmp(psArgs[0], "lock") == 0);
                    771:        
                    772:        if (sub < 0 || !ok) {
                    773:                /* no subcommand or something wrong with value, show info */
                    774:                fprintf(stderr, "%s subcommands are:\n", psArgs[0]);
1.1.1.8   root      775:                for (i = 0; i < ARRAY_SIZE(infotable); i++) {
1.1       root      776:                        if (!lock && infotable[i].lock) {
                    777:                                continue;
                    778:                        }
                    779:                        fprintf(stderr, "- %s: %s\n",
                    780:                                infotable[i].name, infotable[i].info);
                    781:                }
                    782:                return DEBUGGER_CMDDONE;
                    783:        }
                    784: 
                    785:        if (lock) {
                    786:                /* lock given subcommand and value */
                    787:                LockedFunction = sub;
                    788:                LockedArgument = value;
                    789:                fprintf(stderr, "Locked %s output.\n", psArgs[1]);
                    790:        } else {
                    791:                /* do actual work */
1.1.1.7   root      792:                infotable[sub].func(stderr, value);
1.1       root      793:        }
                    794:        return DEBUGGER_CMDDONE;
                    795: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.