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

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

unix.superglobalmegacorp.com

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