Annotation of hatari/src/debug/debugcpu.c, revision 1.1.1.5

1.1       root        1: /*
                      2:   Hatari - debugcpu.c
                      3: 
1.1.1.5 ! root        4:   This file is distributed under the GNU General Public License, version 2
        !             5:   or at your option any later version. Read the file gpl.txt for details.
1.1       root        6: 
                      7:   debugcpu.c - function needed for the CPU debugging tasks like memory
                      8:   and register dumps.
                      9: */
                     10: const char DebugCpu_fileid[] = "Hatari debugcpu.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 "debugcpu.h"
                     22: #include "evaluate.h"
                     23: #include "hatari-glue.h"
1.1.1.3   root       24: #include "history.h"
1.1       root       25: #include "log.h"
                     26: #include "m68000.h"
                     27: #include "memorySnapShot.h"
1.1.1.2   root       28: #include "profile.h"
1.1       root       29: #include "stMemory.h"
                     30: #include "str.h"
                     31: #include "symbols.h"
1.1.1.2   root       32: #include "68kDisass.h"
1.1.1.5 ! root       33: #include "console.h"
        !            34: #include "options.h"
        !            35: 
1.1       root       36: 
                     37: #define MEMDUMP_COLS   16      /* memdump, number of bytes per row */
                     38: #define NON_PRINT_CHAR '.'     /* character to display for non-printables */
                     39: 
                     40: static Uint32 disasm_addr;     /* disasm address */
                     41: static Uint32 memdump_addr;    /* memdump address */
                     42: 
