Annotation of hatari/src/debug/debugdsp.c, revision 1.1.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.