]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Odd interrupt vector test and emulation and misc fixes.
authorToni Wilen <twilen@winuae.net>
Sun, 2 Feb 2020 10:11:47 +0000 (12:11 +0200)
committerToni Wilen <twilen@winuae.net>
Sun, 2 Feb 2020 10:11:47 +0000 (12:11 +0200)
cputest.cpp
cputest/cputest_defines.h
cputest/cputestgen.ini
cputest/main.c
gencpu.cpp
newcpu.cpp

index 3bf061ddbadaf03c9b6edb4bb6e52f8b0f4d9d90..2e33edc0185f5c368cdd7f25258a18d78abfe0ae 100644 (file)
@@ -73,6 +73,7 @@ static int feature_flag_mode = 0;
 static int feature_usp = 0;
 static int feature_exception_vectors = 0;
 static int feature_interrupts = 0;
+static int feature_randomize = 0;
 static TCHAR *feature_instruction_size = NULL;
 static uae_u32 feature_addressing_modes[2];
 static int feature_gzip = 0;
@@ -126,7 +127,7 @@ 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 int exception_extra_frame_size, exception_extra_frame_type;
 static uaecptr test_exception_addr;
 static int test_exception_3_w;
 static int test_exception_3_fc;
@@ -986,6 +987,7 @@ static void doexcstack(void)
        if (!feature_exception_vectors)
                return;
 
+       int interrupt = test_exception >= 24 && test_exception < 24 + 8;
        int original_exception = test_exception;
        // odd exception vector
        test_exception = 3;
@@ -994,6 +996,7 @@ static void doexcstack(void)
        // 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;
+       exception_extra_frame_type = original_exception;
        memcpy(exception_extra_frame, sf, exception_extra_frame_size);
 
        MakeSR();
@@ -1013,6 +1016,12 @@ static void doexcstack(void)
                regs.write_buffer = original_exception * 4;
        }
 
+       if (interrupt) {
+               regs.intmask = original_exception - 24;
+               regs.ir = original_exception;
+               flags |= 0x10000 | 0x20000;
+       }
+
        exception3_read(regs.ir | flags, test_exception_addr, 1, 2);
 }
 
@@ -1661,7 +1670,7 @@ static void save_data(uae_u8 *dst, const TCHAR *dir)
                pl(data, opcode_memory_start);
                fwrite(data, 1, 4, f);
                pl(data, (cpu_lvl << 16) | sr_undefined_mask | (addressing_mask == 0xffffffff ? 0x80000000 : 0) |
-                       (feature_min_interrupt_mask << 20) | (safe_memory_mode << 23) | (feature_interrupts << 26));
+                       (feature_min_interrupt_mask << 20) | (safe_memory_mode << 23) | (feature_interrupts << 26) | (feature_randomize << 28));
                fwrite(data, 1, 4, f);
                pl(data, currprefs.fpu_model);
                fwrite(data, 1, 4, f);
@@ -2763,6 +2772,7 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp)
        regs.read_buffer = regs.irc;
        regs.write_buffer = 0xf00d;
        exception_extra_frame_size = 0;
+       exception_extra_frame_type = 0;
        cpu_cycles = 0;
        regs.loop_mode = 0;
 
