|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.