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

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

unix.superglobalmegacorp.com

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