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

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

unix.superglobalmegacorp.com

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