]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
CPU tester updates.
authorToni Wilen <twilen@winuae.net>
Wed, 14 Aug 2019 18:15:02 +0000 (21:15 +0300)
committerToni Wilen <twilen@winuae.net>
Wed, 14 Aug 2019 18:15:02 +0000 (21:15 +0300)
cputest.cpp
cputest/main.c

index a90002f5f84c7256e79b0c876940eef17ae7d97d..2f8eb85c433a6b1bde7bd57de034decca69df61e 100644 (file)
@@ -97,6 +97,7 @@ static int exception_stack_frame_size;
 static uaecptr test_exception_addr;
 static int test_exception_3_inst;
 static int test_exception_3_w;
+static int test_exception_opcode;
 static uae_u8 imm8_cnt;
 static uae_u16 imm16_cnt;
 static uae_u32 imm32_cnt;
@@ -667,13 +668,21 @@ static void doexcstack(void)
        noaccesshistory = 1;
        testing_active = -1;
 
+       int opcode = (opcode_memory[0] << 8) | (opcode_memory[1]);
+       int statusormask = 0, statusandmask = 0;
+       if (test_exception_opcode >= 0) {
+               opcode = test_exception_opcode;
+               statusormask = (test_exception_opcode >> 16) & 0xff;
+               statusandmask = (test_exception_opcode >> 24) & 0xff;
+       }
+
        int sv = regs.s;
        uaecptr tmp = m68k_areg(regs, 7);
        m68k_areg(regs, 7) = test_memory_end + EXTRA_RESERVED_SPACE;
        if (cpu_lvl == 0) {
                if (test_exception == 3) {
-                       uae_u16 opcode = (opcode_memory[0] << 8) | (opcode_memory[1]);
-                       uae_u16 mode = (sv ? 4 : 0) | (test_exception_3_inst ? 2 : 1);
+                       uae_u16 mode = (sv ? 4 : 0) | (test_exception_3_inst ? 2 : 1) | statusormask;
+                       mode &= ~statusandmask;
                        mode |= test_exception_3_w ? 0 : 16;
                        Exception_build_68000_address_error_stack_frame(mode, opcode, test_exception_addr, regs.pc);
                }
@@ -738,14 +747,18 @@ void exception3_read(uae_u32 opcode, uae_u32 addr)
 {
        test_exception = 3;
        test_exception_3_inst = 0;
+       test_exception_3_w = 0;
        test_exception_addr = addr;
+       test_exception_opcode = opcode;
        doexcstack();
 }
 void exception3_write(uae_u32 opcode, uae_u32 addr)
 {
        test_exception = 3;
        test_exception_3_inst = 0;
+       test_exception_3_w = 1;
        test_exception_addr = addr;
+       test_exception_opcode = opcode;
        doexcstack();
 }
 void REGPARAM2 Exception(int n)
@@ -753,6 +766,7 @@ void REGPARAM2 Exception(int n)
        test_exception = n;
        test_exception_3_inst = 0;
        test_exception_addr = m68k_getpci();
+       test_exception_opcode = -1;
        doexcstack();
 }
 void REGPARAM2 Exception_cpu(int n)
@@ -760,6 +774,7 @@ void REGPARAM2 Exception_cpu(int n)
        test_exception = n;
        test_exception_3_inst = 0;
        test_exception_addr = m68k_getpci();
+       test_exception_opcode = -1;
 
        bool t0 = currprefs.cpu_model >= 68020 && regs.t0;
        // check T0 trace
@@ -774,6 +789,7 @@ void exception3i(uae_u32 opcode, uaecptr addr)
        test_exception_3_inst = 1;
        test_exception_3_w = 0;
        test_exception_addr = addr;
+       test_exception_opcode = opcode;
        doexcstack();
 }
 void exception3b(uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc)
@@ -782,6 +798,7 @@ void exception3b(uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc)
        test_exception_3_inst = i;
        test_exception_3_w = w;
        test_exception_addr = addr;
+       test_exception_opcode = opcode;
        doexcstack();
 }
 
