Annotation of previous_trunk/src/debug/debugcpu.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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