]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
68000/010 odd exception vector address error emulation and tester support.
authorToni Wilen <twilen@winuae.net>
Mon, 6 Jan 2020 12:54:02 +0000 (14:54 +0200)
committerToni Wilen <twilen@winuae.net>
Mon, 6 Jan 2020 12:54:02 +0000 (14:54 +0200)
cputest.cpp
cputest/cputest_defines.h
cputest/cputestgen.ini
cputest/main.c
gencpu.cpp
newcpu.cpp

index 0027b52225c8c1076c9f5b12b3a33ed0beacd5f9..399e58e21d3375ef3c65c048ce78048d84d1e933 100644 (file)
@@ -67,6 +67,7 @@ static int feature_full_extension_format = 0;
 static int feature_test_rounds = 2;
 static int feature_flag_mode = 0;
 static int feature_usp = 0;
+static int feature_exception_vectors = 0;
 static TCHAR *feature_instruction_size = NULL;
 static uae_u32 feature_addressing_modes[2];
 static int ad8r[2], pc8r[2];
@@ -117,6 +118,8 @@ static int forced_immediate_mode;
 static int test_exception;
 static int test_exception_extra;
 static int exception_stack_frame_size;
+static uae_u8 exception_extra_frame[100];
+static int exception_extra_frame_size;
 static uaecptr test_exception_addr;
 static int test_exception_3_w;
 static int test_exception_3_fc;
@@ -811,7 +814,7 @@ void cpureset(void)
        cpu_halted = -1;
 }
 
-static void doexcstack(void)
+static void doexcstack2(void)
 {
        // generate exception but don't store it with test results
 
@@ -877,6 +880,59 @@ static void doexcstack(void)
        noaccesshistory = noac;
 }
 
