|
|
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.