|
|
1.1 root 1: /*
2: * Code to test Hatari conditional breakpoints in src/debug/breakcond.c
3: */
4: #include "main.h"
5: #include "dsp.h"
6: #include "debugcpu.h"
7: #include "breakcond.h"
8: #include "stMemory.h"
9: #include "newcpu.h"
10:
11: #define BITMASK(x) ((1<<(x))-1)
12:
13: /* BreakCond_Command() command strings */
14: #define CMD_LIST NULL
15: #define CMD_REMOVE_ALL "all"
16:
17:
18: static bool SetCpuRegister(const char *regname, Uint32 value)
19: {
20: Uint32 *addr;
21:
22: switch (DebugCpu_GetRegisterAddress(regname, &addr)) {
23: case 32:
24: *addr = value;
25: break;
26: case 16:
27: *(Uint16*)addr = value;
28: break;
29: default:
30: fprintf(stderr, "SETUP ERROR: Register '%s' to set (to %x) is unrecognized!\n", regname, value);
31: return false;
32: }
33: return true;
34: }
35:
36: #if 0
37: static bool SetDspRegister(const char *regname, Uint32 value)
38: {
39: Uint32 *addr, mask;
40:
41: switch (DSP_GetRegisterAddress(regname, &addr, &mask)) {
42: case 32:
43: *addr = value & mask;
44: break;
45: case 16:
46: *(Uint16*)addr = value & mask;
47: break;
48: default:
49: return false;
50: }
51: return true;
52: }
53: #endif
54:
55: int main(int argc, const char *argv[])
56: {
57: const char *parser_fail[] = {
58: /* syntax & register name errors */
59: "",
60: " = ",
61: " a0 d0 ",
62: "gggg=a0",
63: "=a=b=",
64: "a0=d0=20",
65: "a0=d || 0=20",
66: "a0=d & 0=20",
67: ".w&3=2",
68: "d0 = %200",
69: "d0 = \"ICE!BAR",
70: "pc > $200 :foobar",
71: "foo().w=bar()",
72: "(a0.w=d0.l)",
73: "(a0&3)=20",
74: "20 = (a0.w)",
75: "()&=d0",
76: "d0=().w",
77: "255 & 3 = (d0) & && 2 = 2",
78: /* size and mask mismatches with numbers */
79: "d0.w = $ffff0",
80: "(a0).b & 3 < 100",
81: /* more than BC_MAX_CONDITIONS_PER_BREAKPOINT conditions */
82: "1=1 && 2=2 && 3=3 && 4=4 && 5=5",
83: NULL
84: };
85: const char *parser_pass[] = {
86: /* comparisons with normal numbers + indrect addressing */
87: " ($200).w > 200 ",
88: " ($200).w < 200 ",
89: " (200).w = $200 ",
90: " (200).w ! $200 ",
91: /* indirect addressing with registers */
92: "(a0)=(d0)",
93: "(d0).w=(a0).b",
94: /* sizes + multiple conditions + spacing */
95: "(a0).w&3=(d0)&&d0=1",
96: " ( a 0 ) . w & 1 = ( d 0 ) & 1 && d 0 = 3 ",
97: "a0=1 && (d0)&2=(a0).w && ($00ff00).w&1=1",
98: " ($ff820a).b = 2",
99: /* variables */
100: "hbl > 0 && vbl < 2000 && linecycles = 508",
101: /* options */
102: "($200).w ! ($200).w :trace",
103: "($200).w > ($200).w :4",
104: "pc>pc :once",
105: NULL
106: };
107: /* address breakpoint + expression evalution with register */
108: char addr_pass[] = "pc + ($200*16/2 & 0xffff)";
109:
110: const char *match_tests[] = {
111: "a0 = d0",
112: "( $200 ) . b > 200", /* byte access to avoid endianess */
113: "pc < $50000 && pc > $60000",
114: "pc > $50000 && pc < $54000",
115: #define FAILING_BC_TEST_MATCHES 4
116: "pc > $50000 && pc < $60000",
117: "( $200 ) . b > ( 200 ) . b",
118: "d0 = d1",
119: "a0 = pc",
120: NULL
121: };
122: const char *test;
123: char testidx[2] = "1";
124: int i, j, tests = 0, errors = 0;
125: int remaining_matches;
126: bool use_dsp;
127:
128: /* first automated tests... */
129: use_dsp = false;
130: fprintf(stderr, "\nShould FAIL for CPU:\n");
131: for (i = 0; (test = parser_fail[i]); i++) {
132: fprintf(stderr, "-----------------\n- parsing '%s'\n", test);
133: if (BreakCond_Command(test, use_dsp)) {
134: fprintf(stderr, "***ERROR***: should have failed\n");
135: errors++;
136: }
137: }
138: tests += i;
139: fprintf(stderr, "-----------------\n\n");
140: BreakCond_Command(CMD_LIST, use_dsp);
141:
142: fprintf(stderr, "\nShould PASS for CPU:\n");
143: for (i = 0; (test = parser_pass[i]); i++) {
144: fprintf(stderr, "-----------------\n- parsing '%s'\n", test);
145: if (!BreakCond_Command(test, use_dsp)) {
146: fprintf(stderr, "***ERROR***: should have passed\n");
147: errors++;
148: }
149: }
150: tests += i;
151: fprintf(stderr, "\nAddress PASS test for CPU:\n");
152: if (!BreakAddr_Command(addr_pass, use_dsp)) {
153: fprintf(stderr, "***ERROR***: should have passed\n");
154: errors++;
155: }
156: tests += 1;
157:
158: fprintf(stderr, "-----------------\n\n");
159: BreakCond_Command(CMD_LIST, use_dsp);
160: fprintf(stderr, "\n");
161: BreakCond_Command(CMD_REMOVE_ALL, use_dsp);
162: BreakCond_Command(CMD_LIST, use_dsp);
163: fprintf(stderr, "-----------------\n");
164:
165: /* add conditions */
166: fprintf(stderr, "\nLast one(s) should match, first one(s) shouldn't:\n");
167: for (i = 0; (test = match_tests[i]); i++) {
168: fprintf(stderr, "-----------------\n- parsing '%s'\n", test);
169: if (!BreakCond_Command(test, use_dsp)) {
170: fprintf(stderr, "***ERROR***: should have passed\n");
171: errors++;
172: }
173: }
174: tests += i;
175: BreakCond_Command(CMD_LIST, use_dsp);
176: fprintf(stderr, "\n");
177:
178: /* set up registers etc */
179:
180: /* fail indirect equality checks with zerod regs */
181: memset(STRam, 0, sizeof(STRam));
182: STRam[0] = 1;
183: /* !match: "( $200 ) > 200"
184: * match: "( $200 ) . w > ( 200 ) . b"
185: */
186: STRam[0x200] = 100;
187: STRam[200] = 0x20;
188: /* match: "d0 = d1" */
189: SetCpuRegister("d0", 4);
190: SetCpuRegister("d1", 4);
191: /* !match: "pc < $50000 && pc > $60000"
192: * !match: "pc < $50000 && pc > $54000"
193: * match: "pc > $50000 && pc < $60000"
194: */
195: regs.pc = 0x58000;
196: /* !match: "d0 = a0"
197: * match: "pc = a0"
198: */
199: SetCpuRegister("a0", 0x58000);
200:
201: /* check matches */
202: while ((i = BreakCond_MatchCpu())) {
203: fprintf(stderr, "Removing matching CPU breakpoint %d...\n", i);
204: for (j = 0; (test = match_tests[j]); j++) {
205: if (BreakCond_MatchCpuExpression(i, test)) {
206: break;
207: }
208: }
209: if (test) {
210: if (j < FAILING_BC_TEST_MATCHES) {
211: fprintf(stderr, "ERROR: breakpoint should not have matched!\n");
212: errors++;
213: }
214: } else {
215: fprintf(stderr, "WARNING: canonized breakpoint form didn't match\n");
216: errors++;
217: }
218: testidx[0] = '0' + i;
219: BreakCond_Command(testidx, use_dsp); /* remove given */
220: }
221: remaining_matches = BreakCond_BreakPointCount(use_dsp);
222: if (remaining_matches != FAILING_BC_TEST_MATCHES) {
223: fprintf(stderr, "ERROR: wrong number of breakpoints left (%d instead of %d)!\n",
224: remaining_matches, FAILING_BC_TEST_MATCHES);
225: errors++;
226: }
227:
228: fprintf(stderr, "\nOther breakpoints didn't match, removing the rest...\n");
229: BreakCond_Command(CMD_REMOVE_ALL, use_dsp);
230: BreakCond_Command(CMD_LIST, use_dsp);
231: fprintf(stderr, "-----------------\n");
232:
233: /* ...last parse cmd line args as DSP breakpoints */
234: if (argc > 1) {
235: use_dsp = true;
236: fprintf(stderr, "\nCommand line DSP breakpoints:\n");
237: for (argv++; --argc > 0; argv++) {
238: fprintf(stderr, "-----------------\n- parsing '%s'\n", *argv);
239: BreakCond_Command(*argv, use_dsp);
240: }
241: fprintf(stderr, "-----------------\n\n");
242: BreakCond_Command("", use_dsp); /* list */
243:
244: while ((i = BreakCond_MatchDsp())) {
245: fprintf(stderr, "Removing matching DSP breakpoint.\n");
246: testidx[0] = '0' + i;
247: BreakCond_Command(testidx, use_dsp); /* remove given */
248: }
249:
250: BreakCond_Command(CMD_REMOVE_ALL, use_dsp);
251: BreakCond_Command(CMD_LIST, use_dsp);
252: fprintf(stderr, "-----------------\n");
253: }
254: if (errors) {
255: fprintf(stderr, "\n***Detected %d ERRORs in %d automated tests!***\n\n",
256: errors, tests);
257: } else {
258: fprintf(stderr, "\nFinished without any errors!\n\n");
259: }
260: return errors;
261: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.