+static void doexcstack(void)
+{
+       bool changed = false;
+       doexcstack2();
+       if (cpu_lvl >= 2)
+               return;
+       if (test_exception < 4)
+               return;
+
+       int original_exception = test_exception;
+       int opcode = (opcode_memory[0] << 8) | (opcode_memory[1]);
+       if (opcode == 0x419f)
+               printf("");
+
+       // did we got bus error or address error
+       // when fetching exception vector?
+       // (bus error not yet tested)
+       if (regs.vbr & 1) {
+               test_exception = 3;
+               changed = true;
+       } else if (feature_exception_vectors & 1) {
+               test_exception = 3;
+               test_exception_addr = feature_exception_vectors;
+               changed = true;
+       }
+       if (!changed)
+               return;
+
+       // store original exception stack (which may not be complete)
+       uae_u8 *sf = test_memory + test_memory_size + EXTRA_RESERVED_SPACE - exception_stack_frame_size;
+       exception_extra_frame_size = exception_stack_frame_size;
+       memcpy(exception_extra_frame, sf, exception_extra_frame_size);
+
+       MakeSR();
+       regs.sr |= 0x2000;
+       regs.sr &= ~0x8000;
+       MakeFromSR();
+
+       int flags = 0;
+       if (cpu_lvl == 1) {
+               // IF = 1
+               flags |= 0x40000;
+               // low word of address
+               regs.irc = (uae_u16)test_exception_addr;
+               // low word of address
+               regs.read_buffer = regs.irc;
+               // vector offset (not vbr + offset)
+               regs.write_buffer = original_exception * 4;
+       }
+
+       exception3_read(regs.ir | flags, test_exception_addr, 1, 2);
+}
+
 uae_u32 REGPARAM2 op_illg_1(uae_u32 opcode)
 {
        if ((opcode & 0xf000) == 0xf000) {
@@ -1431,6 +1487,21 @@ static bool load_file(const TCHAR *path, const TCHAR *file, uae_u8 *p, int size,
        return true;
 }
 
+static void markfile(const TCHAR *dir)
+{
+       TCHAR path[1000];
+       if (filecount <= 1)
+               return;
+       _stprintf(path, _T("%s/%04d.dat"), dir, filecount - 1);
+       FILE *f = _tfopen(path, _T("r+b"));
+       if (f) {
+               fseek(f, -1, SEEK_END);
+               uae_u8 b = CT_END_FINISH;
+               fwrite(&b, 1, 1, f);
+               fclose(f);
+       }
+}
+
 static void save_data(uae_u8 *dst, const TCHAR *dir)
 {
        TCHAR path[1000];
@@ -1485,7 +1556,16 @@ static void save_data(uae_u8 *dst, const TCHAR *dir)
                fwrite(data, 1, 4, f);
                pl(data, super_stack_memory);
                fwrite(data, 1, 4, f);
+               pl(data, feature_exception_vectors);
+               fwrite(data, 1, 4, f);
+               data[0] = data[1] = data[2] = data[3] = 0;
+               fwrite(data, 1, 4, f);
+               fwrite(data, 1, 4, f);
+               fwrite(data, 1, 4, f);
                fwrite(inst_name, 1, sizeof(inst_name) - 1, f);
+               data[0] = CT_END_FINISH;
+               data[1] = 0;
+               fwrite(data, 1, 2, f);
                fclose(f);
                filecount++;
                save_data(dst, dir);
@@ -1499,6 +1579,7 @@ static void save_data(uae_u8 *dst, const TCHAR *dir)
                fwrite(data, 1, 4, f);
                fwrite(data, 1, 4, f);
                *dst++ = CT_END_FINISH;
+               *dst++ = filecount;
                fwrite(storage_buffer, 1, dst - storage_buffer, f);
                fclose(f);
                filecount++;
@@ -2547,6 +2628,7 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp)
        read_buffer_prev = regs.ir;
        regs.read_buffer = regs.irc;
        regs.write_buffer = 0xf00d;
+       exception_extra_frame_size = 0;
 
        int cnt = (feature_loop_mode + 1) * 2;
        if (multi_mode)
@@ -3806,6 +3888,9 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                                if (feature_usp == 2) {
                                                                        skipped = 1;
                                                                }
+                                                               if (feature_exception_vectors) {
+                                                                       skipped = 1;
+                                                               }
                                                        }
 
                                                        if (cpu_stopped) {
@@ -3833,10 +3918,10 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                                }
                                                                // got exception 3 but didn't want them?
                                                                if (test_exception == 3) {
-                                                                       if ((feature_usp != 1 && feature_usp != 2) && !feature_exception3_data && !(test_exception_3_fc & 2)) {
+                                                                       if ((feature_usp != 1 && feature_usp != 2) && !feature_exception3_data && !(test_exception_3_fc & 2) && !feature_exception_vectors) {
                                                                                skipped = 1;
                                                                        }
-                                                                       if ((feature_usp != 1 && feature_usp != 2) && !feature_exception3_instruction && (test_exception_3_fc & 2)) {
+                                                                       if ((feature_usp != 1 && feature_usp != 2) && !feature_exception3_instruction && (test_exception_3_fc & 2) && !feature_exception_vectors) {
                                                                                skipped = 1;
                                                                        }
                                                                }
@@ -4129,6 +4214,8 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                }
        }
 
+       markfile(dir);
+
        wprintf(_T("- %d tests\n"), subtest_count);
 }
 
@@ -4427,6 +4514,8 @@ int __cdecl main(int argc, char *argv[])
        ini_getval(ini, INISECTION, _T("feature_flags_mode"), &feature_flag_mode);
        feature_usp = 0;
        ini_getval(ini, INISECTION, _T("feature_usp"), &feature_usp);
