From: Toni Wilen Date: Sun, 2 Feb 2020 10:11:47 +0000 (+0200) Subject: Odd interrupt vector test and emulation and misc fixes. X-Git-Tag: 4400~145 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=ed4b58db36b59c393f2f2f6b31b7d69b9b683c96;p=francis%2Fwinuae.git Odd interrupt vector test and emulation and misc fixes. --- diff --git a/cputest.cpp b/cputest.cpp index 3bf061dd..2e33edc0 100644 --- a/cputest.cpp +++ b/cputest.cpp @@ -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 diff --git a/cputest/cputest_defines.h b/cputest/cputest_defines.h index 19ef7081..4e7823e9 100644 --- a/cputest/cputest_defines.h +++ b/cputest/cputest_defines.h @@ -1,5 +1,5 @@ -#define DATA_VERSION 15 +#define DATA_VERSION 16 #define CT_FPREG 0 #define CT_DREG 0 diff --git a/cputest/cputestgen.ini b/cputest/cputestgen.ini index ad774e3d..29d29d91 100644 --- a/cputest/cputestgen.ini +++ b/cputest/cputestgen.ini @@ -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] diff --git a/cputest/main.c b/cputest/main.c index 49ab1d1e..7317501e 100644 --- a/cputest/main.c +++ b/cputest/main.c @@ -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); diff --git a/gencpu.cpp b/gencpu.cpp index 1f25fc7a..5d44ef97 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -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); diff --git a/newcpu.cpp b/newcpu.cpp index 7cf86796..39f281f0 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -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)