Annotation of hatari/src/debug/debugdsp.c, revision 1.1

1.1     ! root        1: /*
        !             2:   Hatari - debugdsp.c
        !             3: 
        !             4:   This file is distributed under the GNU Public License, version 2 or at
        !             5:   your option any later version. Read the file gpl.txt for details.
        !             6: 
        !             7:   debugdsp.c - function needed for the DSP debugging tasks like memory
        !             8:   and register dumps.
        !             9: */
        !            10: const char DebugDsp_fileid[] = "Hatari debugdsp.c : " __DATE__ " " __TIME__;
        !            11: 
        !            12: #include <stdio.h>
        !            13: 
        !            14: #include "config.h"
        !            15: 
        !            16: #include "main.h"
        !            17: #include "breakcond.h"
        !            18: #include "configuration.h"
        !            19: #include "debugui.h"
        !            20: #include "debug_priv.h"
        !            21: #include "debugdsp.h"
        !            22: #include "dsp.h"
        !            23: #include "evaluate.h"
        !            24: #include "memorySnapShot.h"
        !            25: #include "str.h"
        !            26: #include "symbols.h"
        !            27: 
        !            28: static Uint16 dsp_disasm_addr;    /* DSP disasm address */
        !            29: static Uint16 dsp_memdump_addr;   /* DSP memdump address */
        !            30: static char dsp_mem_space = 'P';  /* X, Y, P */
        !            31: 
        !            32: static int nDspActiveCBs = 0;     /* Amount of active conditional breakpoints */
        !            33: static int nDspSteps = 0;         /* Amount of steps for DSP single-stepping */
        !            34: 
        !            35: 
        !            36: /**
        !            37:  * Readline match callback to list register names usable within debugger.
        !            38:  * STATE = 0 -> different text from previous one.
        !            39:  * Return next match or NULL if no matches.
        !            40:  */
        !            41: static char *DebugDsp_MatchRegister(const char *text, int state)
        !            42: {
        !            43:        static const char regs[][4] = {
        !            44:                "a0", "a1", "a2", "b0", "b1", "b2", "la", "lc",
        !            45:                "m0", "m1", "m2", "m3", "m4", "m5", "m6", "m7",
        !            46:                "n0", "n1", "n2", "n3", "n4", "n5", "n6", "n7",
        !            47:                "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
        !            48:                "omr", "pc", "sp", "sr", "ssh", "ssl",
        !            49:                "x0", "x1", "y0", "y1",
        !            50:        };
        !            51:        static int i, len;
        !            52:        
        !            53:        if (!state)
        !            54:        {
        !            55:                /* first match */
        !            56:                i = 0;
        !            57:                len = strlen(text);
        !            58:                if (len > 2)
        !            59:                        return NULL;
        !            60:        }
        !            61:        /* next match */
        !            62:        while (i < ARRAYSIZE(regs)) {
        !            63:                if (strncasecmp(regs[i++], text, len) == 0)
        !            64:                        return (strdup(regs[i-1]));
        !            65:        }
        !            66:        return NULL;
        !            67: }
        !            68: 
        !            69: /**
        !            70:  * Command: Dump or set a DSP register
        !            71:  */
        !            72: int DebugDsp_Register(int nArgc, char *psArgs[])
        !            73: {
        !            74:        char *assign;
        !            75:        Uint32 value;
        !            76:        char *arg;
        !            77: 
        !            78:        if (!bDspEnabled)
        !            79:        {
        !            80:                fprintf(stderr, "DSP isn't present or initialized.\n");
        !            81:                return DEBUGGER_CMDDONE;
        !            82:        }
        !            83: 
        !            84:        if (nArgc == 1)
        !            85:        {
        !            86:                /* No parameter - dump all registers */
        !            87:                DSP_DisasmRegisters();
        !            88:                return DEBUGGER_CMDDONE;
        !            89:        }
        !            90:        arg = psArgs[1];
        !            91: 
        !            92:        assign = strchr(arg, '=');
        !            93:        if (!assign)
        !            94:                goto error_msg;
        !            95: 
        !            96:        *assign++ = '\0';
        !            97:        if (!Eval_Number(Str_Trim(assign), &value))
        !            98:                goto error_msg;
        !            99: 
        !           100:        if (DSP_Disasm_SetRegister(Str_Trim(arg), value))
        !           101:            return DEBUGGER_CMDDONE;
        !           102: 
        !           103: error_msg:
        !           104:        fprintf(stderr,"\tError, usage: dr or dr xx=yyyy\n"
        !           105:                "\tWhere: xx=A0-A2, B0-B2, X0, X1, Y0, Y1, R0-R7,\n"
        !           106:                "\t       N0-N7, M0-M7, LA, LC, PC, SR, SP, OMR, SSH, SSL\n");
        !           107: 
        !           108:        return DEBUGGER_CMDDONE;
        !           109: }
        !           110: 
        !           111: 
        !           112: /**
        !           113:  * Check whether given address matches any DSP symbol, if yes,
        !           114:  * show the matching symbol information.
        !           115:  */
        !           116: static void DebugDsp_ShowMatchedSymbol(Uint32 addr)
        !           117: {
        !           118:        const char *symbol = Symbols_GetByDspAddress(addr);
        !           119:        if (symbol)
        !           120:                fprintf(debugOutput, "%s:\n", symbol);
        !           121: }
        !           122: 
        !           123: 
        !           124: /**
        !           125:  * DSP dissassemble - arg = starting address/range, or PC.
        !           126:  */
        !           127: int DebugDsp_DisAsm(int nArgc, char *psArgs[])
        !           128: {
        !           129:        Uint32 lower, upper;
        !           130:        Uint16 dsp_disasm_upper = 0;
        !           131: 
        !           132:        if (!bDspEnabled)
        !           133:        {
        !           134:                fprintf(stderr, "DSP isn't present or initialized.\n");
        !           135:                return DEBUGGER_CMDDONE;
        !           136:        }
        !           137: 
        !           138:        if (nArgc > 1)
        !           139:        {
        !           140:                switch (Eval_Range(psArgs[1], &lower, &upper))
        !           141:                {
        !           142:                        case -1:
        !           143:                                /* invalid value(s) */
        !           144:                                return DEBUGGER_CMDDONE;
        !           145:                        case 0:
        !           146:                                /* single value */
        !           147:                                break;
        !           148:                        case 1:
        !           149:                                /* range */
        !           150:                                if (upper > 0xFFFF)
        !           151:                                {
        !           152:                                        fprintf(stderr,"Invalid address 0x%x!\n", upper);
        !           153:                                        return DEBUGGER_CMDDONE;
        !           154:                                }
        !           155:                                dsp_disasm_upper = upper;
        !           156:                                break;
        !           157:                }
        !           158: 
        !           159:                if (lower > 0xFFFF)
        !           160:                {
        !           161:                        fprintf(stderr,"Invalid address 0x%x!\n", lower);
        !           162:                        return DEBUGGER_CMDDONE;
        !           163:                }
        !           164:                dsp_disasm_addr = lower;
        !           165:        }
        !           166:        else
        !           167:        {
        !           168:                /* continue */
        !           169:                if(!dsp_disasm_addr)
        !           170:                {
        !           171:                        dsp_disasm_addr = DSP_GetPC();
        !           172:                }
        !           173:        }
        !           174:        if (!dsp_disasm_upper)
        !           175:        {
        !           176:                int lines = ConfigureParams.Debugger.nDisasmLines;
        !           177:                if ( dsp_disasm_addr < (0xFFFF - lines))
        !           178:                        dsp_disasm_upper = dsp_disasm_addr + lines;
        !           179:                else
        !           180:                        dsp_disasm_upper = 0xFFFF;
        !           181:        }
        !           182:        printf("DSP disasm 0x%hx-0x%hx:\n", dsp_disasm_addr, dsp_disasm_upper);
        !           183:        while (dsp_disasm_addr < dsp_disasm_upper) {
        !           184:                DebugDsp_ShowMatchedSymbol(dsp_disasm_addr);
        !           185:                dsp_disasm_addr = DSP_DisasmAddress(dsp_disasm_addr, dsp_disasm_addr);
        !           186:        }
        !           187: 
        !           188:        return DEBUGGER_CMDCONT;
        !           189: }
        !           190: 
        !           191: 
        !           192: /**
        !           193:  * Do a DSP memory dump, args = starting address or range.
        !           194:  * <x|y|p> <address>: dump from X, Y or P, starting from given address,
        !           195:  * e.g. "x 200" or "p 200-300"
        !           196:  */
        !           197: int DebugDsp_MemDump(int nArgc, char *psArgs[])
        !           198: {
        !           199:        Uint32 lower, upper;
        !           200:        Uint16 dsp_memdump_upper = 0;
        !           201:        char space;
        !           202: 
        !           203:        if (!bDspEnabled)
        !           204:        {
        !           205:                fprintf(stderr, "DSP isn't present or initialized.\n");
        !           206:                return DEBUGGER_CMDDONE;
        !           207:        }
        !           208:        if (nArgc != 1 && nArgc != 3)
        !           209:        {
        !           210:                DebugUI_PrintCmdHelp(psArgs[0]);
        !           211:                return DEBUGGER_CMDDONE;
        !           212:        }
        !           213: 
        !           214:        if (nArgc == 3)
        !           215:        {
        !           216:                space = toupper(psArgs[1][0]);
        !           217:                switch (space)
        !           218:                {
        !           219:                case 'X':
        !           220:                case 'Y':
        !           221:                case 'P':
        !           222:                        break;
        !           223:                default:
        !           224:                        fprintf(stderr,"Invalid DSP address space '%c'!\n", space);
        !           225:                        return DEBUGGER_CMDDONE;
        !           226:                }
        !           227:                switch (Eval_Range(psArgs[2], &lower, &upper))
        !           228:                {
        !           229:                case -1:
        !           230:                        /* invalid value(s) */
        !           231:                        return DEBUGGER_CMDDONE;
        !           232:                case 0:
        !           233:                        /* single value */
        !           234:                        break;
        !           235:                case 1:
        !           236:                        /* range */
        !           237:                        if (upper > 0xFFFF)
        !           238:                        {
        !           239:                                fprintf(stderr,"Invalid address 0x%x!\n", upper);
        !           240:                                return DEBUGGER_CMDDONE;
        !           241:                        }
        !           242:                        dsp_memdump_upper = upper;
        !           243:                        break;
        !           244:                }
        !           245:                if (lower > 0xFFFF)
        !           246:                {
        !           247:                        fprintf(stderr,"Invalid address 0x%x!\n", lower);
        !           248:                        return DEBUGGER_CMDDONE;
        !           249:                }
        !           250:                dsp_memdump_addr = lower;
        !           251:                dsp_mem_space = space;
        !           252:        } /* continue */
        !           253: 
        !           254:        if (!dsp_memdump_upper)
        !           255:        {
        !           256:                int lines = ConfigureParams.Debugger.nMemdumpLines;
        !           257:                if ( dsp_memdump_addr < (0xFFFF - lines))
        !           258:                        dsp_memdump_upper = dsp_memdump_addr + lines;
        !           259:                else
        !           260:                        dsp_memdump_upper = 0xFFFF;
        !           261:        }
        !           262: 
        !           263:        printf("DSP memdump from 0x%hx in '%c' address space:\n", dsp_memdump_addr, dsp_mem_space);
        !           264:        dsp_memdump_addr = DSP_DisasmMemory(dsp_memdump_addr, dsp_memdump_upper, dsp_mem_space);
        !           265: 
        !           266:        return DEBUGGER_CMDCONT;
        !           267: }
        !           268: 
        !           269: 
        !           270: /**
        !           271:  * Command: Continue DSP emulation / single-stepping
        !           272:  */
        !           273: static int DebugDsp_Continue(int nArgc, char *psArgv[])
        !           274: {
        !           275:        int steps = 0;
        !           276:        
        !           277:        if (nArgc > 1)
        !           278:        {
        !           279:                steps = atoi(psArgv[1]);
        !           280:        }
        !           281:        if (steps <= 0)
        !           282:        {
        !           283:                nDspSteps = 0;
        !           284:                fprintf(stderr,"Returning to emulation...\n");
        !           285:                return DEBUGGER_END;
        !           286:        }
        !           287:        nDspSteps = steps;
        !           288:        fprintf(stderr,"Returning to emulation for %i DSP instructions...\n", steps);
        !           289:        return DEBUGGER_END;
        !           290: }
        !           291: 
        !           292: 
        !           293: /**
        !           294:  * DSP wrapper for BreakAddr_Command/BreakPointCount, returns DEBUGGER_END
        !           295:  */
        !           296: static int DebugDsp_BreakAddr(int nArgc, char *psArgs[])
        !           297: {
        !           298:        BreakAddr_Command(psArgs[1], true);
        !           299:        return DEBUGGER_CMDDONE;
        !           300: }
        !           301: 
        !           302: /**
        !           303:  * DSP wrapper for BreakCond_Command/BreakPointCount, returns DEBUGGER_END
        !           304:  */
        !           305: static int DebugDsp_BreakCond(int nArgc, char *psArgs[])
        !           306: {
        !           307:        BreakCond_Command(psArgs[1], true);
        !           308:        return DEBUGGER_CMDDONE;
        !           309: }
        !           310: 
        !           311: 
        !           312: /**
        !           313:  * This function is called after each DSP instruction when debugging is enabled.
        !           314:  */
        !           315: void DebugDsp_Check(void)
        !           316: {
        !           317:        /* TODO: show symbols while disassembling DSP instructions */
        !           318:        if (nDspActiveCBs)
        !           319:        {
        !           320:                if (BreakCond_MatchDsp())
        !           321:                        DebugUI();
        !           322:        }
        !           323:        if (nDspSteps)
        !           324:        {
        !           325:                nDspSteps -= 1;
        !           326:                if (nDspSteps == 0)
        !           327:                        DebugUI();
        !           328:        }
        !           329: }
        !           330: 
        !           331: 
        !           332: /**
        !           333:  * Should be called before returning back emulation to tell the DSP core
        !           334:  * to call us after each instruction if "real-time" debugging like
        !           335:  * breakpoints has been set.
        !           336:  */
        !           337: void DebugDsp_SetDebugging(void)
        !           338: {
        !           339:        nDspActiveCBs = BreakCond_BreakPointCount(true);
        !           340:        if (nDspActiveCBs || nDspSteps)
        !           341:                DSP_SetDebugging(true);
        !           342:        else
        !           343:                DSP_SetDebugging(false);
        !           344: }
        !           345: 
        !           346: 
        !           347: static const dbgcommand_t dspcommands[] =
        !           348: {
        !           349:        { NULL, NULL, "DSP commands", NULL, NULL, NULL, false },
        !           350:        { DebugDsp_BreakAddr, Symbols_MatchDspCodeAddress,
        !           351:          "dspaddress", "da",
        !           352:          "set DSP PC address breakpoints",
        !           353:          BreakAddr_Description,
        !           354:          true },
        !           355:        { DebugDsp_BreakCond, BreakCond_MatchDspVariable,
        !           356:          "dspbreak", "db",
        !           357:          "set/remove/list conditional DSP breakpoints",
        !           358:          BreakCond_Description,
        !           359:          true },
        !           360:        { DebugDsp_DisAsm, Symbols_MatchDspCodeAddress,
        !           361:          "dspdisasm", "dd",
        !           362:          "disassemble DSP code",
        !           363:          "[<start address>[-<end address>]]\n"
        !           364:          "\tDisassemble from DSP-PC, otherwise at given address.",
        !           365:          false },
        !           366:        { DebugDsp_MemDump, Symbols_MatchDspDataAddress,
        !           367:          "dspmemdump", "dm",
        !           368:          "dump DSP memory",
        !           369:          "[<x|y|p> <start address>[-<end address>]]\n"
        !           370:          "\tdump DSP memory from given memory space and address, or\n"
        !           371:          "\tcontinue from previous address if not specified.",
        !           372:          false },
        !           373:        { Symbols_Command, NULL,
        !           374:          "dspsymbols", "",
        !           375:          "load DSP symbols & their addresses",
        !           376:          Symbols_Description,
        !           377:          false },
        !           378:        { DebugDsp_Register, DebugDsp_MatchRegister,
        !           379:          "dspreg", "dr",
        !           380:          "read/write DSP registers",
        !           381:          "[REG=value]"
        !           382:          "\tSet or dump contents of DSP registers.",
        !           383:          true },
        !           384:        { DebugDsp_Continue, NULL,
        !           385:          "dspcont", "dc",
        !           386:          "continue emulation / DSP single-stepping",
        !           387:          "[steps]\n"
        !           388:          "\tLeave debugger and continue emulation for <steps> DSP instructions\n"
        !           389:          "\tor forever if no steps have been specified.",
        !           390:          false }
        !           391: };
        !           392: 
        !           393: 
        !           394: /**
        !           395:  * Should be called when debugger is first entered to initialize
        !           396:  * DSP debugging variables.
        !           397:  * 
        !           398:  * if you want disassembly or memdumping to start/continue from
        !           399:  * specific address, you can set them here.  If disassembly
        !           400:  * address is zero, disassembling starts from PC.
        !           401:  * 
        !           402:  * returns number of DSP commands and pointer to array of them.
        !           403:  */
        !           404: int DebugDsp_Init(const dbgcommand_t **table)
        !           405: {
        !           406:        dsp_disasm_addr = 0;
        !           407:        dsp_memdump_addr = 0;
        !           408:        dsp_mem_space = 'P';
        !           409: 
        !           410:        *table = dspcommands;
        !           411:        return ARRAYSIZE(dspcommands);
        !           412: }
        !           413: 
        !           414: /**
        !           415:  * Should be called when debugger is re-entered to reset
        !           416:  * relevant DSP debugging variables.
        !           417:  */
        !           418: void DebugDsp_InitSession(void)
        !           419: {
        !           420:        dsp_disasm_addr = DSP_GetPC();
        !           421: }

unix.superglobalmegacorp.com

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