+       feature_exception_vectors = 0;
+       ini_getval(ini, INISECTION, _T("feature_exception_vectors"), &feature_exception_vectors);
 
        feature_full_extension_format = 0;
        if (currprefs.cpu_model >= 68020) {
index 037dddd7284ef717baa4cf006c28ac28d59f0cb2..9677bb27c71eef172170d01afe70775af5b14667 100644 (file)
@@ -1,5 +1,5 @@
 
-#define DATA_VERSION 13
+#define DATA_VERSION 14
 
 #define CT_FPREG 0
 #define CT_DREG 0
index 97ef082daf7173a27c02dd32605c09390acd0492..b5fc18b22ccee2c06c77f6234e508a61b6ba6539 100644 (file)
@@ -61,6 +61,7 @@ feature_exception3_instruction=0
 ; Multiple values supported (max 8), separated by commas.
 ; Useful for bus error and address error testing
 ; Disables above exception3 modes.
+; If odd value and 68000/010: skip all tests that don't cause address error
 ; Supports 68000 addressing modes only.
 ; If instruction only has destination EA, source Areg, Dreg or immediate is generated.
 feature_target_src_ea=
@@ -85,6 +86,11 @@ feature_safe_memory_mode=R
 ; 3 = take stack from feature_target_opcode_offset
 feature_usp=0
 
+; exception vector bus error/address error test
+; 0: normal
+; non-zero: replace exception vectors with this value (except vectors 2 and 3)
+;feature_exception_vectors=0x0007321
+
 ; CCR/FPU status flags mode
 ; 0 = all combinations (32 CCR loops, 256 FPU loops)
 ; 1 = all zeros and all ones only (2 CCR loops, 32 FPU loops)
index c613cd3479f4aa1c91ee9d2c47dbfc1359508f97..66af492587048ba1ff1ef171fb1328a62928fe7e 100644 (file)
@@ -74,6 +74,7 @@ static uae_u8 *test_data;
 static uae_u8 *safe_memory_start, *safe_memory_end;
 static int safe_memory_mode;
 static uae_u32 user_stack_memory, super_stack_memory;
+static uae_u32 exception_vectors;
 static int test_data_size;
 static uae_u32 oldvbr;
 static uae_u8 *vbr_zero = 0;
@@ -366,12 +367,18 @@ static void start_test(void)
                uae_u32 *p = (uae_u32 *)vbr_zero;
                for (int i = 2; i < 12; i++) {
                        p[i] = (uae_u32)(((uae_u32)&exceptiontable000) + (i - 2) * 2);
+                       if (exception_vectors && i >= 4) {
+                               p[i] = exception_vectors;
+                       }
                        if (i < 12 + 2) {
                                error_vectors[i - 2] = p[i];
                        }
                }
                for (int i = 32; i < 48; i++) {
                        p[i] = (uae_u32)(((uae_u32)&exceptiontable000) + (i - 2) * 2);
+                       if (exception_vectors) {
+                               p[i] = exception_vectors;
+                       }
                }
                exceptiontableinuse = (uae_u32)&exceptiontable000;
        } else {
@@ -390,6 +397,9 @@ static void start_test(void)
                        if (i >= 2 && i < 12) {
                                error_vectors[i - 2] = vbr[i];
                        }
+                       if (exception_vectors && i >= 4) {
+                               vbr[i] = exception_vectors;
+                       }
                }
        }
        setcpu(cpu_lvl, cpustatearraynew, cpustatearraystore);
@@ -2287,6 +2297,10 @@ static int test_mnemo(const char *opcode)
        safe_memory_end = (uae_u8*)read_u32(headerfile, &headoffset);
        user_stack_memory = read_u32(headerfile, &headoffset);
        super_stack_memory = read_u32(headerfile, &headoffset);
+       exception_vectors = read_u32(headerfile, &headoffset);
+       read_u32(headerfile, &headoffset);
+       read_u32(headerfile, &headoffset);
+       read_u32(headerfile, &headoffset);
        memcpy(inst_name, headerfile + headoffset, sizeof(inst_name) - 1);
        inst_name[sizeof(inst_name) - 1] = 0;
        free(headerfile);
@@ -2378,6 +2392,7 @@ static int test_mnemo(const char *opcode)
                                        }
                                }
                        }
+                       quit = 1;
                        break;
                }
                if (gl(test_data) != DATA_VERSION) {
@@ -2388,11 +2403,15 @@ static int test_mnemo(const char *opcode)
                        printf("Test data file header mismatch (old test data file?)\n");
                        break;
                }
