]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Cputester beta updates
authorToni Wilen <twilen@winuae.net>
Mon, 7 Feb 2022 16:00:40 +0000 (18:00 +0200)
committerToni Wilen <twilen@winuae.net>
Mon, 7 Feb 2022 16:00:40 +0000 (18:00 +0200)
cputest.cpp
cputest/asm.S
cputest/cputest_defines.h
cputest/cputestgen.ini
cputest/main.c
cputest/readme.txt
include/cputest.h

index ed869efc83ff34b00b846cc2d8e6b12be2c21d73..04f7b9cde1a3ddaf149dbbad749fd91a683c1517 100644 (file)
@@ -70,6 +70,8 @@ static int feature_usp = 0;
 static int feature_exception_vectors = 0;
 static int feature_interrupts = 0;
 static int feature_instruction_size = 0;
+static int fpu_min_exponent, fpu_max_exponent;
+static int rnd_seed;
 static TCHAR *feature_instruction_size_text = NULL;
 static uae_u32 feature_addressing_modes[2];
 static int feature_gzip = 0;
@@ -169,8 +171,10 @@ static int interrupt_count;
 static int interrupt_cycle_cnt, interrupt_delay_cnt;
 static int interrupt_level;
 static uaecptr test_instruction_end_pc;
-static uaecptr lm_safe_address;
+static uaecptr lm_safe_address1, lm_safe_address2;
 static uae_u8 ccr_cnt;
+static int condition_cnt;
+static int subtest_count;
 
 struct uae_prefs currprefs;
 
@@ -226,9 +230,10 @@ static int is_superstack_use_required(void)
 
 static bool valid_address(uaecptr addr, int size, int rwp)
 {
-       int w = rwp == 2;
+       int w = (rwp & 0x7fff) == 2;
        addr &= addressing_mask;
        size--;
+
        if (low_memory_size != 0xffffffff && addr + size < low_memory_size) {
                if (addr < test_low_memory_start || test_low_memory_start == 0xffffffff)
                        goto oob;
@@ -280,7 +285,7 @@ static bool valid_address(uaecptr addr, int size, int rwp)
        }
        if (addr >= test_memory_start && addr + size < test_memory_end) {
                // make sure we don't modify our test instruction
-               if (testing_active && w) {
+               if ((testing_active && w) || (rwp > 0 && (rwp & 0x8000))) {
                        if (addr >= opcode_memory_start && addr + size < opcode_memory_start + OPCODE_AREA)
                                goto oob;
                }
@@ -300,9 +305,9 @@ oob:
 
 static bool check_valid_addr(uaecptr addr, int size, int rwp)
 {
-       if (!valid_address(addr, 1, rwp))
+       if (!valid_address(addr, 1, rwp | 0x8000))
                return false;
-       if (!valid_address(addr + size - 1, 1, rwp))
+       if (!valid_address(addr + size, 1, rwp | 0x8000))
                return false;
        return true;
 }
@@ -336,7 +341,7 @@ static uae_u8 *get_addr(uaecptr addr, int size, int rwp)
        size--;
 
        // if loop mode: loop mode buffer can be only accessed by loop mode store instruction
-       if (feature_loop_mode_jit && testing_active && addr >= test_memory_start && addr + size < test_memory_start + LM_BUFFER && lm_safe_address != regs.pc) {
+       if (feature_loop_mode_jit && testing_active && addr >= test_memory_start && addr + size < test_memory_start + LM_BUFFER && (lm_safe_address1 != regs.pc && lm_safe_address2 != regs.pc)) {
                goto oob;
        }
 
@@ -368,7 +373,7 @@ static void count_interrupt_cycles(int cycles)
        interrupt_cycle_cnt -= cycles;
        if (interrupt_cycle_cnt <= 0) {
                interrupt_cycle_cnt = 0;
-               interrupt_level = 6;
+               Exception(24 + 6);
        }
 }
 
@@ -841,7 +846,7 @@ uae_u32(*x_cp_next_ilong)(void);
 
 uae_u32(*x_next_iword)(void);
 uae_u32(*x_next_ilong)(void);
-void (*x_do_cycles)(unsigned long);
+void (*x_do_cycles)(uae_u32);
 
 uae_u32(REGPARAM3 *x_cp_get_disp_ea_020)(uae_u32 base, int idx) REGPARAM;
 
@@ -1017,9 +1022,10 @@ void check_t0_trace(void)
        }
 }
 
-void cpureset(void)
+bool cpureset(void)
 {
        cpu_halted = -1;
+       return false;
 }
 
 static void doexcstack2(void)
@@ -2017,7 +2023,7 @@ static uae_u8 *store_rel(uae_u8 *dst, uae_u8 mode, uae_u32 s, uae_u32 d, int ord
        if (diff >= -128 && diff < 128) {
                *dst++ = mode | CT_RELATIVE_START_BYTE;
                *dst++ = diff & 0xff;
-       } else if (diff >= -32768 && diff < 32767) {
+       } else if (diff >= -32768 && diff < 32768) {
                *dst++ = mode | CT_RELATIVE_START_WORD;
                *dst++ = (diff >> 8) & 0xff;
                *dst++ = diff & 0xff;
@@ -2358,7 +2364,7 @@ static void save_data(uae_u8 *dst, const TCHAR *dir, int size)
                pl(data, feature_exception_vectors);
                fwrite(data, 1, 4, f);
                data[0] = data[1] = data[2] = 0;
-               pl(data, feature_loop_mode_cnt);
+               pl(data, feature_loop_mode_cnt | (feature_loop_mode_jit << 8));
                fwrite(&data[0], 1, 4, f);
                fwrite(&data[1], 1, 4, f);
                fwrite(&data[2], 1, 4, f);
@@ -2688,7 +2694,7 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str
                                        addr = pc + 2 - 2;
                                } else {
                                        addr = cur_regs.regs[reg + 8];
-                                       if (reg == 7) {
+                                       if (reg == 7 && flagsp) {
                                                *flagsp |= EAFLAG_SP;
                                        }
                                }
@@ -2760,7 +2766,7 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str
                        uaecptr pce = pc;
                        pc += 2;
                        // calculate lenght of extension
-                       if (mode == Ad8r && reg == 7) {
+                       if (mode == Ad8r && reg == 7 && flagsp) {
                                *flagsp |= EAFLAG_SP;
                        }
                        *eap = ShowEA_disp(&pce, mode == Ad8r ? regs.regs[reg + 8] : pce, NULL, NULL, false);
@@ -3037,6 +3043,12 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str
                                } else if ((imm16_cnt & 15) == 0) {
                                        v = 0;
                                }
+                               // clear A7 from register mask
+                               if (dp->mnemo == i_MVMEL) {
+                                       v &= ~0x8000;
+                               } else if (dp->mnemo == i_MVMLE) {
+                                       v &= ~0x0001;
+                               }
                                imm16_cnt++;
                                put_word_test(pc, v);
                                *isconstant = 16;
@@ -3864,20 +3876,20 @@ static bool check_interrupts(void)
                int ic = interrupt_count & 15;
                int lvl = interrupt_levels[ic];
                if (lvl > 0 && lvl > feature_min_interrupt_mask) {
-                       Exception(lvl + 24);
+                       Exception(24 + lvl);
                        return true;
                }
        }
        return false;
 }
 
-static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp)
+static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool fpumode)
 {
        uae_u16 opc = regs.ir;
        uae_u16 opw1 = (opcode_memory[2] << 8) | (opcode_memory[3] << 0);
        uae_u16 opw2 = (opcode_memory[4] << 8) | (opcode_memory[5] << 0);
-       if (opc == 0x4c58
-               && opw1 == 0xf756
+       if (opc == 0xf208
+               && opw1 == 0xa000
                //&& opw2 == 0x4afc
                )
                printf("");
@@ -3930,7 +3942,7 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp)
                cnt = 100;
        }
        if (feature_interrupts == 2) {
-               interrupt_cycle_cnt = 10;
+               interrupt_cycle_cnt = SERPER * 10 - 20;
        }
 
        for (;;) {
@@ -3974,6 +3986,21 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp)
 
                (*cpufunctbl[opc])(opc);
 
