]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
cputester IPL timing test support updates
authorToni Wilen <twilen@winuae.net>
Sun, 17 Apr 2022 15:07:47 +0000 (18:07 +0300)
committerToni Wilen <twilen@winuae.net>
Sun, 17 Apr 2022 15:07:47 +0000 (18:07 +0300)
cputest.cpp
cputest/cputestgen.ini
cputest/main.c

index ed113d580427fd5cdfc06d7d3d6dd628c40cf5c6..547516bfe94c8ef5404242f9e4a64f9e2f6100bb 100644 (file)
@@ -374,6 +374,7 @@ static void count_interrupt_cycles(int cycles)
        interrupt_cycle_cnt -= cycles;
        if (interrupt_cycle_cnt <= 0) {
                regs.ipl_pin = 1;
+               interrupt_level = 1;
                interrupt_cycle_cnt = 0;
        }
 }
@@ -1474,6 +1475,9 @@ void REGPARAM2 Exception(int n)
        test_exception_addr = m68k_getpci();
        test_exception_opcode = -1;
        doexcstack();
+       if (n >= 24 && n < 24 + 8) {
+               cpu_stopped = 0;
+       }
 }
 void REGPARAM2 Exception_cpu_oldpc(int n, uaecptr oldpc)
 {
@@ -3898,7 +3902,7 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool
        uae_u16 opc = regs.ir;
        uae_u16 opw1 = (opcode_memory[2] << 8) | (opcode_memory[3] << 0);
        uae_u16 opw2 = (opcode_memory[4] << 8) | (opcode_memory[5] << 0);
-       if (opc == 0xf208
+       if (opc == 0x4e72
                && opw1 == 0xa000
                //&& opw2 == 0x4afc
                )
@@ -3974,7 +3978,7 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool
                        abort();
                }
 
-               if (SPCFLAG_TRACE) {
+               if (SPCFLAG_TRACE && !cpu_stopped) {
                        do_trace();
                }
 
@@ -3995,7 +3999,17 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool
                        }
                }
 
-               (*cpufunctbl[opc])(opc);
+               if (cpu_stopped) {
+                       if (!interrupt_cycle_cnt) {
+                               test_exception = -1;
+                               break;
+                       }
+                       do_cycles_test(2);
+                       ipl_fetch();
+                       do_cycles_test(2);
+               } else {
+                       (*cpufunctbl[opc])(opc);
+               }
 
                if (fpumode) {
                        // skip result has too large or small exponent
@@ -4023,9 +4037,12 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool
                }
 
 