@@ -2988,7 +2998,11 @@ static uae_u8 *save_exception(uae_u8 *p, struct instr *dp)
 {
        uae_u8 *op = p;
        p++;
-       *p++ = test_exception_extra;
+       *p++ = test_exception_extra | (exception_extra_frame_type ? 0x40 : 0x00);
+       // bus/address error aborted group 2 exception
+       if (exception_extra_frame_type) {
+               *p++ = exception_extra_frame_type;
+       }
        // Separate, non-stacked Trace
        if (test_exception_extra & 0x80) {
                *p++ = trace_store_sr >> 8;
@@ -4057,10 +4071,18 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                                if (feature_exception3_instruction == 2) {
                                                                        skipped = 1;
                                                                }
-                                                               if (feature_usp == 2) {
+                                                               if (feature_exception_vectors) {
                                                                        skipped = 1;
                                                                }
-                                                               if (feature_exception_vectors) {
+                                                       }
+
+                                                       if (feature_usp == 2) {
+                                                               // need exception 3
+                                                               if (test_exception != 3) {
+                                                                       skipped = 1;
+                                                               }
+                                                               // need also extra exception
+                                                               if (!exception_extra_frame_type) {
                                                                        skipped = 1;
                                                                }
                                                        }
@@ -4769,6 +4791,8 @@ static int test(struct ini_data *ini, const TCHAR *sections, const TCHAR *testna
        ini_getvalx(ini, sections, _T("feature_exception_vectors"), &feature_exception_vectors);
        feature_interrupts = 0;
        ini_getvalx(ini, sections, _T("feature_interrupts"), &feature_interrupts);
+       feature_randomize = 0;
+       ini_getvalx(ini, sections, _T("feature_randomize"), &feature_randomize);
 
        feature_full_extension_format = 0;
        if (currprefs.cpu_model >= 68020) {
@@ -5130,7 +5154,7 @@ static int test(struct ini_data *ini, const TCHAR *sections, const TCHAR *testna
 
                        if (verbose == 1)
                                verbose = 0;
-                       for (int j = 1; lookuptab[j].name; j++) {
+                       for (int j = 1; lookuptab[j].name[0]; j++) {
                                test_mnemo_text(path, lookuptab[j].name);
                        }
                        // Illegal instructions last. All currently selected CPU model's unsupported opcodes
index 19ef70812b70ba26d640018026c86e95143a3652..4e7823e9e9848c8c8092caf9b6c5b8a0a8bf6b1a 100644 (file)
@@ -1,5 +1,5 @@
 
-#define DATA_VERSION 15
+#define DATA_VERSION 16
 
 #define CT_FPREG 0
 #define CT_DREG 0
index ad774e3da9dd12eeabd4c766e12114348e55a130..29d29d9117b34592991e1e46ea3908c84e9949dc 100644 (file)
@@ -168,10 +168,10 @@ mode=all
 ; basic instruction test
 [test=ALL]
 enabled=0
-mode=tas
+mode=all
 feature_sr_mask=0xa000
 
-; interrupt exception test
+; interrupt exception
 [test=IRQ]
 enabled=0
 mode=nop,ext,swap
@@ -192,10 +192,23 @@ feature_target_dst_ea=0x87fff1,0x7111
 mode=all
 
 ; user stack address error
-[test=ODD_STACK]
+[test=ODD_STK]
 enabled=0
 feature_usp=2
-mode=all
+mode=branchs
+
+; exception vector address error
+[test=ODD_EXC]
+enabled=0
+feature_exception_vectors=0x000123
+mode=chk,trap,trapv,divu,divs,orsr
+
+; interrupt exception with odd interrupt vectors
+[test=ODD_IRQ]
+enabled=1
+mode=nop,ext,swap
+feature_interrupts=1
+feature_exception_vectors=0x000123
 
 ; prefetch bus error (requires extra hardware)
 [test=BE_PR]
index 49ab1d1ea7407279761d3444ffc4e4facaf51962..7317501e6bfb7b5493ddda3c101cd908ff7a00db 100644 (file)
@@ -137,6 +137,7 @@ static int exitcnt;
 static short cycles, cycles_range, cycles_adjust;
 static short gotcycles;
 static short interrupttest;
+static short randomizetest;
 static uae_u32 cyclecounter_addr;
 static short uae;
 #ifdef AMIGA
@@ -1383,7 +1384,7 @@ static void out_regs(struct registers *r, int before)
 
 }
 
-static void hexdump(uae_u8 *p, int len)
+static void hexdump(uae_u8 *p, int len, short lf)
 {
        for (int i = 0; i < len; i++) {
                if (i > 0)
@@ -1391,7 +1392,8 @@ static void hexdump(uae_u8 *p, int len)
                sprintf(outbp, "%02x", p[i]);
                outbp += strlen(outbp);
        }
-       *outbp++ = '\n';
+       if (lf)
+               *outbp++ = '\n';
 }
 
 static uae_u8 last_exception[256], last_exception_extra;
@@ -1418,7 +1420,7 @@ static int compare_exception(uae_u8 *s1, uae_u8 *s2, int len, int domask, uae_u8
        }
 }
 
-static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, short excnum, short *gotexcnum, short *experr, short *extratrace)
+static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, short excnum, short *gotexcnum, short *experr, short *extratrace, short *group2with1)
 {
        int exclen = 0;
        uae_u8 *exc;
@@ -1438,8 +1440,12 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, short excnu
        if (excdatalen != 0xff) {
                // check possible extra trace
                last_exception_extra = *p++;
-               if ((last_exception_extra & 0x7f) == 9) {
-                       exceptioncount[0][last_exception_extra & 0x7f]++;
+               if (last_exception_extra & 0x40) {
+                       *group2with1 = *p++;
+                       last_exception_extra &= ~0x40;
+               }
+               if ((last_exception_extra & 0x3f) == 9) {
+                       exceptioncount[0][last_exception_extra & 0x3f]++;
                        uae_u32 ret = (regs->tracedata[1] << 16) | regs->tracedata[2];
                        uae_u16 sr = regs->tracedata[0];
                        if (regs->tracecnt == 0) {
@@ -1692,10 +1698,10 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, short excnu
                outbp += strlen(outbp);
                strcpy(outbp, "Expected: ");
                outbp += strlen(outbp);
-               hexdump(exc, exclen);
+               hexdump(exc, exclen, 1);
                strcpy(outbp, "Got     : ");
                outbp += strlen(outbp);
-               hexdump(sp, exclen);
+               hexdump(sp, exclen, 1);
                *experr = 1;
        }
        exception_stored = exclen;
@@ -1709,7 +1715,7 @@ static int getexceptioncycles(int exc)
                {
                case 2:
                case 3:
-                       return 56;
+                       return 60;
                case 4:
                case 5:
                case 6:
@@ -1812,7 +1818,7 @@ static int get_cycles_amiga(void)
 }
 #endif
 
-static int check_cycles(int exc, int extratrace)
+static int check_cycles(int exc, short extratrace, short extrag2w1)
 {
        int gotcycles = 0;
 
@@ -1880,6 +1886,19 @@ static int check_cycles(int exc, int extratrace)
        if (extratrace) {
                expectedcycles += getexceptioncycles(9);
        }
+       // address error during group 2 exception stacking (=odd exception vector)
+       if (extrag2w1) {
+               // 4 idle, write pc low, write sr, write pc high, read vector high, read vector low
+               expectedcycles += 6 * 4;
+               if (cpu_lvl == 1) {
+                       // 68010: frame type
+                       expectedcycles += 4;
+               }
+               if (extrag2w1 >= 24 && extrag2w1 < 24 + 8) {
+                       // interrupt
+                       expectedcycles += 2 + 4 + 4;
+               }
+       }
 
        if (0 || abs(gotcycles - expectedcycles) > cycles_range) {
                addinfo();
@@ -1942,6 +1961,7 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr)
        int errflag = 0;
        int errflag_orig = 0;
        short extratrace = 0;
+       short extrag2w1 = 0;
        short exceptionnum = 0;
        uae_u8 *outbp_old = outbp;
        exception_stored = 0;
@@ -1970,7 +1990,7 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr)
                        }
                        if (ignore_errors) {
                                if (exc) {
-                                       p = validate_exception(&test_regs, p, exc, &cpuexc, &experr, &extratrace);
+                                       p = validate_exception(&test_regs, p, exc, &cpuexc, &experr, &extratrace, &extrag2w1);
                                }
                                errflag_orig |= errflag;
                                errflag = 0;
@@ -1986,7 +2006,7 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr)
                                break;
                        }
                        if (exc) {
-                               p = validate_exception(&test_regs, p, exc, &cpuexc, &experr, &extratrace);
+                               p = validate_exception(&test_regs, p, exc, &cpuexc, &experr, &extratrace, &extrag2w1);
                                if (experr) {
                                        errflag |= 1 << 16;
                                        errflag_orig |= errflag;
@@ -2253,7 +2273,7 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr)
                                        outbp += strlen(outbp);
                                }
                        } else {
-                               if (!check_cycles(exc, extratrace)) {
+                               if (!check_cycles(exc, extratrace, extrag2w1)) {
                                        errflag |= 1 << 8;
                                }
                        }
@@ -2285,10 +2305,13 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr)
                                sprintf(outbp, "OK: exception %d ", exc);
                                outbp += strlen(outbp);
                                if (exception_stored) {
-                                       hexdump(last_exception, exception_stored);
-                               } else {
-                                       *outbp++ = '\n';
+                                       hexdump(last_exception, exception_stored, 0);
                                }
+                               if (extrag2w1) {
+                                       sprintf(outbp, " (+EXC %d)", extrag2w1);
+                                       outbp += strlen(outbp);
+                               }
+                               *outbp++ = '\n';
                        }
                        if ((exc == 3 || exc == 2) && cpu_lvl == 0) {
                                sprintf(outbp, "RW=%d IN=%d FC=%d\n",
@@ -2353,6 +2376,17 @@ static void clear_interrupt(void)
 }
 #endif
 
+static uae_u32 xorshiftstate;
+static uae_u32 xorshift32(void)
+{
+       uae_u32 x = xorshiftstate;
+       x ^= x << 13;
+       x ^= x >> 17;
+       x ^= x << 5;
+       xorshiftstate = x;
+       return xorshiftstate;
+}
+
 static void process_test(uae_u8 *p)
 {
        outbp = outbuffer2;
@@ -2610,6 +2644,11 @@ static void process_test(uae_u8 *p)
 #endif
                        }
 
+                       if (randomizetest) {
+                               ;
+                       }
+
+
                        if (*p == CT_END) {
                                p++;
                                break;
@@ -2697,6 +2736,7 @@ static int test_mnemo(const char *opcode)
        interrupt_mask = (lvl_mask >> 20) & 7;
        addressing_mask = (lvl_mask & 0x80000000) ? 0xffffffff : 0x00ffffff;
        interrupttest = (lvl_mask >> 26) & 1;
+       randomizetest = (lvl_mask >> 28) & 1;
        sr_undefined_mask = lvl_mask & 0xffff;
        safe_memory_mode = (lvl_mask >> 23) & 3;
        fpu_model = read_u32(headerfile, &headoffset);
index 1f25fc7ab2288b691834b03d8c0522c05d389fbd..5d44ef97ec0553a96ee54d51bb71594bcb595476 100644 (file)
@@ -6032,6 +6032,7 @@ static void gen_opcode (unsigned int opcode)
                gen_set_fault_pc (false, true);
                sync_m68k_pc();
                out("Exception_cpu(src + 32);\n");
+               write_return_cycles_noadd(0);
                did_prefetch = 1;
                clear_m68k_offset();
                break;
@@ -6164,6 +6165,11 @@ static void gen_opcode (unsigned int opcode)
                        out("uae_u16 format = %s(a + 2 + 4);\n", srcw);
                        count_read++;
                        check_bus_error("", 6, 0, 1, NULL, 1);
+
+                       out("uae_u32 pc = %s(a + 2) << 16;\n", srcw);
+                       count_read++;
+                       check_bus_error("", 2, 0, 1, NULL, 1);
+
                        out("int frame = format >> 12;\n");
                        out("int offset = 8;\n");
                        out("if (frame == 0x0) {\n");
@@ -6178,9 +6184,6 @@ static void gen_opcode (unsigned int opcode)
                        write_return_cycles(0);
                        out("}\n");
 
-                       out("uae_u32 pc = %s(a + 2) << 16;\n", srcw);
-                       count_read++;
-                       check_bus_error("", 2, 0, 1, NULL, 1);
                        out("pc |= %s(a + 2 + 2); \n", srcw);
                        count_read++;
                        check_bus_error("", 4, 0, 1, NULL, 1);
index 7cf8679630a1ac82420bb57a1cd54ad486f5d0e4..39f281f0d261961f292ef5e463340caacfe199d8 100644 (file)
@@ -2451,6 +2451,15 @@ Interrupt:
 - 2 idle cycles
 - prefetch
 
+68010:
+
+...
+- write SR
+- write PC high word
+- write frame format
+- read exception address high word
+...
+
 */
 
 static void exception3f(uae_u32 opcode, uaecptr addr, bool writeaccess, bool instructionaccess, bool notinstruction, uaecptr pc, int size, bool plus2, int fc);
@@ -2486,7 +2495,7 @@ static void Exception_ce000 (int nr)
                if (nr == 7) // TRAPV
                        start = 0;
                else if (nr == 2 || nr == 3)
-                       start = 8;
+                       start = 4 + 8;
        }
 
        if (start)
@@ -2586,6 +2595,8 @@ kludge_me_do:
                cpu_halt(CPU_HALT_DOUBLE_FAULT);
                return;
        }
+       if (interrupt)
+               regs.intmask = nr - 24;
        newpc = x_get_word (regs.vbr + 4 * vector_nr) << 16; // read high address
        newpc |= x_get_word (regs.vbr + 4 * vector_nr + 2); // read low address
        exception_in_exception = 0;
@@ -2601,7 +2612,12 @@ kludge_me_do:
                        regs.t1 = 0;
                        MakeSR();
                        m68k_setpc(regs.vbr + 4 * vector_nr);
-                       exception3_read(regs.ir | 0x40000, newpc, 1, 2);
+                       if (interrupt) {
+                               regs.ir = nr;
+                               exception3_read(regs.ir | 0x20000 | 0x10000, newpc, 1, 2);
+                       } else {
+                               exception3_read(regs.ir | 0x40000, newpc, 1, 2);
+                       }
                } else if (currprefs.cpu_model == 68010) {
                        // offset, not vbr + offset
                        regs.t1 = 0;
@@ -2616,8 +2632,6 @@ kludge_me_do:
                return;
        }
        m68k_setpc (newpc);
-       if (interrupt)
-               regs.intmask = nr - 24;
        branch_stack_push(currpc, currpc);
        regs.ir = x_get_word (m68k_getpc ()); // prefetch 1
 #if HARDWARE_BUS_ERROR_EMULATION
@@ -3032,12 +3046,10 @@ static void Exception_normal (int nr)
                                x_put_word (m68k_areg (regs, 7), 0x1000 + vector_nr * 4);
                        }
                } else {
-                       add_approximate_exception_cycles(nr);
                        Exception_build_stack_frame_common(oldpc, currpc, regs.mmu_ssw, nr);
                        used_exception_build_stack_frame = true;
                }
        } else {
-               add_approximate_exception_cycles(nr);
                nextpc = m68k_getpc ();
                if (nr == 2 || nr == 3) {
                        // 68000 bus/address error
@@ -3064,6 +3076,8 @@ kludge_me_do:
                cpu_halt(CPU_HALT_DOUBLE_FAULT);
                return;
        }
+       if (interrupt)
+               regs.intmask = nr - 24;
        newpc = x_get_long (regs.vbr + 4 * vector_nr);
        exception_in_exception = 0;
        if (newpc & 1) {
@@ -3071,11 +3085,17 @@ kludge_me_do:
                        cpu_halt(CPU_HALT_DOUBLE_FAULT);
                        return;
                }
+               x_do_cycles(adjust_cycles(6 * 4 * CYCLE_UNIT / 2));
                if (currprefs.cpu_model == 68000) {
                        regs.t1 = 0;
                        MakeSR();
                        m68k_setpc(regs.vbr + 4 * vector_nr);
-                       exception3_read(regs.ir | 0x40000, newpc, 1, 2);
+                       if (interrupt) {
+                               regs.ir = nr;
+                               exception3_read(regs.ir | 0x20000 | 0x10000, newpc, 1, 2);
+                       } else {
+                               exception3_read(regs.ir | 0x40000, newpc, 1, 2);
+                       }
                } else if (currprefs.cpu_model == 68010) {
                        regs.t1 = 0;
                        MakeSR();
@@ -3088,8 +3108,7 @@ kludge_me_do:
                }
                return;
        }
-       if (interrupt)
-               regs.intmask = nr - 24;
+       add_approximate_exception_cycles(nr);
        m68k_setpc (newpc);
        cache_default_data &= ~CACHE_DISABLE_ALLOCATE;
 #ifdef JIT
@@ -7024,7 +7043,7 @@ void exception3_read(uae_u32 opcode, uaecptr addr, int size, int fc)
                opcode = regs.ir;
        }
        last_di_for_exception_3 = 1;
-       exception3f (opcode, addr, false, ia, ni, 0xffffffff, size, false, fc);
+       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)
 {
@@ -7042,7 +7061,7 @@ void exception3_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int f
                opcode = regs.ir;
        }
        last_di_for_exception_3 = 1;
-       exception3f (opcode, addr, true, ia, ni, 0xffffffff, size, false, fc);
+       exception3f(opcode, addr, true, ia, ni, 0xffffffff, size, false, fc);
        regs.write_buffer = val;
 }
 void exception3i(uae_u32 opcode, uaecptr addr)