-               if (test_data[test_data_size - 1] != CT_END_FINISH) {
+               if (test_data[test_data_size - 2] != CT_END_FINISH) {
                        printf("Invalid test data file (footer)\n");
                        free(test_data);
                        exit(0);
                }
+
+               // last file?
+               int last = test_data[test_data_size - 1] == CT_END_FINISH;
+
                test_data_size -= 16;
                if (test_data_size <= 0)
                        break;
@@ -2403,7 +2422,7 @@ static int test_mnemo(const char *opcode)
 
                free(test_data);
 
-               if (errors || quit) {
+               if (errors || quit || last) {
                        break;
                }
 
@@ -2503,6 +2522,7 @@ int main(int argc, char *argv[])
                printf("ccrmask = ignore CCR bits that are not set.\n");
                printf("nodisasm = do not disassemble failed test.\n");
                printf("basicexc = do only basic checks when exception is 2 or 3.\n");
+               printf("askifmissing = ask for new path if dat file is missing.\n");
                return 0;
        }
 
index f786b8bb8e51720f8e42aba976801d4a9bb55eb8..435c1b90dca52c58bbfdfb89bea616d1981186a6 100644 (file)
@@ -6138,8 +6138,12 @@ static void gen_opcode (unsigned int opcode)
                break;
        case i_TRAPV:
                sync_m68k_pc();
+               // TRAPV is really weird
                // If V is set but prefetch causes bus error: S is set.
                // for some reason T is also cleared!
+               if (using_prefetch) {
+                       printf("\tuae_u16 opcode_v = opcode;\n");
+               }
                fill_prefetch_next_after(1,
                        "\t\tif (GET_VFLG()) {\n"
                        "\t\t\tMakeSR();\n"
@@ -6151,6 +6155,11 @@ static void gen_opcode (unsigned int opcode)
                        "\t\t\tif(regs.t1) opcode |= 0x10000;\n"
                        "\t\t}\n");
                printf("\tif (GET_VFLG()) {\n");
+               if (using_prefetch) {
+                       // If exception vector is odd,
+                       // stacked opcode is TRAPV
+                       printf("\t\tregs.ir = opcode_v;\n");
+               }
                printf("\t\tException_cpu(7);\n");
                write_return_cycles("\t\t", 0);
                printf("\t}\n");
index a3e816179ef8ac0bb6c37ce788cd025e074f4c22..ad316f2c163479786c2fa2c6ac058bbd3849c1b7 100644 (file)
@@ -2541,7 +2541,7 @@ static void Exception_ce000 (int nr)
                        exception_in_exception = -1;
                        frame_id = 8;
                        x_put_word(m68k_areg(regs, 7) + 0, ssw); // ssw
-                       x_put_long(m68k_areg(regs, 7) + 2, last_addr_for_exception_3); // fault addr
+                       x_put_long(m68k_areg(regs, 7) + 2, last_fault_for_exception_3); // fault addr
                        x_put_word(m68k_areg(regs, 7) + 6, 0); // unused
                        x_put_word(m68k_areg(regs, 7) + 8, regs.write_buffer); // data output buffer
                        x_put_word(m68k_areg(regs, 7) + 10, 0); // unused
@@ -2594,9 +2594,15 @@ kludge_me_do:
                        // if exception vector is odd:
                        // opcode is last opcode executed, address is address of exception vector
                        // pc is last prefetch address
-                       exception3b(regs.opcode, newpc, false, true, regs.vbr + 4 * vector_nr);
+                       regs.t1 = 0;
+                       MakeSR();
+                       m68k_setpc(regs.vbr + 4 * vector_nr);
+                       exception3_read(regs.ir | 0x40000, newpc, 1, 2);
                } else if (currprefs.cpu_model == 68010) {
-                       regs.write_buffer = regs.vbr + 4 * vector_nr;
+                       // offset, not vbr + offset
+                       regs.t1 = 0;
+                       MakeSR();
+                       regs.write_buffer = 4 * vector_nr;
                        regs.read_buffer = newpc;
                        regs.irc = regs.read_buffer;
                        exception3b(regs.opcode, newpc, false, true, newpc);
@@ -2973,7 +2979,7 @@ static void Exception_normal (int nr)
                                ssw |= last_writeaccess_for_exception_3 ? 0x0000 : 0x0100; // RW
                                if (last_op_for_exception_3 & 0x20000)
                                        ssw &= 0x00ff;
-                               regs.mmu_fault_addr = last_addr_for_exception_3;
+                               regs.mmu_fault_addr = last_fault_for_exception_3;
                                Exception_build_stack_frame(oldpc, currpc, ssw, nr, 0x08);
                                used_exception_build_stack_frame = true;
                        }
