Annotation of hatari/src/debug/vars.c, revision 1.1.1.2

1.1       root        1: /*
                      2:   Hatari - vars.c
                      3: 
                      4:   Copyright (c) 2016 by Eero Tamminen
                      5: 
                      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.
                      8: 
                      9:   vars.c - Hatari internal variable value and OS call number accessors
                     10:   for conditional breakpoint and evaluate commands.
                     11: */
                     12: const char Vars_fileid[] = "Hatari vars.c : " __DATE__ " " __TIME__;
                     13: 
                     14: #include <stdio.h>
                     15: #include <stdlib.h>
                     16: #include "main.h"
                     17: #include "configuration.h"
                     18: #include "stMemory.h"
                     19: #include "m68000.h"
                     20: #include "screen.h"    /* for defines needed by video.h */
                     21: #include "video.h"     /* for Hatari video variable addresses */
                     22: 
                     23: #include "debugInfo.h"
                     24: #include "debugcpu.h"
                     25: #include "debugdsp.h"
                     26: #include "debugui.h"
                     27: #include "symbols.h"
                     28: #include "68kDisass.h"
                     29: #include "vars.h"
                     30: 
                     31: 
1.1.1.2 ! root       32: static Uint32 GetCycleCounter(void)
        !            33: {
        !            34:        /* 64-bit, so only lower 32-bits are returned */
        !            35:        return CyclesGlobalClockCounter;
        !            36: }
        !            37: 
