From: Toni Wilen Date: Sat, 28 Sep 2019 07:18:55 +0000 (+0300) Subject: More detailed error output, now also includes source, destination and stack contents... X-Git-Tag: 4300~100 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=ee199ca13e85a4818b9be40262d233b73ee2ccea;p=francis%2Fwinuae.git More detailed error output, now also includes source, destination and stack contents (before and after if changed) depending on tested instruction. --- diff --git a/cputest.cpp b/cputest.cpp index 5d53b26a..fd08746b 100644 --- a/cputest.cpp +++ b/cputest.cpp @@ -1225,7 +1225,7 @@ static void save_data(uae_u8 *dst, const TCHAR *dir) } if (filecount == 0) { uae_u8 data[4]; - pl(data, 0x00000002); + pl(data, DATA_VERSION); fwrite(data, 1, 4, f); pl(data, (uae_u32)starttime); fwrite(data, 1, 4, f); @@ -1255,7 +1255,7 @@ static void save_data(uae_u8 *dst, const TCHAR *dir) save_data(dst, dir); } else { uae_u8 data[4]; - pl(data, 0x00000002); + pl(data, DATA_VERSION); fwrite(data, 1, 4, f); pl(data, (uae_u32)starttime); fwrite(data, 1, 4, f); @@ -2315,6 +2315,11 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi } regs.sr = feature_min_interrupt_mask << 8; + uae_u32 srcaddr_old = 0xffffffff; + uae_u32 dstaddr_old = 0xffffffff; + uae_u32 srcaddr = 0xffffffff; + uae_u32 dstaddr = 0xffffffff; + for (int opcode = 0; opcode < 65536; opcode++) { struct instr *dp = table68k + opcode; @@ -2488,7 +2493,6 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi TCHAR out[256]; - uaecptr srcaddr, dstaddr; memset(out, 0, sizeof(out)); // disassemble and output generated instruction for (int i = 0; i < MAX_REGISTERS; i++) { @@ -2498,6 +2502,8 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi regs.fp[i].fpx = cur_fpuregisters[i]; } uaecptr nextpc; + srcaddr = 0xffffffff; + dstaddr = 0xffffffff; m68k_disasm_2(out, sizeof(out) / sizeof(TCHAR), opcode_memory_start, &nextpc, 1, &srcaddr, &dstaddr, 0xffffffff, 0); if (verbose) { my_trim(out); @@ -2556,6 +2562,15 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi testing_active = 0; } + if (srcaddr != srcaddr_old) { + dst = store_reg(dst, CT_SRCADDR, srcaddr_old, srcaddr, -1); + srcaddr_old = srcaddr; + } + if (dstaddr != dstaddr_old) { + dst = store_reg(dst, CT_DSTADDR, dstaddr_old, dstaddr, -1); + dstaddr_old = dstaddr; + } + *dst++ = CT_END_INIT; int exception_array[256] = { 0 }; diff --git a/cputest/cputest_defines.h b/cputest/cputest_defines.h index 9f332d90..d1a1d68e 100644 --- a/cputest/cputest_defines.h +++ b/cputest/cputest_defines.h @@ -1,4 +1,6 @@ +#define DATA_VERSION 3 + #define CT_FPREG 0 #define CT_DREG 0 #define CT_AREG 8 @@ -9,6 +11,8 @@ #define CT_FPIAR 20 #define CT_FPSR 21 #define CT_FPCR 22 +#define CT_SRCADDR 28 +#define CT_DSTADDR 29 #define CT_MEMWRITE 30 #define CT_MEMWRITES 31 #define CT_DATA_MASK 31 diff --git a/cputest/main.c b/cputest/main.c index 9b2315bf..e4c80548 100644 --- a/cputest/main.c +++ b/cputest/main.c @@ -45,6 +45,7 @@ struct registers uae_u32 excframe; struct fpureg fpuregs[8]; uae_u32 fpiar, fpcr, fpsr; + uae_u32 srcaddr, dstaddr; }; static struct registers test_regs; @@ -59,7 +60,7 @@ static int high_memory_size; static uae_u32 test_low_memory_start, test_low_memory_end; static uae_u32 test_high_memory_start, test_high_memory_end; static uae_u8 *test_memory; -static uae_u32 test_memory_addr; +static uae_u32 test_memory_addr, test_memory_end; static uae_u32 test_memory_size; static uae_u8 *test_data; static int test_data_size; @@ -106,6 +107,12 @@ static uae_u8 ccr_mask; static uae_u32 addressing_mask = 0x00ffffff; static uae_u32 interrupt_mask; +#define SIZE_STORED_ADDRESS 20 +static uae_u8 srcaddr[SIZE_STORED_ADDRESS]; +static uae_u8 dstaddr[SIZE_STORED_ADDRESS]; +static uae_u8 stackaddr[SIZE_STORED_ADDRESS]; +static uae_u32 stackaddr_ptr; + #ifndef M68K #define xmemcpy memcpy @@ -670,7 +677,13 @@ static uae_u8 *restore_data(uae_u8 *p) exit(0); } int mode = v & CT_DATA_MASK; - if (mode < CT_AREG + 8) { + if (mode == CT_SRCADDR) { + int size; + p = restore_value(p, ®s.srcaddr, &size); + } else if (mode == CT_DSTADDR) { + int size; + p = restore_value(p, ®s.dstaddr, &size); + } else if (mode < CT_AREG + 8) { int size; if ((v & CT_SIZE_MASK) == CT_SIZE_FPU) { p = restore_fpvalue(p, ®s.fpuregs[mode]); @@ -703,9 +716,48 @@ static uae_u8 *restore_data(uae_u8 *p) return p; } -static uae_u16 test_ccrignoremask; +static uae_u16 test_sr, test_ccrignoremask; static uae_u32 test_fpsr, test_fpcr; + +static int is_valid_test_addr(uae_u32 a) +{ + return (a >= test_low_memory_start && a < test_low_memory_end && test_low_memory_start != 0xffffffff) || + (a >= test_high_memory_start && a < test_high_memory_end && test_high_memory_start != 0xffffffff) || + (a >= test_memory_addr && a < test_memory_end); +} + +static int addr_diff(uae_u8 *ap, uae_u8 *bp, int size) +{ + for (int i = 0; i < size; i++) { + if (is_valid_test_addr((uae_u32)bp)) { + if (*ap != *bp) + return 1; + } + ap++; + bp++; + } + return 0; +} + +static void addinfo_bytes(char *name, uae_u8 *src, uae_u32 address, int offset, int len) +{ + sprintf(outbp, "%s: %08lx ", name, address); + outbp += strlen(outbp); + int cnt = 0; + while (len-- > 0) { + if (offset == 0) + *outbp++ = '*'; + else if (cnt > 0) + *outbp++ = '.'; + sprintf(outbp, "%02x", src[cnt]); + outbp += 2; + offset++; + cnt++; + } + *outbp++ = '\n'; +} + extern uae_u16 disasm_instr(uae_u16 *, char *); static void addinfo(void) @@ -732,6 +784,7 @@ static void addinfo(void) int offset = 0; int lines = 0; while (lines++ < 10) { + tmpbuffer[0] = 0; int v = disasm_instr(code + offset, tmpbuffer); for (int i = 0; i < v; i++) { uae_u16 v = (p[i * 2 + 0] << 8) | (p[i * 2 + 1]); @@ -754,8 +807,27 @@ static void addinfo(void) if (v < 0) break; } - *outbp++ = '\n'; *outbp = 0; + if (code[0] == 0x4e73 || code[0] == 0x4e74 || code[0] == 0x4e75) { + addinfo_bytes("SA", stackaddr, stackaddr_ptr, -SIZE_STORED_ADDRESS / 2, SIZE_STORED_ADDRESS); + addinfo_bytes(" ", (uae_u8 *)stackaddr_ptr - SIZE_STORED_ADDRESS / 2, stackaddr_ptr, -SIZE_STORED_ADDRESS / 2, SIZE_STORED_ADDRESS); + } + if (regs.srcaddr != 0xffffffff) { + uae_u8 *a = srcaddr; + uae_u8 *b = (uae_u8 *)regs.srcaddr - SIZE_STORED_ADDRESS / 2; + addinfo_bytes("SA", a, regs.srcaddr, -SIZE_STORED_ADDRESS / 2, SIZE_STORED_ADDRESS); + if (addr_diff(a, b, SIZE_STORED_ADDRESS)) { + addinfo_bytes(" ", b, regs.srcaddr, -SIZE_STORED_ADDRESS / 2, SIZE_STORED_ADDRESS); + } + } + if (regs.dstaddr != 0xffffffff) { + uae_u8 *a = dstaddr; + uae_u8 *b = (uae_u8*)regs.dstaddr - SIZE_STORED_ADDRESS / 2; + addinfo_bytes("DA", a, regs.dstaddr, -SIZE_STORED_ADDRESS / 2, SIZE_STORED_ADDRESS); + if (addr_diff(a, b, SIZE_STORED_ADDRESS)) { + addinfo_bytes(" ", b, regs.dstaddr, -SIZE_STORED_ADDRESS / 2, SIZE_STORED_ADDRESS); + } + } #if 0 int Disass68k(long addr, char *labelBuffer, char *opcodeBuffer, char *operandBuffer, char *commentBuffer); @@ -788,24 +860,56 @@ static const struct srbit srbits[] = { static void out_regs(struct registers *r, int before) { - for (int i = 0; i < 16; i++) { - if (i > 0 && (i % 4) == 0) { - strcat(outbp, "\n"); - } else if ((i % 8) != 0) { - strcat(outbp, " "); + if (before) { + for (int i = 0; i < 16; i++) { + if (i > 0 && (i % 4) == 0) { + strcat(outbp, "\n"); + } else if ((i % 8) != 0) { + strcat(outbp, " "); + } + outbp += strlen(outbp); + sprintf(outbp, "%c%d:%c%08lx", i < 8 ? 'D' : 'A', i & 7, test_regs.regs[i] != regs.regs[i] ? '*' : ' ', r->regs[i]); + outbp += strlen(outbp); + } + *outbp++ = '\n'; + } else { + // output only lines that have at least one modified register to save screen space + int outdone = 0; + for (int i = 0; i < 4; i++) { + int diff = 0; + for (int j = 0; j < 4; j++) { + int idx = i * 4 + j; + if (test_regs.regs[idx] != regs.regs[idx]) { + diff = 1; + outdone = 1; + } + } + if (diff) { + for (int j = 0; j < 4; j++) { + int idx = i * 4 + j; + if (j > 0) + *outbp++ = ' '; + sprintf(outbp, "%c%d:%c%08lx", idx < 8 ? 'D' : 'A', idx & 7, test_regs.regs[idx] != regs.regs[idx] ? '*' : ' ', r->regs[idx]); + outbp += strlen(outbp); + } + } + } + if (outdone) { + *outbp++ = '\n'; } - outbp += strlen(outbp); - sprintf(outbp, "%c%d:%c%08lx", i < 8 ? 'D' : 'A', i & 7, test_regs.regs[i] != regs.regs[i] ? '*' : ' ', r->regs[i]); - outbp += strlen(outbp); } - strcat(outbp, "\n"); outbp += strlen(outbp); - sprintf(outbp, "SR:%c%04x PC: %08lx ISP: %08lx MSP: %08lx\n", - test_regs.sr != last_registers.sr ? '*' : ' ', before ? regs.sr : test_regs.sr, - r->pc, r->ssp, r->msp); + sprintf(outbp, "SR:%c%04x PC: %08lx ISP: %08lx", test_sr != last_registers.sr ? '*' : ' ', before ? test_sr : test_regs.sr, r->pc, r->ssp); + outbp += strlen(outbp); + if (cpu_lvl >= 2 && cpu_lvl <= 4) { + sprintf(outbp, " MSP: %08lx\n", r->msp); + outbp += strlen(outbp); + } + *outbp++ = '\n'; + outbp += strlen(outbp); if (before >= 0) { - uae_u16 s = before ? regs.sr : test_regs.sr; // current value + uae_u16 s = before ? test_sr : test_regs.sr; // current value uae_u16 s1 = regs.sr; // original value uae_u16 s2 = test_regs.sr; // test result value uae_u16 s3 = last_registers.sr; // expected result value @@ -1111,7 +1215,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr) if ((val & (sr_undefined_mask & test_ccrignoremask)) != (test_regs.sr & (sr_undefined_mask & test_ccrignoremask)) && !ignore_errors && !ignore_sr) { addinfo(); if (dooutput) { - sprintf(outbp, "SR: expected %04x -> %04x but got %04x (%04x)\n", regs.sr & 0xffff, val & 0xffff, test_regs.sr & 0xffff, test_ccrignoremask); + sprintf(outbp, "SR: expected %04x -> %04x but got %04x (%04x)\n", test_sr & 0xffff, val & 0xffff, test_regs.sr & 0xffff, test_ccrignoremask); outbp += strlen(outbp); } errors++; @@ -1216,7 +1320,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr) } } else { end_test(); - printf("Unknown test data %02x\n", v); + printf("Unknown test data %02x mode %d\n", v, mode); exit(0); } } @@ -1310,6 +1414,20 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr) return p; } +static void store_addr(uae_u32 s, uae_u8 *d) +{ + if (s == 0xffffffff) + return; + for (int i = -SIZE_STORED_ADDRESS / 2; i < SIZE_STORED_ADDRESS / 2; i++) { + uae_u32 ss = s + i; + if (is_valid_test_addr(ss)) { + *d++ = *((uae_u8 *)ss); + } else { + *d++ = 0; + } + } +} + static void process_test(uae_u8 *p) { outbp = outbuffer; @@ -1319,6 +1437,8 @@ static void process_test(uae_u8 *p) memset(®s, 0, sizeof(struct registers)); regs.sr = interrupt_mask << 8; + regs.srcaddr = 0xffffffff; + regs.dstaddr = 0xffffffff; start_test(); @@ -1341,6 +1461,9 @@ static void process_test(uae_u8 *p) break; p++; + store_addr(regs.srcaddr, srcaddr); + store_addr(regs.srcaddr, dstaddr); + xmemcpy(&last_registers, ®s, sizeof(struct registers)); int fpumode = fpu_model && (opcode_memory[0] & 0xf0) == 0xf0; @@ -1354,6 +1477,7 @@ static void process_test(uae_u8 *p) uae_u32 last_pc = opcode_memory_addr; uae_u32 last_fpiar = opcode_memory_addr; + int old_super = -1; for (;;) { uae_u16 sr_mask = 0; @@ -1389,7 +1513,7 @@ static void process_test(uae_u8 *p) test_regs.sr = (ccr ? 31 : 0); } test_regs.sr |= sr_mask | (interrupt_mask << 8); - uae_u32 test_sr = test_regs.sr; + test_sr = test_regs.sr; if (fpumode) { if (flag_mode == 0) { test_regs.fpsr = (ccr & 15) << 24; @@ -1401,7 +1525,13 @@ static void process_test(uae_u8 *p) test_fpsr = test_regs.fpsr; test_fpcr = test_regs.fpcr; } + int super = (test_regs.sr & 0x2000) != 0; + if (super != old_super) { + stackaddr_ptr = super ? regs.ssp : regs.regs[15]; + store_addr(stackaddr_ptr, stackaddr); + old_super = super; + } if ((*p) == CT_END_SKIP) { @@ -1519,7 +1649,7 @@ static int test_mnemo(const char *path, const char *opcode) int header_size = 32; fread(data, 1, 4, f); v = gl(data); - if (v != 0x00000002) { + if (v != DATA_VERSION) { printf("Invalid test data file (header)\n"); exit(0); } @@ -1532,6 +1662,7 @@ static int test_mnemo(const char *path, const char *opcode) test_memory_addr = gl(data); fread(data, 1, 4, f); test_memory_size = gl(data); + test_memory_end = test_memory_addr + test_memory_size; fread(data, 1, 4, f); opcode_memory_addr = gl(data) + test_memory_addr; fread(data, 1, 4, f); @@ -1620,7 +1751,7 @@ static int test_mnemo(const char *path, const char *opcode) if (!f) break; fread(data, 1, 4, f); - if (gl(data) != 0x00000002) { + if (gl(data) != DATA_VERSION) { printf("Invalid test data file (header)\n"); exit(0); } diff --git a/cputest/readme.txt b/cputest/readme.txt index 0a05ca44..b4404794 100644 --- a/cputest/readme.txt +++ b/cputest/readme.txt @@ -55,7 +55,7 @@ Not implemented or only partially implemented: 68010+: -- MOVEC: Only MOVEC to An/Dn is tested and read value is ignored. Basically only verifies if correct and only correct CPU model specific control registers exist. +- MOVEC: Most control registers tested: Write all ones, write all zeros, read it back, restore original value. 68040+ TC/TT registers enable bit is always zero. - RTE: long frames with undefined fields are skipped. Basic frame types 0 and 2 are verified, also unsupported frame types are tested, error is reported if CPU does not generate frame exception. - 68020+ undefined addressing mode bit combinations are not tested. diff --git a/disasm.cpp b/disasm.cpp index ecf6810c..d083f012 100644 --- a/disasm.cpp +++ b/disasm.cpp @@ -1591,7 +1591,7 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn int segid, lastsegid; TCHAR *symbolpos; - seaddr2 = deaddr2 = 0; + seaddr2 = deaddr2 = 0xffffffff; oldpc = pc; opcode = get_word_debug (pc); extra = get_word_debug (pc + 2);