]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
CPUTester update (68000 IPL timing, wait states, etc)
authorToni Wilen <twilen@winuae.net>
Sun, 12 Mar 2023 08:04:45 +0000 (10:04 +0200)
committerToni Wilen <twilen@winuae.net>
Sun, 12 Mar 2023 08:04:45 +0000 (10:04 +0200)
cputest.cpp
cputest/amiga.S
cputest/asm.S
cputest/cputest_defines.h
cputest/cputestgen.ini
cputest/main.c
cputest_support.cpp

index c4b6cd99b990c54fb868dfcdc7456616475fb224..ad80f70af3e9c8d6d87a824e74ca3bc3e837212d 100644 (file)
@@ -40,6 +40,7 @@ int hardware_bus_error, hardware_bus_error_fake;
 
 struct mmufixup mmufixup[2];
 cpuop_func *cpufunctbl[65536];
+cpuop_func_noret *cpufunctbl_noret[65536];
 struct cputbl_data
 {
        uae_s16 length;
@@ -51,12 +52,15 @@ static struct cputbl_data cpudatatbl[65536];
 struct regstruct regs;
 struct flag_struct regflags;
 int cpu_cycles;
+static int cycle_count_disable;
 
 static int verbose = 1;
 static int feature_exception3_data = 0;
 static int feature_exception3_instruction = 0;
 static int feature_sr_mask = 0;
 static int feature_undefined_ccr = 0;
+static int feature_initial_interrupt = 0;
+static int feature_initial_interrupt_mask = 0;
 static int feature_min_interrupt_mask = 0;
 static int feature_loop_mode_cnt = 0;
 static int feature_loop_mode_register = -1;
@@ -69,12 +73,14 @@ 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_waitstates = 0;
 static int feature_instruction_size = 0;
 static int fpu_min_exponent, fpu_max_exponent;
 static int max_file_size;
 static int rnd_seed, rnd_seed_prev;
 static TCHAR *feature_instruction_size_text = NULL;
 static uae_u32 feature_addressing_modes[2];
+static uae_u32 feature_condition_codes;
 static int feature_gzip = 0;
 static int ad8r[2], pc8r[2];
 static int multi_mode;
@@ -147,6 +153,8 @@ static int test_memory_access_mask;
 static uae_u32 opcode_memory_address;
 static uaecptr branch_target;
 static uaecptr branch_target_pc;
+static uae_u16 test_opcode;
+static int test_absw;
 
 static uae_u8 imm8_cnt;
 static uae_u16 imm16_cnt;
@@ -173,8 +181,11 @@ static uae_u16 extra_or, extra_and;
 static struct regstruct cur_regs;
 static uae_u16 read_buffer_prev;
 static int interrupt_count;
+static uaecptr interrupt_pc;
 static int interrupt_cycle_cnt, interrupt_delay_cnt;
 static int interrupt_level;
+static int waitstate_cycle_cnt;
+static int waitstate_delay_cnt;
 static uaecptr test_instruction_end_pc;
 static uaecptr lm_safe_address1, lm_safe_address2;
 static uae_u8 ccr_cnt;
@@ -242,11 +253,15 @@ static bool valid_address(uaecptr addr, int size, int rwp)
        if (low_memory_size != 0xffffffff && addr + size < low_memory_size) {
                if (addr < test_low_memory_start || test_low_memory_start == 0xffffffff)
                        goto oob;
+               // only accept low memory when testing short absolute addressing
+               if (!test_absw) {
+                       goto oob;
+               }
                // exception vectors needed during tests
                if (currprefs.cpu_model == 68000) {
                        if ((addr + size >= 0x08 && addr < 0x30 || (addr + size >= 0x80 && addr < 0xc0)))
                                goto oob;
-                       if (feature_interrupts && (addr + size >= 0x64 && addr < 0x7c))
+                       if (feature_interrupts && (addr + size >= 0x60 && addr < 0x80))
                                goto oob;
                }
                if (addr + size >= test_low_memory_end)
@@ -263,6 +278,10 @@ static bool valid_address(uaecptr addr, int size, int rwp)
                        goto oob;
                if (addr + size >= test_high_memory_end)
                        goto oob;
+               // only accept high memory when testing short absolute addressing
+               if (!test_absw) {
+                       goto oob;
+               }
                if (w && hmem_rom)
                        goto oob;
                if (testing_active) {
@@ -371,15 +390,33 @@ oob:
        return dummy_memory;
 }
 
-static void count_interrupt_cycles(int cycles)
+static void count_cycles(int cycles)
 {
-       if (!interrupt_cycle_cnt)
+       if (cycle_count_disable) {
                return;
-       interrupt_cycle_cnt -= cycles;
-       if (interrupt_cycle_cnt <= 0) {
-               regs.ipl_pin = IPL_TEST_IPL_LEVEL;
-               interrupt_level = regs.ipl_pin;
-               interrupt_cycle_cnt = 0;
+       }
+       while (cycles > 0) {
+               cycles--;
+               cpu_cycles++;
+               if (interrupt_cycle_cnt != 0) {
+                       interrupt_cycle_cnt--;
+                       if (interrupt_cycle_cnt == 0) {
+                               if (regs.ipl_pin < IPL_TEST_IPL_LEVEL) {
+                                       regs.ipl_pin = IPL_TEST_IPL_LEVEL;
+                                       regs.ipl_pin_change_evt = cpu_cycles;
+                               }
+                               if (cpu_cycles == regs.ipl_evt_pre + cpuipldelay2) {
+                                       if (regs.ipl_evt_pre_mode) {
+                                               ipl_fetch_next();
+                                       } else {
+                                               ipl_fetch_now();
+                                       }
+                               }
+                               interrupt_pc = regs.pc;
+                               interrupt_level = regs.ipl_pin;
+                               interrupt_cycle_cnt = 0;
+                       }
+               }
        }
 }
 
@@ -387,19 +424,65 @@ void do_cycles_test(int cycles)
 {
        if (!testing_active)
                return;
-       cpu_cycles += cycles;
-       count_interrupt_cycles(cycles);
+       count_cycles(cycles);
 }
 
-static void add_memory_cycles(int c)
+static void add_memory_cycles(uaecptr addr, int c)
 {
-       if (!testing_active)
+       if (cycle_count_disable) {
                return;
-       if (trace_store_pc != 0xffffffff)
+       }
+       if (!testing_active) {
+               return;
+       }
+       if (trace_store_pc != 0xffffffff) {
                return;
-       c *= 4;
-       cpu_cycles += c;
-       count_interrupt_cycles(c);
+       }
+       if (waitstate_cycle_cnt && (addr & addressing_mask) < 0x200000 && c > 0) {
+               c *= 2;
+               while (c > 0) {
+                       int now = cpu_cycles;
+                       int ipl = regs.ipl_pin;
+                       count_cycles(2);
+                       c--;
+                       // wait for free bus cycle
+                       for (;;) {
+                               int cb = (cpu_cycles - waitstate_cycle_cnt) / 2;
+                               // remove init cycles
+                               cb -= 3;
+                               if (cb < 0) {
+                                       break;
+                               }
+                               if (feature_waitstates == 1) {
+                                       cb %= 3;
+                                       // AB-AB-AB-..
+                                       if (cb == 2) {
+                                               break;
+                                       }
+                               } else {
+                                       // -BC--BCD-BCD..
+                                       // 012301230123
+                                       if (cb == 0 || cb == 3) {
+                                               break;
+                                       }
+                                       cb %= 4;
+                                       if (cb == 0) {
+                                               break;
+                                       }
+                               }
+                               ipl = regs.ipl_pin;
+                               count_cycles(2);
+                       }
+                       count_cycles(2);
+                       c--;
+                       if (now == regs.ipl_evt) {
+                               regs.ipl[0] = ipl;
+                       }
+               }
+       } else {
+               c *= 4;
+               count_cycles(c);
+       }
 }
 
 static void check_bus_error(uaecptr addr, int write, int fc)
@@ -439,7 +522,7 @@ static uae_u8 get_ibyte_test(uaecptr addr)
 {
        check_bus_error(addr, 0, regs.s ? 5 : 1);
        uae_u8 *p = get_addr(addr, 1, 4);
-       add_memory_cycles(1);
+       add_memory_cycles(addr, 1);
        return *p;
 }
 
@@ -450,7 +533,7 @@ static uae_u16 get_iword_test(uaecptr addr)
                return (get_ibyte_test(addr + 0) << 8) | (get_ibyte_test(addr + 1) << 0);
        } else {
                uae_u8 *p = get_addr(addr, 2, 4);
-               add_memory_cycles(1);
+               add_memory_cycles(addr, 1);
                return (p[0] << 8) | (p[1]);
        }
 }
@@ -471,7 +554,7 @@ uae_u32 get_ilong_test(uaecptr addr)
        } else {
                uae_u8 *p = get_addr(addr, 4, 4);
                v = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]);
-               add_memory_cycles(2);
+               add_memory_cycles(addr, 2);
        }
        return v;
 }
@@ -482,11 +565,13 @@ uae_u16 get_word_test_prefetch(int o)
        if (cpu_lvl < 2) {
                o -= 2;
        }
-       add_memory_cycles(-1);
+       cycle_count_disable = 1;
        regs.irc = get_iword_test(m68k_getpci() + o + 2);
+       cycle_count_disable = 0;
        read_buffer_prev = regs.read_buffer;
        regs.read_buffer = regs.irc;
-       return get_iword_test(m68k_getpci() + o);
+       uae_u16 v = get_iword_test(m68k_getpci() + o);
+       return v;
 }
 
 static void previoussame(uaecptr addr, int size, uae_u32 *old)
@@ -524,12 +609,14 @@ void put_byte_test(uaecptr addr, uae_u32 v)
 {
        if (!testing_active && is_nowrite_address(addr, 1))
                return;
-       if (feature_interrupts >= 2 && addr == IPL_TRIGGER_ADDR) {
-               add_memory_cycles(1);
+       if (feature_interrupts >= 2) {
+               if (addr == IPL_TRIGGER_ADDR) {
+                       add_memory_cycles(addr, 1);
 #if IPL_TRIGGER_ADDR_SIZE == 1
-               interrupt_cycle_cnt = INTERRUPT_CYCLES;
+                       interrupt_cycle_cnt = INTERRUPT_CYCLES;
 #endif
-               return;
+                       return;
+               }
        }
        check_bus_error(addr, 1, regs.s ? 5 : 1);
        uae_u8 *p = get_addr(addr, 1, 2);
@@ -550,18 +637,25 @@ void put_byte_test(uaecptr addr, uae_u32 v)
        regs.write_buffer &= 0xff00;
        regs.write_buffer |= v & 0xff;
        *p = v;
-       add_memory_cycles(1);
+       add_memory_cycles(addr, 1);
 }
 void put_word_test(uaecptr addr, uae_u32 v)
 {
        if (!testing_active && is_nowrite_address(addr, 1))
                return;
-       if (feature_interrupts >= 2 && addr == IPL_TRIGGER_ADDR) {
-               add_memory_cycles(1);
+       if (feature_interrupts >= 2) {
+               if (addr == IPL_BLTSIZE) {
+                       add_memory_cycles(addr, 1);
+                       waitstate_cycle_cnt = cpu_cycles;
+                       return;
+               }
+               if (addr == IPL_TRIGGER_ADDR) {
+                       add_memory_cycles(addr, 1);
 #if IPL_TRIGGER_ADDR_SIZE == 2
-               interrupt_cycle_cnt = INTERRUPT_CYCLES;
+                       interrupt_cycle_cnt = INTERRUPT_CYCLES;
 #endif
-               return;
+                       return;
+               }
        }
        check_bus_error(addr, 1, regs.s ? 5 : 1);
        if (addr & 1) {
@@ -587,7 +681,7 @@ void put_word_test(uaecptr addr, uae_u32 v)
                p[1] = v & 0xff;
        }
        regs.write_buffer = v;
-       add_memory_cycles(1);
+       add_memory_cycles(addr, 1);
 }
 void put_long_test(uaecptr addr, uae_u32 v)
 {
@@ -621,7 +715,7 @@ void put_long_test(uaecptr addr, uae_u32 v)
                p[1] = v >> 16;
                p[2] = v >> 8;
                p[3] = v >> 0;
-               add_memory_cycles(2);
+               add_memory_cycles(addr, 2);
        }
        regs.write_buffer = v;
 }
@@ -660,7 +754,7 @@ uae_u32 get_byte_test(uaecptr addr)
        read_buffer_prev = regs.read_buffer;
        regs.read_buffer &= 0xff00;
        regs.read_buffer |= *p;
-       add_memory_cycles(1);
+       add_memory_cycles(addr, 1);
        return *p;
 }
 uae_u32 get_word_test(uaecptr addr)