@@ -3029,12 +3035,17 @@ kludge_me_do:
                        return;
                }
                if (currprefs.cpu_model == 68000) {
-                       exception3b(regs.opcode, newpc, false, true, regs.vbr + 4 * vector_nr);
+                       regs.t1 = 0;
+                       MakeSR();
+                       m68k_setpc(regs.vbr + 4 * vector_nr);
+                       exception3_read(regs.ir | 0x40000, newpc, 1, 2);
                } else if (currprefs.cpu_model == 68010) {
-                       regs.write_buffer = regs.vbr + 4 * vector_nr;
+                       regs.t1 = 0;
+                       MakeSR();
+                       regs.write_buffer = 4 * vector_nr;
                        regs.read_buffer = newpc;
                        regs.irc = regs.read_buffer;
-                       exception3b(regs.opcode, newpc, false, true, newpc);
+                       exception3b(regs.ir, newpc, false, true, newpc);
                } else {
                        exception3_notinstruction(regs.ir, newpc);
                }
@@ -6953,6 +6964,7 @@ static void exception3f (uae_u32 opcode, uaecptr addr, bool writeaccess, bool in
 
 void exception3_notinstruction(uae_u32 opcode, uaecptr addr)
 {
+       last_di_for_exception_3 = 1;
        exception3f (opcode, addr, true, false, true, 0xffffffff, 1, false, -1);
 }
 static void exception3_read_special(uae_u32 opcode, uaecptr addr, int size, int fc)
@@ -6962,6 +6974,7 @@ static void exception3_read_special(uae_u32 opcode, uaecptr addr, int size, int
 void exception3_read(uae_u32 opcode, uaecptr addr, int size, int fc)
 {
        bool ni = false;
+       bool ia = false;
        if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible) {
                if (generates_group1_exception(regs.ir) && !(opcode & 0x20000)) {
                        ni = true;
@@ -6969,13 +6982,17 @@ void exception3_read(uae_u32 opcode, uaecptr addr, int size, int fc)
                }
                if (opcode & 0x10000)
                        ni = true;
+               if (opcode & 0x40000)
+                       ia = true;
                opcode = regs.ir;
        }
-       exception3f (opcode, addr, false, 0, ni, 0xffffffff, size, false, fc);
+       last_di_for_exception_3 = 1;
+       exception3f (opcode, addr, false, ia, ni, 0xffffffff, size, false, fc);
 }
 void exception3_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc)
 {
        bool ni = false;
+       bool ia = false;
        if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible) {
                if (generates_group1_exception(regs.ir) && !(opcode & 0x20000)) {
                        ni = true;
@@ -6983,17 +7000,22 @@ void exception3_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int f
                }
                if (opcode & 0x10000)
                        ni = true;
+               if (opcode & 0x40000)
+                       ia = true;
                opcode = regs.ir;
        }
-       exception3f (opcode, addr, true, 0, ni, 0xffffffff, size, false, fc);
+       last_di_for_exception_3 = 1;
+       exception3f (opcode, addr, true, ia, ni, 0xffffffff, size, false, fc);
        regs.write_buffer = val;
 }
-void exception3i (uae_u32 opcode, uaecptr addr)
+void exception3i(uae_u32 opcode, uaecptr addr)
 {
+       last_di_for_exception_3 = 0;
        exception3f (opcode, addr, 0, 1, false, 0xffffffff, 1, true, -1);
 }
-void exception3b (uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc)
+void exception3b(uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc)
 {
+       last_di_for_exception_3 = 0;
        exception3f (opcode, addr, w, i, false, pc, 1, true, -1);
 }