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

1.1       root        1: /*
                      2:  * Hatari - history.c
                      3:  * 
1.1.1.3 ! root        4:  * Copyright (C) 2011-2013 by Eero Tamminen
1.1       root        5:  *
1.1.1.2   root        6:  * This file is distributed under the GNU General Public License, version 2
                      7:  * or at your option any later version. Read the file gpl.txt for details.
1.1       root        8:  *
                      9:  * history.c - functions for debugger entry & breakpoint history
                     10:  */
                     11: const char History_fileid[] = "Hatari history.c : " __DATE__ " " __TIME__;
                     12: 
                     13: #include <assert.h>
                     14: 
                     15: #include "main.h"
                     16: #include "debugui.h"
                     17: #include "debug_priv.h"
                     18: #include "dsp.h"
                     19: #include "dsp_core.h"
                     20: #include "evaluate.h"
                     21: #include "history.h"
                     22: #include "m68000.h"
                     23: #include "68kDisass.h"
                     24: 
1.1.1.3 ! root       25: #define HISTORY_ITEMS_MIN 64
1.1.1.2   root       26: 
                     27: history_type_t HistoryTracking;
1.1       root       28: 
                     29: typedef struct {
                     30:        bool shown:1;
                     31:        bool valid:1;
                     32:        bool for_dsp:1;
                     33:        /* reason for debugger entry/breakpoint hit */
                     34:        debug_reason_t reason:8;
                     35:        union {
                     36:                Uint16 dsp;
                     37:                Uint32 cpu;
                     38:        } pc;
                     39: } hist_item_t;
                     40: 
                     41: static struct {
1.1.1.3 ! root       42:        unsigned idx;      /* index to current history item */
        !            43:        unsigned count;    /* how many items of history are collected */
        !            44:        unsigned limit;    /* ring-buffer size */
        !            45:        hist_item_t *item; /* ring-buffer */
1.1       root       46: } History;
                     47: 
                     48: 
                     49: /**
                     50:  * Convert debugger entry/breakpoint entry reason to a string
                     51:  */
1.1.1.2   root       52: static const char* History_ReasonStr(debug_reason_t reason)
1.1       root       53: {
                     54:        switch(reason) {
                     55:        case REASON_CPU_EXCEPTION:
                     56:                return "CPU exception";
                     57:        case REASON_CPU_BREAKPOINT:
                     58:                return "CPU breakpoint";
                     59:        case REASON_DSP_BREAKPOINT:
                     60:                return "DSP breakpoint";
                     61:        case REASON_CPU_STEPS:
                     62:                return "CPU steps";
                     63:        case REASON_DSP_STEPS:
                     64:                return "DSP steps";
                     65:        case REASON_USER:
                     66:                return "User break";
                     67:        default:
                     68:                return "Unknown reason";
                     69:        }
                     70: }
                     71: 
                     72: 
                     73: /**
1.1.1.2   root       74:  * Set what kind of history is collected.
                     75:  * Clear history if tracking type changes as rest of
                     76:  * data wouldn't then be anymore valid.
1.1       root       77:  */
1.1.1.3 ! root       78: static void History_Enable(history_type_t track, unsigned limit)
1.1       root       79: {
1.1.1.2   root       80:        const char *msg;
1.1.1.3 ! root       81:        if (track != HistoryTracking || limit != History.limit) {
        !            82:                fprintf(stderr, "Re-allocating & zeroing history due to type/limit change.\n");
        !            83:                if (History.item) {
        !            84:                        free(History.item);
        !            85:                }
1.1       root       86:                memset(&History, 0, sizeof(History));
1.1.1.3 ! root       87:                History.item = calloc(limit, sizeof(History.item[0]));
        !            88:                History.limit = limit;
1.1       root       89:        }
1.1.1.2   root       90:        switch (track) {
                     91:        case HISTORY_TRACK_NONE:
                     92:                msg = "disabled";
                     93:                break;
                     94:        case HISTORY_TRACK_CPU:
                     95:                msg = "enabled for CPU";
                     96:                break;
                     97:        case HISTORY_TRACK_DSP:
                     98:                msg = "enabled for DSP";
                     99:                break;
                    100:        case HISTORY_TRACK_ALL:
                    101:                msg = "enabled for CPU & DSP";
                    102:                break;
                    103:        default:
                    104:                msg = "error";
                    105:        }
                    106:        HistoryTracking = track;
1.1.1.3 ! root      107:        fprintf(stderr, "History tracking %s (max. %d instructions).\n", msg, limit);
1.1       root      108: }
                    109: 
                    110: /**
                    111:  * Advance & initialize next history item in ring buffer
                    112:  */
                    113: static void History_Advance(void)
                    114: {
                    115:        History.idx++;
1.1.1.3 ! root      116:        History.idx %= History.limit;
1.1       root      117:        History.item[History.idx].valid = true;
                    118:        History.item[History.idx].shown = false;
                    119:        History.item[History.idx].reason = REASON_NONE;
                    120:        History.count++;
                    121: }
                    122: 
                    123: /**
                    124:  * Add CPU PC to history
                    125:  */
                    126: void History_AddCpu(void)
                    127: {
                    128:        Uint32 pc = M68000_GetPC();
                    129: 
                    130:        History_Advance();
                    131:        History.item[History.idx].for_dsp = false;
                    132:        History.item[History.idx].pc.cpu = pc;
                    133: }
                    134: 
                    135: /**
                    136:  * Add DSP PC to history
                    137:  */
                    138: void History_AddDsp(void)
                    139: {
                    140:        Uint16 pc = DSP_GetPC();
                    141: 
                    142:        History_Advance();
                    143:        History.item[History.idx].for_dsp = true;
                    144:        History.item[History.idx].pc.dsp = pc;
                    145: }
                    146: 
                    147: /**
                    148:  * Flag last history entry as debugger entry point, with given reason
                    149:  */
                    150: void History_Mark(debug_reason_t reason)
                    151: {
1.1.1.3 ! root      152:        if (History.item) {
        !           153:                History.item[History.idx].reason = reason;
        !           154:        }
1.1       root      155: }
                    156: 
                    157: /**
                    158:  * Show collected CPU/DSP debugger/breakpoint history
                    159:  */
                    160: void History_Show(Uint32 count)
                    161: {
                    162:        bool show_all;
                    163:        int i;
                    164: 
1.1.1.3 ! root      165:        if (History.count > History.limit) {
        !           166:                History.count = History.limit;
1.1       root      167:        }
                    168:        if (count > History.count) {
                    169:                count = History.count;
                    170:        } else {
                    171:                if (!count) {
                    172:                        /* default to all */
                    173:                        count = History.count;
                    174:                }
                    175:        }
                    176:        if (count <= 0) {
                    177:                fprintf(stderr,  "No history items to show.\n");
                    178:                return;
                    179:        }
                    180: 
                    181:        i = History.idx;
                    182:        show_all = false;
                    183:        if (History.item[i].shown) {
                    184:                /* even last item already shown, show all again */
                    185:                show_all = true;
                    186:        }
1.1.1.3 ! root      187:        i = (i + History.limit - count) % History.limit;
1.1       root      188: 
                    189:        while (count-- > 0) {
                    190:                i++;
1.1.1.3 ! root      191:                i %= History.limit;
1.1       root      192:                if (!History.item[i].valid) {
                    193:                        fprintf(stderr, "ERROR: invalid history item %d!", count);
                    194:                }
                    195:                if (History.item[i].shown && !show_all) {
                    196:                        continue;
                    197:                }
                    198:                History.item[i].shown = true;
                    199: 
                    200:                if (History.item[i].for_dsp) {
                    201:                        Uint16 pc = History.item[i].pc.dsp;
1.1.1.2   root      202:                        DSP_DisasmAddress(stderr, pc, pc);
1.1       root      203:                } else {
                    204:                        Uint32 dummy;
1.1.1.2   root      205:                        Disasm(stderr, History.item[i].pc.cpu, &dummy, 1);
1.1       root      206:                }
                    207:                if (History.item[i].reason != REASON_NONE) {
                    208:                        fprintf(stderr, "Debugger: *%s*\n", History_ReasonStr(History.item[i].reason));
                    209:                }
                    210:        }
                    211: }
                    212: 