@@ -675,7 +769,7 @@ uae_u32 get_word_test(uaecptr addr)
        }
        read_buffer_prev = regs.read_buffer;
        regs.read_buffer = v;
-       add_memory_cycles(1);
+       add_memory_cycles(addr, 1);
        return v;
 }
 uae_u32 get_long_test(uaecptr addr)
@@ -694,7 +788,7 @@ uae_u32 get_long_test(uaecptr addr)
        } else {
                uae_u8 *p = get_addr(addr, 4, 1);
                v = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]);
-               add_memory_cycles(2);
+               add_memory_cycles(addr, 2);
        }
        read_buffer_prev = regs.read_buffer;
        regs.read_buffer = v;
@@ -831,7 +925,7 @@ uae_u32 next_ilong_test(void)
 bool mmu_op30(uaecptr pc, uae_u32 opcode, uae_u16 extra, uaecptr extraa)
 {
        m68k_setpc(pc);
-       op_illg(opcode);
+       op_illg_noret(opcode);
        return true;
 }
 
@@ -840,18 +934,36 @@ bool is_cycle_ce(uaecptr addr)
        return 0;
 }
 
+void ipl_fetch_next_pre(void)
+{
+       ipl_fetch_next();
+       regs.ipl_evt_pre = cpu_cycles;
+       regs.ipl_evt_pre_mode = 1;
+}
+
+void ipl_fetch_now_pre(void)
+{
+       ipl_fetch_now();
+       regs.ipl_evt_pre = cpu_cycles;
+       regs.ipl_evt_pre_mode = 0;
+}
+
 // ipl check was early enough, interrupt possible after current instruction
 void ipl_fetch_now(void)
 {
-       if (regs.ipl[0] != regs.ipl_pin) {
-               regs.ipl[0] = regs.ipl_pin;
-               regs.ipl[1] = 0;
-       }
+       int c = cpu_cycles;
+       regs.ipl_evt = c;
+       regs.ipl[0] = regs.ipl_pin;
+       regs.ipl[1] = 0;
 }
 // ipl check was too late, interrupt possible after following instruction
 void ipl_fetch_next(void)
 {
-       if (regs.ipl[1] != regs.ipl_pin) {
+       int c = cpu_cycles;
+       if (c - regs.ipl_pin_change_evt >= cpuipldelay4) {
+               regs.ipl[0] = regs.ipl_pin;
+               regs.ipl[1] = 0;
+       } else {
                regs.ipl[1] = regs.ipl_pin;
        }
 }
@@ -933,8 +1045,7 @@ static void activate_trace(void)
 static void do_trace(void)
 {
        if (cpu_stopped) {
-               m68k_incpci(4);
-               cpu_stopped = 0;
+               return;
        }
        regs.trace_pc = regs.pc;
        if (regs.t0 && !regs.t1 && currprefs.cpu_model >= 68020) {
@@ -967,11 +1078,26 @@ void MakeFromSR_x(int t0trace)
        SET_VFLG((regs.sr >> 1) & 1);
        SET_CFLG(regs.sr & 1);
 
+       if (regs.t1 == ((regs.sr >> 15) & 1) &&
+               regs.t0 == ((regs.sr >> 14) & 1) &&
+               regs.s  == ((regs.sr >> 13) & 1) &&
+               regs.m  == ((regs.sr >> 12) & 1) &&
+               regs.intmask == ((regs.sr >> 8) & 7))
+               return;
+
        regs.t1 = (regs.sr >> 15) & 1;
        regs.t0 = (regs.sr >> 14) & 1;
-       regs.s = (regs.sr >> 13) & 1;
-       regs.m = (regs.sr >> 12) & 1;
-       regs.intmask = (regs.sr >> 8) & 7;
+       regs.s  = (regs.sr >> 13) & 1;
+       regs.m  = (regs.sr >> 12) & 1;
+       
+       if (regs.intmask != ((regs.sr >> 8) & 7)) {
+               int newimask = (regs.sr >> 8) & 7;
+               // STOP intmask change enabling already active interrupt: delay it by 1 STOP round
+               if (t0trace < 0 && regs.ipl[0] <= regs.intmask && regs.ipl[0] > newimask && regs.ipl[0] < 7) {
+                       regs.ipl[0] = 0;
+               }
+               regs.intmask = newimask;
+       }
 
        if (currprefs.cpu_model >= 68020) {
                /* 68060 does not have MSP but does have M-bit.. */
@@ -1021,7 +1147,7 @@ void MakeFromSR_x(int t0trace)
        }
        // STOP SR-modification does not generate T0
        // If this SR modification set Tx bit, no trace until next instruction.
-       if ((oldt0 && t0trace && currprefs.cpu_model >= 68020) || oldt1) {
+       if (!cpu_stopped && ((oldt0 && t0trace && currprefs.cpu_model >= 68020) || oldt1)) {
                // Always trace if Tx bits were already set, even if this SR modification cleared them.
                activate_trace();
        }
@@ -1220,7 +1346,7 @@ static void doexcstack(void)
        exception3_read(regs.ir | flags, test_exception_addr, 1, 2);
 }
 
-uae_u32 REGPARAM2 op_illg_1(uae_u32 opcode)
+void REGPARAM2 op_illg_1_noret(uae_u32 opcode)
 {
        if ((opcode & 0xf000) == 0xf000) {
                if (currprefs.cpu_model == 68030) {
@@ -1229,7 +1355,7 @@ uae_u32 REGPARAM2 op_illg_1(uae_u32 opcode)
                        // we can't test any MMU opcodes without parsing following word. TODO.
                        if ((opcode & 0xfe00) == 0xf000) {
                                test_exception = -1;
-                               return 0;
+                               return;
                        }
                }
                test_exception = 11;
@@ -1242,25 +1368,39 @@ uae_u32 REGPARAM2 op_illg_1(uae_u32 opcode)
                test_exception = 4;
        }
        doexcstack();
-       return 0;
 }
 void REGPARAM2 op_unimpl(uae_u32 opcode)
 {
        test_exception = 61;
        doexcstack();
 }
-uae_u32 REGPARAM2 op_unimpl_1(uae_u32 opcode)
+void REGPARAM2 op_unimpl_1_noret(uae_u32 opcode)
 {
        if ((opcode & 0xf000) == 0xf000 || currprefs.cpu_model < 68060) {
-               op_illg(opcode);
+               op_illg_noret(opcode);
        } else {
                op_unimpl(opcode);
        }
+}
+uae_u32 REGPARAM2 op_unimpl_1(uae_u32 opcode)
+{
+       op_unimpl_1_noret(opcode);
+       return 0;
+}
+
+void REGPARAM2 op_illg_noret(uae_u32 opcode)
+{
+       op_illg_1_noret(opcode);
+}
+uae_u32 REGPARAM2 op_illg_1(uae_u32 opcode)
+{
+       op_illg_1_noret(opcode);
        return 0;
 }
 uae_u32 REGPARAM2 op_illg(uae_u32 opcode)
 {
-       return op_illg_1(opcode);
+       op_illg_1_noret(opcode);
+       return 0;
 }
 
 static void exception3_pc_inc(void)
@@ -1423,7 +1563,7 @@ void exception3_read_prefetch_only(uae_u32 opcode, uae_u32 addr)
                regs.irc = regs.read_buffer;
                regs.read_buffer = prev;
        } else {
-               add_memory_cycles(1);
+               add_memory_cycles(addr, 1);
        }
        test_exception = 3;
        test_exception_3_w = 0;
@@ -1441,7 +1581,7 @@ void exception3_read_prefetch(uae_u32 opcode, uae_u32 addr)
        if (cpu_lvl == 1) {
                get_word_test(addr & ~1);
        } else {
-               add_memory_cycles(1);
+               add_memory_cycles(addr, 1);
        }
        exception3_pc_inc();
 
@@ -1461,7 +1601,7 @@ void exception3_read_prefetch_68040bug(uae_u32 opcode, uae_u32 addr, uae_u16 sec
        if (cpu_lvl == 1) {
                get_word_test(addr & ~1);
        } else {
-               add_memory_cycles(1);
+               add_memory_cycles(addr, 1);
        }
        exception3_pc_inc();
 
@@ -1490,20 +1630,20 @@ void exception3_read_access(uae_u32 opcode, uae_u32 addr, int size, int fc)
        if (cpu_lvl == 1) {
                get_word_test(addr & ~1);
        } else {
-               add_memory_cycles(1);
+               add_memory_cycles(addr, 1);
        }
        exception3_read(opcode, addr, size, fc);
 }
 
 void exception3_write_access(uae_u32 opcode, uae_u32 addr, int size, uae_u32 val, int fc)
 {
-       add_memory_cycles(1);
+       add_memory_cycles(addr, 1);
        exception3_write(opcode, addr, size, val, fc);
 }
 
 uae_u16 exception3_word_read(uaecptr addr)
 {
-       add_memory_cycles(1);
+       add_memory_cycles(addr, 1);
        return 0;
 }
 
@@ -1974,10 +2114,11 @@ static void compressfiles(const TCHAR *dir)
 static void mergefiles(const TCHAR *dir)
 {
        int tsize = 0;
+       int mergecount = 0;
        FILE *of = NULL;
        int oi = -1;
        unsigned char zero[4] = { 0, 0, 0, 0 };
-       unsigned char head[4] = { 0xff, 0xff, 0xff, 0xff };
+       unsigned char head[4] = { 0xaf, 'M', 'R', 'G'};
        TCHAR opath[1000];
        for (int i = 0; i < filecount; i++) {
                TCHAR path[1000];
@@ -2018,6 +2159,7 @@ static void mergefiles(const TCHAR *dir)
                                wprintf(_T("Couldn't open '%s'\n"), opath);
                                abort();
                        }
+                       mergecount++;
                }
                if (oi != i) {
                        _tunlink(path);
@@ -2040,6 +2182,7 @@ static void mergefiles(const TCHAR *dir)
                fwrite(zero, 1, 4, of);
                fclose(of);
        }
+       wprintf(_T("Number of files after merge: %d -> %d\n"), filecount, mergecount);
 }
 
 static void save_memory(const TCHAR *path, const TCHAR *name, uae_u8 *p, int size)
@@ -2069,7 +2212,6 @@ static void deletefile(const TCHAR *path, const TCHAR *name)
        _tunlink(path2);
 }
 