+               if (fpumode) {
+                       // skip result 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;
+                                       if (exp != 0x0000) {
+                                               if (exp < fpu_min_exponent || exp > fpu_max_exponent) {
+                                                       test_exception = -1;
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+               }
+
                if (test_ins) {
                        // skip if test instruction modified loop mode register
                        if (feature_loop_mode_jit || feature_loop_mode_68010) {
@@ -4367,6 +4394,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                        xorshiftstate ^= ovrfilename[i];
                }
        }
+       xorshiftstate ^= rnd_seed;
 
        int pathlen = _tcslen(path);
        _stprintf(dir, _T("%s%s"), path, mns);
@@ -4416,12 +4444,13 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
 
        int quick = 0;
        int rounds = feature_test_rounds;
-       int subtest_count = 0;
        int data_saved = 0;
        int first_cycles = 1;
 
        int count = 0;
 
+       subtest_count = 0;
+
        if (feature_loop_mode_jit) {
                registers[8 + 3] = test_memory_start; // A3 = start of test memory
        }
@@ -4545,8 +4574,8 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                for (int i = 0; i < MAX_REGISTERS; i++) {
                        dst = store_reg(dst, CT_DREG + i, 0, cur_regs.regs[i], -1);
                }
-               for (int i = 0; i < 8; i++) {
-                       if (fpumode) {
+               if (fpumode) {
+                       for (int i = 0; i < 8; i++) {
                                dst = store_fpureg(dst, CT_FPREG + i, NULL, cur_regs.fp[i].fpx, 1);
                        }
                        dst = store_reg(dst, CT_FPIAR, 0, cur_regs.fpiar, -1);
@@ -4561,6 +4590,11 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                uae_u32 instructionendpc_old = opcode_memory_start;
                uae_u32 startpc_old = opcode_memory_start;
                int branch_target_swap_mode_old = 0;
+               int doopcodeswap = 1;
+
+               if (feature_interrupts == 2) {
+                       doopcodeswap = 0;
+               }
 
                if (verbose) {
                        if (target_ea[0] != 0xffffffff)
@@ -4691,7 +4725,8 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        fpuopsize = -1;
                                        test_exception = 0;
                                        test_exception_extra = 0;
-                                       lm_safe_address = 0xffffffff;
+                                       lm_safe_address1 = 0xffffffff;
+                                       lm_safe_address2 = 0xffffffff;
 
                                        target_ea[0] = target_ea_bak[0];
                                        target_ea[1] = target_ea_bak[1];
@@ -4736,10 +4771,15 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        // interrupt timing test mode
                                        if (feature_interrupts == 2) {
                                                pc -= 2;
-                                               put_word_test(pc + 0, 0x7000 | interrupt_delay_cnt); // moveq #x,d0 (4 cycles)
-                                               put_word_test(pc + 2, 0xe0b9); // ror.l d0,d1 (4 + 4 + d0 * 2 cycles)
-                                               put_word_test(pc + 4, NOP_OPCODE);
-                                               pc += 6;
+                                               // move.w #x,0xdff032 (SERDAT) (20 cycles)
+                                               put_long_test(pc + 0, (0x33fc << 16) | 0x100 | '!');
+                                               put_long_test(pc + 4, 0x00dff030);
+//                                             // moveq #x,d0 (4 cycles)
+//                                             put_word_test(pc + 8, 0x7000 | interrupt_delay_cnt);
+                                               // ror.l d0,d0 (4 + 4 + d0 * 2 cycles)
+                                               put_word_test(pc + 8, 0xe0b8);
+                                               put_word_test(pc + 10, NOP_OPCODE); // (4 cycles)
+                                               pc += 12;
                                                opcode_memory_address = startpc = pc;
                                                pc += 2;
                                        }
@@ -4751,7 +4791,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                put_long_test(pc, 0x4e500004 | (dp->sreg << 16));
                                                pc += 4;
                                                opcode_memory_address = pc;
-                                               loopmode_jump_offset = -4;
+                                               loopmode_jump_offset = 4;
                                                pc += 2;
                                        }
 
@@ -4908,11 +4948,37 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        if (feature_loop_mode_jit || feature_loop_mode_68010) {
                                                int cctype = isccinst(dp);
                                                // dbf dn, opcode_memory_start
-                                               if (feature_loop_mode_jit) {
+                                               if (feature_loop_mode_jit == 1 || feature_loop_mode_jit == 2) {
                                                        // move ccr,(a3)+
-                                                       lm_safe_address = pc;
+                                                       lm_safe_address1 = pc;
                                                        put_word(pc, LM_OPCODE);
                                                        pc += 2;
+                                               } else if (feature_loop_mode_jit == 3) {
+                                                       static const int consts[] = { 5, 7, 9, 11, 0 };
+                                                       int c = condition_cnt % 5;
+                                                       int cond = consts[c];
+                                                       if (cond == 0) {
+                                                               // X
+                                                               put_long(pc, 0x91c8c188); // SUBA.L A0,A0 ; EXG.L D0,A0
+                                                               pc += 4;
+                                                               put_word(pc, 0x4040); // NEGX.W D0
+                                                               pc += 2;
+                                                       } else {
+                                                               // CZVN
+                                                               put_word(pc, (cond << 8) | 0x50c0); // Scc D0
+                                                               pc += 2;
+                                                       }
+                                                       put_word(pc, 0x3040); // MOVE.W D0,A0
+                                                       pc += 2;
+                                                       lm_safe_address1 = pc;
+                                                       put_word(pc, 0x36c8); // MOVE.W A0,(A3)+
+                                                       pc += 2;
+                                                       put_long(pc, 0x307c0000 | c); // MOVEA.W #x,A0
+                                                       pc += 4;
+                                                       lm_safe_address2 = pc;
+                                                       put_word(pc, 0x36c8); // MOVE.W A0,(A3)+
+                                                       pc += 2;
+                                                       condition_cnt++;
                                                }
                                                // dbf dn,label
                                                put_long_test(pc, ((0x51c8 | feature_loop_mode_register) << 16) | ((opcode_memory_address - pc - loopmode_jump_offset - 2) & 0xffff));
@@ -4937,7 +5003,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                                // bra.s start
                                                                put_word(pc, 0x6000 + (0xfe - pc - opcode_memory_address));
                                                                pc += 2;
-                                                       } else if (feature_loop_mode_jit == 2) {
+                                                       } else if (feature_loop_mode_jit == 2 || feature_loop_mode_jit == 4) {
                                                                // generate extra round with randomized CCR
                                                                // tst.l dx
                                                                put_word(pc, 0x4a80 | feature_loop_mode_register);
@@ -4970,7 +5036,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
 
                                        // end word, needed to detect if instruction finished normally when
                                        // running on real hardware.
-                                       uae_u32 originalendopcode = (ILLG_OPCODE << 16) | NOP_OPCODE;
+                                       uae_u32 originalendopcode = (NOP_OPCODE << 16) | ILLG_OPCODE;
                                        uae_u32 endopcode = originalendopcode;
                                        uae_u32 actualendpc = pc;
                                        uae_u32 instruction_end_pc = pc;
@@ -5019,7 +5085,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        uaecptr nextpc;
                                        srcaddr = 0xffffffff;
                                        dstaddr = 0xffffffff;
-                                       uae_u32 dflags = m68k_disasm_2(out, sizeof(out) / sizeof(TCHAR), opcode_memory_address, &nextpc, 1, &srcaddr, &dstaddr, 0xffffffff, 0);
+                                       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);
                                                wprintf(_T("%08u %s"), subtest_count, out);
@@ -5035,7 +5101,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                                out_of_test_space = false;
                                                                if (get_word_test(nextpc) == ILLG_OPCODE)
                                                                        break;
-                                                               m68k_disasm_2(out, sizeof(out) / sizeof(TCHAR), nextpc, &nextpc, 1, NULL, NULL, 0xffffffff, 0);
+                                                               m68k_disasm_2(out, sizeof(out) / sizeof(TCHAR), nextpc, NULL, 0, &nextpc, 1, NULL, NULL, 0xffffffff, 0);
                                                                my_trim(out);
                                                                wprintf(_T("%08u %s\n"), subtest_count, out);
                                                        }
@@ -5043,7 +5109,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        }
                                        
                                        // disassembler may set this
-                                       out_of_test_space = false;
+                                       out_of_test_space = false;
 
                                        if ((dflags & 1) && target_ea[0] != 0xffffffff && srcaddr != 0xffffffff && srcaddr != target_ea[0]) {
                                                if (verbose) {
@@ -5152,8 +5218,13 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        if (bc) {
                                                if (feature_loop_mode_jit) {
                                                        if (srcaddr != test_instruction_end_pc) {
-                                                               // addq.w #2,a3, jmp xxx
-                                                               put_long_test(srcaddr, 0x544b4ef9);
+                                                               if (feature_loop_mode_jit >= 3) {
+                                                                       // addq.w #4,a3, jmp xxx
+                                                                       put_long_test(srcaddr, 0x584b4ef9);
+                                                               } else {
+                                                                       // addq.w #2,a3, jmp xxx
+                                                                       put_long_test(srcaddr, 0x544b4ef9);
+                                                               }
                                                                put_long_test(srcaddr + 4, test_instruction_end_pc);
                                                        }
                                                } else {
@@ -5181,6 +5252,9 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                }
                                        }
 
+                                       if (subtest_count == 8192)
+                                               printf("");
+
                                        // save opcode memory
                                        dst = store_mem_bytes(dst, opcode_memory_start, instruction_end_pc - opcode_memory_start, oldcodebytes, true);
 
@@ -5220,6 +5294,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;
 
@@ -5236,6 +5316,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        int t_cnt = 0;
 
                                        int extraccr = 0;
+                                       interrupt_delay_cnt = -1;
 
                                        // extra loops for supervisor and trace
                                        uae_u16 sr_allowed_mask = feature_sr_mask & 0xf000;
@@ -5245,24 +5326,31 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                uae_u16 sr_mask = 0;
 
                                                int maxflag;
+                                               int maxflagcnt;
+                                               int maxflagshift;
                                                int flagmode = 0;
                                                if (fpumode) {
                                                        if (fpuopcode == FPUOPP_ILLEGAL || feature_flag_mode > 1) {
                                                                // Illegal FPU instruction: all on/all off only (*2)
                                                                maxflag = 2;
+                                                               maxflagshift = 1;
                                                        } else if (dp->mnemo == i_FDBcc || dp->mnemo == i_FScc || dp->mnemo == i_FTRAPcc || dp->mnemo == i_FBcc) {
                                                                // FXXcc-instruction: FPU condition codes (*16)
                                                                maxflag = 16;
+                                                               maxflagshift = 4;
                                                                flagmode = 1;
                                                        } else {
                                                                // Other FPU instructions: FPU rounding and precision (*16)
                                                                maxflag = 16;
+                                                               maxflagshift = 4;
                                                        }
                                                } else {
                                                        maxflag = 32; // all flag combinations (*32)
+                                                       maxflagshift = 5;
                                                        if (feature_flag_mode > 1 || (feature_flag_mode == 1 && (dp->mnemo == i_ILLG || !isccinst(dp)))) {
                                                                // if not cc instruction or illegal or forced: all on/all off (*2)
                                                                maxflag = 2;
+                                                               maxflagshift = 1;
                                                        }
                                                }
 
@@ -5283,10 +5371,16 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                }
                                                *dst++ = (uae_u8)(maxflag | (fpumode ? 0x80 : 0x00) | (flagmode ? 0x40 : 0x00));
 
+                                               maxflagcnt = maxflag;
+                                               if (feature_interrupts == 2) {
+                                                       maxflagcnt *= 64;
+                                               }
+
                                                // Test every CPU CCR or FPU SR/rounding/precision combination
-                                               for (int ccr = 0; ccr < maxflag; ccr++) {
+                                               for (int ccrcnt = 0; ccrcnt < maxflagcnt; ccrcnt++) {
 
                                                        bool skipped = false;
+                                                       int ccr = ccrcnt & ((1 << maxflagshift) - 1);
 
                                                        out_of_test_space = 0;
                                                        test_exception = 0;
@@ -5306,7 +5400,9 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
 
                                                        // swap end opcode illegal/nop
                                                        noaccesshistory++;
-                                                       endopcode = (endopcode >> 16) | (endopcode << 16);
+                                                       if (doopcodeswap) {
+                                                               endopcode = (endopcode >> 16) | (endopcode << 16);
+                                                       }
                                                        int extraopcodeendsize = ((endopcode >> 16) == NOP_OPCODE) ? 2 : 0;
                                                        int endopcodesize = 0;
                                                        if (!is_nowrite_address(pc - 4, 4)) {
@@ -5406,6 +5502,10 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                        }
                                                        regs.sr |= feature_min_interrupt_mask << 8;
 
+                                                       if (feature_interrupts == 2) {
+                                                               regs.regs[0] = ccrcnt >> maxflagshift;
+                                                       }
+
                                                        // override special register values
                                                        for (int i = 0; i < regdatacnt; i++) {
                                                                struct regdata *rd = &regdatas[i];
@@ -5430,11 +5530,11 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                        if (regs.sr & 0x2000)
                                                                prev_s_cnt++;
 
-                                                       if (subtest_count == 2052)
-                                                               printf("");
+                                                       if (subtest_count == 20609)
+                                                               printf("");
 
                                                        // execute test instruction(s)
-                                                       execute_ins(pc - endopcodesize, branch_target_pc, dp);
+                                                       execute_ins(pc - endopcodesize, branch_target_pc, dp, fpumode);
 
                                                        if (regs.s)
                                                                s_cnt++;
@@ -5704,6 +5804,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                        // undo any test instruction generated memory modifications
                                                        undo_memory(ahist, ahcnt_start);
                                                }
+
                                        nextextra:
                                                extraccr++;
                                                if (extraccr >= 16)
@@ -5757,7 +5858,7 @@ 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"), ok, exception_array[0], prev_s_cnt, s_cnt, t_cnt, cnt_stopped);
+                                               wprintf(_T(" OK=%d OB=%d S=%d/%d T=%d STP=%d I=%d"), ok, exception_array[0], prev_s_cnt, s_cnt, t_cnt, cnt_stopped, interrupt_delay_cnt);
                                                if (!ccr_done)
                                                        wprintf(_T(" X"));
                                                for (int i = 2; i < 128; i++) {
@@ -5847,14 +5948,18 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                        nextround = true;
                }
 
+#if 0
+               // interrupt delay test from 0 to 63
                if (feature_interrupts == 2) {
                        interrupt_delay_cnt++;
                        if (interrupt_delay_cnt >= 64) {
-                               nextround = false;
+                               break;
                        } else {
                                nextround = true;
+                               rounds = 1;
                        }
                }
+#endif
 
                if (target_opcode_address != 0xffffffff || target_usp_address != 0xffffffff) {
                        nextround = false;
@@ -6279,6 +6384,12 @@ static int test(struct ini_data *ini, const TCHAR *sections, const TCHAR *testna
                addressing_mask = 0xffffffff;
        }
 
+       currprefs.int_no_unimplemented = true;
+       ini_getvalx(ini, sections, _T("cpu_unimplemented"), &v);
+       if (v) {
+               currprefs.int_no_unimplemented = false;
+       }
+
        currprefs.fpu_model = 0;
        currprefs.fpu_mode = 1;
        ini_getvalx(ini, sections, _T("fpu"), &currprefs.fpu_model);
@@ -6303,6 +6414,29 @@ static int test(struct ini_data *ini, const TCHAR *sections, const TCHAR *testna
                }
        }
 
+       currprefs.fpu_no_unimplemented = true;
+       if (ini_getvalx(ini, sections, _T("fpu_unimplemented"), &v)) {
+               if (v) {
+                       currprefs.fpu_no_unimplemented = false;
+               }
+       }
+
+       fpu_min_exponent = 0;
+       fpu_max_exponent = 32768;
+       if (ini_getvalx(ini, sections, _T("fpu_min_exponent"), &v)) {
+               if (v >= 0) {
+                       fpu_min_exponent = v;
+               }
+       }
+       if (ini_getvalx(ini, sections, _T("fpu_max_exponent"), &v)) {
+               if (v >= 0) {
+                       fpu_max_exponent = v;
+               }
+       }
+
+       rnd_seed = 0;
+       ini_getvalx(ini, sections, _T("seed"), &rnd_seed);
+
        verbose = 1;
        ini_getvalx(ini, sections, _T("verbose"), &verbose);
 
@@ -6802,9 +6936,6 @@ static int test(struct ini_data *ini, const TCHAR *sections, const TCHAR *testna
                cpudatatbl[opcode].branch = tbl[i].branch;
        }
 
-       currprefs.int_no_unimplemented = true;
-       currprefs.fpu_no_unimplemented = true;
-
        for (int opcode = 0; opcode < 65536; opcode++) {
                cpuop_func *f;
                instr *table = &table68k[opcode];
@@ -6994,6 +7125,8 @@ int __cdecl main(int argc, char *argv[])
                return 0;
        }
 
+       disasm_init();
+
        TCHAR *sptr = sections;
        _tcscpy(sections, INISECTION);
        sptr += _tcslen(sptr) + 1;
index b1e22947b3513b76e43ad06162a4af14877b58f0..5ff07086f32e72dcbe8d5a58cdaafa9a85f51275 100644 (file)
@@ -25,6 +25,7 @@
        .globl _cyclereg_address5
        .globl _cyclereg_address6
        .globl _berrcopy
+       .globl _fpucomp
 
 | must match main.c
 S_DREG = 0
@@ -49,6 +50,20 @@ S_FPSR = S_FPCR+4
 S_FSAVE = S_FPSR+4
 S_NEXT = S_FSAVE+216
 
+       | v1, v2, limit
+       | abs((v2 - v1) / v1) > limit
+_fpucomp:
+       move.l 4(sp),a0
+       fmovem.x (a0),fp0-fp2
+       fsub.x fp0,fp1
+       fdiv.x fp0,fp1
+       fabs.x fp1
+       moveq #1,d0
+       fcmp.x fp1,fp2
+       fbgt .larger
+       moveq #0,d0
+.larger:
+       rts
 
        | src, dst, size, >68000
 _berrcopy:
@@ -214,7 +229,7 @@ _execute_test010:
 _cyclereg_address2:
        move.w CYCLEREG,cycles
        | pre set data output buffer.
-       | we don't want random DOB contents in bus/address error frame
+       | we dont want random DOB contents in bus/address error frame
        move.w #0xf00d,dummy
        rte
 
index cc3a445871a1431306c7ae59e71ce05b3880dcee..4bca3244a591a3322b070f9b9c222ee81fb0873b 100644 (file)
@@ -1,5 +1,5 @@
 
-#define DATA_VERSION 21
+#define DATA_VERSION 22
 
 #define CT_FPREG 0
 #define CT_DREG 0
@@ -11,6 +11,7 @@
 #define CT_FPIAR 20
 #define CT_FPSR 21
 #define CT_FPCR 22
+#define CT_EDATA 23
 #define CT_CYCLES 25
 #define CT_ENDPC 26
 #define CT_BRANCHTARGET 27
@@ -21,6 +22,8 @@
 #define CT_DATA_MASK 31
 #define CT_EXCEPTION_MASK 63
 
+#define CT_EDATA_IRQ_CYCLES 1
+
 #define CT_SIZE_BYTE (0 << 5)
 #define CT_SIZE_WORD (1 << 5)
 #define CT_SIZE_LONG (2 << 5)
@@ -54,3 +57,5 @@
 #define NOP_OPCODE 0x2048
 #define ILLG_OPCODE 0x4afc
 #define LM_OPCODE 0x42db
+
+#define SERPER 8
index d26f6e96f67d22c710902ccaa7abc968f5c0b27d..a5d97cbf1ef0593f1bc6b87ab5ad76877f54e88f 100644 (file)
@@ -1,18 +1,30 @@
 [cputest]
 
 ; CPU model (68000, 68020, 68030, 68040 or 68060).
-cpu=68000
+cpu=68040
 
 ; CPU address space.
 ; If 24-bit, tester will assume upper 8-bits of addresses gets ignored.
 ; 24 = 24-bit address space, 32 = 32-bit address space. 680x0 = this and higher CPU models are 32-bit.
-cpu_address_space=68030
+cpu_address_space=68020
+
+; 1 = all instructions are supported (for example MOVEP if 68060 etc)
+cpu_no_unimplemented=0
 
 ; FPU model (empty string or 0, 68881, 68882, 68040, 68060)
 ; Enable only when testing FPU. Only FPU instruction tests are allowed if FPU is enabled.
 ; if CPU is 68040/060 and FPU is 68881/68882, FPU type will be automatically corrected.
 fpu=
 
+; 1 = all instructions are supported (for example FSxxx and FDxx if 6888x, all normally
+; unimplemented (software emulated) if 68040/68060
+fpu_no_unimplemented=0
+
+; Don't generate tests that create result that has larger or smaller 16-bit extended double exponent.
+; Min exponent >0 does not prevent zero results.
+fpu_min_exponent=
+fpu_max_exponent=
+
 ; Write generated instructions to standard output. Always disabled in "all" mode.
 verbose=1
 
@@ -28,24 +40,28 @@ feature_gzip=0
 
 ; Low address space limits. Real hardware must have RAM in this space. Comment out to disable.
 ; Start should be zero if Amiga, set to 0x0800 if Atari ST.
-; Must be disabled if cycle counting, cycle count tests must only access real Fast RAM.
-test_low_memory_start=0x0000
-test_low_memory_end=0x8000
+; Must be disabled if cycle counting (instruction/interrupt), cycle count tests must only access real Fast RAM.
+;test_low_memory_start=0x0000
+;test_low_memory_end=0x8000
 
 ; High address space limits (0x00ff8000 to 0x01000000 is complete space if 24-bit). Comment out to disable.
 ; Automatically disabled if 32-bit CPU and end == 0x01000000
-test_high_memory_start=0x00ff8000
+;test_high_memory_start=0x00ff8000
 test_high_memory_end=0x01000000
 
 ; ROM high address space. High memory is only used for read tests, uses last 32k of ROM image file.
 high_rom=D:\amiga\roms\Kickstart v3.1 rev 40.63 (1993)(Commodore)(A500-A600-A2000)[!].rom
 
 ; main test memory start and size (real hardware must have RAM in this address space)
-test_memory_start=0x860000
+test_memory_start=0x00460000
 ;test_memory_start=0x68800000
 ;test_memory_start=0x43800000
 ;test_memory_start=0x07800000
 test_memory_size=0xa0000
+;
+;test_memory_start=0x340000
+;test_memory_size=0x80000
+
 
 ; address where test instructions are located
 ; if not defined: mid point of test memory
@@ -126,8 +142,13 @@ feature_flags_mode=1
 feature_min_interrupt_mask=0
 
 ; Interrupt test
-; If enabled, interrupt request is set before test.
+; 1 = interrupt request is set before test.
 ; Tests all INTREQ bits one by one. Compatible with cycle count mode.
+; 2 = test CPU IPL sampling timing.
+; Uses serial port to generate timing interrupt. Requires serial port TX connected to RX.
+; Generates multiple extra tests.
+; Used delay instruction: ROL.L D0,D0 (D0 = number of CPU clocks * 2)
+; All test rounds that generate interrupt immediately after test instuction has been executed are stored.
 ; Amiga only
 feature_interrupts=0
 
@@ -151,14 +172,16 @@ feature_undefined_ccr=0
 ; reg=0x1234 or reg=100
 ;feature_forced_register=
 
-; generate loop test: label: <test instruction> dbf dn,label
-; value: 0 = disabled, >0 = number of loops
-; feature_loop_mode=0
-; feature_loop_mode_register=7
-; only generate 68010 loop mode compatible instructions
-: feature_loop_mode_68010=0
-; reload changed address register(s) (-(an) or (an)+) after each round
-; feature_loop_mode_reload=1
+; generate JIT loop test: label: <test instruction>, <store CCR>, dbf dn,label
+; value: 0 = disabled, 1 = enable, 2 = enable + extra rounds with random CCR, 3 = no CCR check/store
+;feature_loop_mode=0
+;feature_loop_mode_register=7 (default)
+;feature_loop_mode_cnt=8 (default)
+
+; generate 68010 loop mode tests
+;feature_loop_mode_68010=0
+;feature_loop_mode_register=7 (default)
+;feature_loop_mode_cnt=8 (default)
 
 ; 68020+ addressing modes (this makes test files much larger if other addressing modes are also enabled)
 ; currently does not generate any reserved mode bit combinations.
@@ -185,6 +208,9 @@ feature_instruction_size=
 ; branch = all branch instructions (branchj = non-stack only, branchs = stack using)
 mode=
 
+; random seed (XOR'd with internally generated static seed)
+seed=
+
 ; test groups
 ; use key=* to restore default value
 
@@ -207,6 +233,14 @@ feature_sr_mask=0x8000
 feature_undefined_ccr=1
 mode=all
 
+; interrupt timing test
+[test=IPL]
+cpu=68000-68010
+enabled=0
+feature_undefined_ccr=1
+feature_interrupts=2
+mode=exg,neg,not,ror,rol,swap
+
 ; interrupt exception
 [test=IRQ]
 enabled=0
@@ -345,8 +379,7 @@ mode=all
 enabled=0
 cpu=68010
 feature_loop_mode_68010=1
-feature_loop_mode=3
-feature_loop_mode_register=7
+feature_loop_mode_cnt=3
 min_opcode_test_rounds=100
 feature_undefined_ccr=1
 mode=all
@@ -377,6 +410,7 @@ enabled=0
 cpu=68020-68060
 feature_addressing_modes_src=Ad8rf,PC8rf
 test_rounds=4
+verbose=0
 min_opcode_test_rounds=5000
 mode=not,move
 
@@ -385,6 +419,7 @@ enabled=0
 cpu=68020-68060
 feature_addressing_modes_dst=Ad8rf,PC8rf
 test_rounds=4
+verbose=0
 min_opcode_test_rounds=5000
 mode=add,move
 
@@ -432,6 +467,7 @@ enabled=0
 verbose=1
 cpu=68020-68060
 fpu=68882
+feature_sr_mask=0xc000
 exceptions=-48,-49,-50,-51,-52,-53,-54
 min_opcode_test_rounds=5000
 mode=fmove,fsmove,fdmove,fint,fintrz,fneg,fsneg,fdneg,fabs,fsabs,fdabs,fdiv,fsdiv,fddiv,fadd,fsadd,fdadd,fmul,fsmul,fdmul,fsgldiv,fsglmul,fsub,fssub,fdsub,fcmp,ftst,fsqrt
@@ -440,7 +476,7 @@ mode=fmove,fsmove,fdmove,fint,fintrz,fneg,fsneg,fdneg,fabs,fsabs,fdabs,fdiv,fsdi
 ; no arithmetic exceptions, unsupported instructions or datatypes, denormals or unnormals.
 [test=FCPX]
 enabled=0
-verbose=1
+verbose=0
 cpu=68020-68030
 fpu=68882
 exceptions=-48,-49,-50,-51,-52,-53,-54
@@ -451,9 +487,10 @@ mode=flog10,flogn,flognp1,fsin,fsincos,fsinh,ftan,ftanh,ftentox
 ; non-arithmetic instructions (FMOVEM also includes FMOVE to/from control register)
 [test=FINT]
 enabled=0
-verbose=1
+verbose=0
 cpu=68020-68060
 fpu=68882
+feature_sr_mask=0xc000
 mode=fmovecr,fmovem,fdbcc,fbcc,ftrapcc,fscc
 
 ; packed datatype
@@ -477,19 +514,64 @@ cpu=68020-68060
 fpu=68882
 exceptions=11,55,60,61
 feature_flags_mode=2
-mode=fillegal
+mode=fall
 
 ; ******************
-; JIT loop mode test
+; JIT tests
 ; ******************
 
 [test=JITLM]
 enabled=0
 cpu=68020-68060
 cpu_address_space=68020
-feature_loop_mode=8
-feature_loop_mode_reload=1
-feature_loop_mode_register=7
+feature_loop_mode=1
 opcode_memory_start=-1
+mode=mvmel,mvmle,link,unlk
+feature_flags_mode=1
+test_rounds=3
+verbose=0
+
+; basic tests
+[test=JITB]
+enabled=0
+cpu=68020-68060
+cpu_address_space=68020
+feature_flags_mode=0
+verbose=1
 mode=all
+
+; 68020+ addressing mode tests
+[test=JITES]
+enabled=0
+cpu=68020-68060
+feature_addressing_modes_src=Ad8rf,PC8rf
+cpu_address_space=68020
+feature_loop_mode=1
+opcode_memory_start=-1
+test_rounds=4
+verbose=0
+min_opcode_test_rounds=5000
+mode=not,move
+
+[test=JITED]
+enabled=0
+cpu=68020-68060
+feature_addressing_modes_dst=Ad8rf,PC8rf
+cpu_address_space=68020
+feature_loop_mode=1
+opcode_memory_start=-1
+test_rounds=4
+verbose=0
+min_opcode_test_rounds=5000
+mode=add,move
+
+[test=JITX]
+enabled=0
+cpu=68020-68060
+cpu_address_space=68020
+feature_loop_mode=3
+opcode_memory_start=-1
+test_rounds=4
+feature_flags_mode=1
 verbose=0
+mode=scc,dbcc,bcc
index f3b1d5b7875fbec3b1e6b63a4e3633de0cc8bce9..5a1c90600944e70ac2ddc7760ff1a0ade9a4d678 100644 (file)
@@ -61,6 +61,15 @@ struct registers
        uae_u16 fpeaset;
 };
 
+
+struct irqresult
+{
+       uae_u32 pc;
+       uae_u16 sr;
+};
+
+static struct irqresult irqresults[64 + 1], irqresults2[64 + 1];
+
 static short continue_on_error;
 static struct registers test_regs;
 static struct registers last_regs;
@@ -90,7 +99,7 @@ static int cpu_lvl, fpu_model;
 static uae_u16 sr_undefined_mask;
 static int check_undefined_sr;
 static short is_fpu_adjust;
-static short fpu_adjust_man, fpu_adjust_exp, fpu_adjust_zb;
+static short fpu_adjust_exp;
 struct fpureg fpu_adjust;
 static uae_u32 cpustatearraystore[16];
 static uae_u32 cpustatearraynew[] = {
@@ -132,6 +141,7 @@ static int fpu_approx, fpu_approxcnt;
 static short dooutput = 1;
 static short quit;
 static uae_u8 ccr_mask;
+static uae_u32 fpsr_ignore_mask;
 static uae_u32 addressing_mask = 0x00ffffff;
 static uae_u32 interrupt_mask;
 static short loop_mode_jit, loop_mode_68010, loop_mode_cnt;
@@ -144,10 +154,12 @@ static short skipregchange;
 static short skipccrchange;
 static short askifmissing;
 static short nextall;
-static int exitcnt;
+static int exitcnt, irqcnt;
 static short cycles, cycles_range, cycles_adjust;
 static short gotcycles;
 static short interrupttest;
+static short interrupt_delay_cnt;
+static short interrupttest_diff_cnt;
 static uae_u32 cyclecounter_addr;
 static int errorcnt;
 static short uaemode;
@@ -222,6 +234,10 @@ static void flushcache(uae_u32 v)
 static void berrcopy(void *src, void *dst, uae_u32 size, uae_u32 hasvbr)
 {
 }
+static uae_u32 fpucomp(void *v)
+{
+       return 0;
+}
 static void *error_vector;
 #else
 
@@ -246,6 +262,7 @@ extern void setcpu(uae_u32, uae_u32*, uae_u32*);
 extern void flushcache(uae_u32);
 extern void *error_vector;
 extern void berrcopy(void*, void*, uae_u32, uae_u32);
+extern uae_u32 fpucomp(void*);
 
 #endif
 static uae_u32 exceptiontableinuse;
@@ -301,6 +318,29 @@ uae_s32 lls(uae_u16 *p)
        return (uae_s32)llu(p);
 }
 
+static void interrupt_results(void)
+{
+       if (interrupttest == 2) {
+               short pvcnt = 0;
+               for(short i = 0; i < 64; i++) {
+                       struct irqresult *irq1 = &irqresults[i];
+                       struct irqresult *irq2 = &irqresults[i + 1];
+                       if (irq1->pc == irq2->pc && irq1->sr == irq2->sr && i < 63) {
+                               pvcnt++;
+                       }
+                       if (irq1->pc != irq2->pc || irq1->sr != irq2->sr || i == 63) {
+                               if (irq1->sr == 0x6000) {
+                                       printf("S%02d-%02d: %08x ", i - pvcnt, i, irq1->pc);
+                               } else {
+                                       printf("U%02d-%02d: %08x ", i - pvcnt, i, irq1->pc);
+                               }
+                               pvcnt = 0;
+                       }
+               }
+               printf("\n");
+       }
+}
+
 static void endinfo(void)
 {
        printf("Last test: %u\n", testcnt);
@@ -1194,12 +1234,30 @@ static uae_u8 *restore_memory(uae_u8 *p, int storedata)
        return p;
 }
 
+static uae_u8 *restore_edata(uae_u8 *p)
+{
+       p++;
+       uae_u8 v = *p++;
+       switch(v)
+       {
+               case CT_EDATA_IRQ_CYCLES:
+                       interrupt_delay_cnt = *p++;
+               break;
+               default:
+               end_test();
+               printf("Unexpected CT_EDATA 0x%02x\n", *p);
+               endinfo();
+               exit(0);
+       }
+       return p;
+}
+
 static uae_u8 *restore_data(uae_u8 *p, struct registers *r)
 {
        uae_u8 v = *p;
        if (v & CT_END) {
                end_test();
-               printf("Unexpected end bit!? offset %d\n", p - test_data);
+               printf("Unexpected end bit!? 0x%02x offset %d\n", v, p - test_data);
                endinfo();
                exit(0);
        }
@@ -1248,6 +1306,8 @@ static uae_u8 *restore_data(uae_u8 *p, struct registers *r)
                p = restore_memory(p, 1);
        } else if (mode == CT_MEMWRITES) {
                p = restore_memory(p, 0);
+       } else if (mode == CT_EDATA) {
+               p = restore_edata(p);
        } else {
                end_test();
                printf("Unexpected mode %02x\n", v);
@@ -1613,6 +1673,52 @@ static int compare_exception(uae_u8 *s1, uae_u8 *s2, int len, int domask, uae_u8
        }
 }
 
+static uae_u8 *get_exceptionframe(struct registers *regs, short excnum, int *sizep)
+{
+       uae_u8 *frame = (uae_u8 *)regs->excframe;
+       short size = 0;
+       if (cpu_lvl == 0) {
+               if (excnum == 2 || excnum == 3) {
+                       size = 14;
+               } else {
+                       size = 6;
+               }
+               *sizep = size;
+               return frame;
+       }
+       uae_u16 type = (frame[4] << 8) | frame[5];
+       switch (type >> 12)
+       {
+       case 0:
+               size = 8;
+               break;
+       case 2:
+       case 3:
+               size = 12;
+               break;
+       case 4:
+               size = 16;
+               break;
+       case 7:
+               size = 60;
+               break;
+       case 8:
+               size = 82;
+               break;
+       case 9:
+               size = 20;
+               break;
+       case 10:
+               size = 32;
+               break;
+       case 11:
+               size = 92;
+               break;
+       }
+       *sizep = size;
+       return frame;
+}
+
 static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, short excnum, short *gotexcnum, short *experr, short *extratrace, short *group2with1)
 {
        int exclen = 0;
@@ -2070,6 +2176,16 @@ static int get_cycles_amiga(void)
 
 static uae_u16 test_intena, test_intreq;
 
+static void set_interrupt_sertest(void)
+{
+       volatile uae_u16 *intena = (uae_u16 *)0xdff09a;
+       volatile uae_u16 *serper = (uae_u16 *)0xdff032;
+       // enable serial receive interrupt
+       *intena = 0x8000 | 0x4000 | 0x0800;
+       // serial period
+       *serper = SERPER;
+}
+
 static void set_interrupt(void)
 {
        if (interrupt_count < 15) {
@@ -2191,29 +2307,6 @@ static int check_cycles(int exc, short extratrace, short extrag2w1, struct regis
        return 1;
 }
 
-static short getzobits(uae_u32 *vvp, uae_u8 b)
-{
-       uae_u32 vv[2];
-
-       vv[0] = vvp[0];
-       vv[1] = vvp[1];
-       // xxxx-yyyyyyy-00000001 <> xxxx-yyyyyyyy-00000000
-       if ((vv[1] & 0x1f) == 0x01) {
-               vv[1] &= ~1;
-       }
-       int bc = 0;
-       for (short i = 1; i >= 0; i--) {
-               uae_u32 v = vv[i];
-               for (short j = 0; j < 32; j++) {
-                       if ((v & 1) != b)
-                               return bc;
-                       v >>= 1;
-                       bc++;
-               }
-       }
-       return bc;
-}
-
 // mostly ugly workarounds for logarithmic/trigonometric functions
 // not returning identical values (6888x algorithms are unknown)
 static short fpucheckextra(struct fpureg *f1, struct fpureg *f2)
@@ -2229,97 +2322,44 @@ static short fpucheckextra(struct fpureg *f1, struct fpureg *f2)
        m2[1] = f2->m[1];
        uae_u16 exp1 = f1->exp & 0x7fff;
        uae_u16 exp2 = f2->exp & 0x7fff;
-       // NaN or Infinite: both must match but skip possible last bits
+       // NaN or Infinite
        if (exp1 == 0x7fff || exp2 == 0x7fff) {
-               goto lastbits;
+               if (m1[0] == 0 && m1[1] == 0) {
+                       if (m2[0] != 0 || m2[1] != 0) {
+                               return 0;
+                       }
+               }
+               if (m2[0] == 0 && m2[1] == 0) {
+                       if (m1[0] != 0 || m1[1] != 0) {
+                               return 0;
+                       }
+               }
+               return 1;
        }
        // Zero: both must match
        if ((!exp1 && !m1[0] && !m1[1]) || (!exp2 && !m2[0] && !m2[1])) {
                return 0;
        }
-
-       // rounding difference
-       // yyyy-ffffffff-ffffffff <> xxxx+1-80000000-00000000
-       if (exp1 == exp2 + 1 && m1[0] == 0x80000000 && m1[1] == 0x00000000 && (m2[0] & 0xffff0000) == 0xffff0000) {
-               exp1--;
-               m1[0] = m2[0];
-               m1[1] = m2[1];
-       } else if (exp2 == exp1 + 1 && m2[0] == 0x80000000 && m2[1] == 0x00000000 && (m1[0] & 0xffff0000) == 0xffff0000) {
-               exp2--;
-               m2[0] = m1[0];
-               m2[1] = m1[1];
+       if ((!exp1 && !m1[0] && !m1[1]) && (!exp2 && !m2[0] && !m2[1])) {
+               return 1;
        }
 
-       if (fpu_adjust_exp >= 0) {
-               if (abs(exp1 - exp2) > fpu_adjust_exp)
-                       return 0;
-       }
+       uae_u32 vx[9];
+       vx[0] = f1->exp << 16;
+       vx[1] = f1->m[0];
+       vx[2] = f1->m[1];
+       vx[3] = f2->exp << 16;
+       vx[4] = f2->m[0];
+       vx[5] = f2->m[1];
+       vx[6] = fpu_adjust_exp << 16;
+       vx[7] = 0x80000000;
+       vx[8] = 0x00000000;
 
-       // Some functions return xxxxxxxx-xxxxx800
-       // ...f800 -> ...ffff
-       // ...0800 -> ...0000
-       if ((m1[1] & 0xffff) == 0x0800) {
-               m1[1] &= ~0xffff;
-       }
-       if ((m1[1] & 0xffff) == 0xf800) {
-               m1[1] |= 0xffff;
-       }
-       if ((m2[1] & 0xffff) == 0x0800) {
-               m2[1] &= ~0xffff;
+       if (fpucomp(vx)) {
+               fpu_approx++;
+               return 1;
        }
-       if ((m2[1] & 0xffff) == 0xf800) {
-               m2[1] |= 0xffff;
-       }
-
-       short zb1 = getzobits(m1, 0);
-       short zb2 = getzobits(m2, 0);
-       short ob1 = getzobits(m1, 1);
-       short ob2 = getzobits(m2, 1);
-
-       // if another value ends to multiple zero bits
-       // and another to multiple one bits:
-       // skip it.
-       if (zb1 >= 4 && ob2 >= 4 && !zb2) {
-               zb2 = zb1;
-       } else if (zb2 >= 4 && ob1 >= 4 && !zb1) {
-               zb1 = zb2;
-       }
-
-       if (fpu_adjust_zb >= 0) {
-
-               if (abs(zb1 - zb2) > fpu_adjust_zb)
-                       return 0;
-       }
-
-lastbits:
-       // skip n bits from the end
-       if (fpu_adjust_man >= 0) {
-               short shift = zb1 < zb2 ? zb1 : zb2;
-               short startm = 1;
-               if (shift >= 32) {
-                       startm = 0;
-                       shift -= 32;
-               }
-
-               short diff = 0;
-               for (short i = startm; i >= 0; i--) {
-                       while (shift < 32) {
-                               short v1 = (m1[i] >> shift) & 1;
-                               short v2 = (m2[i] >> shift) & 1;
-                               if (v1 != v2) {
-                                       diff++;
-                                       if (diff > fpu_adjust_man) {
-                                               return 0;
-                                       }
-                               }
-                               shift++;
-                       }
-                       shift = 0;
-               }
-       }
-
-       fpu_approx++;
-       return 1;
+       return 0;
 }
 
 static void loop_mode_error(uae_u32 ov, uae_u32 nv)
@@ -2386,6 +2426,12 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr, st
        uae_u8 fpiar_changed = 0, fpsr_changed = 0, fpcr_changed = 0;
        short exc = -1;
 
+       if (interrupttest == 2) {
+               struct irqresult *irq = &irqresults[interrupt_delay_cnt];
+               irq->pc = tregs->pc;
+               irq->sr = tregs->sr & 0xff00;
+       }
+
        if (loop_mode_jit) {
                memset(lmtable1, 0xff, sizeof(lmtable1));
                memset(lmtable2, 0xff, sizeof(lmtable2));
@@ -2469,14 +2515,20 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr, st
                                if (lregs->pc + opcodeendsizeextra != tregs->pc) {
                                        branched2 = lregs->pc < opcode_memory_addr || lregs->pc >= opcode_memory_addr + OPCODE_AREA;
                                        if (dooutput) {
-                                               sprintf(outbp, "PC (%c): expected %08x but got %08x\n", branched ? 'B' : '-', lregs->pc, tregs->pc);
+                                               int excsize;
+                                               uae_u8 *excp;
+                                               sprintf(outbp, "PC (%c): expected %08x but got %08x ", branched ? 'B' : '-', lregs->pc, tregs->pc);
                                                outbp += strlen(outbp);
                                                if (tregs->pc == opcode_memory_addr) {
-                                                       sprintf(outbp, "Got unexpected exception %d (unsupported instruction?)\n", cpuexc);
+                                                       sprintf(outbp, "Got unexpected exception %d (unsupported instruction?) ", cpuexc);
                                                } else {
-                                                       sprintf(outbp, "Got unexpected exception %d\n", cpuexc);
+                                                       sprintf(outbp, "Got unexpected exception %d ", cpuexc);
                                                }
                                                outbp += strlen(outbp);
+                                               excp = get_exceptionframe(&test_regs, cpuexc, &excsize);
+                                               if (excp && excsize) {
+                                                       hexdump(excp, excsize, 1);
+                                               }
                                        }
                                        errflag |= 1 << 16;
                                }
@@ -2501,7 +2553,13 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr, st
                                        } else if (cpuexc == 4) {
                                                sprintf(outbp, "Exception: expected %d but got %d (or no exception)\n", exc, cpuexc);
                                        } else {
+                                               int excsize;
+                                               uae_u8 *excp;
                                                sprintf(outbp, "Exception: expected %d but got %d\n", exc, cpuexc);
+                                               excp = get_exceptionframe(&test_regs, cpuexc, &excsize);
+                                               if (excp && excsize) {
+                                                       hexdump(excp, excsize, 1);
+                                               }
                                        }
                                        experr = 1;
                                }
@@ -2630,7 +2688,7 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr, st
                        int size;
                        p = restore_value(p, &val, &size);
                        if (val != tregs->fpsr) {
-                               if (!ignore_errors) {
+                               if (!ignore_errors && ((val & fpsr_ignore_mask) != (tregs->fpsr & fpsr_ignore_mask))) {
                                        if (dooutput) {
                                                if (sregs->fpsr == tregs->fpsr) {
                                                        sprintf(outbp, "FPSR: expected %08x but register was not modified\n", val);
@@ -2768,7 +2826,7 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr, st
                        }
                }
                if (!ignore_sr) {
-                       if (fpsr_changed && tregs->fpsr != lregs->fpsr) {
+                       if (fpsr_changed && (tregs->fpsr & fpsr_ignore_mask) != (lregs->fpsr & fpsr_ignore_mask)) {
                                if (dooutput) {
                                        uae_u32 val = lregs->fpsr;
                                        sprintf(outbp, "FPSR: expected %08x -> %08x but got %08x\n", sregs->fpsr, val, tregs->fpsr);
@@ -2809,30 +2867,46 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr, st
        }
 
        if (loop_mode_jit) {
-               short idx = 0, cnt = 0, end = loop_mode_cnt * 2;
+               short idx = 0, cnt = 0, end = loop_mode_cnt;
                for (;;) {
-                       uae_u16 v1, v2;
-                       v1 = lmtable1[idx];
-                       v2 = lmtable2[idx];
+                       uae_u16 v1a = lmtable1[idx];
+                       uae_u16 v2a = lmtable2[idx];
+                       uae_u16 v1b = lmtable1[idx + 1];
+                       uae_u16 v2b = lmtable2[idx + 1];
                        idx++;
+                       if (loop_mode_jit == 3 || loop_mode_jit == 4) {
+                               idx++;
+                       }
                        if (idx >= LM_BUFFER / 2) {
                                break;
                        }
-                       if (v1 == 0xffff && v2 == 0xffff) {
+                       if (v1a == 0xffff && v2a == 0xffff) {
                                continue;
                        }
                        cnt++;
-                       if (v1 != v2) {
-                               sprintf(outbp, "LM %02d/%02d CCR: %02x != %02x",
-                                       cnt, end, v1, v2);
-                               outbp += strlen(outbp);
-                               sprintf(outbp, " X%c%d N%c%d Z%c%d V%c%d C%c%d\n",
-                                       (v1 & 0x10) != (v2 & 0x10) ? '!' : '=', (v2 & 0x10) != 0,
-                                       (v1 & 0x08) != (v2 & 0x08) ? '!' : '=', (v2 & 0x08) != 0,
-                                       (v1 & 0x04) != (v2 & 0x04) ? '!' : '=', (v2 & 0x04) != 0,
-                                       (v1 & 0x02) != (v2 & 0x02) ? '!' : '=', (v2 & 0x02) != 0,
-                                       (v1 & 0x01) != (v2 & 0x01) ? '!' : '=', (v2 & 0x01) != 0);
-                               outbp += strlen(outbp);
+                       if (v1a != v2a) {
+                               if (loop_mode_jit == 3 || loop_mode_jit == 4) {
+                                       static const char *constss[] = { "C", "Z", "V", "N", "X" };
+                                       const char *c = "?";
+                                       if (v1b < 5 && v1b == v2b) {
+                                               c = constss[v1b];
+                                       }
+                                       sprintf(outbp, "LM %02d/%02d %s: %d %c %d (%04x %04x - %04x %04x)\n",
+                                               cnt, end, c, (v1a & 0xff) != 0, v1a != v2a ? '!' : '=', (v2a & 0xff) != 0,
+                                               v1a, v1b, v2a, v2b);
+                                       outbp += strlen(outbp);
+                               } else if (loop_mode_jit == 1 || loop_mode_jit == 2) {
+                                       sprintf(outbp, "LM %02d/%02d CCR: %02x != %02x",
+                                               cnt, end, v1a, v2a);
+                                       outbp += strlen(outbp);
+                                       sprintf(outbp, " X%c%d N%c%d Z%c%d V%c%d C%c%d\n",
+                                               (v1a & 0x10) != (v2a & 0x10) ? '!' : '=', (v2a & 0x10) != 0,
+                                               (v1a & 0x08) != (v2a & 0x08) ? '!' : '=', (v2a & 0x08) != 0,
+                                               (v1a & 0x04) != (v2a & 0x04) ? '!' : '=', (v2a & 0x04) != 0,
+                                               (v1a & 0x02) != (v2a & 0x02) ? '!' : '=', (v2a & 0x02) != 0,
+                                               (v1a & 0x01) != (v2a & 0x01) ? '!' : '=', (v2a & 0x01) != 0);
+                                       outbp += strlen(outbp);
+                               }
                        }
                        if (cnt >= end) {
                                break;
@@ -2948,9 +3022,9 @@ static uae_u32 xorshift32(void)
 static void copyregs(struct registers *d, struct registers *s, short fpumode)
 {
        if (fpumode) {
-               memcpy(&d->regs[0], &s->regs[0], offsetof(struct registers, fsave));
+               memcpy(d->regs, s->regs, offsetof(struct registers, fsave));
        } else {
-               memcpy(&d->regs[0], &s->regs[0], offsetof(struct registers, fpuregs));
+               memcpy(d->regs, s->regs, offsetof(struct registers, fpuregs));
        }
 }
 
@@ -2982,9 +3056,20 @@ static void process_test(uae_u8 *p)
        clear_interrupt();
 #endif
        ahcnt = 0;
+       
+       short doopcodeswap = 1;
+       
+       if (interrupttest == 2) {
+               doopcodeswap = 0;
+       }
 
        for (;;) {
 
+               if (interrupttest == 2) {
+                       memcpy(irqresults2, irqresults, sizeof(irqresults));
+                       memset(irqresults, 0, sizeof(irqresults));
+               }
+
                cur_regs.endpc = endpc;
                cur_regs.pc = startpc;
 
@@ -3016,7 +3101,7 @@ static void process_test(uae_u8 *p)
 
                copyregs(&last_regs, &cur_regs, fpumode);
 
-               uae_u32 originalopcodeend = (ILLG_OPCODE << 16) | NOP_OPCODE;
+               uae_u32 originalopcodeend = (NOP_OPCODE << 16) | ILLG_OPCODE;
                short opcodeendsizeextra = 0;
                uae_u32 opcodeend = originalopcodeend;
                int extraccr = 0;
@@ -3042,22 +3127,31 @@ static void process_test(uae_u8 *p)
                                sr_mask |= 0x1000; // M
 
                        uae_u8 ccrmode = *p++;
-                       int maxccr = ccrmode & 0x3f;
+                       short maxccr = ccrmode & 0x3f;
+                       short ccrshift = 0;
+                       while ((maxccr - 1) & (1 << ccrshift)) {
+                               ccrshift++;
+                       }
+                       ccrshift--;
+                       if (interrupttest == 2) {
+                               maxccr *= 64;
+                       }
                        testcntsubmax = maxccr;
                        testcntsub = 0;
-                       for (short ccr = 0;  ccr < maxccr; ccr++, testcntsub++) {
-
+                       for (short ccrcnt = 0;  ccrcnt < maxccr; ccrcnt++, testcntsub++) {
+                               short ccr = ccrcnt & (maxccr - 1);
                                fpu_approx = 0;
 
-                               opcodeend = (opcodeend >> 16) | (opcodeend << 16);
-                               opcodeendsizeextra = opcodeendsizeextra ? 0 : 2;
+                               if (doopcodeswap) {
+                                       opcodeend = (opcodeend >> 16) | (opcodeend << 16);
+                               }
+                               opcodeendsizeextra = (opcodeend >> 16) == NOP_OPCODE ? 2 : 0;
                                if (validendsize == 2) {
                                        pl(opcode_memory_end, opcodeend);
                                } else if (validendsize == 1) {
                                        pw(opcode_memory_end, opcodeend >> 16);
                                }
 
-
                                if (cur_regs.branchtarget != 0xffffffff && !(cur_regs.branchtarget & 1)) {
                                        if (cur_regs.branchtarget_mode == 1) {
                                                uae_u32 bv = gl((uae_u8*)cur_regs.branchtarget);
@@ -3075,11 +3169,11 @@ static void process_test(uae_u8 *p)
 
                                cur_regs.ssp = super_stack_memory - 0x80;
                                cur_regs.msp = super_stack_memory;
+                               cur_regs.fpiar = 0xffffffff;
 
                                copyregs(&test_regs, &cur_regs, fpumode);
 
                                test_regs.pc = startpc;
-                               test_regs.fpiar = startpc;
                                test_regs.cyclest = 0xffffffff;
                                test_regs.fpeaset = 0;
 
@@ -3112,7 +3206,7 @@ static void process_test(uae_u8 *p)
                                }
 
 #ifdef AMIGA
-                               if (interrupttest) {
+                               if (interrupttest == 1) {
                                        interrupt_count = *p++;
                                }
 #endif
@@ -3161,6 +3255,11 @@ static void process_test(uae_u8 *p)
                                }
 
                                test_regs.expsr = test_regs.sr | 0x2000;
+                               
+                               if (interrupttest == 2) {
+                                       interrupt_delay_cnt = ccrcnt >> ccrshift;
+                                       cur_regs.regs[0] = test_regs.regs[0] = interrupt_delay_cnt;
+                               }
 
                                // internally modified registers become part of cur_regs
                                cur_regs.sr = test_regs.sr;
@@ -3184,7 +3283,10 @@ static void process_test(uae_u8 *p)
 
                                if (exitcnt >= 0) {
                                        exitcnt--;
-                                       if (exitcnt < 0) {
+                                       if (exitcnt == -1) {
+                                               volatile UWORD *cp = (volatile UWORD*)0x100;
+                                               *cp = 0x1234;
+#if 0
                                                addinfo();
                                                strcat(outbp, "Registers before:\n");
                                                outbp += strlen(outbp);
@@ -3192,7 +3294,11 @@ static void process_test(uae_u8 *p)
                                                end_test();
                                                printf(outbuffer);
                                                printf("\nExit count expired\n");
+                                               if (interrupttest == 2) {
+                                                       interrupt_results();
+                                               }
                                                exit(0);
+#endif
                                        }
                                }
 
@@ -3223,8 +3329,10 @@ static void process_test(uae_u8 *p)
 
 
 #ifdef AMIGA
-                                               if (interrupttest) {
+                                               if (interrupttest == 1) {
                                                        set_interrupt();
+                                               } else  if (interrupttest == 2) {
+                                                       set_interrupt_sertest();
                                                }
 #endif
                                                if (cpu_lvl == 1) {
@@ -3289,26 +3397,29 @@ static void process_test(uae_u8 *p)
                                        fpu_approxcnt++;
                                }
 
-                               if (quit || errors) {
-                                       if (!quit && errorcnt > 0 && totalerrors < errorcnt) {
-                                               if (totalerrors > 0) {
-                                                       strcat(stored_outbuffer, "----------------------------------------\n");
-                                               }
-                                               if (strlen(stored_outbuffer) + strlen(outbuffer) + 40 >= outbuffer_size) {
+                               if (interrupttest != 2) {
+
+                                       if (quit || errors) {
+                                               if (!quit && errorcnt > 0 && totalerrors < errorcnt) {
+                                                       if (totalerrors > 0) {
+                                                               strcat(stored_outbuffer, "----------------------------------------\n");
+                                                       }
+                                                       if (strlen(stored_outbuffer) + strlen(outbuffer) + 40 >= outbuffer_size) {
+                                                               goto end;
+                                                       }
+                                                       strcat(stored_outbuffer, outbuffer);
+                                                       outbp = stored_outbuffer + strlen(stored_outbuffer);
+                                                       out_endinfo();
+                                                       infoadded = 0;
+                                                       errors = 0;
+                                                       outbuffer[0] = 0;
+                                                       outbuffer2[0] = 0;
+                                                       outbp = outbuffer2;
+                                               } else {
                                                        goto end;
                                                }
-                                               strcat(stored_outbuffer, outbuffer);
-                                               outbp = stored_outbuffer + strlen(stored_outbuffer);
-                                               out_endinfo();
-                                               infoadded = 0;
-                                               errors = 0;
-                                               outbuffer[0] = 0;
-                                               outbuffer2[0] = 0;
-                                               outbp = outbuffer2;
-                                       } else {
-                                               goto end;
+                                               totalerrors++;
                                        }
-                                       totalerrors++;
                                }
                        }
 
@@ -3328,6 +3439,20 @@ static void process_test(uae_u8 *p)
                }
 
                restoreahist();
+               
+               // increase count when interrupt test returns different results
+               if (interrupttest == 2) {
+                       if (memcmp(irqresults, irqresults2, sizeof(irqresults))) {
+                               interrupttest_diff_cnt++;
+                               if (interrupttest_diff_cnt == irqcnt) {
+                                       end_test();
+                                       printf(outbuffer);
+                                       printf("Interrupt test count expired\n");
+                                       interrupt_results();
+                                       exit(0);
+                               }
+                       }
+               }
 
        }
 
@@ -3343,6 +3468,9 @@ end:
                        printf("%s", outbuffer);
                }
        }
+       if (interrupttest == 2) {
+               interrupt_results();
+       }
 }
 
 static void freestuff(void)
@@ -3402,7 +3530,7 @@ static int test_mnemo(const char *opcode)
        lvl = (lvl_mask >> 16) & 15;
        interrupt_mask = (lvl_mask >> 20) & 7;
        addressing_mask = (lvl_mask & 0x80000000) ? 0xffffffff : 0x00ffffff;
-       interrupttest = (lvl_mask >> 26) & 1;
+       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;
@@ -3421,6 +3549,9 @@ static int test_mnemo(const char *opcode)
        if (loop_mode_jit || loop_mode_68010) {
                loop_mode_cnt = v & 0xff;
        }
+       if ((v >> 8) & 15) {
+               loop_mode_jit = (v >> 8) & 15;
+       }
        read_u32(headerfile, &headoffset);
        read_u32(headerfile, &headoffset);
        memcpy(inst_name, headerfile + headoffset, sizeof(inst_name) - 1);
@@ -3590,11 +3721,16 @@ static int test_mnemo(const char *opcode)
 
 static int getparamval(const char *p)
 {
+       ULONG inv = 0;
+       if (p[0] == '~') {
+               inv = 0xffffffff;
+               p++;
+       }
        if (strlen(p) > 2 && p[0] == '0' && toupper(p[1]) == 'X') {
                char *endptr;
-               return strtol(p + 2, &endptr, 16);
+               return strtol(p + 2, &endptr, 16) ^ inv;
        } else {
-               return atol(p);
+               return atol(p) ^ inv;
        }
 }
 
@@ -3670,7 +3806,8 @@ int main(int argc, char *argv[])
                printf("-skipreg = do not validate registers.\n");
                printf("-askifmissing = ask for new path if dat file is missing.\n");
                printf("-exit n = exit after n tests.\n");
-               printf("-fpuadj <exp diff> <man bit count diff> <man zero bit count diff>.\n");
+               printf("-fpuadj <exp> 16-bit exponent range value. (16383 = 1.0)\n");
+               printf("-fpsrmask = ignore FPSR bits that are not set.");
                printf("-cycles [range adjust] = check cycle counts.\n");
                printf("-cyclecnt <address>. Use custom hardware cycle counter.\n");
 #ifdef AMIGA
@@ -3684,13 +3821,12 @@ int main(int argc, char *argv[])
 
        check_undefined_sr = 1;
        ccr_mask = 0xff;
+       fpsr_ignore_mask = 0xffffffff;
        disasm = 1;
        exitcnt = -1;
        cyclecounter_addr = 0xffffffff;
        cycles_range = 2;
        fpu_adjust_exp = -1;
-       fpu_adjust_man = -1;
-       fpu_adjust_zb = -1;
 
        for (int i = 1; i < argc; i++) {
                char *s = argv[i];
@@ -3711,6 +3847,12 @@ int main(int argc, char *argv[])
                                ccr_mask = ~getparamval(next);
                                i++;
                        }
+               } else if (!_stricmp(s, "-fpsrmask")) {
+                       fpsr_ignore_mask = 0;
+                       if (next) {
+                               fpsr_ignore_mask = ~getparamval(next);
+                               i++;
+                       }
                } else if (!_stricmp(s, "-silent")) {
                        dooutput = 0;
                } else if (!_stricmp(s, "-68000")) {
@@ -3746,20 +3888,17 @@ int main(int argc, char *argv[])
                                exitcnt = atoi(next);
                                i++;
                        }
+               } else if (!_stricmp(s, "-irqcnt")) {
+                       if (next) {
+                               irqcnt = atoi(next);
+                               i++;
+                       }
                } else if (!_stricmp(s, "-prealloc")) {
                        prealloc = 1;
                } else if (!_stricmp(s, "-fpuadj")) {
                        if (next) {
                                fpu_adjust_exp = atol(next);
-                               char *p = strchr(next, ',');
-                               if (p) {
-                                       fpu_adjust_man = atol(p + 1);
-                                       char *p = strchr(next, ',');
-                                       if (p) {
-                                               fpu_adjust_zb = atol(p + 1);
-                                       }
-                               }
-                               if (fpu_adjust_exp >= 0 || fpu_adjust_man >= 0 || fpu_adjust_zb >= 0) {
+                               if (fpu_adjust_exp >= 0) {
                                        is_fpu_adjust = 1;
                                }
 
@@ -3893,9 +4032,10 @@ int main(int argc, char *argv[])
                                return 0;
                        }
 #define MAX_FILE_LEN 128
-#define MAX_MNEMOS 256
-                       char *dirs = calloc(MAX_MNEMOS, MAX_FILE_LEN);
+#define MAX_FILES 500
+                       char *dirs = calloc(MAX_FILES, MAX_FILE_LEN);
                        int diroff = 0;
+                       int dircnt = 0;
                        if (!dirs)
                                return 0;
 
@@ -3906,9 +4046,10 @@ int main(int argc, char *argv[])
                                int d = isdir(path, dr->d_name);
                                if (d && dr->d_name[0] != '.') {
                                        strcpy(dirs + diroff, dr->d_name);
+                                       dircnt++;
                                        diroff += MAX_FILE_LEN;
-                                       if (diroff >= MAX_FILE_LEN * MAX_MNEMOS) {
-                                               printf("too many directories!?\n");
+                                       if (dircnt >= MAX_FILES) {
+                                               printf("too many directories!? (%d)\n", dircnt);
                                                return 0;
                                        }
                                }
index f3c81d28c690bcbe4ce850802d91cb0cbcfee100..b9a5e49f89a88e64c2ca9f15743ce550ffe9ebd5 100644 (file)
@@ -218,3 +218,7 @@ Only test generator was updated. Data structures or m68k tester has not been cha
 - Interrupt testing (Amiga only, INTREQ bits set one by one, validate correct exception).
 - Multiple test sets can be generated and tested in single step.
 - Stack usage reduced, gzip decompression works with default 4096 byte stack.
+
+06.12.2021
+
+- FPU testing improvements
index bbfd0e31c501d6fd7eb69c85a41fc6d58f1309be..a640d236dc3b968a50e2ccc0a666ef97bb4955e4 100644 (file)
@@ -66,4 +66,4 @@ void m68k_do_jsr_ce(uaecptr oldpc, uaecptr dest);
 void m68k_setstopped(void);
 void check_t0_trace(void);
 
-void cpureset(void);
+bool cpureset(void);