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

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

unix.superglobalmegacorp.com

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