1.1.1.2   root       43: static bool bCpuProfiling;     /* Whether CPU profiling is activated */
1.1       root       44: static int nCpuActiveCBs = 0;  /* Amount of active conditional breakpoints */
                     45: static int nCpuSteps = 0;      /* Amount of steps for CPU single-stepping */
                     46: 
                     47: 
                     48: /**
                     49:  * Load a binary file to a memory address.
                     50:  */
                     51: static int DebugCpu_LoadBin(int nArgc, char *psArgs[])
                     52: {
                     53:        FILE *fp;
                     54:        unsigned char c;
                     55:        Uint32 address;
                     56:        int i=0;
                     57: 
                     58:        if (nArgc < 3)
                     59:        {
                     60:                DebugUI_PrintCmdHelp(psArgs[0]);
                     61:                return DEBUGGER_CMDDONE;
                     62:        }
                     63: 
                     64:        if (!Eval_Number(psArgs[2], &address))
                     65:        {
                     66:                fprintf(stderr, "Invalid address!\n");
                     67:                return DEBUGGER_CMDDONE;
                     68:        }
                     69:        address &= 0x00FFFFFF;
                     70: 
                     71:        if ((fp = fopen(psArgs[1], "rb")) == NULL)
                     72:        {
                     73:                fprintf(stderr, "Cannot open file '%s'!\n", psArgs[1]);
                     74:                return DEBUGGER_CMDDONE;
                     75:        }
                     76: 
                     77:        c = fgetc(fp);
                     78:        while (!feof(fp))
                     79:        {
                     80:                i++;
                     81:                STMemory_WriteByte(address++, c);
                     82:                c = fgetc(fp);
                     83:        }
                     84:        fprintf(stderr,"  Read 0x%x bytes.\n", i);
                     85:        fclose(fp);
                     86: 
                     87:        return DEBUGGER_CMDDONE;
                     88: }
                     89: 
                     90: 
                     91: /**
                     92:  * Dump memory from an address to a binary file.
                     93:  */
                     94: static int DebugCpu_SaveBin(int nArgc, char *psArgs[])
                     95: {
                     96:        FILE *fp;
                     97:        unsigned char c;
                     98:        Uint32 address;
                     99:        Uint32 bytes, i = 0;
                    100: 
                    101:        if (nArgc < 4)
                    102:        {
                    103:                DebugUI_PrintCmdHelp(psArgs[0]);
                    104:                return DEBUGGER_CMDDONE;
                    105:        }
                    106: 
                    107:        if (!Eval_Number(psArgs[2], &address))
                    108:        {
                    109:                fprintf(stderr, "  Invalid address!\n");
                    110:                return DEBUGGER_CMDDONE;
                    111:        }
                    112:        address &= 0x00FFFFFF;
                    113: 
                    114:        if (!Eval_Number(psArgs[3], &bytes))
                    115:        {
                    116:                fprintf(stderr, "  Invalid length!\n");
                    117:                return DEBUGGER_CMDDONE;
                    118:        }
                    119: 
                    120:        if ((fp = fopen(psArgs[1], "wb")) == NULL)
                    121:        {
                    122:                fprintf(stderr,"  Cannot open file '%s'!\n", psArgs[1]);
                    123:                return DEBUGGER_CMDDONE;
                    124:        }
                    125: 
                    126:        while (i < bytes)
                    127:        {
                    128:                c = STMemory_ReadByte(address++);
                    129:                fputc(c, fp);
                    130:                i++;
                    131:        }
                    132:        fclose(fp);
                    133:        fprintf(stderr, "  Wrote 0x%x bytes.\n", bytes);
                    134: 
                    135:        return DEBUGGER_CMDDONE;
                    136: }
                    137: 
                    138: 
                    139: /**
1.1.1.2   root      140:  * Check whether given address matches any CPU symbol and whether
                    141:  * there's profiling information available for it.  If yes, show it.
1.1       root      142:  */
1.1.1.2   root      143: static void DebugCpu_ShowAddressInfo(Uint32 addr)
1.1       root      144: {
1.1.1.4   root      145:        const char *symbol = Symbols_GetByCpuAddress(addr);
1.1       root      146:        if (symbol)
1.1.1.4   root      147:                fprintf(debugOutput, "%s:\n", symbol);
1.1       root      148: }
                    149: 
                    150: /**
                    151:  * Dissassemble - arg = starting address, or PC.
                    152:  */
                    153: int DebugCpu_DisAsm(int nArgc, char *psArgs[])
                    154: {
                    155:        Uint32 disasm_upper = 0;
                    156:        int insts, max_insts;
                    157:        uaecptr nextpc;
                    158: 
                    159:        if (nArgc > 1)
                    160:        {
1.1.1.2   root      161:                switch (Eval_Range(psArgs[1], &disasm_addr, &disasm_upper, false))
1.1       root      162:                {
                    163:                case -1:
                    164:                        /* invalid value(s) */
                    165:                        return DEBUGGER_CMDDONE;
                    166:                case 0:
                    167:                        /* single value */
                    168:                        break;
                    169:                case 1:
                    170:                        /* range */
                    171:                        disasm_upper &= 0x00FFFFFF;
                    172:                        break;
                    173:                }
                    174:        }
                    175:        else
                    176:        {
                    177:                /* continue */
                    178:                if(!disasm_addr)
                    179:                        disasm_addr = M68000_GetPC();
                    180:        }
                    181:        disasm_addr &= 0x00FFFFFF;
                    182: 
                    183:        /* limit is topmost address or instruction count */
                    184:        if (disasm_upper)
                    185:        {
                    186:                max_insts = INT_MAX;
                    187:        }
                    188:        else
                    189:        {
                    190:                disasm_upper = 0x00FFFFFF;
                    191:                max_insts = ConfigureParams.Debugger.nDisasmLines;
                    192:        }
                    193: 
                    194:        /* output a range */
                    195:        for (insts = 0; insts < max_insts && disasm_addr < disasm_upper; insts++)
                    196:        {
1.1.1.2   root      197:                DebugCpu_ShowAddressInfo(disasm_addr);
1.1.1.5 ! root      198:                Disasm(debugOutput, (uaecptr)disasm_addr, &nextpc, 1);
1.1       root      199:                disasm_addr = nextpc;
                    200:        }
                    201:        fflush(debugOutput);
                    202: 
                    203:        return DEBUGGER_CMDCONT;
                    204: }
                    205: 
                    206: 
                    207: /**
                    208:  * Readline match callback to list register names usable within debugger.
                    209:  * STATE = 0 -> different text from previous one.
                    210:  * Return next match or NULL if no matches.
                    211:  */
                    212: static char *DebugCpu_MatchRegister(const char *text, int state)
                    213: {
                    214:        static const char regs[][3] = {
                    215:                "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
                    216:                "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
                    217:                "pc", "sr"
                    218:        };
                    219:        static int i, len;
                    220:        
                    221:        if (!state)
                    222:        {
                    223:                /* first match */
                    224:                i = 0;
                    225:                len = strlen(text);
                    226:                if (len > 2)
                    227:                        return NULL;
                    228:        }
                    229:        /* next match */
                    230:        while (i < ARRAYSIZE(regs)) {
                    231:                if (strncasecmp(regs[i++], text, len) == 0)
                    232:                        return (strdup(regs[i-1]));
                    233:        }
                    234:        return NULL;
                    235: }
                    236: 
                    237: 
                    238: /**
1.1.1.5 ! root      239:  * Set address of the named 32-bit register to given argument.
1.1       root      240:  * Return register size in bits or zero for uknown register name.
                    241:  * Handles D0-7 data and A0-7 address registers, but not PC & SR
                    242:  * registers as they need to be accessed using UAE accessors.
                    243:  */
                    244: int DebugCpu_GetRegisterAddress(const char *reg, Uint32 **addr)
                    245: {
                    246:        char r0, r1;
                    247:        if (!reg[0] || !reg[1] || reg[2])
                    248:                return 0;
                    249:        
                    250:        r0 = toupper(reg[0]);
                    251:        r1 = toupper(reg[1]);
                    252: 
                    253:        if (r0 == 'D')  /* Data regs? */
                    254:        {
                    255:                if (r1 >= '0' && r1 <= '7')
                    256:                {
                    257:                        *addr = &(Regs[REG_D0 + r1 - '0']);
                    258:                        return 32;
                    259:                }
                    260:                fprintf(stderr,"\tBad data register, valid values are 0-7\n");
                    261:                return 0;
                    262:        }
                    263:        if(r0 == 'A')  /* Address regs? */
                    264:        {
                    265:                if (r1 >= '0' && r1 <= '7')
                    266:                {
                    267:                        *addr = &(Regs[REG_A0 + r1 - '0']);
                    268:                        return 32;
                    269:                }
                    270:                fprintf(stderr,"\tBad address register, valid values are 0-7\n");
                    271:                return 0;
                    272:        }
                    273:        return 0;
                    274: }
                    275: 
                    276: 
                    277: /**
                    278:  * Dump or set CPU registers
                    279:  */
                    280: int DebugCpu_Register(int nArgc, char *psArgs[])
                    281: {
                    282:        char reg[3], *assign;
                    283:        Uint32 value;
                    284:        char *arg;
                    285: 
                    286:        /* If no parameter has been given, simply dump all registers */
                    287:        if (nArgc == 1)
                    288:        {
                    289:                uaecptr nextpc;
                    290:                /* use the UAE function instead */
                    291:                m68k_dumpstate(debugOutput, &nextpc);
                    292:                fflush(debugOutput);
                    293:                return DEBUGGER_CMDDONE;
                    294:        }
                    295: 
                    296:        arg = psArgs[1];
                    297: 
                    298:        assign = strchr(arg, '=');
                    299:        if (!assign)
                    300:        {
                    301:                goto error_msg;
                    302:        }
                    303: 
                    304:        *assign++ = '\0';
                    305:        if (!Eval_Number(Str_Trim(assign), &value))
                    306:        {
                    307:                goto error_msg;
                    308:        }
                    309: 
                    310:        arg = Str_Trim(arg);
                    311:        if (strlen(arg) != 2)
                    312:        {
                    313:                goto error_msg;
                    314:        }
                    315:        reg[0] = toupper(arg[0]);
                    316:        reg[1] = toupper(arg[1]);
                    317:        reg[2] = '\0';
                    318:        
                    319:        /* set SR and update conditional flags for the UAE CPU core. */
                    320:        if (reg[0] == 'S' && reg[1] == 'R')
                    321:        {
                    322:                M68000_SetSR(value);
                    323:        }
                    324:        else if (reg[0] == 'P' && reg[1] == 'C')   /* set PC? */
                    325:        {
                    326:                M68000_SetPC(value);
                    327:        }
                    328:        else
                    329:        {
                    330:                Uint32 *regaddr;
                    331:                /* check&set data and address registers */
                    332:                if (DebugCpu_GetRegisterAddress(reg, &regaddr))
                    333:                {
                    334:                        *regaddr = value;
                    335:                }
                    336:                else
                    337:                {
                    338:                        goto error_msg;
                    339:                }
                    340:        }
                    341:        return DEBUGGER_CMDDONE;
                    342: 
                    343: error_msg:
                    344:        fprintf(stderr,"\tError, usage: r or r xx=yyyy\n\tWhere: xx=A0-A7, D0-D7, PC or SR.\n");
                    345:        return DEBUGGER_CMDDONE;
                    346: }
                    347: 
                    348: 
                    349: /**
1.1.1.2   root      350:  * CPU wrapper for BreakAddr_Command().
1.1       root      351:  */
                    352: static int DebugCpu_BreakAddr(int nArgc, char *psArgs[])
                    353: {
                    354:        BreakAddr_Command(psArgs[1], false);
                    355:        return DEBUGGER_CMDDONE;
                    356: }
                    357: 
                    358: /**
1.1.1.2   root      359:  * CPU wrapper for BreakCond_Command().
1.1       root      360:  */
                    361: static int DebugCpu_BreakCond(int nArgc, char *psArgs[])
                    362: {
                    363:        BreakCond_Command(psArgs[1], false);
                    364:        return DEBUGGER_CMDDONE;
                    365: }
                    366: 