-               // Test did one or more out of bounds memory accesses
-               // or CPU stopped or was reset: skip
-               if (out_of_test_space || cpu_stopped) {
+               // One or more out of bounds memory accesses: skip
+               if (out_of_test_space) {
+                       break;
+               }
+               // CPU stopped or was reset: skip
+               if (cpu_stopped && feature_interrupts != 2) {
                        break;
                }
 
@@ -4060,18 +4077,21 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool
                }
 
                if (feature_interrupts == 2) {
-                       if (regs.ipl > regs.intmask) {
+                       if (!test_exception && regs.ipl > regs.intmask) {
+                               if (cpu_stopped) {
+                                       do_cycles_test(4);
+                               }
                                Exception(24 + regs.ipl);
                                break;
                        }
                } else {
-                       if (regs.ipl_pin > regs.intmask) {
+                       if (!test_exception && regs.ipl_pin > regs.intmask) {
                                Exception(24 + regs.ipl_pin);
                                break;
                        }
                }
 
-               if (regs.pc == endpc || regs.pc == targetpc) {
+               if ((regs.pc == endpc || regs.pc == targetpc) && !cpu_stopped) {
                        // Trace is only added as an exception if there was no other exceptions
                        // Trace stacked with other exception is handled later
                        if (SPCFLAG_DOTRACE && !test_exception && trace_store_pc == 0xffffffffff) {
@@ -4130,7 +4150,10 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool
 
        if (feature_interrupts == 2) {
                // IPL test must cause some exception
-               if (!test_exception) {
+               if (!test_exception || test_exception == 8) {
+                       test_exception = -1;
+               }
+               if (cpu_stopped) {
                        test_exception = -1;
                }
                // Interrupt start must be before test instruction,
@@ -4801,18 +4824,30 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                startpc = opcode_memory_address;
                                        }
 
-                                       // interrupt timing test mode
+                                       // interrupt IPL timing test mode
                                        if (feature_interrupts == 2) {
                                                pc -= 2;
-                                               // moveq #x,d0 (4)
-                                               put_word_test(pc + 0, 0x7000 | interrupt_delay_cnt);
-                                               // move.b d0,0xdcfffc (RTCW) (8 + 4 + 4)
-                                               put_word_test(pc + 2, 0x13c0);
-                                               put_long_test(pc + 4, IPL_TRIGGER_ADDR);
+                                               // save CCR
+                                               if (cpu_lvl == 0) {
+                                                       // move sr,d7
+                                                       put_word_test(pc + 0, 0x40c7); // 4 cycles
+                                               } else {
+                                                       // move ccr,d7
+                                                       put_word_test(pc + 0, 0x42c7); // 4 cycles
+                                               }
+                                               // moveq #x,d0 (4 cycles)
+                                               put_word_test(pc + 2, 0x7000 | interrupt_delay_cnt);
+                                               // move.b d0,0xdc0000 (RTCW) (8 + 4 + 4)
+                                               put_word_test(pc + 4, 0x13c0);
+                                               put_long_test(pc + 6, IPL_TRIGGER_ADDR);
                                                // ror.l d0,d0 (4 + 4 + d0 * 2 cycles)
-                                               put_word_test(pc + 8, 0xe0b8);
-                                               put_word_test(pc + 10, NOP_OPCODE); // (4 cycles)
-                                               pc += 12;
+                                               put_word_test(pc + 10, 0xe0b8);
+                                               // restore CCR
+                                               // move d7,ccr
+                                               put_word_test(pc + 12, 0x44c7); // 12 cycles
+                                               put_word_test(pc + 14, NOP_OPCODE); // 4 cycles
+                                               put_word_test(pc + 16, NOP_OPCODE); // 4 cycles
+                                               pc += 18;
                                                opcode_memory_address = pc;
                                                pc += 2;
                                        }
@@ -5128,7 +5163,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                if (dstaddr != 0xffffffff && srcaddr != dstaddr) {
                                                        outbytes(_T("D"), dstaddr);
                                                }
-                                               if (feature_loop_mode_jit || feature_loop_mode_68010) { // || feature_interrupts == 2) {
+                                               if (feature_loop_mode_jit || feature_loop_mode_68010 || verbose >= 3) {
                                                        wprintf(_T("\n"));
                                                        nextpc = opcode_memory_start;
                                                        for (int i = 0; i < 20; i++) {
@@ -5550,7 +5585,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                        if (regs.sr & 0x2000)
                                                                prev_s_cnt++;
 
-                                                       if (subtest_count == 20609)
+                                                       if (subtest_count == 433)
                                                                printf("");
 
                                                        // execute test instruction(s)
@@ -5936,8 +5971,10 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                }
                dst = storage_buffer;
 
-               if (opcodecnt == 1 && target_address == 0xffffffff && target_opcode_address == 0xffffffff && target_usp_address == 0xffffffff && subtest_count >= feature_test_rounds_opcode)
+               if (feature_interrupts != 2 && opcodecnt == 1 && target_address == 0xffffffff &&
+                       target_opcode_address == 0xffffffff && target_usp_address == 0xffffffff && subtest_count >= feature_test_rounds_opcode)
                        break;
+
                if (lookup->mnemo == i_ILLG || fpuopcode == FPUOPP_ILLEGAL)
                        break;
 
@@ -5977,6 +6014,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                        } else {
                                nextround = true;
                                rounds = 1;
+                               quick = 0;
                        }
                }
 
index 4d193156dd18d78e05f3e3346fc5d719b3799140..9e3755d875963f1e97c77729d8a6108c41cc8087 100644 (file)
@@ -148,8 +148,8 @@ feature_min_interrupt_mask=0
 ; Uses serial port to generate timing interrupt. Requires serial port TX connected to RX.
 ; Generates multiple extra tests.
 ; Used delay instruction: ROL.L D0,D0 (D0 = number of CPU clocks * 2)
-; All test rounds that generate interrupt immediately after test instuction has been executed are stored.
-; Amiga only
+; All test rounds that generate interrupt immediately before or immediately after test instuction
+; has been executed are stored. Amiga only.
 feature_interrupts=0
 
 ; SR extra mask.
index 28f0dd86103eb685ce702d180fd9ef430cb64a86..bc60e243d50036d8b97aebc4907d0ff67c52be00 100644 (file)
@@ -145,7 +145,8 @@ static short skipregchange;
 static short skipccrchange;
 static short askifmissing;
 static short nextall;
-static int exitcnt, irqcnt;
+static short exitmode;
+static int exitcnt, exitcnt2, irqcnt;
 static short cycles, cycles_range, cycles_adjust;
 static short gotcycles;
 static short interrupttest;
@@ -2125,10 +2126,10 @@ static int get_cycles_amiga(void)
        }
 
        // hpos 0-1: vertical count hasn't been increased yet
-       if (hstart <= 1) {
+       if (hstart <= 0) {
                vstart++;
        }
-       if (hend <= 1) {
+       if (hend <= 0) {
                vend++;
        }
 
@@ -2502,12 +2503,15 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr, st
                                if (dooutput) {
                                        if (cpuexc == 4 && lregs->pc + opcodeendsizeextra == tregs->pc) {
                                                sprintf(outbp, "Exception: expected %d but got no exception.\n", exc);
+                                               outbp += strlen(outbp);
                                        } else if (cpuexc == 4) {
                                                sprintf(outbp, "Exception: expected %d but got %d (or no exception)\n", exc, cpuexc);
+                                               outbp += strlen(outbp);
                                        } else {
                                                int excsize;
                                                uae_u8 *excp;
                                                sprintf(outbp, "Exception: expected %d but got %d\n", exc, cpuexc);
+                                               outbp += strlen(outbp);
                                                excp = get_exceptionframe(&test_regs, cpuexc, &excsize);
                                                if (excp && excsize) {
                                                        hexdump(excp, excsize, 1);
@@ -2515,7 +2519,6 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr, st
                                        }
                                        experr = 1;
                                }
-                               outbp += strlen(outbp);
                                errflag |= 1 << 16;
                        }
                        break;
@@ -2871,7 +2874,7 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr, st
                errflag = 0;
        }
 
-       if (exitcnt == 0 && !errflag) {
+       if (exitcnt == 0 && !exitmode && !errflag) {
                errflag = 1;
        }
 
@@ -3222,6 +3225,9 @@ static void process_test(uae_u8 *p)
 
                                if (exitcnt >= 0) {
                                        exitcnt--;
+                                       if (!exitcnt && exitmode) {
+                                               goto end;
+                                       }
                                }
 
                                if ((*p) == CT_END_SKIP) {
@@ -3370,6 +3376,9 @@ end:
                        printf("%s", outbuffer);
                }
        }
+       if (exitcnt == 0 && exitmode) {
+               printf("Exit count expired\n");
+       }
 }
 
 static void freestuff(void)
@@ -3533,6 +3542,7 @@ static int test_mnemo(const char *opcode)
        fpu_approxcnt = 0;
        memset(exceptioncount, 0, sizeof(exceptioncount));
        supercnt = 0;
+       exitcnt = exitcnt2;
 
        uae_u8 *test_data_prealloc = NULL;
 
@@ -3598,7 +3608,7 @@ static int test_mnemo(const char *opcode)
                }
                test_data = NULL;
 
-               if (errors || quit || last) {
+               if (errors || quit || last || (!exitcnt && exitmode)) {
                        break;
                }
 
@@ -3610,7 +3620,7 @@ static int test_mnemo(const char *opcode)
                out_endinfo();
                printf("%s", outbuffer);
        }
-       if (exitcnt == 0) {
+       if (exitcnt == 0 && !exitmode) {
                printf("Exit count expired\n");
        }
        if (!errors && !quit) {
@@ -3707,6 +3717,7 @@ int main(int argc, char *argv[])
                printf("-skipreg = do not validate registers.\n");
                printf("-askifmissing = ask for new path if dat file is missing.\n");
                printf("-exit n = exit after n tests.\n");
+               printf("-exitok n = exit after n tests, continue normally.\n");
                printf("-fpuadj <exp> 16-bit exponent range value. (16383 = 1.0)\n");
                printf("-fpsrmask = ignore FPSR bits that are not set.\n");
                printf("-cycles [range adjust] = check cycle counts.\n");
@@ -3724,7 +3735,8 @@ int main(int argc, char *argv[])
        ccr_mask = 0xff;
        fpsr_ignore_mask = 0xffffffff;
        disasm = 1;
-       exitcnt = -1;
+       exitcnt2 = -1;
+       exitmode = 0;
        cyclecounter_addr = 0xffffffff;
        cycles_range = 2;
        fpu_adjust_exp = -1;
@@ -3786,7 +3798,14 @@ int main(int argc, char *argv[])
                        nextall = 1;
                } else if (!_stricmp(s, "-exit")) {
                        if (next) {
-                               exitcnt = atoi(next);
+                               exitcnt2 = atoi(next);
+                               exitmode = 0;
+                               i++;
+                       }
+               } else if (!_stricmp(s, "-exitok")) {
+                       if (next) {
+                               exitcnt2 = atoi(next);
+                               exitmode = 1;
                                i++;
                        }
                } else if (!_stricmp(s, "-irqcnt")) {
@@ -3926,7 +3945,7 @@ int main(int argc, char *argv[])
                        }
                }
 
-               if (!_stricmp(opcode, "all")) {
+               if (!_stricmp(opcode, "all") || (opcode[0] && opcode[strlen(opcode) - 1] == '*')) {
                        DIR *d = opendir(path);
                        if (!d) {
                                printf("Couldn't list directory '%s'\n", path);
@@ -3940,6 +3959,7 @@ int main(int argc, char *argv[])
                        if (!dirs)
                                return 0;
 
+                       // get directory
                        for (;;) {
                                struct dirent *dr = readdir(d);
                                if (!dr)
@@ -3947,6 +3967,7 @@ int main(int argc, char *argv[])
                                int d = isdir(path, dr->d_name);
                                if (d && dr->d_name[0] != '.') {
                                        strcpy(dirs + diroff, dr->d_name);
+                                       printf("%s\n", dr->d_name);
                                        dircnt++;
                                        diroff += MAX_FILE_LEN;
                                        if (dircnt >= MAX_FILES) {
@@ -3957,6 +3978,7 @@ int main(int argc, char *argv[])
                        }
                        closedir(d);
 
+                       // sort directory
                        for (int i = 0; i < diroff; i += MAX_FILE_LEN) {
                                for (int j = i + MAX_FILE_LEN; j < diroff; j += MAX_FILE_LEN) {
                                        if (_stricmp(dirs + i, dirs + j) > 0) {
@@ -3985,42 +4007,32 @@ int main(int argc, char *argv[])
                        if (nextall) {
                                first += MAX_FILE_LEN;
                        }
+
                        int err = 0;
-                       for (int i = first; i < diroff; i += MAX_FILE_LEN) {
-                               if (test_mnemo(dirs + i)) {
-                                       err = 1;
-                                       if (stop_on_error)
-                                               break;
+                       if (!_stricmp(opcode, "all")) {
+                               for (int i = first; i < diroff; i += MAX_FILE_LEN) {
+                                       if (test_mnemo(dirs + i)) {
+                                               err = 1;
+                                               if (stop_on_error)
+                                                       break;
+                                       }
                                }
-                       }
-
-                       free(dirs);
-
-                       if (err && stop_on_error)
-                               break;
-
-               } else if (opcode[0] && opcode[strlen(opcode) - 1] == '*') {
-                       DIR *d = opendir(path);
-                       if (!d) {
-                               printf("Couldn't list directory '%s'\n", path);
-                               return 0;
-                       }
-                       for (;;) {
-                               struct dirent *dr = readdir(d);
-                               if (!dr)
-                                       break;
-                               if (!strnicmp(dr->d_name, opcode, strlen(opcode) - 1)) {
-                                       int d = isdir(path, dr->d_name);
-                                       if (d) {
-                                               if (test_mnemo(dr->d_name)) {
+                       } else {
+                               for (int i = first; i < diroff; i += MAX_FILE_LEN) {
+                                       char *name = dirs + i;
+                                       if (!strnicmp(name, opcode, strlen(opcode) - 1)) {
+                                               if (test_mnemo(name)) {
                                                        if (stop_on_error)
                                                                break;
                                                }
                                        }
                                }
                        }
-                       closedir(d);
 
+                       free(dirs);
+
+                       if (err && stop_on_error)
+                               break;
 
                } else {
                        if (test_mnemo(opcode)) {