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

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

unix.superglobalmegacorp.com

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