1.1       root       38: /* Accessor functions for calculated Hatari values */
                     39: static Uint32 GetLineCycles(void)
                     40: {
                     41:        int dummy1, dummy2, lcycles;
                     42:        Video_GetPosition(&dummy1, &dummy2 , &lcycles);
                     43:        return lcycles;
                     44: }
                     45: static Uint32 GetFrameCycles(void)
                     46: {
                     47:        int dummy1, dummy2, fcycles;
                     48:        Video_GetPosition(&fcycles, &dummy1, &dummy2);
                     49:        return fcycles;
                     50: }
                     51: 
                     52: /* helpers for TOS OS call opcode accessor functions */
                     53: #define INVALID_OPCODE 0xFFFFu
                     54: 
                     55: static inline Uint16 getLineOpcode(Uint8 line)
                     56: {
                     57:        Uint32 pc;
                     58:        Uint16 instr;
                     59:        pc = M68000_GetPC();
                     60:        instr = STMemory_ReadWord(pc);
                     61:        /* for opcode X, Line-A = 0xA00X, Line-F = 0xF00X */
                     62:        if ((instr >> 12) == line) {
                     63:                return instr & 0xFF;
                     64:        }
                     65:        return INVALID_OPCODE;
                     66: }
                     67: static inline bool isTrap(Uint8 trap)
                     68: {
                     69:        Uint32 pc;
                     70:        Uint16 instr;
                     71:        pc = M68000_GetPC();
                     72:        instr = STMemory_ReadWord(pc);
                     73:        return (instr == (Uint16)0x4e40u + trap);
                     74: }
                     75: static inline Uint16 getControlOpcode(void)
                     76: {
                     77:        /* Control[] address from D1, opcode in Control[0] */
                     78:        return STMemory_ReadWord(STMemory_ReadLong(Regs[REG_D1]));
                     79: }
                     80: static inline Uint16 getStackOpcode(void)
                     81: {
                     82:        return STMemory_ReadWord(Regs[REG_A7]);
                     83: }
                     84: 
                     85: /* Actual TOS OS call opcode accessor functions */
                     86: static Uint32 GetLineAOpcode(void)
                     87: {
                     88:        return getLineOpcode(0xA);
                     89: }
                     90: static Uint32 GetLineFOpcode(void)
                     91: {
                     92:        return getLineOpcode(0xF);
                     93: }
                     94: static Uint32 GetGemdosOpcode(void)
                     95: {
                     96:        if (isTrap(1)) {
                     97:                return getStackOpcode();
                     98:        }
                     99:        return INVALID_OPCODE;
                    100: }
                    101: static Uint32 GetBiosOpcode(void)
                    102: {
                    103:        if (isTrap(13)) {
                    104:                return getStackOpcode();
                    105:        }
                    106:        return INVALID_OPCODE;
                    107: }
                    108: static Uint32 GetXbiosOpcode(void)
                    109: {
                    110:        if (isTrap(14)) {
                    111:                return getStackOpcode();
                    112:        }
                    113:        return INVALID_OPCODE;
                    114: }
                    115: static Uint32 GetAesOpcode(void)
                    116: {
                    117:        if (isTrap(2)) {
                    118:                Uint16 d0 = Regs[REG_D0];
                    119:                if (d0 == 0xC8) {
                    120:                        return getControlOpcode();
                    121:                } else if (d0 == 0xC9) {
                    122:                        /* same as appl_yield() */
                    123:                        return 0x11;
                    124:                }
                    125:        }
                    126:        return INVALID_OPCODE;
                    127: }
                    128: static Uint32 GetVdiOpcode(void)
                    129: {
                    130:        if (isTrap(2)) {
                    131:                Uint16 d0 = Regs[REG_D0];
                    132:                if (d0 == 0x73) {
                    133:                        return getControlOpcode();
                    134:                } else if (d0 == 0xFFFE) {
                    135:                        /* -2 = vq_[v]gdos() */
                    136:                        return 0xFFFE;
                    137:                }
                    138:        }
                    139:        return INVALID_OPCODE;
                    140: }
                    141: 
                    142: static Uint32 GetNextPC(void)
                    143: {
                    144:        return Disasm_GetNextPC(M68000_GetPC());
                    145: }
                    146: 
                    147: /* sorted by variable name so that this can be bisected */
                    148: static const var_addr_t hatari_vars[] = {
                    149:        { "AesOpcode", (Uint32*)GetAesOpcode, VALUE_TYPE_FUNCTION32, 16, "$FFFF when not on AES trap" },
                    150:        { "Basepage", (Uint32*)DebugInfo_GetBASEPAGE, VALUE_TYPE_FUNCTION32, 0, "invalid before Desktop is up" },
                    151:        { "BiosOpcode", (Uint32*)GetBiosOpcode, VALUE_TYPE_FUNCTION32, 16, "$FFFF when not on BIOS trap" },
                    152:        { "BSS", (Uint32*)DebugInfo_GetBSS, VALUE_TYPE_FUNCTION32, 0, "invalid before Desktop is up" },
                    153:        { "CpuInstr", (Uint32*)DebugCpu_InstrCount, VALUE_TYPE_FUNCTION32, 0, "CPU instructions count" },
                    154:        { "CpuOpcodeType", (Uint32*)DebugCpu_OpcodeType, VALUE_TYPE_FUNCTION32, 0, "internal CPU instruction type" },
1.1.1.2 ! root      155:        { "CycleCounter", (Uint32*)GetCycleCounter, VALUE_TYPE_FUNCTION32, 0, "global cycles counter (lower 32-bits)" },
1.1       root      156:        { "DATA", (Uint32*)DebugInfo_GetDATA, VALUE_TYPE_FUNCTION32, 0, "invalid before Desktop is up" },
                    157: #if ENABLE_DSP_EMU
                    158:        { "DspInstr", (Uint32*)DebugDsp_InstrCount, VALUE_TYPE_FUNCTION32, 0, "DSP instructions count" },
                    159:        { "DspOpcodeType", (Uint32*)DebugDsp_OpcodeType, VALUE_TYPE_FUNCTION32, 0, "internal DSP instruction type" },
                    160: #endif
                    161:        { "FrameCycles", (Uint32*)GetFrameCycles, VALUE_TYPE_FUNCTION32, 0, NULL },
                    162:        { "GemdosOpcode", (Uint32*)GetGemdosOpcode, VALUE_TYPE_FUNCTION32, 16, "$FFFF when not on GEMDOS trap" },
                    163:        { "HBL", (Uint32*)&nHBL, VALUE_TYPE_VAR32, sizeof(nHBL)*8, NULL },
                    164:        { "LineAOpcode", (Uint32*)GetLineAOpcode, VALUE_TYPE_FUNCTION32, 16, "$FFFF when not on Line-A opcode" },
                    165:        { "LineCycles", (Uint32*)GetLineCycles, VALUE_TYPE_FUNCTION32, 0, "is always divisable by 4" },
                    166:        { "LineFOpcode", (Uint32*)GetLineFOpcode, VALUE_TYPE_FUNCTION32, 16, "$FFFF when not on Line-F opcode" },
                    167:        { "NextPC", (Uint32*)GetNextPC, VALUE_TYPE_FUNCTION32, 0, NULL },
                    168:        { "TEXT", (Uint32*)DebugInfo_GetTEXT, VALUE_TYPE_FUNCTION32, 0, "invalid before Desktop is up" },
                    169:        { "TEXTEnd", (Uint32*)DebugInfo_GetTEXTEnd, VALUE_TYPE_FUNCTION32, 0, "invalid before Desktop is up" },
                    170:        { "VBL", (Uint32*)&nVBLs, VALUE_TYPE_VAR32, sizeof(nVBLs)*8, NULL },
                    171:        { "VdiOpcode", (Uint32*)GetVdiOpcode, VALUE_TYPE_FUNCTION32, 16, "$FFFF when not on VDI trap" },
                    172:        { "XbiosOpcode", (Uint32*)GetXbiosOpcode, VALUE_TYPE_FUNCTION32, 16, "$FFFF when not on XBIOS trap" }
                    173: };
                    174: 
                    175: 
                    176: /**
                    177:  * Readline match callback for Hatari variable and CPU variable/symbol name completion.
                    178:  * STATE = 0 -> different text from previous one.
                    179:  * Return next match or NULL if no matches.
                    180:  */
                    181: char *Vars_MatchCpuVariable(const char *text, int state)
                    182: {
                    183:        static int i, len;
                    184:        const char *name;
                    185: 
                    186:        if (!state) {
                    187:                /* first match */
                    188:                len = strlen(text);
                    189:                i = 0;
                    190:        }
                    191:        /* next match */
                    192:        while (i < ARRAY_SIZE(hatari_vars)) {
                    193:                name = hatari_vars[i++].name;
                    194:                if (strncasecmp(name, text, len) == 0)
                    195:                        return (strdup(name));
                    196:        }
                    197:        /* no variable match, check all CPU symbols */
                    198:        return Symbols_MatchCpuAddress(text, state);
                    199: }
                    200: 
                    201: 
                    202: /**
                    203:  * If given string matches Hatari variable name, return its struct pointer,
                    204:  * otherwise return NULL.
                    205:  */
                    206: const var_addr_t *Vars_ParseVariable(const char *name)
                    207: {
                    208:        const var_addr_t *hvar;
                    209:        /* left, right, middle, direction */
                    210:         int l, r, m, dir;
                    211: 
                    212:        /* bisect */
                    213:        l = 0;
                    214:        r = ARRAY_SIZE(hatari_vars) - 1;
                    215:        do {
                    216:                m = (l+r) >> 1;
                    217:                hvar = hatari_vars + m;
                    218:                dir = strcasecmp(name, hvar->name);
                    219:                if (dir == 0) {
                    220:                        return hvar;
                    221:                }
                    222:                if (dir < 0) {
                    223:                        r = m-1;
                    224:                } else {
                    225:                        l = m+1;
                    226:                }
                    227:        } while (l <= r);
                    228:        return NULL;
                    229: }
                    230: 
                    231: 
                    232: /**
                    233:  * Return Uint32 value from given Hatari variable struct*
                    234:  */
                    235: Uint32 Vars_GetValue(const var_addr_t *hvar)
                    236: {
                    237:        switch (hvar->vtype) {
                    238:        case VALUE_TYPE_FUNCTION32:
                    239:                return ((Uint32(*)(void))(hvar->addr))();
                    240:        case VALUE_TYPE_VAR32:
                    241:                return *(hvar->addr);
                    242:        default:
                    243:                fprintf(stderr, "ERROR: variable '%s' has unsupported type '%d'\n",
                    244:                        hvar->name, hvar->vtype);
                    245:                exit(-1);
                    246:        }
                    247: }
                    248: 
                    249: 
                    250: /**
                    251:  * If given string is a Hatari variable name, set value to given
                    252:  * variable's value and return true, otherwise return false.
                    253:  */
                    254: bool Vars_GetVariableValue(const char *name, Uint32 *value)
                    255: {
                    256:        const var_addr_t *hvar;
                    257: 
                    258:        if (!(hvar = Vars_ParseVariable(name))) {
                    259:                return false;
                    260:        }
                    261:        *value = Vars_GetValue(hvar);
                    262:        return true;
                    263: }
                    264: 
                    265: 
                    266: /**
                    267:  * List Hatari variable names & current values
                    268:  */
                    269: int Vars_List(int nArgc, char *psArgv[])
                    270: {
                    271:        Uint32 value;
                    272:        int i;
                    273:        fputs("Hatari debugger builtin symbols and their values are:\n", stderr);
                    274:        for (i = 0; i < ARRAY_SIZE(hatari_vars); i++) {
                    275:                const var_addr_t *hvar = hatari_vars + i;
                    276:                value = Vars_GetValue(hvar);
                    277:                fprintf(stderr, "  - %s: $%X / #%d", hvar->name, value, value);
                    278:                if (hvar->info) {
                    279:                        fprintf(stderr, " -- %s\n", hvar->info);
                    280:                } else {
                    281:                        fprintf(stderr, "\n");
                    282:                }
                    283:        }
                    284:        return DEBUGGER_CMDDONE;
                    285: }

unix.superglobalmegacorp.com

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