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