1.1.1.3 ! root      213: /*
        !           214:  * Readline callback
        !           215:  */
        !           216: char *History_Match(const char *text, int state)
        !           217: {
        !           218:        static const char* cmds[] = { "cpu", "dsp", "off" };
        !           219:        return DebugUI_MatchHelper(cmds, ARRAYSIZE(cmds), text, state);
        !           220: }
        !           221: 
1.1       root      222: /**
                    223:  * Command: Show collected CPU/DSP debugger/breakpoint history
                    224:  */
                    225: int History_Parse(int nArgc, char *psArgs[])
                    226: {
1.1.1.3 ! root      227:        int count, limit = 0;
1.1       root      228: 
1.1.1.3 ! root      229:        if (nArgc < 2) {
        !           230:                return DebugUI_PrintCmdHelp(psArgs[0]);
        !           231:        }
        !           232:        if (nArgc > 2) {
        !           233:                limit = atoi(psArgs[2]);
        !           234:        }
        !           235:        /* make sure value is valid & positive */
        !           236:        if (!limit) {
        !           237:                limit = History.limit;
        !           238:        }
        !           239:        if (limit < HISTORY_ITEMS_MIN) {
        !           240:                limit = HISTORY_ITEMS_MIN;
1.1       root      241:        }
                    242:        count = atoi(psArgs[1]);
1.1.1.3 ! root      243: 
        !           244:        if (count <= 0) {
1.1       root      245:                /* no count -> enable or disable? */
                    246:                if (strcmp(psArgs[1], "on") == 0) {
1.1.1.3 ! root      247:                        History_Enable(HISTORY_TRACK_ALL, limit);
1.1       root      248:                        return DEBUGGER_CMDDONE;
                    249:                }
                    250:                if (strcmp(psArgs[1], "off") == 0) {
1.1.1.3 ! root      251:                        History_Enable(HISTORY_TRACK_NONE, limit);
1.1.1.2   root      252:                        return DEBUGGER_CMDDONE;
                    253:                }
                    254:                if (strcmp(psArgs[1], "cpu") == 0) {
1.1.1.3 ! root      255:                        History_Enable(HISTORY_TRACK_CPU, limit);
1.1.1.2   root      256:                        return DEBUGGER_CMDDONE;
                    257:                }
                    258:                if (strcmp(psArgs[1], "dsp") == 0) {
1.1.1.3 ! root      259:                        History_Enable(HISTORY_TRACK_DSP, limit);
1.1       root      260:                        return DEBUGGER_CMDDONE;
                    261:                }
1.1.1.3 ! root      262:                fprintf(stderr,  "History range is 1-<limit>\n");
        !           263:                return DebugUI_PrintCmdHelp(psArgs[0]);
1.1       root      264:        }
                    265: 
                    266:        History_Show(count);
                    267:        return DEBUGGER_CMDDONE;
                    268: }

unix.superglobalmegacorp.com

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