1.1.1.2   root      367: /**
                    368:  * CPU wrapper for Profile_Command().
                    369:  */
                    370: static int DebugCpu_Profile(int nArgc, char *psArgs[])
                    371: {
1.1.1.5 ! root      372:        return Profile_Command(nArgc, psArgs, false);
1.1.1.2   root      373: }
                    374: 
1.1       root      375: 
                    376: /**
                    377:  * Do a memory dump, args = starting address.
                    378:  */
                    379: int DebugCpu_MemDump(int nArgc, char *psArgs[])
                    380: {
                    381:        int i;
                    382:        char c;
                    383:        Uint32 memdump_upper = 0;
                    384: 
                    385:        if (nArgc > 1)
                    386:        {
1.1.1.2   root      387:                switch (Eval_Range(psArgs[1], &memdump_addr, &memdump_upper, false))
1.1       root      388:                {
                    389:                case -1:
                    390:                        /* invalid value(s) */
                    391:                        return DEBUGGER_CMDDONE;
                    392:                case 0:
                    393:                        /* single value */
                    394:                        break;
                    395:                case 1:
                    396:                        /* range */
                    397:                        break;
                    398:                }
                    399:        } /* continue */
                    400:        memdump_addr &= 0x00FFFFFF;
                    401: 
                    402:        if (!memdump_upper)
                    403:        {
                    404:                memdump_upper = memdump_addr + MEMDUMP_COLS * ConfigureParams.Debugger.nMemdumpLines;
                    405:        }
                    406:        memdump_upper &= 0x00FFFFFF;
                    407: 
                    408:        while (memdump_addr < memdump_upper)
                    409:        {
                    410:                fprintf(debugOutput, "%6.6X: ", memdump_addr); /* print address */
                    411:                for (i = 0; i < MEMDUMP_COLS; i++)               /* print hex data */
                    412:                        fprintf(debugOutput, "%2.2x ", STMemory_ReadByte(memdump_addr++));
                    413:                fprintf(debugOutput, "  ");                     /* print ASCII data */
                    414:                for (i = 0; i < MEMDUMP_COLS; i++)
                    415:                {
                    416:                        c = STMemory_ReadByte(memdump_addr-MEMDUMP_COLS+i);
                    417:                        if(!isprint((unsigned)c))
                    418:                                c = NON_PRINT_CHAR;             /* non-printable as dots */
                    419:                        fprintf(debugOutput,"%c", c);
                    420:                }
                    421:                fprintf(debugOutput, "\n");            /* newline */
                    422:        } /* while */
                    423:        fflush(debugOutput);
                    424: 
                    425:        return DEBUGGER_CMDCONT;
                    426: }
                    427: 
                    428: 
                    429: /**
                    430:  * Command: Write to memory, arg = starting address, followed by bytes.
                    431:  */
                    432: static int DebugCpu_MemWrite(int nArgc, char *psArgs[])
                    433: {
                    434:        int i, numBytes;
                    435:        Uint32 write_addr, d;
                    436:        unsigned char bytes[256]; /* store bytes */
                    437: 
                    438:        if (nArgc < 3)
                    439:        {
                    440:                DebugUI_PrintCmdHelp(psArgs[0]);
                    441:                return DEBUGGER_CMDDONE;
                    442:        }
                    443: 
                    444:        /* Read address */
                    445:        if (!Eval_Number(psArgs[1], &write_addr))
                    446:        {
                    447:                fprintf(stderr, "Bad address!\n");
                    448:                return DEBUGGER_CMDDONE;
                    449:        }
                    450: 
                    451:        write_addr &= 0x00FFFFFF;
                    452:        numBytes = 0;
                    453: 
                    454:        /* get bytes data */
                    455:        for (i = 2; i < nArgc; i++)
                    456:        {
                    457:                if (!Eval_Number(psArgs[i], &d) || d > 255)
                    458:                {
                    459:                        fprintf(stderr, "Bad byte argument: '%s'!\n", psArgs[i]);
                    460:                        return DEBUGGER_CMDDONE;
                    461:                }
                    462: 
                    463:                bytes[numBytes] = d & 0x0FF;
                    464:                numBytes++;
                    465:        }
                    466: 
                    467:        /* write the data */
                    468:        for (i = 0; i < numBytes; i++)
                    469:                STMemory_WriteByte(write_addr + i, bytes[i]);
                    470: 
                    471:        return DEBUGGER_CMDDONE;
                    472: }
                    473: 
                    474: 
                    475: /**
                    476:  * Command: Continue CPU emulation / single-stepping
                    477:  */
                    478: static int DebugCpu_Continue(int nArgc, char *psArgv[])
                    479: {
                    480:        int steps = 0;
                    481:        
                    482:        if (nArgc > 1)
                    483:        {
                    484:                steps = atoi(psArgv[1]);
                    485:        }
                    486:        if (steps <= 0)
                    487:        {
                    488:                nCpuSteps = 0;
                    489:                fprintf(stderr,"Returning to emulation...\n");
                    490:                return DEBUGGER_END;
                    491:        }
                    492:        nCpuSteps = steps;
                    493:        fprintf(stderr,"Returning to emulation for %i CPU instructions...\n", steps);
                    494:        return DEBUGGER_END;
                    495: }
                    496: 