-
 static uae_u8 *modify_reg(uae_u8 *dst, struct regstruct *regs, uae_u8 type, uae_u32 *valp)
 {
        int mode = type & CT_DATA_MASK;
@@ -2283,7 +2425,7 @@ static uae_u8 *store_reg(uae_u8 *dst, uae_u8 mode, uae_u32 s, uae_u32 d, int siz
        return dst;
 }
 
-static uae_u8 *store_mem_bytes(uae_u8 *dst, uaecptr start, int len, uae_u8 *old, bool header)
+static uae_u8 *store_mem_bytes(uae_u8 *dst, uaecptr start, int len, uae_u8 *old)
 {
        if (!len)
                return dst;
@@ -2310,11 +2452,6 @@ static uae_u8 *store_mem_bytes(uae_u8 *dst, uaecptr start, int len, uae_u8 *old,
        }
        // end
        offset = start - oldstart;
-       if (offset > 7) {
-               start -= (offset - 7);
-               old -= (offset - 7);
-               offset = 7;
-       }
        len -= offset;
        if (old) {
                for (int i = len - 1; i >= 0; i--) {
@@ -2326,18 +2463,16 @@ static uae_u8 *store_mem_bytes(uae_u8 *dst, uaecptr start, int len, uae_u8 *old,
        }
        if (!len)
                return dst;
-       if (header) {
-               *dst++ = CT_MEMWRITES | CT_PC_BYTES;
-       }
-       if (len > 32) {
-               *dst++ = (offset << 5) | 31;
+       *dst++ = CT_MEMWRITES | CT_PC_BYTES;
+       if ((len > 32 || offset > 7) || (len == 31 && offset == 7)) {
+               *dst++ = 0xff;
+               *dst++ = offset;
                *dst++ = len;
        } else {
                *dst++ = (offset << 5) | (uae_u8)(len == 32 ? 0 : len);
        }
        for (int i = 0; i < len; i++) {
                *dst++ = get_byte_test(start);
-               start++;
        }
        return dst;
 }
@@ -2470,6 +2605,12 @@ static void save_data(uae_u8 *dst, const TCHAR *dir, int size)
                        (feature_min_interrupt_mask << 20) | (safe_memory_mode << 23) | (feature_interrupts << 26) |
                        ((feature_loop_mode_jit ? 1 : 0) << 28) | ((feature_loop_mode_68010 ? 1 : 0) << 29));
                fwrite(data, 1, 4, f);
+               pl(data, (feature_initial_interrupt_mask & 7));
+               fwrite(data, 1, 4, f);
+               pl(data, 0);
+               fwrite(data, 1, 4, f);
+               pl(data, 0);
+               fwrite(data, 1, 4, f);
                pl(data, currprefs.fpu_model);
                fwrite(data, 1, 4, f);
                pl(data, test_low_memory_start);
@@ -2832,7 +2973,10 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str
                                        if (currprefs.cpu_model >= 68020)
                                                v &= ~0x100;
                                        ereg = v >> 12;
-                                       if (loopmodelimit && (ereg == 0 || ereg == 8 + 3 || ereg == 8 + 7 || ((1 << ereg) & ignore_register_mask))) {
+                                       if (loopmodelimit && (ereg == 0 || ereg == 8 + 3 || ereg == 8 + 7)) {
+                                               continue;
+                                       }
+                                       if ((1 << ereg) & ignore_register_mask) {
                                                continue;
                                        }
                                        break;
@@ -2916,6 +3060,7 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str
                uae_u32 v;
                if (!high_memory && !low_memory)
                        return -1;
+               test_absw = 1;
                for (;;) {
                        v = rand16();
                        if (immabsw_cnt & 1)
@@ -3162,11 +3307,15 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str
                                        else
                                                *isconstant = -1;
                                } else {
-                                       put_word_test(pc, imm16_cnt);
+                                       if (dp->mnemo == i_STOP) {
+                                               put_word_test(pc, imm16_cnt | 0x2000);
+                                       } else {
+                                               put_word_test(pc, imm16_cnt);
+                                       }
                                        if (dp->mnemo == i_STOP && feature_interrupts > 0) {
                                                // STOP hack to keep STOP test size smaller.
-                                               if (feature_interrupts > 1) {
-                                                       imm16_cnt += 0x0100;
+                                               if (feature_interrupts > 0) {
+                                                       imm16_cnt += 0x0080;
                                                } else {
                                                        imm16_cnt += 0x0001;
                                                }
@@ -3342,9 +3491,10 @@ static int create_ea_exact(uae_u16 *opcodep, uaecptr pc, int mode, int reg, stru
        }
        case absw:
        {
-               if (target >= test_low_memory_start && target < test_low_memory_end) {
+               if ((target >= test_low_memory_start && target < test_low_memory_end) || (target >= test_high_memory_start && target < test_high_memory_end)) {
                        put_word_test(pc, target);
                        *eap = target;
+                       test_absw = 1;
                        return 2;
                }
                return -2;
@@ -4012,17 +4162,16 @@ static const int interrupt_levels[] =
        0, 1, 1, 1, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6
 };
 
-static bool check_interrupts(void)
+static void check_interrupts(void)
 {
        if (feature_interrupts == 1) {
                int ic = interrupt_count & 15;
                int lvl = interrupt_levels[ic];
                if (lvl > 0 && lvl > feature_min_interrupt_mask) {
-                       Exception(24 + lvl);
-                       return true;
+                       regs.ipl_pin = lvl;
+                       return;
                }
        }
-       return false;
 }
 
 static int get_ipl(void)
@@ -4035,7 +4184,7 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool
        uae_u16 opc = regs.ir;
        int off = opcode_memory_address - opcode_memory_start + 2;
        uae_u16 opw1 = (opcode_memory[off + 0] << 8) | (opcode_memory[off + 1] << 0);
-       uae_u16 opw2 = (opcode_memory[off + 2] << 8) | (opcode_memory[off + 2] << 0);
+       uae_u16 opw2 = (opcode_memory[off + 2] << 8) | (opcode_memory[off + 3] << 0);
        if (opc == 0x4e72
                && opw1 == 0xa000
                //&& opw2 == 0x4afc
@@ -4072,16 +4221,37 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool
        exception_extra_frame_type = 0;
        cpu_cycles = 0;
        regs.loop_mode = 0;
-       regs.ipl_pin = 0;
+       regs.ipl_pin = feature_initial_interrupt;
+       interrupt_level = regs.ipl_pin;
        regs.ipl[0] = regs.ipl[1] = 0;
+       regs.ipl_evt_pre = 0;
+       regs.ipl_evt = 0;
        interrupt_level = 0;
        interrupt_cycle_cnt = 0;
        test_exception_orig = 0;
+       waitstate_cycle_cnt = 0;
+       cpuipldelay2 = 2;
+       cpuipldelay4 = 4;
 
        int cnt = 2;
        uaecptr first_pc = regs.pc;
        uae_u32 loop_mode_reg = 0;
        int stop_count = 0;
+       bool starts = regs.s;
+       int startimask = regs.intmask;
+       bool imaskintprevented = false;
+
+       if (regs.ipl_pin > regs.intmask) {
+               wprintf(_T("Interrupt immediately active! IPL=%d IMASK=%d\n"), regs.ipl_pin, regs.intmask);
+               abort();
+       }
+       if (feature_interrupts == 1) {
+               check_interrupts();
+               if (regs.ipl_pin > regs.intmask) {
+                       Exception(24 + regs.ipl_pin);
+                       goto end;
+               }
+       }
 
        if (feature_loop_mode_68010) {
                // 68010 loop mode
@@ -4093,9 +4263,6 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool
        if (multi_mode) {
                cnt = 100;
        }
-       if (feature_interrupts >= 2) {
-               interrupt_cycle_cnt = INTERRUPT_CYCLES;
-       }
 
        for (;;) {
 
@@ -4119,9 +4286,7 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool
                        do_trace();
                }
 
-               if (check_interrupts()) {
-                       break;
-               }
+               check_interrupts();
 
                regs.instruction_pc = regs.pc;
                regs.fp_ea_set = false;
@@ -4143,10 +4308,11 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool
                        }
                }
 
-               (*cpufunctbl[opc])(opc);
+               test_opcode = opc;
+               (*cpufunctbl_noret[opc])(opc);
 
                if (fpumode) {
-                       // skip result has too large or small exponent
+                       // skip result if it has too large or small exponent
                        for (int i = 0; i < 8; i++) {
                                if (regs.fp[i].fpx.high != cur_regs.fp[i].fpx.high || regs.fp[i].fpx.low != cur_regs.fp[i].fpx.low) {
                                        int exp = regs.fp[i].fpx.high & 0x7fff;
@@ -4176,11 +4342,6 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool
                        break;
                }
 
-               // CPU stopped or was reset: skip
-               if (cpu_stopped && feature_interrupts < 2) {
-                       break;
-               }
-
                // Supervisor mode and A7 was modified and not RTE+stack mode: skip this test round.
                if (s && regs.s && regs.regs[15] != a7 && (dp->mnemo != i_RTE || feature_usp < 3)) {
                        // but not if RTE
@@ -4206,23 +4367,51 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool
                        break;
                }
 
-               if (get_ipl() > regs.intmask) {
-                       Exception(24 + get_ipl());
-                       break;
-               }
-               regs.ipl[0] = regs.ipl[1];
-               regs.ipl[1] = 0;
-
-               if ((regs.pc == endpc || regs.pc == targetpc) && !cpu_stopped && feature_interrupts < 2) {
+               if (((regs.pc == endpc && feature_interrupts < 2) || (regs.pc == targetpc && feature_interrupts < 2)) && !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) {
                                Exception(9);
+                               break;
                        }
+               }
 
-                       break;
+               if (feature_interrupts >= 1) {
+                       if (SPCFLAG_DOTRACE) {
+                               if (trace_store_pc != 0xffffffff) {
+                                       wprintf(_T(" Full trace in interrupt mode!?\n"));
+                                       abort();
+                               }
+                               MakeSR();
+                               if (cpu_stopped) {
+                                       cpu_stopped = 0;
+                                       m68k_incpci(4);
+                                       regs.ir = get_iword_test(regs.pc + 0);
+                                       regs.irc = get_iword_test(regs.pc + 2);
+                               }
+                               trace_store_pc = regs.pc;
+                               trace_store_sr = regs.sr;
+                               SPCFLAG_DOTRACE = 0;
+                               // pending interrupt always triggers during trace processing
+                               regs.ipl[0] = regs.ipl_pin;
+                       }
+               }
+
+               int ipl = get_ipl();
+               if (ipl > 0) {
+                       if (ipl > regs.intmask) {
+                               Exception(24 + ipl);
+                               break;
+                       }
+                       if (ipl > startimask && ipl <= regs.intmask && !imaskintprevented) {
+                               printf("*");
+                               imaskintprevented = true;
+                       }
                }
 
+               regs.ipl[0] = regs.ipl[1];
+               regs.ipl[1] = 0;
+
                if (test_exception) {
                        break;
                }
@@ -4233,6 +4422,10 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool
                if (!feature_loop_mode_jit && !feature_loop_mode_68010) {
                        // trace after NOP
                        if (SPCFLAG_DOTRACE) {
+                               if (feature_interrupts == 3) {
+                                       Exception(9);
+                                       break;
+                               }
                                MakeSR();
                                // store only first
                                if (trace_store_pc == 0xffffffff) {
@@ -4266,6 +4459,7 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool
                opc = regs.ir;
        }
 
+end:
        test_exception_orig = test_exception;
 
        // if still stopped: skip test
@@ -4274,8 +4468,12 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool
        }
 
        if (feature_interrupts >= 2) {
-               // Skip test if end exception
-               if (regs.pc == endpc || regs.pc == targetpc) {
+               // Skip test if end exception and no prevented interrupt
+               if ((regs.pc == endpc || regs.pc == targetpc) && !imaskintprevented) {
+                       test_exception = -1;
+               }
+               // skip if check or privilege violation
+               if (test_exception == 6 || test_exception == 8) {
                        test_exception = -1;
                }
                // Skip test if no exception
@@ -4288,11 +4486,18 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool
                if (test_exception >= 24 && test_exception <= 24 + 8) {
                        if (test_exception_addr != opcode_memory_address &&
                                test_exception_addr != opcode_memory_address - 2 &&
+                               test_exception_addr != test_instruction_end_pc - 4 &&
+                               test_exception_addr != test_instruction_end_pc - 2 &&
                                test_exception_addr != test_instruction_end_pc &&
-                               test_exception_addr != branch_target) {
+                               test_exception_addr != branch_target &&
+                               test_exception_addr != branch_target + 2) {
                                test_exception = -1;
                        }
                }
+               if (starts && (test_exception >= 24 && test_exception <= 24 + 8)) {
+                       printf("");
+               }
+
        }
 
        testing_active = 0;
@@ -4630,7 +4835,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
        int quick = 0;
        int rounds = feature_test_rounds;
        int data_saved = 0;
-       int first_cycles = 1;
+       int first_save = 1;
 
        int count = 0;
 
@@ -4641,6 +4846,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
        }
 
        ignore_register_mask = 0;
+       ignore_register_mask |= 1 << 15; // SP
        if (feature_loop_mode_register >= 0) {
                ignore_register_mask |= 1 << feature_loop_mode_register;
        }
@@ -4727,8 +4933,9 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
        full_format_cnt = 0;
        last_exception_len = -1;
        interrupt_count = 0;
-
        interrupt_delay_cnt = 0;
+       interrupt_pc = 0;
+       waitstate_delay_cnt = 0;
 
        int sr_override = 0;
 
@@ -4791,7 +4998,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                        }
                        dst = store_reg(dst, CT_FPIAR, 0, cur_regs.fpiar, -1);
                }
-               cur_regs.sr = feature_min_interrupt_mask << 8;
+               cur_regs.sr = feature_initial_interrupt_mask << 8;
 
                uae_u32 srcaddr_old = 0xffffffff;
                uae_u32 dstaddr_old = 0xffffffff;
@@ -4832,6 +5039,8 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                // skip all unsupported instructions if not specifically testing i_ILLG
                                if (dp->clev > cpu_lvl)
                                        continue;
+                               if (dp->ccuse && !(feature_condition_codes & (1 << dp->cc)))
+                                       continue;
                        }
 
                        if (feature_loop_mode_68010) {
@@ -4897,6 +5106,9 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                constant_loops = 1;
                                        }
                                }
+                               if (feature_interrupts) {
+                                       constant_loops = 1;
+                               }
 
                                while (constant_loops-- > 0) {
                                        uae_u8 oldcodebytes[OPCODE_AREA];
@@ -4938,6 +5150,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        test_exception_extra = 0;
                                        lm_safe_address1 = 0xffffffff;
                                        lm_safe_address2 = 0xffffffff;
+                                       test_absw = 0;
 
                                        target_ea[0] = target_ea_bak[0];
                                        target_ea[1] = target_ea_bak[1];
@@ -4982,15 +5195,17 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        // interrupt IPL timing test mode
                                        if (feature_interrupts >= 2) {
                                                pc -= 2;
-                                               // 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
+                                               if (!feature_waitstates) {
+                                                       // 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
+                                                       }
+                                                       pc += 2;
                                                }
-                                               pc += 2;
 #if IPL_TRIGGER_ADDR_SIZE == 1
                                                // move.b #x,xxx.L (4 * 4 + 4)
                                                put_long_test(pc, (0x13fc << 16) | IPL_TRIGGER_DATA);
@@ -5026,20 +5241,30 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                // ror.l d0,d0 (4 + 4 + d0 * 2 cycles)
                                                put_word_test(pc, 0xe0b8);
                                                pc += 2;
-                                               // restore CCR
-                                               // move d7,ccr
-                                               put_word_test(pc, 0x44c7); // 12 cycles
-                                               pc += 2;
-                                               put_word_test(pc, NOP_OPCODE); // 4 cycles
-                                               pc += 2;
-                                               put_word_test(pc, NOP_OPCODE); // 4 cycles
+                                               if (feature_waitstates) {
+                                                       // move.w #x,0xdff058
+                                                       put_long_test(pc, (0x33fc << 16) | (2 * 64 + 63));
+                                                       pc += 4;
+                                                       put_long_test(pc, IPL_BLTSIZE);
+                                                       pc += 4;
+                                                       // lsl.b #1+,d0
+                                                       put_word_test(pc, 0xe308 + waitstate_delay_cnt * 0x200); // 4+n*2 cycles
+                                                       pc += 2;
+                                               }
+                                               if (!feature_waitstates) {
+                                                       // restore CCR
+                                                       // move d7, ccr
+                                                       put_word_test(pc, 0x44c7); // 12 cycles
+                                                       pc += 2;
+                                               }
+                                               put_word_test(pc, REAL_NOP_OPCODE); // 4 cycles
                                                pc += 2;
                                                if (feature_interrupts >= 3) {
                                                        // or #$8000,sr
                                                        put_long_test(pc, 0x007c8000);
                                                        pc += 4;
                                                } else {
-                                                       put_word_test(pc, NOP_OPCODE); // 4 cycles
+                                                       put_word_test(pc, IPL_TEST_NOP1); // 4 cycles
                                                        pc += 2;
                                                }
                                                opcode_memory_address = pc;
@@ -5185,6 +5410,11 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
 
                                        }
 
+                                       if (feature_interrupts >= 2) {
+                                               put_long_test(pc, (IPL_TEST_NOP2 << 16) | REAL_NOP_OPCODE); // 8 cycles
+                                               pc += 4;
+                                       }
+
                                        // if bus error stack checking and RTE: copy USP to ISP before RTE
                                        if (dp->mnemo == i_RTE && feature_usp == 3) {
                                                put_word_test(opcode_memory_address, 0x4e6f); // MOVE USP,A7
@@ -5348,9 +5578,6 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        srcaddr = 0xffffffff;
                                        dstaddr = 0xffffffff;
 
-                                       if (opc == 0x4efb && get_word_debug(opcode_memory_address + 2) == 0x06d4)
-                                               printf("");
-
                                        uae_u32 dflags = m68k_disasm_2(out, sizeof(out) / sizeof(TCHAR), opcode_memory_address, NULL, 0, &nextpc, 1, &srcaddr, &dstaddr, 0xffffffff, 0);
                                        if (verbose) {
                                                my_trim(out);
@@ -5375,10 +5602,6 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                }
                                        }
 
-
-                                       if (srcaddr == 0x006b022e)
-                                               printf("");
-                                       
                                        // disassembler may set this
                                        out_of_test_space = false;
 
@@ -5523,11 +5746,11 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                }
                                        }
 
-                                       if (subtest_count == 262144)
+                                       if (subtest_count > 0)
                                                printf("");
 
                                        // save opcode memory
-                                       dst = store_mem_bytes(dst, opcode_memory_start, instruction_end_pc - opcode_memory_start, oldcodebytes, true);
+                                       dst = store_mem_bytes(dst, opcode_memory_start, instruction_end_pc - opcode_memory_start, oldcodebytes);
 
                                        // store branch target and stack modifications (these needs to be rolled back after the test)
                                        dst = store_mem_writes(dst, 1);
@@ -5565,6 +5788,12 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                dst = store_reg(dst, CT_AREG + 7, 0, target_usp_address, sz_long);
                                        }
 
+                                       if (feature_interrupts >= 2) {
+                                               *dst++ = CT_EDATA;
+                                               *dst++ = CT_EDATA_IRQ_CYCLES;
+                                               *dst++ = interrupt_delay_cnt;
+                                       }
+
                                        // pre-test data end
                                        *dst++ = CT_END_INIT;
 
@@ -5761,7 +5990,10 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                        } else {
                                                                regs.sr = ((ccr & 1) ? 31 : 0) | sr_mask;
                                                        }
-                                                       regs.sr |= feature_min_interrupt_mask << 8;
+                                                       if (feature_initial_interrupt_mask > ((regs.sr >> 8) & 7)) {
+                                                               regs.sr &= ~(7 << 8);
+                                                               regs.sr |= feature_initial_interrupt_mask << 8;
+                                                       }
 
                                                        // override special register values
                                                        for (int i = 0; i < regdatacnt; i++) {
@@ -5787,7 +6019,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                        if (regs.sr & 0x2000)
                                                                prev_s_cnt++;
 
-                                                       if (subtest_count == 77171)
+                                                       if (subtest_count == 9)
                                                                printf("");
 
                                                        // execute test instruction(s)
@@ -5901,10 +6133,12 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                        } else if (test_exception) {
                                                                // generated exception
                                                                exception_array[test_exception]++;
-                                                               if (test_exception == 8 && !(sr_mask & 0x2000) && !(feature_sr_mask & 0x2000)) {
-                                                                       // Privilege violation exception and S mask not set? Switch to super mode in next round.
-                                                                       sr_mask_request |= 0x2000;
-                                                                       sr_allowed_mask |= 0x2000;
+                                                               if (test_exception == 8) {
+                                                                       if (!(sr_mask & 0x2000) && !(feature_sr_mask & 0x2000)) {
+                                                                               // Privilege violation exception and S mask not set? Switch to super mode in next round.
+                                                                               sr_mask_request |= 0x2000;
+                                                                               sr_allowed_mask |= 0x2000;
+                                                                       }
                                                                }
                                                                // got exception 3 but didn't want them?
                                                                if (test_exception == 3) {
@@ -5988,21 +6222,21 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                                for (int i = 0; i < MAX_REGISTERS; i++) {
                                                                        uae_u32 s = last_regs.regs[i];
                                                                        uae_u32 d = regs.regs[i];
-                                                                       if (s != d) {
+                                                                       if (s != d || first_save) {
                                                                                if (storeregs) {
-                                                                                       dst = store_reg(dst, CT_DREG + i, s, d, -1);
+                                                                                       dst = store_reg(dst, CT_DREG + i, s, d, first_save ? sz_long : -1);
                                                                                }
                                                                                last_regs.regs[i] = d;
                                                                        }
                                                                }
                                                                // SR/CCR
                                                                uae_u32 ccrignoremask = get_ccr_ignore(dp, extraword, false) << 16;
-                                                               if ((regs.sr | ccrignoremask) != last_regs.sr) {
-                                                                       dst = store_reg(dst, CT_SR, last_regs.sr, regs.sr | ccrignoremask, -1);
+                                                               if ((regs.sr | ccrignoremask) != last_regs.sr || first_save) {
+                                                                       dst = store_reg(dst, CT_SR, last_regs.sr, regs.sr | ccrignoremask, first_save ? sz_word : -1);
                                                                        last_regs.sr = regs.sr | ccrignoremask;
                                                                }
                                                                // PC
-                                                               if (regs.pc - extraopcodeendsize != last_regs.pc) {
+                                                               if (regs.pc - extraopcodeendsize != last_regs.pc || first_save) {
                                                                        dst = store_rel(dst, CT_PC, last_regs.pc, regs.pc - extraopcodeendsize, 0);
                                                                        last_regs.pc = regs.pc - extraopcodeendsize;
                                                                }
@@ -6011,29 +6245,31 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                                        for (int i = 0; i < 8; i++) {
                                                                                floatx80 s = last_regs.fp[i].fpx;
                                                                                floatx80 d = regs.fp[i].fpx;
-                                                                               if (s.high != d.high || s.low != d.low) {
+                                                                               if (s.high != d.high || s.low != d.low || first_save) {
                                                                                        dst = store_fpureg(dst, CT_FPREG + i, &s, d, 0);
                                                                                        last_regs.fp[i].fpx = d;
                                                                                }
                                                                        }
-                                                                       if (regs.fpiar != last_regs.fpiar) {
-                                                                               dst = store_reg(dst, CT_FPIAR, last_regs.fpiar, regs.fpiar, -1);
+                                                                       if (regs.fpiar != last_regs.fpiar || first_save) {
+                                                                               dst = store_reg(dst, CT_FPIAR, last_regs.fpiar, regs.fpiar, first_save  ? sz_long : -1);
                                                                                last_regs.fpiar = regs.fpiar;
                                                                        }
-                                                                       if (regs.fpsr != last_regs.fpsr) {
-                                                                               dst = store_reg(dst, CT_FPSR, last_regs.fpsr, regs.fpsr, -1);
+                                                                       if (regs.fpsr != last_regs.fpsr || first_save) {
+                                                                               dst = store_reg(dst, CT_FPSR, last_regs.fpsr, regs.fpsr, first_save ? sz_long : -1);
                                                                                last_regs.fpsr = regs.fpsr;
                                                                        }
-                                                                       if (regs.fpcr != last_regs.fpcr) {
-                                                                               dst = store_reg(dst, CT_FPCR, last_regs.fpcr, regs.fpcr, -1);
+                                                                       if (regs.fpcr != last_regs.fpcr || first_save) {
+                                                                               dst = store_reg(dst, CT_FPCR, last_regs.fpcr, regs.fpcr, first_save ? sz_long : -1);
                                                                                last_regs.fpcr = regs.fpcr;
                                                                        }
                                                                }
-                                                               if (cpu_lvl <= 1 && (last_cpu_cycles != cpu_cycles || first_cycles)) {
-                                                                       dst = store_reg(dst, CT_CYCLES, last_cpu_cycles, cpu_cycles, first_cycles  ? sz_word : -1);
+                                                               if (cpu_lvl <= 1 && (last_cpu_cycles != cpu_cycles || first_save)) {
+                                                                       dst = store_reg(dst, CT_CYCLES, last_cpu_cycles, cpu_cycles, first_save ? sz_word : -1);
                                                                        last_cpu_cycles = cpu_cycles;
-                                                                       first_cycles = 0;
                                                                }
+
+                                                               first_save = 0;
+
                                                                // store test instruction generated changes
                                                                dst = store_mem_writes(dst, 0);
                                                                uae_u8 bcflag = regs.pc == branch_target_pc ? CT_BRANCHED : 0;
@@ -6115,10 +6351,10 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                }
                                        }
                                        if (verbose) {
-                                               wprintf(_T(" OK=%d OB=%d S=%d/%d T=%d STP=%d I=%d/%d EX=%d %08x %08x"), ok, exception_array[0],
+                                               wprintf(_T(" OK=%d OB=%d S=%d/%d T=%d S=%d I=%d/%d EX=%d %08x %08x %08x"), ok, exception_array[0],
                                                        prev_s_cnt, s_cnt, t_cnt, cnt_stopped, interrupt_delay_cnt, interrupt_cycle_cnt,
                                                        test_exception_orig,
-                                                       test_exception_addr, regs.pc);
+                                                       test_exception_addr, regs.pc, interrupt_pc);
                                                if (!ccr_done)
                                                        wprintf(_T(" X"));
                                                for (int i = 2; i < 128; i++) {
@@ -6212,7 +6448,15 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
 
                // interrupt delay test
                if (feature_interrupts >= 2) {
-                       interrupt_delay_cnt++;
+                       if (feature_waitstates) {
+                               waitstate_delay_cnt++;
+                               if (waitstate_delay_cnt >= 3) {
+                                       waitstate_delay_cnt = 0;
+                                       interrupt_delay_cnt++;
+                               }
+                       } else {
+                               interrupt_delay_cnt++;
+                       }
                        if (interrupt_delay_cnt > 2 * 63) {
                                break;
                        } else {
@@ -6447,6 +6691,12 @@ static const TCHAR *addrmodes[] =
        _T("absw"), _T("absl"), _T("PC16"), _T("PC8r"), _T("imm"), _T("Ad8rf"), _T("PC8rf"),
        NULL
 };
+static const TCHAR *ccnames[] =
+{
+       _T("T"), _T("F"), _T("HI"),_T("LS"),_T("CC"),_T("CS"),_T("NE"),_T("EQ"),
+       _T("VC"),_T("VS"),_T("PL"),_T("MI"),_T("GE"),_T("LT"),_T("GT"),_T("LE")
+};
+
 
 #define INISECTION _T("cputest")
 
@@ -6717,6 +6967,7 @@ static int test(struct ini_data *ini, const TCHAR *sections, const TCHAR *testna
        feature_addressing_modes[1] = 0xffffffff;
        ad8r[0] = ad8r[1] = 1;
        pc8r[0] = pc8r[1] = 1;
+       feature_condition_codes = 0xffffffff;
 
        feature_exception3_data = 0;
        ini_getvalx(ini, sections, _T("feature_exception3_data"), &feature_exception3_data);
@@ -6869,6 +7120,12 @@ static int test(struct ini_data *ini, const TCHAR *sections, const TCHAR *testna
        feature_undefined_ccr = 0;
        ini_getvalx(ini, sections, _T("feature_undefined_ccr"), &feature_undefined_ccr);
 
+       feature_initial_interrupt = 0;
+       ini_getvalx(ini, sections, _T("feature_initial_interrupt"), &feature_initial_interrupt);
+
+       feature_initial_interrupt_mask = 0;
+       ini_getvalx(ini, sections, _T("feature_initial_interrupt_mask"), &feature_initial_interrupt_mask);
+
        feature_min_interrupt_mask = 0;
        ini_getvalx(ini, sections, _T("feature_min_interrupt_mask"), &feature_min_interrupt_mask);
 
@@ -6900,6 +7157,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_waitstates = 0;
+       ini_getvalx(ini, sections, _T("feature_waitstates"), &feature_waitstates);
 
        feature_full_extension_format = 0;
        if (currprefs.cpu_model >= 68020) {
@@ -6953,6 +7212,29 @@ static int test(struct ini_data *ini, const TCHAR *sections, const TCHAR *testna
                }
        }
 
+       TCHAR *cc = NULL;
+       if (ini_getstringx(ini, sections, _T("feature_condition_codes"), &cc)) {
+               feature_condition_codes = 0;
+               TCHAR *p = cc;
+               while (p && *p) {
+                       TCHAR *pp = _tcschr(p, ',');
+                       if (pp) {
+                               *pp++ = 0;
+                       }
+                       TCHAR cctext[256];
+                       _tcscpy(cctext, p);
+                       my_trim(cctext);
+                       for (int i = 0; ccnames[i]; i++) {
+                               if (!_tcsicmp(ccnames[i], cctext)) {
+                                       feature_condition_codes |= 1 << i;
+                                       break;
+                               }
+                       }
+                       p = pp;
+               }
+               xfree(cc);
+       }
+
 
        TCHAR *mode = NULL;
        ini_getstringx(ini, sections, _T("mode"), &mode);
@@ -7198,11 +7480,12 @@ static int test(struct ini_data *ini, const TCHAR *sections, const TCHAR *testna
 
        for (int opcode = 0; opcode < 65536; opcode++) {
                cpufunctbl[opcode] = op_illg_1;
+               cpufunctbl_noret[opcode] = op_illg_1_noret;
        }
-
-       for (int i = 0; tbl[i].handler_ff != NULL; i++) {
+       for (int i = 0; tbl[i].handler_ff != NULL || tbl[i].handler_ff_noret != NULL; i++) {
                int opcode = tbl[i].opcode;
                cpufunctbl[opcode] = tbl[i].handler_ff;
+               cpufunctbl_noret[opcode] = tbl[i].handler_ff_noret;
                cpudatatbl[opcode].length = tbl[i].length;
                cpudatatbl[opcode].disp020[0] = tbl[i].disp020[0];
                cpudatatbl[opcode].disp020[1] = tbl[i].disp020[1];
@@ -7210,7 +7493,6 @@ static int test(struct ini_data *ini, const TCHAR *sections, const TCHAR *testna
        }
 
        for (int opcode = 0; opcode < 65536; opcode++) {
-               cpuop_func *f;
                instr *table = &table68k[opcode];
 
                if (table->mnemo == i_ILLG)
@@ -7224,6 +7506,7 @@ static int test(struct ini_data *ini, const TCHAR *sections, const TCHAR *testna
                                // generates unimplemented instruction exception.
                                if (currprefs.int_no_unimplemented && table->unimpclev == 5) {
                                        cpufunctbl[opcode] = op_unimpl_1;
+                                       cpufunctbl_noret[opcode] = op_unimpl_1_noret;
                                        continue;
                                }
                                // remove unimplemented instruction that were removed in previous models,
@@ -7232,10 +7515,11 @@ static int test(struct ini_data *ini, const TCHAR *sections, const TCHAR *testna
                                // clev=4: implemented in 68040 or later. unimpclev=5: not in 68060
                                if (table->unimpclev < 5 || (table->clev == 4 && table->unimpclev == 5)) {
                                        cpufunctbl[opcode] = op_illg_1;
+                                       cpufunctbl_noret[opcode] = op_illg_1_noret;
                                        continue;
                                }
                        } else {
-                               cpufunctbl[opcode] = op_illg_1;
+                               cpufunctbl_noret[opcode] = op_illg_1_noret;
                                continue;
                        }
                }
@@ -7252,10 +7536,10 @@ static int test(struct ini_data *ini, const TCHAR *sections, const TCHAR *testna
 
                if (table->handler != -1) {
                        int idx = table->handler;
-                       f = cpufunctbl[idx];
-                       if (f == op_illg_1)
+                       if (cpufunctbl[idx] == op_illg_1 || cpufunctbl_noret[idx] == op_illg_1_noret)
                                abort();
-                       cpufunctbl[opcode] = f;
+                       cpufunctbl[opcode] = cpufunctbl[idx];
+                       cpufunctbl_noret[opcode] = cpufunctbl_noret[idx];
                        memcpy(&cpudatatbl[opcode], &cpudatatbl[idx], sizeof(struct cputbl_data));
                }
 
index 2470430a40a5fad026044ad397864f6ab01fcb18..6fe792c63d15ab2e0b5807d68a97e7e028281b2d 100644 (file)
@@ -6,6 +6,8 @@
        
        .globl _allocate_absolute
        .globl _free_absolute
+       .globl _allocate_blttemp
+       .globl _free_blttemp
        .globl _touser
        .globl _tosuper
        .globl _testexit
@@ -44,12 +46,29 @@ uaefuncname:
        .asciz "uaelib_demux"
 
 sync:
+       move.l a1,d0
+       lea 0xdff040,a1
+       move.w #0x0400+0x200+0x0100,(a1)+ | BCD
+       move.w #0x0000,(a1)+
+       addq.l #4,a1
+       move.l d0,(a1)+ | A
+       move.l d0,(a1)+ | B
+       move.l d0,(a1)+ | C
+       move.l d0,(a1)+ | D
        move.b 0xdff006,d0
        beq.s sync
-       cmp.b #0xff,d0
-       beq.s sync
-       cmp.b #0x38,d0
-       beq.s sync
+       cmp.b #0xfc,d0
+       bcc.s sync
+       cmp.b #0x34,d0
+       bcs.s sync2
+       cmp.b #0x39,d0
+       bcs.s sync
+sync2:
+       move.b 0xdff007,d0
+       cmp.b #110,d0
+       bcs.s sync2
+       cmp.b #130,d0
+       bcc.s sync2
        | above prevent wraparound between
        | dff004.w and dff006.w reads
        move.l 0xdff004,d0
@@ -70,9 +89,11 @@ _tosuper:
        move.l 4.w,a6
        jsr -0x78(a6) | Disable
        jsr -0x96(a6) | SuperState
+       move.w 0xdff002,dmacon
        tst.l 8+1*4(sp)
        beq.s .keepdisplay
-       move.w #0x0200,0xdff096
+       move.w #0x7fff,0xdff096
+       move.w #0x8000+0x0400+0x0200+0x0040,0xdff096
 .keepdisplay:
        move.w #0x2700,sr
        move.l (sp)+,a6
@@ -84,7 +105,10 @@ _touser:
        move.l 4.w,a6
        move.l 8(sp),d0
        jsr -0x9c(a6) | UserState
-       move.w #0x8200,0xdff096
+       move.w #0x7fff,0xdff096
+       move.w dmacon,d0
+       or.w #0x8000,d0
+       move.w d0,0xdff096
        jsr -0x7e(a6) | Enable
        move.l (sp)+,a6
        rts
@@ -109,6 +133,24 @@ _allocate_absolute:
        move.l (sp)+,a6
        rts
 
+_allocate_blttemp:
+       move.l a6,-(sp)
+       move.l 8(sp),d0
+       move.l #65536+2,d1
+       move.l 4.w,a6
+       jsr -0xc6(a6) | AllocMem
+       move.l (sp)+,a6
+       rts
+_free_blttemp:
+       move.l a6,-(sp)
+       move.l 8(sp),a1
+       move.l 12(sp),d0
+       move.l 4.w,a6
+       jsr -0xd2(a6) | FreeMem
+       move.l (sp)+,a6
+       rts
+
+
        | return CPU model (68000=0, 68010=1, 68020=2, 68030=3, 68040=4, 68060=5)
 _get_cpu_model:
        move.l 4.w,a0
@@ -151,4 +193,7 @@ illg:
        move.l a1,sp
        rte
 
+dmacon:
+       dc.l 0
+
        .include "asm.S"
index 0d2616e5f8b862e5804c5faa9e7aee88a2979638..79ef69c5aeb8d6d9bcd268950ce721a03ce6d97a 100644 (file)
@@ -43,7 +43,8 @@ S_TRACESTACK = S_TRACECNT+4
 S_CYCLES = S_TRACESTACK+12
 S_CYCLES2 = S_CYCLES+4
 S_CYCLEST = S_CYCLES2+4
-S_FPU = S_CYCLEST+4
+S_BLTTEMP = S_CYCLEST+4
+S_FPU = S_BLTTEMP+4
 S_FPIAR = S_FPU+8*12
 S_FPCR = S_FPIAR+4
 S_FPSR = S_FPCR+4
@@ -202,6 +203,7 @@ _execute_test000:
        move.w S_SR+2(a0),-(sp)
        move.l S_AREG+7*4(a0),a1
        move.l a1,USP
+       move.l S_BLTTEMP(a0),a1
        bsr sync
        move.l d0,S_CYCLES2(a0)
        movem.l (a0),d0-d7/a0-a6
@@ -292,6 +294,7 @@ exception_trace000:
        move.w sr,-(sp)
 _cyclereg_address3:
        move.w CYCLEREG,cycles+4
+       | pop SR and bsr.s exception_trace000
        addq.l #2+4,sp
        move.l a0,-(sp)
        move.l datapointer(pc),a0
@@ -364,16 +367,23 @@ _cyclereg_address4:
        bcs.s .okpc
        cmp.l #asm_end,2+4+2(sp)
        bhi.s .okpc
-       | interrupt?
-       cmp.l #_exceptiontable000+24*2,2(sp)
-       bcs.s .okpc
-       cmp.l #_exceptiontable000+(24+8)*2,2(sp)
-       bcc.s .okpc
-       | possibly IPL tester spurious interrupt
-       | ignore it. Mark cycle count as invalid.
-#ifdef AMIGA
-       move.w #0x0800,0xdff09c
-#endif
+       move.w #0x7fff,0xdff09c
+       | Interrupt exception interrupted trace?
+       cmp.l #_exceptiontable000+(9-2)*2,2+4+2(sp)
+       bne.s .notokpc
+       | Store trace, copy trace PC/SR to interrupt PC/SR
+       move.l a0,-(sp)
+       move.l datapointer(pc),a0
+       move.l 4+2+6+4+0(sp),S_TRACESTACK(a0)
+       move.l 4+2+6+4+4(sp),S_TRACESTACK+4(a0)
+       | set exception PC and SR same as Trace
+       move.w 4+2+6+4+0(sp),4+2+4+0(sp)
+       move.l 4+2+6+4+2(sp),4+2+4+2(sp)
+       addq.l #1,S_TRACECNT(a0)
+       move.l (sp)+,a0
+       bra.s .okpc
+.notokpc:
+       | Mark cycle count as invalid.
        move.l #0xffffffff,cycles
        addq.l #2+4,sp
        rte
@@ -404,7 +414,7 @@ _cyclereg_address4:
        cmp.w #24+8,d0
        bcc.s .nointerrupt
 #ifdef AMIGA
-       move.w #0x0800,0xdff09c
+       move.w #0x7fff,0xdff09c
 #endif
 .nointerrupt:
 
index 8c79a2e59e7eac029058cb26accd842ce3fa22a0..c4a9af13264d6f990c2367975e215ba9c464525c 100644 (file)
@@ -1,5 +1,5 @@
 
-#define DATA_VERSION 23
+#define DATA_VERSION 24
 
 #define CT_FPREG 0
 #define CT_DREG 0
 // MOVEA.L A0,A0
 // not NOP because on 68040 NOP generates T0 trace.
 #define NOP_OPCODE 0x2048
+#define REAL_NOP_OPCODE 0x4e71
 #define ILLG_OPCODE 0x4afc
 #define LM_OPCODE 0x42db
 
+#define IPL_TEST_NOP1 0x4e71
+#define IPL_TEST_NOP2 0x4e71
+
 #define IPL_TRIGGER_ADDR 0xdff030
 #define IPL_TRIGGER_ADDR_SIZE 2
-#define IPL_TRIGGER_DATA 0x100
+#define IPL_TRIGGER_DATA (0x100 | 0xCA)
 #define IPL_TRIGGER_SERPER 10
-#define INTERRUPT_CYCLES ((((IPL_TRIGGER_SERPER + 1) * 9) + (((IPL_TRIGGER_SERPER + 1) - 1) / 2) + 1 + 3 + 9) * 2)
+#define INTERRUPT_CYCLES ((((IPL_TRIGGER_SERPER + 1) * 9) + (((IPL_TRIGGER_SERPER + 1) - 1) / 2) + 1 + 3 + 9 + 0) * 2)
 #define IPL_TRIGGER_INTMASK 0x0800
 #define IPL_TEST_IPL_LEVEL 5
+#define IPL_BLTSIZE 0xdff058
index 69e139aebf81487de420e91957579cdd340713cb..3af7dcda45170b500c539b6069f9a433e4e28f69 100644 (file)
@@ -139,12 +139,18 @@ exceptions=
 ; 2 = always all zeros and all ones only
 feature_flags_mode=1
 
+; SR initial interrupt mask
+feature_initial_interrupt_mask=0
+
 ; SR min interrupt mask
 ; Amiga: can be zero.
 ; Atari ST: should be 4 or larger.
 ; Skips all tests that would set lower interrupt mask.
 feature_min_interrupt_mask=0
 
+; Initial active interrupt level, 0 to 6. (Amiga only)
+feature_initial_interrupt=0
+
 ; Interrupt test
 ; 1 = interrupt request is set before test.
 ; Tests all INTREQ bits one by one. Compatible with cycle count mode.
@@ -202,6 +208,11 @@ feature_full_extension_format=0
 feature_addressing_modes_src=
 feature_addressing_modes_dst=
 
+; empty = all condition codes
+; T, F, HI, LS, CC etc.. select condition codes to generate. All others will be skipped.
+; Xcc instructions only.
+feature_condition_codes=
+
 ; Limit test instruction size
 ; B = byte, W = word, L = long, empty = no size limit
 ; FPU only: S = single, D = double, X = extended, P = packed
@@ -234,10 +245,27 @@ feature_sr_mask=0x8000
 [test=BASIC]
 cpu=68000-68010
 enabled=0
+verbose=0
 feature_sr_mask=0x8000
 feature_undefined_ccr=1
 mode=all
 
+; interrupt timing test with waitstates
+[test=WIPL]
+cpu=68000-68010
+enabled=1
+verbose=0
+feature_undefined_ccr=1
+feature_interrupts=2
+feature_waitstates=2
+#feature_addressing_modes_src=dreg
+feature_condition_codes=
+# wait state mode requires use of chip ram
+test_memory_start=0xd0000
+test_memory_size=0x20000
+rnd_seed=10
+mode=btst.b
+
 ; interrupt timing test
 [test=IPL]
 cpu=68000-68010
@@ -245,17 +273,33 @@ enabled=1
 verbose=0
 feature_undefined_ccr=1
 feature_interrupts=2
-;feature_sr_mask=0x2100
-mode=all
+feature_sr_mask=0x2000
+#feature_addressing_modes_dst=apdi
+feature_condition_codes=pl
+rnd_seed=10
+mode=btst.b
+
+; STOP/SR modification timing special test
+[test=SR]
+cpu=68000-68010
+enabled=0
+verbose=0
+feature_undefined_ccr=1
+feature_interrupts=1
+feature_initial_interrupt_mask=4
+feature_sr_mask=0x8000
+#mode=stop,eorsr.w,andsr.w,mvsr2.w,mv2sr.w
+mode=stop
 
 ; interrupt exception
 [test=IRQ]
 enabled=0
+verbose=0
 cpu=68000-68010
 feature_sr_mask=0x8000
 feature_interrupts=1
 feature_undefined_ccr=1
-mode=jsr,jmp,bsr,bcc,dbcc,nop,exg,swap,stop,mvsr2,mv2sr,andsr,eorsr,orsr
+mode=jsr,jmp,bsr,bcc,dbcc,nop,exg,swap,stop,mvsr2.w,mv2sr.w,andsr.w,eorsr.w,orsr.w
 min_opcode_test_rounds=100
 
 ; source EA address error
index dfab4727f93e4d060eefe045b3a1de1b8c3b73ac..76c60cbce878fdfba9282169d37240c6bca91908 100644 (file)
@@ -49,6 +49,7 @@ struct registers
        uae_u32 tracecnt;
        uae_u16 tracedata[6];
        uae_u32 cycles, cycles2, cyclest;
+       uae_u32 blttemp;
 
        struct fpureg fpuregs[8];
        uae_u32 fpiar, fpcr, fpsr;
@@ -77,6 +78,8 @@ static uae_u8 *test_memory;
 static uae_u32 test_memory_addr, test_memory_end;
 static uae_u32 test_memory_size;
 static uae_u8 *test_data;
+#define BLT_TEMP_SIZE 8000
+static uae_u32 blt_data;
 static uae_u8 *safe_memory_start, *safe_memory_end;
 static short safe_memory_mode;
 static uae_u32 user_stack_memory, super_stack_memory;
@@ -136,6 +139,8 @@ static uae_u8 ccr_mask;
 static uae_u32 fpsr_ignore_mask;
 static uae_u32 addressing_mask = 0x00ffffff;
 static uae_u32 interrupt_mask;
+static short initial_interrupt_mask;
+static short initial_interrupt;
 static short loop_mode_jit, loop_mode_68010, loop_mode_cnt;
 static short instructionsize;
 static short disasm;
@@ -163,6 +168,8 @@ static uae_u16 main_intena;
 static int prealloc_test_data_size = 1001000;
 static int prealloc_gzip_size = 500000;
 static int prealloc;
+static uae_u8 *debug_item_data;
+static short debug_item_count;
 
 #define SIZE_STORED_ADDRESS_OFFSET 6
 #define SIZE_STORED_ADDRESS 20
@@ -190,6 +197,13 @@ static uae_u8 *allocate_absolute(uae_u32 addr, uae_u32 size)
 static void free_absolute(uae_u32 addr, uae_u32 size)
 {
 }
+static uae_u8 *allocate_blttemp(uae_u32 size)
+{
+       return calloc(1, size);
+}
+static void free_blttemp(uae_u32 addr, uae_u32 size)
+{
+}
 static void execute_test000(struct registers *regs)
 {
 }
@@ -245,6 +259,8 @@ static void xmemcpy(void *d, void *s, int size)
 
 extern uae_u8 *allocate_absolute(uae_u32, uae_u32);
 extern void free_absolute(uae_u32, uae_u32);
+extern uae_u32 allocate_blttemp(uae_u32);
+extern void free_blttemp(uae_u32, uae_u32);
 extern void execute_test000(struct registers*);
 extern void execute_test010(struct registers *);
 extern void execute_test020(struct registers *);
@@ -454,7 +470,7 @@ static void start_test(void)
                                error_vectors[i - 2] = p[i];
                        }
                }
-               if (interrupttest) {
+               if (interrupttest || initial_interrupt_mask || initial_interrupt) {
                        for (int i = 24; i < 24 + 8; i++) {
                                p[i] = (uae_u32)(((uae_u32)&exceptiontable000) + (i - 2) * 2);
                                if (exception_vectors) {
@@ -618,7 +634,7 @@ static int load_file_offset(FILE *f, int *foffsetp)
        unsigned char buf[4] = { 0 };
        fseek(f, *foffsetp, SEEK_SET);
        fread(buf, 1, sizeof(buf), f);
-       if (buf[0] == 0xff && buf[1] == 0xff && buf[2] == 0xff && buf[3] == 0xff) {
+       if (buf[0] == 0xaf && buf[1] == 'M' && buf[2] == 'R' && buf[3] == 'G') {
                fread(buf, 1, sizeof(buf), f);
                size = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3] << 0);
                if (size == 0) {
@@ -653,7 +669,7 @@ static uae_u8 *load_file(const char *path, const char *file, uae_u8 *p, int *siz
        }
        FILE *f = fopen(fname, "rb");
        if (f) {
-               int gsize;
+               int gsize = 0;
                if (foffsetp) {
                        gsize = load_file_offset(f, foffsetp);
                        if (gsize == 0) {
@@ -663,7 +679,7 @@ static uae_u8 *load_file(const char *path, const char *file, uae_u8 *p, int *siz
                                *sizep = gsize;
                        }
                }
-               if (*sizep <= 0) {
+               if (*sizep <= 0 || foffsetp == NULL) {
                        fseek(f, 0, SEEK_END);
                        gsize = ftell(f);
                        fseek(f, 0, SEEK_SET);
@@ -719,11 +735,17 @@ static uae_u8 *load_file(const char *path, const char *file, uae_u8 *p, int *siz
                        printf("Decompressing '%s' (%d -> %d)\n", fname, gsize, size);
                        callinflate(p, gzdata, inflatestack);
                        *sizep = size;
+                       if (!prealloc_gzip) {
+                               free(gzbuf);
+                       }
                        return p;
                } else if (candirect) {
                        printf("Decompressing '%s' (%d -> %d)\n", fname, gsize, size);
                        callinflate(p, gzdata, inflatestack);
                        *sizep = size;
+                       if (!prealloc_gzip) {
+                               free(gzbuf);
+                       }
                        return p;
                } else {
                        unpack = calloc(1, size);
@@ -870,6 +892,11 @@ end:
        return p;
 }
 
+static void endinfo_debug(uae_u8 *p)
+{
+       printf("PTR %08x, %08x, count %d\n", debug_item_data, p, debug_item_count);
+}
+
 static void pl(uae_u8 *p, uae_u32 v)
 {
        p[0] = v >> 24;
@@ -899,6 +926,7 @@ static uae_u8 *restore_fpvalue(uae_u8 *p, struct fpureg *fp)
        if ((v & CT_SIZE_MASK) != CT_SIZE_FPU) {
                end_test();
                printf("Expected CT_SIZE_FPU, got %02x\n", v);
+               endinfo_debug(p);
                endinfo();
                exit(0);
        }
@@ -967,7 +995,8 @@ static uae_u8 *restore_value(uae_u8 *p, uae_u32 *vp, int *sizep)
                break;
                case CT_SIZE_FPU:
                end_test();
-               printf("Unexpected CT_SIZE_FPU\n");
+               printf("Unexpected CT_SIZE_FPU (%02x)\n", v);
+               endinfo_debug(p);
                endinfo();
                exit(0);
                break;
@@ -1020,6 +1049,7 @@ static uae_u8 *restore_rel(uae_u8 *p, uae_u32 *vp, int nocheck)
                                } else if ((val & addressing_mask) < test_memory_addr || (val & addressing_mask) >= test_memory_addr + test_memory_size) {
                                        end_test();
                                        printf("restore_rel CT_ABSOLUTE_LONG outside of test memory! %08x\n", v);
+                                       endinfo_debug(p);
                                        endinfo();
                                        exit(0);
                                }
@@ -1039,11 +1069,13 @@ static uae_u8 *restore_rel_ordered(uae_u8 *p, uae_u32 *vp)
 }
 
 
-static void validate_mode(uae_u8 mode, uae_u8 v)
+static void validate_mode(uae_u8 *p, uae_u8 v)
 {
+       uae_u8 mode = p[0];
        if ((mode & CT_DATA_MASK) != v) {
                end_test();
                printf("CT_MEMWRITE expected but got %02X\n", mode);
+               endinfo_debug(p);
                endinfo();
                exit(0);
        }
@@ -1066,7 +1098,7 @@ static uae_u8 *get_memory_addr(uae_u8 *p, uae_u8 **addrp)
                        } else {
                                addr = low_memory + offset;
                        }
-                       validate_mode(p[0], CT_MEMWRITE);
+                       validate_mode(p, CT_MEMWRITE);
                        *addrp = addr;
                        return p;
                }
@@ -1083,7 +1115,7 @@ static uae_u8 *get_memory_addr(uae_u8 *p, uae_u8 **addrp)
 #else
                                uae_u8 *addr = (uae_u8*)val;
 #endif
-                               validate_mode(p[0], CT_MEMWRITE);
+                               validate_mode(p, CT_MEMWRITE);
                                *addrp = addr;
                                return p;
                        } else if (val >= test_memory_addr && val < test_memory_addr + test_memory_size) {
@@ -1092,12 +1124,13 @@ static uae_u8 *get_memory_addr(uae_u8 *p, uae_u8 **addrp)
 #else
                                uae_u8 *addr = (uae_u8*)val;
 #endif
-                               validate_mode(p[0], CT_MEMWRITE);
+                               validate_mode(p, CT_MEMWRITE);
                                *addrp = addr;
                                return p;
                        } else {
                                end_test();
                                printf("get_memory_addr CT_ABSOLUTE_LONG outside of test memory! %08x\n", val);
+                               endinfo_debug(p);
                                endinfo();
                                exit(0);
                        }
@@ -1109,7 +1142,7 @@ static uae_u8 *get_memory_addr(uae_u8 *p, uae_u8 **addrp)
                        val |= *p++;
                        uae_s16 offset = (uae_s16)val;
                        uae_u8 *addr = opcode_memory + offset;
-                       validate_mode(p[0], CT_MEMWRITE);
+                       validate_mode(p, CT_MEMWRITE);
                        *addrp = addr;
                        return p;
                }
@@ -1118,6 +1151,7 @@ static uae_u8 *get_memory_addr(uae_u8 *p, uae_u8 **addrp)
                default:
                        end_test();
                        printf("get_memory_addr unknown size %02x\n", v);
+                       endinfo_debug(p);
                        endinfo();
                        exit(0);
        }
@@ -1171,21 +1205,27 @@ static void restoreahist(void)
 static uae_u8 *restore_bytes(uae_u8 *mem, uae_u8 *p)
 {
        uae_u8 *addr = mem;
-       uae_u16 v = *p++;
-       addr += v >> 5;
-       v &= 31;
-       if (v == 31) {
-               v = *p++;
-               if (v == 0) {
-                       v = 256;
+       uae_u16 len, offset;
+       if (*p == 0xff) {
+               p++;
+               offset = *p++;
+               len = *p++;
+               if (len == 0) {
+                       len = 256;
+               }
+       } else {
+               uae_u8 v = *p++;
+               offset = v >> 5;
+               len = v & 31;
+               if (len == 0) {
+                       len = 32;
                }
-       } else if (v == 0) {
-               v = 32;
        }
+       addr += offset;
 #ifndef _MSC_VER
-       xmemcpy(addr, p, v);
+       xmemcpy(addr, p, len);
 #endif
-       p += v;
+       p += len;
        return p;
 }
 
@@ -1230,6 +1270,7 @@ static uae_u8 *restore_memory(uae_u8 *p, int storedata)
                        default:
                                end_test();
                                printf("Unknown restore_memory type!?\n");
+                               endinfo_debug(p);
                                endinfo();
                                exit(0);
                                break;
@@ -1251,6 +1292,7 @@ static uae_u8 *restore_memory(uae_u8 *p, int storedata)
                        default:
                                end_test();
                                printf("Unknown restore_memory type!?\n");
+                               endinfo_debug(p);
                                endinfo();
                                exit(0);
                                break;
@@ -1271,6 +1313,7 @@ static uae_u8 *restore_edata(uae_u8 *p)
                default:
                end_test();
                printf("Unexpected CT_EDATA 0x%02x\n", *p);
+               endinfo_debug(p);
                endinfo();
                exit(0);
        }
@@ -1283,6 +1326,7 @@ static uae_u8 *restore_data(uae_u8 *p, struct registers *r)
        if (v & CT_END) {
                end_test();
                printf("Unexpected end bit!? 0x%02x offset %d\n", v, p - test_data);
+               endinfo_debug(p);
                endinfo();
                exit(0);
        }
@@ -1510,18 +1554,20 @@ struct srbit
 {
        char *name;
        int bit;
+       int size;
 };
 static const struct srbit srbits[] = {
-       { "T1", 15 },
-       { "T0", 14 },
-       { "S", 13 },
-       { "M", 12 },
-       { "X", 4 },
-       { "N", 3 },
-       { "Z", 2 },
-       { "V", 1 },
-       { "C", 0 },
-       { NULL, 0 }
+       { "T1", 15, 1 },
+       { "T0", 14, 1 },
+       { "S", 13, 1 },
+       { "M", 12, 1 },
+       { "IM", 8, 3 },
+       { "X", 4, 1 },
+       { "N", 3, 1 },
+       { "Z", 2, 1 },
+       { "V", 1, 1 },
+       { "C", 0, 1 },
+       { NULL, 0, 0 }
 };
 
 // r = registers to output
@@ -1593,9 +1639,13 @@ static void out_regs(struct registers *r, struct registers *r1, struct registers
                for (int i = 0; srbits[i].name; i++) {
                        if (i > 0)
                                *outbp++ = ' ';
-                       uae_u16 mask = 1 << srbits[i].bit;
+                       uae_u16 mask = 0;
+                       for (int j = 0; j < srbits[i].size; j++) {
+                               mask <<= 1;
+                               mask |= 1 << srbits[i].bit;
+                       }
                        sprintf(outbp, "%s%c%d", srbits[i].name,
-                               (s2 & mask) != (s3 & mask) ? '!' : ((s1 & mask) != (s2 & mask) ? '*' : '='), (s & mask) != 0);
+                               (s2 & mask) != (s3 & mask) ? '!' : ((s1 & mask) != (s2 & mask) ? '*' : '='), (s & mask) >> srbits[i].bit);
                        outbp += strlen(outbp);
                }
                *outbp++ = '\n';
@@ -1782,19 +1832,19 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, short excnu
                                }
                                sprintf(outbp, "Expected trace exception (PC=%08x) but got none.\n", pc);
                                outbp += strlen(outbp);
-                               *experr = 1;
+                               *experr |= 2;
                        } else if (!(last_exception_extra & 0x80)) {
                                // Trace stacked with group 2 exception
                                if (!(sr & 0x2000) || (sr | 0x2000 | 0xc000) != (regs->sr | 0x2000 | 0xc000)) {
                                        sprintf(outbp, "Trace (%d stacked) SR mismatch: %04x != %04x\n", excnum, sr, regs->sr);
                                        outbp += strlen(outbp);
-                                       *experr = 1;
+                                       *experr |= 2;
                                }
                                uae_u32 retv = exceptiontableinuse + (excnum - 2) * 2;
                                if (ret != retv) {
                                        sprintf(outbp, "Trace (%d stacked) PC mismatch: %08x != %08x\n", excnum, ret, retv);
                                        outbp += strlen(outbp);
-                                       *experr = 1;
+                                       *experr |= 2;
                                }
                                *extratrace = 1;
                        } else {
@@ -1806,13 +1856,14 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, short excnu
                                if ((vsr & test_ccrignoremask) != (sr & test_ccrignoremask)) {
                                        sprintf(outbp, "Trace (non-stacked) SR mismatch: %04x != %04x (PC=%08x)\n", sr, vsr, v);
                                        outbp += strlen(outbp);
-                                       *experr = 1;
+                                       *experr |= 2;
                                }
                                if (v != ret) {
                                        sprintf(outbp, "Trace (non-stacked) PC mismatch: %08x != %08x (SR=%04x)\n", ret, v, vsr);
                                        outbp += strlen(outbp);
-                                       *experr = 1;
+                                       *experr |= 2;
                                }
+                               *extratrace = -1;
                        }
                } else if (!last_exception_extra && excnum != 9) {
                        if (regs->tracecnt > 0) {
@@ -1824,7 +1875,7 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, short excnu
                                        sprintf(outbp, "Exception %d also pending.\n", excnum);
                                        outbp += strlen(outbp);
                                }
-                               *experr = 1;
+                               *experr |= 2;
                        }
                } else if (last_exception_extra) {
                        end_test();
@@ -2081,7 +2132,7 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, short excnu
                strcpy(outbp, "Got     : ");
                outbp += strlen(outbp);
                hexdump(sp, exclen, 1);
-               *experr = 1;
+               *experr |= 1;
        }
        exception_stored = exclen;
        return p;
@@ -2200,6 +2251,18 @@ static int get_cycles_amiga(void)
 
 static uae_u16 test_intena, test_intreq;
 
+static const uae_u16 itable[] =
+{
+       0,
+       1 << 2,
+       1 << 3,
+       1 << 4,
+       1 << 7,
+       1 << 11,
+       1 << 13,
+       0
+};
+
 static void set_interrupt(void)
 {
        if (interrupttest == 1) {
@@ -2221,6 +2284,13 @@ static void set_interrupt(void)
                *intena = 0x8000 | 0x4000 | IPL_TRIGGER_INTMASK;
                *intreq = IPL_TRIGGER_INTMASK;
        }
+       if (initial_interrupt) {
+               uae_u16 mask = itable[initial_interrupt];
+               volatile uae_u16 *intena = (uae_u16*)0xdff09a;
+               volatile uae_u16 *intreq = (uae_u16*)0xdff09c;
+               *intena = 0x8000 | 0x4000 | mask;
+               *intreq = 0x8000 | mask;
+       }
 }
 
 static void clear_interrupt(void)
@@ -2305,7 +2375,7 @@ static int check_cycles(int exc, short extratrace, short extrag2w1, struct regis
        }
        gotcycles += cycles_adjust;
 
-       if (extratrace) {
+       if (extratrace > 0) {
                expectedcycles += getexceptioncycles(9);
        }
        // address error during group 2 exception stacking (=odd exception vector)
@@ -2328,10 +2398,9 @@ static int check_cycles(int exc, short extratrace, short extrag2w1, struct regis
        }
 
        if (0 || abs(gotcycles - expectedcycles) > cycles_range) {
-               addinfo();
-               sprintf(outbp, "Got %d cycles (%d + %d) but expected %d (%d + %d)\n",
+               sprintf(outbp, "Got %d cycles (%d + %d) but expected %d (%d + %d) %08x\n",
                        gotcycles, gotcycles - exceptioncycles, exceptioncycles,
-                       expectedcycles, expectedcycles - exceptioncycles, exceptioncycles);
+                       expectedcycles, expectedcycles - exceptioncycles, exceptioncycles, test_regs.cycles);
                outbp += strlen(outbp);
                return 0;
        }
@@ -2521,7 +2590,7 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr, st
                        if (cpu_lvl > 0 && exc >= 2 && cpuexc010 != cpuexc) {
                                if (dooutput) {
                                        sprintf(outbp, "Exception: vector number does not match vector offset! (%d <> %d) %d\n", exc, cpuexc010, cpuexc);
-                                       experr = 1;
+                                       experr |= 1;
                                        outbp += strlen(outbp);
                                        errflag |= 1 << 16;
                                }
@@ -2589,7 +2658,11 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr, st
                                                        hexdump(excp, excsize, 1);
                                                }
                                        }
-                                       experr = 1;
+                                       if ((experr & 2) && !(experr & 1) && extratrace) {
+                                               sprintf(outbp, "Valid trace exception found\n");
+                                               outbp += strlen(outbp);
+                                       }
+                                       experr |= 2;
                                }
                                errflag |= 1 << 16;
                        }
@@ -2967,7 +3040,7 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr, st
                }
 #endif
                if (exc > 1) {
-                       if (!experr) {
+                       if (!(experr & 1)) {
                                sprintf(outbp, "OK: exception %d ", exc);
                                outbp += strlen(outbp);
                                if (exception_stored) {
@@ -3002,7 +3075,7 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr, st
 
 static void out_endinfo(void)
 {
-       sprintf(outbp, "%u (%u/%u) ", testcnt, testcntsub, testcntsubmax);
+       sprintf(outbp, "%u (%u/%u/%u) ", testcnt, testcntsub, testcntsubmax, interrupt_delay_cnt);
        outbp += strlen(outbp);
        sprintf(outbp, "S=%d", supercnt);
        outbp += strlen(outbp);
@@ -3104,7 +3177,7 @@ static void process_test(uae_u8 *p)
 
        short doopcodeswap = 1;
 
-       if (interrupttest >= 1) {
+       if (interrupttest >= 2) {
                doopcodeswap = 0;
        }
 
@@ -3113,12 +3186,16 @@ static void process_test(uae_u8 *p)
                cur_regs.endpc = endpc;
                cur_regs.pc = startpc;
 
+               debug_item_data = p;
+               debug_item_count = 0;
                for (;;) {
                        uae_u8 v = *p;
                        if (v == CT_END_INIT || v == CT_END_FINISH)
                                break;
                        p = restore_data(p, &cur_regs);
+                       debug_item_count++;
                }
+               debug_item_count = -1;
                if (*p == CT_END_FINISH)
                        break;
                p++;
@@ -3213,6 +3290,7 @@ static void process_test(uae_u8 *p)
                                test_regs.pc = startpc;
                                test_regs.cyclest = 0xffffffff;
                                test_regs.fpeaset = 0;
+                               test_regs.blttemp = blt_data;
 
 #ifdef M68K
                                if (stackcopysize > 0)
@@ -3223,7 +3301,7 @@ static void process_test(uae_u8 *p)
                                } else {
                                        test_regs.sr = (ccr & 1) ? 31 : 0;
                                }
-                               test_regs.sr |= sr_mask | (interrupt_mask << 8);
+                               test_regs.sr |= sr_mask | (initial_interrupt_mask << 8);
                                if (fpumode) {
                                        test_regs.fpcr = 0;
                                        test_regs.fpsr = 0;
@@ -3347,7 +3425,7 @@ static void process_test(uae_u8 *p)
 
 
 #ifdef AMIGA
-                                               if (interrupttest) {
+                                               if (interrupttest || initial_interrupt_mask || initial_interrupt) {
                                                        set_interrupt();
                                                }
 #endif
@@ -3365,7 +3443,7 @@ static void process_test(uae_u8 *p)
                                                }
 
 #ifdef AMIGA
-                                               if (interrupttest) {
+                                               if (interrupttest || initial_interrupt_mask || initial_interrupt) {
                                                        clear_interrupt();
                                                }
 #endif
@@ -3494,8 +3572,12 @@ end:
 
 static void freestuff(void)
 {
-       if (test_memory && test_memory_addr)
+       if (test_memory && test_memory_addr) {
                free_absolute(test_memory_addr, test_memory_size);
+       }
+       if (blt_data) {
+               free_blttemp(blt_data, BLT_TEMP_SIZE);
+       }
 #ifdef WAITEXIT
        getchar();
 #endif
@@ -3546,15 +3628,20 @@ static int test_mnemo(const char *opcode)
        test_memory_end = test_memory_addr + test_memory_size;
        opcode_memory_addr = read_u32(headerfile, &headoffset);
        opcode_memory = (uae_u8*)opcode_memory_addr;
-       uae_u32 lvl_mask = read_u32(headerfile, &headoffset);
-       lvl = (lvl_mask >> 16) & 15;
-       interrupt_mask = (lvl_mask >> 20) & 7;
-       addressing_mask = (lvl_mask & 0x80000000) ? 0xffffffff : 0x00ffffff;
-       interrupttest = (lvl_mask >> 26) & 3;
-       sr_undefined_mask = lvl_mask & 0xffff;
-       safe_memory_mode = (lvl_mask >> 23) & 7;
-       loop_mode_jit = (lvl_mask >> 28) & 1;
-       loop_mode_68010 = (lvl_mask >> 29) & 1;
+       v = read_u32(headerfile, &headoffset);
+       lvl = (v >> 16) & 15;
+       interrupt_mask = (v >> 20) & 7;
+       addressing_mask = (v & 0x80000000) ? 0xffffffff : 0x00ffffff;
+       interrupttest = (v >> 26) & 3;
+       sr_undefined_mask = v & 0xffff;
+       safe_memory_mode = (v >> 23) & 7;
+       loop_mode_jit = (v >> 28) & 1;
+       loop_mode_68010 = (v >> 29) & 1;
+       v = read_u32(headerfile, &headoffset);
+       initial_interrupt_mask = v & 7;
+       initial_interrupt = (v >> 3) & 7;
+       v = read_u32(headerfile, &headoffset);
+       v = read_u32(headerfile, &headoffset);
        fpu_model = read_u32(headerfile, &headoffset);
        test_low_memory_start = read_u32(headerfile, &headoffset);
        test_low_memory_end = read_u32(headerfile, &headoffset);
@@ -3666,6 +3753,12 @@ static int test_mnemo(const char *opcode)
                }
        }
 
+       blt_data = allocate_blttemp(BLT_TEMP_SIZE);
+       if (!blt_data) {
+               printf("blt_temp failed to allocated.\n");
+               exit(0);
+       }
+
        int otestcnt = -1;
        for (;;) {
                if (otestcnt != testcnt) {
@@ -3739,6 +3832,11 @@ static int test_mnemo(const char *opcode)
                }
        }
 
+       if (blt_data) {
+               free_blttemp(blt_data, BLT_TEMP_SIZE);
+               blt_data = 0;
+       }
+
        if (errorcnt == 0) {
                outbp = outbuffer;
                out_endinfo();
index a1d998e98c3121b98ae73697fc887391dc32bfa8..71c5a6d93237ced17916638ad3e75279635217e2 100644 (file)
 #include "cpummu030.h"
 
 cpuop_func *loop_mode_table[65536];
+int cpuipldelay2, cpuipldelay4;
 
 void my_trim(TCHAR *s)
 {
        int len;
        while (s[0] != '\0' && _tcscspn(s, _T("\t \r\n")) == 0)
-               memmove(s, s + 1, (_tcslen(s + 1) + 1) * sizeof(TCHAR));
-       len = _tcslen(s);
+               memmove(s, s + 1, (uaetcslen(s + 1) + 1) * sizeof(TCHAR));
+       len = uaetcslen(s);
        while (len > 0 && _tcscspn(s + len - 1, _T("\t \r\n")) == 0)
                s[--len] = '\0';
 }
@@ -40,8 +41,8 @@ TCHAR *buf_out(TCHAR *buffer, int *bufsize, const TCHAR *format, ...)
                return 0;
        count = _vsntprintf(buffer, (*bufsize) - 1, format, parms);
        va_end(parms);
-       *bufsize -= _tcslen(buffer);
-       return buffer + _tcslen(buffer);
+       *bufsize -= uaetcslen(buffer);
+       return buffer + uaetcslen(buffer);
 }
 
 void fpux_restore(int *v)
@@ -52,10 +53,11 @@ void fp_init_native(void)
        wprintf(_T("fp_init_native called!"));
        exit(0);
 }
-void fp_init_native_80(void)
+bool fp_init_native_80(void)
 {
        wprintf(_T("fp_init_native_80 called!"));
        exit(0);
+       return false;
 }
 void init_fpucw_x87(void)
 {