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

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

unix.superglobalmegacorp.com

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