|
|
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: /* missing options file */ ! 79: "pc>pc :file no-such-file", ! 80: /* size and mask mismatches with numbers */ ! 81: "d0.w = $ffff0", ! 82: "(a0).b & 3 < 100", ! 83: /* more than BC_MAX_CONDITIONS_PER_BREAKPOINT conditions */ ! 84: "1=1 && 2=2 && 3=3 && 4=4 && 5=5", ! 85: NULL ! 86: }; ! 87: const char *parser_pass[] = { ! 88: /* comparisons with normal numbers + indrect addressing */ ! 89: " ($200).w > 200 ", ! 90: " ($200).w < 200 ", ! 91: " (200).w = $200 ", ! 92: " (200).w ! $200 ", ! 93: /* indirect addressing with registers */ ! 94: "(a0)=(d0)", ! 95: "(d0).w=(a0).b", ! 96: /* sizes + multiple conditions + spacing */ ! 97: "(a0).w&3=(d0)&&d0=1", ! 98: " ( a 0 ) . w & 1 = ( d 0 ) & 1 && d 0 = 3 ", ! 99: "a0=1 && (d0)&2=(a0).w && ($00ff00).w&1=1", ! 100: " ($ff820a).b = 2", ! 101: /* variables */ ! 102: "hbl > 0 && vbl < 2000 && linecycles = 508", ! 103: /* options */ ! 104: "($200).w ! ($200).w :trace", ! 105: "($200).w > ($200).w :4 :lock", ! 106: "pc>pc :file data/test.ini :once", ! 107: NULL ! 108: }; ! 109: /* address breakpoint + expression evalution with register */ ! 110: char addr_pass[] = "pc + ($200*16/2 & 0xffff)"; ! 111: ! 112: const char *match_tests[] = { ! 113: "a0 = d0", ! 114: "( $200 ) . b > 200", /* byte access to avoid endianess */ ! 115: "pc < $50000 && pc > $60000", ! 116: "pc > $50000 && pc < $54000", ! 117: #define FAILING_BC_TEST_MATCHES 4 ! 118: "pc > $50000 && pc < $60000", ! 119: "( $200 ) . b > ( 200 ) . b", ! 120: "d0 = d1", ! 121: "a0 = pc", ! 122: NULL ! 123: }; ! 124: const char *test; ! 125: char testidx[2] = "1"; ! 126: int i, j, tests = 0, errors = 0; ! 127: int remaining_matches; ! 128: bool use_dsp; ! 129: ! 130: /* first automated tests... */ ! 131: use_dsp = false; ! 132: fprintf(stderr, "\nShould FAIL for CPU:\n"); ! 133: for (i = 0; (test = parser_fail[i]); i++) { ! 134: fprintf(stderr, "-----------------\n- parsing '%s'\n", test); ! 135: if (BreakCond_Command(test, use_dsp)) { ! 136: fprintf(stderr, "***ERROR***: should have failed\n"); ! 137: errors++; ! 138: } ! 139: } ! 140: tests += i; ! 141: fprintf(stderr, "-----------------\n\n"); ! 142: BreakCond_Command(CMD_LIST, use_dsp); ! 143: ! 144: fprintf(stderr, "\nShould PASS for CPU:\n"); ! 145: for (i = 0; (test = parser_pass[i]); i++) { ! 146: fprintf(stderr, "-----------------\n- parsing '%s'\n", test); ! 147: if (!BreakCond_Command(test, use_dsp)) { ! 148: fprintf(stderr, "***ERROR***: should have passed\n"); ! 149: errors++; ! 150: } ! 151: } ! 152: tests += i; ! 153: fprintf(stderr, "\nAddress PASS test for CPU:\n"); ! 154: if (!BreakAddr_Command(addr_pass, use_dsp)) { ! 155: fprintf(stderr, "***ERROR***: should have passed\n"); ! 156: errors++; ! 157: } ! 158: tests += 1; ! 159: ! 160: fprintf(stderr, "-----------------\n\n"); ! 161: BreakCond_Command(CMD_LIST, use_dsp); ! 162: fprintf(stderr, "\n"); ! 163: BreakCond_Command(CMD_REMOVE_ALL, use_dsp); ! 164: BreakCond_Command(CMD_LIST, use_dsp); ! 165: fprintf(stderr, "-----------------\n"); ! 166: ! 167: /* add conditions */ ! 168: fprintf(stderr, "\nLast one(s) should match, first one(s) shouldn't:\n"); ! 169: for (i = 0; (test = match_tests[i]); i++) { ! 170: fprintf(stderr, "-----------------\n- parsing '%s'\n", test); ! 171: if (!BreakCond_Command(test, use_dsp)) { ! 172: fprintf(stderr, "***ERROR***: should have passed\n"); ! 173: errors++; ! 174: } ! 175: } ! 176: tests += i; ! 177: BreakCond_Command(CMD_LIST, use_dsp); ! 178: fprintf(stderr, "\n"); ! 179: ! 180: /* set up registers etc */ ! 181: ! 182: /* fail indirect equality checks with zerod regs */ ! 183: memset(STRam, 0, sizeof(STRam)); ! 184: STRam[0] = 1; ! 185: /* !match: "( $200 ) > 200" ! 186: * match: "( $200 ) . w > ( 200 ) . b" ! 187: */ ! 188: STRam[0x200] = 100; ! 189: STRam[200] = 0x20; ! 190: /* match: "d0 = d1" */ ! 191: SetCpuRegister("d0", 4); ! 192: SetCpuRegister("d1", 4); ! 193: /* !match: "pc < $50000 && pc > $60000" ! 194: * !match: "pc < $50000 && pc > $54000" ! 195: * match: "pc > $50000 && pc < $60000" ! 196: */ ! 197: regs.pc = 0x58000; ! 198: /* !match: "d0 = a0" ! 199: * match: "pc = a0" ! 200: */ ! 201: SetCpuRegister("a0", 0x58000); ! 202: ! 203: /* check matches */ ! 204: while ((i = BreakCond_MatchCpu())) { ! 205: fprintf(stderr, "Removing matching CPU breakpoint %d...\n", i); ! 206: for (j = 0; (test = match_tests[j]); j++) { ! 207: if (BreakCond_MatchCpuExpression(i, test)) { ! 208: break; ! 209: } ! 210: } ! 211: if (test) { ! 212: if (j < FAILING_BC_TEST_MATCHES) { ! 213: fprintf(stderr, "ERROR: breakpoint should not have matched!\n"); ! 214: errors++; ! 215: } ! 216: } else { ! 217: fprintf(stderr, "WARNING: canonized breakpoint form didn't match\n"); ! 218: errors++; ! 219: } ! 220: testidx[0] = '0' + i; ! 221: BreakCond_Command(testidx, use_dsp); /* remove given */ ! 222: } ! 223: remaining_matches = BreakCond_BreakPointCount(use_dsp); ! 224: if (remaining_matches != FAILING_BC_TEST_MATCHES) { ! 225: fprintf(stderr, "ERROR: wrong number of breakpoints left (%d instead of %d)!\n", ! 226: remaining_matches, FAILING_BC_TEST_MATCHES); ! 227: errors++; ! 228: } ! 229: ! 230: fprintf(stderr, "\nOther breakpoints didn't match, removing the rest...\n"); ! 231: BreakCond_Command(CMD_REMOVE_ALL, use_dsp); ! 232: BreakCond_Command(CMD_LIST, use_dsp); ! 233: fprintf(stderr, "-----------------\n"); ! 234: ! 235: /* ...last parse cmd line args as DSP breakpoints */ ! 236: if (argc > 1) { ! 237: use_dsp = true; ! 238: fprintf(stderr, "\nCommand line DSP breakpoints:\n"); ! 239: for (argv++; --argc > 0; argv++) { ! 240: fprintf(stderr, "-----------------\n- parsing '%s'\n", *argv); ! 241: BreakCond_Command(*argv, use_dsp); ! 242: } ! 243: fprintf(stderr, "-----------------\n\n"); ! 244: BreakCond_Command("", use_dsp); /* list */ ! 245: ! 246: while ((i = BreakCond_MatchDsp())) { ! 247: fprintf(stderr, "Removing matching DSP breakpoint.\n"); ! 248: testidx[0] = '0' + i; ! 249: BreakCond_Command(testidx, use_dsp); /* remove given */ ! 250: } ! 251: ! 252: BreakCond_Command(CMD_REMOVE_ALL, use_dsp); ! 253: BreakCond_Command(CMD_LIST, use_dsp); ! 254: fprintf(stderr, "-----------------\n"); ! 255: } ! 256: if (errors) { ! 257: fprintf(stderr, "\n***Detected %d ERRORs in %d automated tests!***\n\n", ! 258: errors, tests); ! 259: } else { ! 260: fprintf(stderr, "\nFinished without any errors!\n\n"); ! 261: } ! 262: return errors; ! 263: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.