@@ -1484,17 +1501,6 @@ static int handle_specials_pack(uae_u16 opcode, uaecptr pc, struct instr *dp, in
 
 static void handle_specials_extra(uae_u16 opcode, uaecptr pc, struct instr *dp)
 {
-       // if MOVES to A7: change it to MOVES from A7. SSP modification would cause crash.
-       if (dp->mnemo == i_MOVES) {
-               uae_u16 extra = get_word_test(opcode_memory_start + 2);
-               if (!(extra & 0x800)) {
-                       int reg = extra >> 12;
-                       if (reg == 7 + 8) {
-                               extra |= 0x800;
-                               put_word_test(opcode_memory_start + 2, extra);
-                       }
-               }
-       }
        // cas undocumented (marked as zero in document) fields do something weird, for example
        // setting bit 9 will make "Du" address register but results are not correct.
        // so lets make sure unused zero bits are zeroed.
@@ -1624,8 +1630,16 @@ static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc)
                        do_trace();
 
                regs.instruction_pc = regs.pc;
+               uaecptr a7 = regs.regs[15];
+               int s = regs.s;
+
                (*cpufunctbl[opc])(opc);
 
+               // supervisor mode and A7 was modified: skip this test round.
+               if (s && regs.regs[15] != a7) {
+                       test_exception = -1;
+               }
+
                if (!test_exception) {
                        if (SPCFLAG_DOTRACE)
                                Exception(9);
@@ -1709,7 +1723,6 @@ static int is_test_trace(struct instr *dp)
        {
        case i_STOP:
        case i_MV2SR:
-       case i_MVSR2:
                return 1;
        }
        return 0;
@@ -1745,7 +1758,11 @@ static uae_u8 *save_exception(uae_u8 *p, struct instr *dp)
        // SR and PC was already saved with non-exception data
        if (cpu_lvl == 0) {
                if (test_exception == 3) {
+                       // status
                        *p++ = sf[1];
+                       // opcode (which is not necessarily current opcode!)
+                       *p++ = sf[6];
+                       *p++ = sf[7];
                        // access address
                        p = store_rel(p, 0, opcode_memory_start, gl(sf + 2), 1);
                }
@@ -2039,7 +2056,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, int opcodesize, in
 
                                        if (opc == 0xf228)
                                                printf("");
-                                       if (subtest_count == 3136)
+                                       if (subtest_count == 1537)
                                                printf("");
 
 
@@ -2305,7 +2322,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, int opcodesize, in
                                                        if (regs.sr & 0x2000)
                                                                prev_s_cnt++;
 
-                                                       if (subtest_count == 928)
+                                                       if (subtest_count == 1536)
                                                                printf("");
 
                                                        execute_ins(opc, pc - 2, branch_target);
@@ -2326,6 +2343,9 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, int opcodesize, in
                                                                // instruction accessed memory out of test address space bounds
                                                                skipped = 1;
                                                                did_out_of_bounds = true;
+                                                       } else if (test_exception < 0) {
+                                                               // something happened that requires test skip
+                                                               skipped = 1;
                                                        } else if (test_exception) {
                                                                // generated exception
                                                                exception_array[test_exception]++;
@@ -2615,7 +2635,7 @@ int __cdecl main(int argc, char *argv[])
 
        struct ini_data *ini = ini_load(_T("cputestgen.ini"), false);
        if (!ini) {
-               wprintf(_T("couldn't open cputestgen.ini"));
+               wprintf(_T("Couldn't open cputestgen.ini"));
                return 0;
        }
 
@@ -2793,28 +2813,32 @@ int __cdecl main(int argc, char *argv[])
 
        fill_memory();
 
-       TCHAR *lmem_rom_name = NULL;
-       ini_getstring(ini, INISECTION, _T("low_rom"), &lmem_rom_name);
-       if (lmem_rom_name && test_low_memory_start != 0xffffffff) {
-               if (load_file(NULL, lmem_rom_name, low_memory_temp, low_memory_size, 0)) {
-                       wprintf(_T("Low test memory ROM loaded\n"));
-                       lmem_rom = 1;
+       if (test_low_memory_start != 0xffffffff) {
+               TCHAR *lmem_rom_name = NULL;
+               ini_getstring(ini, INISECTION, _T("low_rom"), &lmem_rom_name);
+               if (lmem_rom_name) {
+                       if (load_file(NULL, lmem_rom_name, low_memory_temp, low_memory_size, 0)) {
+                               wprintf(_T("Low test memory ROM loaded\n"));
+                               lmem_rom = 1;
+                       }
                }
+               free(lmem_rom_name);
+               save_memory(path, _T("lmem.dat"), low_memory_temp, low_memory_size);
        }
-       free(lmem_rom_name);
 
-       TCHAR *hmem_rom_name = NULL;
-       ini_getstring(ini, INISECTION, _T("high_rom"), &hmem_rom_name);
-       if (hmem_rom_name && test_high_memory_start != 0xffffffff) {
-               if (load_file(NULL, hmem_rom_name, high_memory_temp, high_memory_size, -1)) {
-                       wprintf(_T("High test memory ROM loaded\n"));
-                       hmem_rom = 1;
+       if (test_high_memory_start != 0xffffffff) {
+               TCHAR *hmem_rom_name = NULL;
+               ini_getstring(ini, INISECTION, _T("high_rom"), &hmem_rom_name);
+               if (hmem_rom_name) {
+                       if (load_file(NULL, hmem_rom_name, high_memory_temp, high_memory_size, -1)) {
+                               wprintf(_T("High test memory ROM loaded\n"));
+                               hmem_rom = 1;
+                       }
                }
+               free(hmem_rom_name);
+               save_memory(path, _T("hmem.dat"), high_memory_temp, high_memory_size);
        }
-       free(hmem_rom_name);
 
-       save_memory(path, _T("lmem.dat"), low_memory_temp, low_memory_size);
-       save_memory(path, _T("hmem.dat"), high_memory_temp, high_memory_size);
        save_memory(path, _T("tmem.dat"), test_memory_temp, test_memory_size);
 
        storage_buffer = (uae_u8 *)calloc(max_storage_buffer, 1);
index f338f7f51d97ffd8002badbfc7d3af277730e51b..4a256cf46e626fd9467d60d29053b0a4d8471a02 100644 (file)
@@ -267,14 +267,17 @@ static void end_test(void)
        touser(enable_data);
 }
 
-static uae_u8 *load_file(const char *path, const char *file, uae_u8 *p, int *sizep)
+static uae_u8 *load_file(const char *path, const char *file, uae_u8 *p, int *sizep, int exiterror)
 {
        char fname[256];
        sprintf(fname, "%s%s", path, file);
        FILE *f = fopen(fname, "rb");
        if (!f) {
-               printf("Couldn't open '%s'\n", fname);
-               exit(0);
+               if (exiterror) {
+                       printf("Couldn't open '%s'\n", fname);
+                       exit(0);
+               }
+               return NULL; 
        }
        int size = *sizep;
        if (size < 0) {
@@ -681,9 +684,6 @@ static uae_u8 *restore_data(uae_u8 *p)
        return p;
 }
 
-int    Disass68k(long addr, char *labelBuffer, char *opcodeBuffer, char *operandBuffer, char *commentBuffer);
-void Disasm_SetCPUType(int CPU, int FPU);
-
 static uae_u16 test_sr, test_ccrignoremask;
 static uae_u32 test_fpsr, test_fpcr;
 
@@ -722,6 +722,8 @@ static void addinfo(void)
        *outbp = 0;
 
 #if 0
+int    Disass68k(long addr, char *labelBuffer, char *opcodeBuffer, char *operandBuffer, char *commentBuffer);
+void Disasm_SetCPUType(int CPU, int FPU);
        Disasm_SetCPUType(0, 0);
        char buf1[80], buf2[80], buf3[80], buf4[80];
        Disass68k((long)opcode_memory, buf1, buf2, buf3, buf4);
@@ -764,16 +766,18 @@ static void out_regs(struct registers *r, int before)
        outbp += strlen(outbp);
        sprintf(outbp, "SR:%c%04x   PC: %08lx ISP: %08lx MSP: %08lx\n", test_regs.sr != test_sr ? '*' : ' ', before ? test_sr : r->sr, r->pc, r->ssp, r->msp);
        outbp += strlen(outbp);
-       uae_u16 s = before ? test_sr : r->sr;
-       uae_u16 s1 = test_regs.sr;
-       uae_u16 s2 = test_sr;
-       uae_u16 s3 = before ? s1 : last_registers.sr;
-       for (int i = 0; srbits[i].name; i++) {
-               if (i > 0)
-                       *outbp++ = ' ';
-               uae_u16 mask = 1 << srbits[i].bit;
-               sprintf(outbp, "%s%c%d", srbits[i].name, (s3 & mask) != (s1 & mask) ? '!' : ((s1 & mask) != (s2 & mask) ? '*' : '='), (s & mask) != 0);
-               outbp += strlen(outbp);
+       if (before >= 0) {
+               uae_u16 s = before ? test_sr : r->sr;
+               uae_u16 s1 = test_regs.sr;
+               uae_u16 s2 = test_sr;
+               uae_u16 s3 = before ? s1 : last_registers.sr;
+               for (int i = 0; srbits[i].name; i++) {
+                       if (i > 0)
+                               *outbp++ = ' ';
+                       uae_u16 mask = 1 << srbits[i].bit;
+                       sprintf(outbp, "%s%c%d", srbits[i].name, (s3 & mask) != (s1 & mask) ? '!' : ((s1 & mask) != (s2 & mask) ? '*' : '='), (s & mask) != 0);
+                       outbp += strlen(outbp);
+               }
        }
 
        if (!fpu_model) {
@@ -823,7 +827,7 @@ static void hexdump(uae_u8 *p, int len)
 static uae_u8 last_exception[256];
 static int last_exception_len;
 
-static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum)
+static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum, int sameexc)
 {
        int exclen = 0;
        uae_u8 *exc;
@@ -840,15 +844,18 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum)
                if (cpu_lvl == 0) {
                        if (excnum == 3) {
                                // status (with undocumented opcode part)
-                               exc[0] = opcode_memory[0];
-                               exc[1] = (opcode_memory[1] & 0xf0) | (*p++);
+                               uae_u8 opcode0 = p[1];
+                               uae_u8 opcode1 = p[2];
+                               exc[0] = opcode0;
+                               exc[1] = (opcode1 & ~0x1f) | p[0];
+                               p += 3;
                                // access address
                                v = opcode_memory_addr;
                                p = restore_rel_ordered(p, &v);
                                pl(exc + 2, v);
                                // opcode
-                               exc[6] = opcode_memory[0];
-                               exc[7] = opcode_memory[1];
+                               exc[6] = opcode0;
+                               exc[7] = opcode1;
                                // sr
                                exc[8] = regs->sr >> 8;
                                exc[9] = regs->sr;
@@ -914,7 +921,7 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum)
        } else {
                exclen = last_exception_len;
        }
-       if (exclen == 0)
+       if (exclen == 0 || !sameexc)
                return p;
        if (memcmp(exc, sp, exclen)) {
                strcpy(outbp, "Exception stack frame mismatch:\n");
@@ -987,8 +994,12 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                endinfo();
                                exit(0);
                        }
-                       if (ignore_errors)
+                       if (ignore_errors) {
+                               if (exc) {
+                                       p = validate_exception(&test_regs, p, exc, exc == cpuexc);
+                               }
                                break;
+                       }
                        if (exc == 0 && cpuexc == 4) {
                                // successful complete generates exception 4 with matching PC
                                if (last_registers.pc != test_regs.pc && dooutput) {
@@ -999,7 +1010,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                break;
                        }
                        if (exc) {
-                               p = validate_exception(&test_regs, p, exc);
+                               p = validate_exception(&test_regs, p, exc, exc == cpuexc);
                        }
                        if (exc != cpuexc) {
                                addinfo();
@@ -1052,10 +1063,11 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                        // High 16 bit: ignore mask, low 16 bit: SR/CCR
                        p = restore_value(p, &val, &size);
                        test_ccrignoremask = ~(val >> 16);
-                       if ((val & (sr_undefined_mask | test_ccrignoremask)) != (test_regs.sr & (sr_undefined_mask | test_ccrignoremask)) && !ignore_errors && !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\n", test_sr, val & 0xffff, test_regs.sr & 0xffff);
+                                       sprintf(outbp, "SR: expected %04x -> %04x but got %04x (%04x)\n", test_sr, val & 0xffff, test_regs.sr & 0xffff, test_ccrignoremask);
                                        outbp += strlen(outbp);
                                }
                                errors++;
@@ -1375,7 +1387,7 @@ static void process_test(uae_u8 *p)
 
                                if (testexit()) {
                                        end_test();
-                                       printf("\nAborted\n");
+                                       printf("\nAborted (%ld)\n", testcnt);
                                        exit(0);
                                }
 
@@ -1465,6 +1477,15 @@ static int test_mnemo(const char *path, const char *opcode)
                sr_undefined_mask = 0xffff;
        }
 
+       if (lmem_rom >= 0 && (low_memory_size <= 0 || !low_memory_temp)) {
+               printf("lmem.dat required but it was not loaded or was missing.\n");
+               return 0;
+       }
+       if (hmem_rom >= 0 && (high_memory_size <= 0 || !high_memory_temp)) {
+               printf("hmem.dat required but it was not loaded or was missing.\n");
+               return 0;
+       }
+
        if (!absallocated) {
                test_memory = allocate_absolute(test_memory_addr, test_memory_size);
                if (!test_memory) {
@@ -1481,7 +1502,7 @@ static int test_mnemo(const char *path, const char *opcode)
        opcode_memory = test_memory + (opcode_memory_addr - test_memory_addr);
 
        size = test_memory_size;
-       load_file(path, "tmem.dat", test_memory, &size);
+       load_file(path, "tmem.dat", test_memory, &size, 1);
        if (size != test_memory_size) {
                printf("tmem.dat size mismatch\n");
                exit(0);
@@ -1505,8 +1526,8 @@ static int test_mnemo(const char *path, const char *opcode)
                }
                fread(data, 1, 4, f);
                if (gl(data) != starttimeid) {
-                       printf("Test data file header mismatch\n");
-                       exit(0);
+                       printf("Test data file header mismatch (old test data file?)\n");
+                       goto next;
                }
                fseek(f, 0, SEEK_END);
                test_data_size = ftell(f);
@@ -1535,6 +1556,7 @@ static int test_mnemo(const char *path, const char *opcode)
                        break;
 
                free(test_data);
+next:
                filecnt++;
        }
 
@@ -1618,33 +1640,28 @@ int main(int argc, char *argv[])
                } else if (!_stricmp(s, "ccrmask")) {
                        ccr_mask = 0;
                        if (next) {
-                               ccr_mask = getparamval(next);
+                               ccr_mask = ~getparamval(next);
                                i++;
                        }
                }
        }
 
        low_memory_size = -1;
-       low_memory_temp = load_file(path, "lmem.dat", NULL, &low_memory_size);
+       low_memory_temp = load_file(path, "lmem.dat", NULL, &low_memory_size, 0);
        high_memory_size = -1;
-       high_memory_temp = load_file(path, "hmem.dat", NULL, &high_memory_size);
-
-       if (low_memory_size < 0 || !low_memory_temp) {
-               printf("Couldn't allocate low memory\n");
-               return 0;
-       }
-       if (high_memory_size < 0 || !high_memory_temp) {
-               printf("Couldn't allocate low memory\n");
-               return 0;
-       }
+       high_memory_temp = load_file(path, "hmem.dat", NULL, &high_memory_size, 0);
 
 #ifndef M68K
-       low_memory = calloc(1, low_memory_size);
-       high_memory = calloc(1, high_memory_size);
+       if (low_memory_size > 0)
+               low_memory = calloc(1, low_memory_size);
+       if (high_memory_size > 0)
+               high_memory = calloc(1, high_memory_size);
 #endif
 
-       low_memory_back = calloc(1, low_memory_size);
-       high_memory_back = calloc(1, high_memory_size);
+       if (low_memory_size > 0)
+               low_memory_back = calloc(1, low_memory_size);
+       if (high_memory_size > 0)
+               high_memory_back = calloc(1, high_memory_size);
 
        if (!_stricmp(opcode, "all")) {
                DIR *d = opendir(path);