1.1.1.5 ! root      497: /**
        !           498:  * Command: Single-step CPU
        !           499:  */
        !           500: static int DebugCpu_Step(int nArgc, char *psArgv[])
        !           501: {
        !           502:        nCpuSteps = 1;
        !           503:        return DEBUGGER_END;
        !           504: }
        !           505: 
        !           506: /**
        !           507:  * Command: Step CPU, but proceed through subroutines
        !           508:  * Does this by temporary conditional breakpoint
        !           509:  */
        !           510: static int DebugCpu_Next(int nArgc, char *psArgv[])
        !           511: {
        !           512:        char command[32];
        !           513:        Uint32 nextpc = Disasm_GetNextPC(M68000_GetPC());
        !           514:        sprintf(command, "pc=$%x :once :quiet\n", nextpc);
        !           515:        if (BreakCond_Command(command, false)) {
        !           516:                nCpuSteps = 0;          /* using breakpoint, not steps */
        !           517:                return DEBUGGER_END;
        !           518:        }
        !           519:        return DEBUGGER_CMDDONE;
        !           520: }
        !           521: 
1.1       root      522: 
                    523: /**
                    524:  * This function is called after each CPU instruction when debugging is enabled.
                    525:  */
                    526: void DebugCpu_Check(void)
                    527: {
1.1.1.2   root      528:        if (bCpuProfiling)
                    529:        {
                    530:                Profile_CpuUpdate();
                    531:        }
1.1.1.4   root      532:        if (LOG_TRACE_LEVEL((TRACE_CPU_DISASM|TRACE_CPU_SYMBOLS)))
1.1       root      533:        {
1.1.1.2   root      534:                DebugCpu_ShowAddressInfo(M68000_GetPC());
1.1       root      535:        }
                    536:        if (nCpuActiveCBs)
                    537:        {
                    538:                if (BreakCond_MatchCpu())
1.1.1.5 ! root      539:                {
1.1.1.3   root      540:                        DebugUI(REASON_CPU_BREAKPOINT);
1.1.1.5 ! root      541:                        /* make sure we don't decrease step count
        !           542:                         * below, before even even getting out of here
        !           543:                         */
        !           544:                        if (nCpuSteps)
        !           545:                                nCpuSteps++;
        !           546:                }
1.1       root      547:        }
                    548:        if (nCpuSteps)
                    549:        {
1.1.1.5 ! root      550:                nCpuSteps--;
1.1       root      551:                if (nCpuSteps == 0)
1.1.1.3   root      552:                        DebugUI(REASON_CPU_STEPS);
                    553:        }
1.1.1.5 ! root      554:        if (History_TrackCpu())
1.1.1.3   root      555:        {
                    556:                History_AddCpu();
1.1       root      557:        }
1.1.1.5 ! root      558:        if (ConOutDevice != CONOUT_DEVICE_NONE)
        !           559:        {
        !           560:                Console_Check();
        !           561:        }
1.1       root      562: }
                    563: 
                    564: /**
                    565:  * Should be called before returning back emulation to tell the CPU core
                    566:  * to call us after each instruction if "real-time" debugging like
                    567:  * breakpoints has been set.
                    568:  */
                    569: void DebugCpu_SetDebugging(void)
                    570: {
1.1.1.2   root      571:        bCpuProfiling = Profile_CpuStart();
1.1       root      572:        nCpuActiveCBs = BreakCond_BreakPointCount(false);
1.1.1.2   root      573: 
1.1.1.5 ! root      574:        if (nCpuActiveCBs || nCpuSteps || bCpuProfiling || History_TrackCpu()
        !           575:            || LOG_TRACE_LEVEL((TRACE_CPU_DISASM|TRACE_CPU_SYMBOLS))
        !           576:            || ConOutDevice != CONOUT_DEVICE_NONE)
1.1       root      577:                M68000_SetSpecial(SPCFLAG_DEBUGGER);
                    578:        else
                    579:                M68000_UnsetSpecial(SPCFLAG_DEBUGGER);
                    580: }
                    581: 
                    582: 
                    583: static const dbgcommand_t cpucommands[] =
                    584: {
                    585:        { NULL, NULL, "CPU commands", NULL, NULL, NULL, false },
                    586:        /* NULL as match function will complete file names */
                    587:        { DebugCpu_BreakAddr, Symbols_MatchCpuCodeAddress,
                    588:          "address", "a",
                    589:          "set CPU PC address breakpoints",
                    590:          BreakAddr_Description,
                    591:          true  },
                    592:        { DebugCpu_BreakCond, BreakCond_MatchCpuVariable,
                    593:          "breakpoint", "b",
                    594:          "set/remove/list conditional CPU breakpoints",
                    595:          BreakCond_Description,
                    596:          true },
                    597:        { DebugCpu_DisAsm, Symbols_MatchCpuCodeAddress,
                    598:          "disasm", "d",
                    599:          "disassemble from PC, or given address",
                    600:          "[<start address>[-<end address>]]\n"
                    601:          "\tIf no address is given, this command disassembles from the last\n"
                    602:          "\tposition or from current PC if no last position is available.",
                    603:          false },
1.1.1.2   root      604:        { DebugCpu_Profile, Profile_Match,
                    605:          "profile", "",
                    606:          "profile CPU code",
                    607:          Profile_Description,
                    608:          false },
1.1       root      609:        { DebugCpu_Register, DebugCpu_MatchRegister,
                    610:          "cpureg", "r",
                    611:          "dump register values or set register to value",
                    612:          "[REG=value]\n"
                    613:          "\tSet CPU register to value or dumps all register if no parameter\n"
                    614:          "\thas been specified.",
                    615:          true },
                    616:        { DebugCpu_MemDump, Symbols_MatchCpuDataAddress,
                    617:          "memdump", "m",
                    618:          "dump memory",
                    619:          "[<start address>[-<end address>]]\n"
                    620:          "\tdump memory at address or continue dump from previous address.",
                    621:          false },
                    622:        { DebugCpu_MemWrite, Symbols_MatchCpuAddress,
                    623:          "memwrite", "w",
                    624:          "write bytes to memory",
                    625:          "address byte1 [byte2 ...]\n"
                    626:          "\tWrite bytes to a memory address, bytes are space separated\n"
1.1.1.5 ! root      627:          "\tvalues in current number base.",
1.1       root      628:          false },
                    629:        { DebugCpu_LoadBin, NULL,
                    630:          "loadbin", "l",
                    631:          "load a file into memory",
                    632:          "filename address\n"
                    633:          "\tLoad the file <filename> into memory starting at <address>.",
                    634:          false },
                    635:        { DebugCpu_SaveBin, NULL,
1.1.1.5 ! root      636:          "savebin", "",
1.1       root      637:          "save memory to a file",
                    638:          "filename address length\n"
                    639:          "\tSave the memory block at <address> with given <length> to\n"
                    640:          "\tthe file <filename>.",
                    641:          false },
                    642:        { Symbols_Command, NULL,
                    643:          "symbols", "",
                    644:          "load CPU symbols & their addresses",
                    645:          Symbols_Description,
                    646:          false },
1.1.1.5 ! root      647:        { DebugCpu_Step, NULL,
        !           648:          "step", "s",
        !           649:          "single-step CPU",
        !           650:          "\n"
        !           651:          "\tExecute next CPU instruction (equals 'c 1')",
        !           652:          false },
        !           653:        { DebugCpu_Next, NULL,
        !           654:          "next", "n",
        !           655:          "step CPU, proceeding through subroutine calls",
        !           656:          "\n"
        !           657:          "\tLike the 'step' command as long as subroutine calls do not\n"
        !           658:           "\thappen. When they do, the call is treated as one instruction.",
        !           659:          false },
1.1       root      660:        { DebugCpu_Continue, NULL,
                    661:          "cont", "c",
                    662:          "continue emulation / CPU single-stepping",
                    663:          "[steps]\n"
                    664:          "\tLeave debugger and continue emulation for <steps> CPU instructions\n"
                    665:          "\tor forever if no steps have been specified.",
                    666:          false }
                    667: };
                    668: 
                    669: 
                    670: /**
                    671:  * Should be called when debugger is first entered to initialize
                    672:  * CPU debugging variables.
                    673:  * 
                    674:  * if you want disassembly or memdumping to start/continue from
                    675:  * specific address, you can set them here.  If disassembly
                    676:  * address is zero, disassembling starts from PC.
                    677:  * 
                    678:  * returns number of CPU commands and pointer to array of them.
                    679:  */
                    680: int DebugCpu_Init(const dbgcommand_t **table)
                    681: {
                    682:        memdump_addr = 0;
                    683:        disasm_addr = 0;
                    684:        
                    685:        *table = cpucommands;
                    686:        return ARRAYSIZE(cpucommands);
                    687: }
                    688: 
                    689: /**
                    690:  * Should be called when debugger is re-entered to reset
                    691:  * relevant CPU debugging variables.
                    692:  */
                    693: void DebugCpu_InitSession(void)
                    694: {
                    695:        disasm_addr = M68000_GetPC();
1.1.1.2   root      696:        Profile_CpuStop();
1.1       root      697: }

unix.superglobalmegacorp.com

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