Annotation of hatari/src/debug/vars.c, revision 1.1.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.