]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
CPU tester updates. 68060 special cases: MOVEC, HALT, PULSE, LPSTOP fix. RTE 68010...
authorToni Wilen <twilen@winuae.net>
Sun, 8 Sep 2019 15:09:18 +0000 (18:09 +0300)
committerToni Wilen <twilen@winuae.net>
Sun, 8 Sep 2019 15:09:18 +0000 (18:09 +0300)
14 files changed:
cputest.cpp
cputest/amiga.S
cputest/cputest_defines.h
cputest/cputestgen.ini
cputest/main.c
cputest/readme.txt [new file with mode: 0644]
disasm.cpp
gencpu.cpp
include/cputest.h
include/newcpu.h
include/readcpu.h
newcpu_common.cpp
readcpu.cpp
table68k

index acfbdf84535942c3aeb90ce6ecbc0a37f45d9d40..712be3cadad13d6ea755b6bcd9d9efa5dd63893e 100644 (file)
@@ -107,9 +107,11 @@ static uae_u32 immabsl_cnt;
 static uae_u32 addressing_mask;
 static int opcodecnt;
 static int cpu_stopped;
+static int cpu_halted;
 static int cpu_lvl = 0;
 static int test_count;
 static int testing_active;
+static uae_u16 testing_active_opcode;
 static time_t starttime;
 static int filecount;
 static uae_u16 sr_undefined_mask;
@@ -134,6 +136,16 @@ static int noaccesshistory = 0;
 static struct accesshistory ahist[MAX_ACCESSHIST];
 static struct accesshistory ahist2[MAX_ACCESSHIST];
 
+static int is_superstack_use_required(void)
+{
+       switch (testing_active_opcode)
+       {
+       case 0x4e73: // RTE
+               return 1;
+       }
+       return 0;
+}
+
 #define OPCODE_AREA 32
 
 static bool valid_address(uaecptr addr, int size, int w)
@@ -176,6 +188,18 @@ static bool valid_address(uaecptr addr, int size, int w)
                test_memory_accessed = w ? -1 : 1;
                return 1;
        }
+       if (addr >= test_memory_end - RESERVED_SUPERSTACK && addr + size < test_memory_end) {
+               // allow only instructions that have to access super stack, for example RTE
+               // read-only
+               if (w)
+                       goto oob;
+               if (testing_active) {
+                       if (is_superstack_use_required()) {
+                               test_memory_accessed = 1;
+                               return 1;
+                       }
+               }
+       }
 oob:
        return 0;
 }
@@ -440,9 +464,11 @@ void dfc_nommu_put_long(uaecptr addr, uae_u32 v)
        put_long_test(addr, v);
 }
 
-uae_u16 get_wordi_test(uaecptr addr)
+uae_u16 get_wordi_test(int o)
 {
-       return get_word_test(addr);
+       uae_u32 v = get_word_test_prefetch(o);
+       regs.pc += 2;
+       return v;
 }
 
 uae_u32 memory_get_byte(uaecptr addr)
@@ -653,6 +679,11 @@ void REGPARAM2 MakeFromSR(void)
        MakeFromSR_x(0);
 }
 
+void cpu_halt(int halt)
+{
+       cpu_halted = halt;
+}
+
 static void exception_check_trace(int nr)
 {
        SPCFLAG_TRACE = 0;
@@ -688,7 +719,7 @@ void check_t0_trace(void)
 
 void cpureset(void)
 {
-       test_exception = 1;
+       cpu_halted = -1;
 }
 
 static void doexcstack(void)
@@ -1461,7 +1492,21 @@ static int create_ea(uae_u16 *opcodep, uaecptr pc, int mode, int reg, struct ins
                        if (opcodecnt == 1) {
                                // STOP #xxxx: test all combinations
                                // (also includes RTD)
-                               put_word_test(pc, imm16_cnt++);
+                               if (dp->mnemo == i_LPSTOP) {
+                                       uae_u16 lp = 0x01c0;
+                                       if (imm16_cnt & (0x40 | 0x80)) {
+                                               for (;;) {
+                                                       lp = rand16();
+                                                       if (lp != 0x01c0)
+                                                               break;
+                                               }
+                                       }
+                                       put_word_test(pc, lp);
+                                       put_word_test(pc + 2, imm16_cnt++);
+                                       pc += 2;
+                               } else {
+                                       put_word_test(pc, imm16_cnt++);
+                               }
                                if (imm16_cnt == 0)
                                        *isconstant = 0;
                                else
@@ -1632,17 +1677,102 @@ static void handle_specials_extra(uae_u16 opcode, uaecptr pc, struct instr *dp)
        }
 }
 
+static uae_u32 generate_stack_return(int cnt)
+{
+       uae_u32 v = rand32();
+       switch (cnt & 3)
+       {
+       case 0:
+       case 3:
+               v = opcode_memory_start + 128;
+               break;
+       case 1:
+               v &= 0xffff;
+               if (test_low_memory_start == 0xffffffff)
+                       v |= 0x8000;
+               if (test_high_memory_start == 0xffffffff)
+                       v &= 0x7fff;
+               break;
+       case 2:
+               v = opcode_memory_start + (uae_s16)v;
+               break;
+       }
+       if (!feature_exception3_instruction)
+               v &= ~1;
+       return v;
+}
+
+static int handle_rte(uae_u16 opcode, uaecptr pc, struct instr *dp, int *isconstant, uaecptr addr)
+{
+       // skip bus error/address error frames because internal fields can't be simply randomized
+       int offset = 2;
+       int frame, v;
+
+       imm_special++;
+       for (;;) {
+               frame = (imm_special >> 2) & 15;
+               // 68010 bus/address error
+               if (cpu_lvl == 1 && (frame == 8)) {
+                       imm_special += 4;
+                       continue;
+               }
+               if ((cpu_lvl == 2 || cpu_lvl == 3) && (frame == 9 || frame == 10 || frame == 11)) {
+                       imm_special += 4;
+                       continue;
+               }
+               // 68040 FP post-instruction, FP unimplemented, Address error
+               if (cpu_lvl == 4 && (frame == 3 || frame == 4 || frame == 7)) {
+                       imm_special += 4;
+                       continue;
+               }
+               // 68060 access fault/FP disabled, FP post-instruction
+               if (cpu_lvl == 5 && (frame == 3 || frame == 4)) {
+                       imm_special += 4;
+                       continue;
+               }
+               // throwaway frame
+               if (frame == 1) {
+                       imm_special += 4;
+                       continue;
+               }
+               break;  
+       }
+       v = imm_special >> 6;
+       uae_u16 sr = v & 31;
+       sr |= (v >> 5) << 12;
+       put_word_test(addr, sr);
+       addr += 2 + 4;
+       // frame + vector offset
+       put_word_test(addr, (frame << 12) | (rand16() & 0x0fff));
+       addr += 2;
+#if 0
+       if (frame == 1) {
+               int imm_special_tmp = imm_special;
+               imm_special &= ~(15 << 2);
+               if (rand8() & 1)
+                       imm_special |= 2 << 2;
+               handle_rte(opcode, addr, dp, isconstant, addr);
+               imm_special = imm_special_tmp;
+               v = generate_stack_return(imm_special);
+               put_long_test(addr + 2, v);
+               offset += 8 + 2;
+#endif
+       if (frame == 2) {
+               put_long_test(addr, rand32());
+       }
+       return offset;
+}
+
 static int handle_specials_stack(uae_u16 opcode, uaecptr pc, struct instr *dp, int *isconstant)
 {
        int offset = 0;
        if (dp->mnemo == i_RTE || dp->mnemo == i_RTD || dp->mnemo == i_RTS || dp->mnemo == i_RTR || dp->mnemo == i_UNLK) {
                uae_u32 v;
                uaecptr addr = regs.regs[8 + 7];
-               imm_special++;
                // RTE, RTD, RTS and RTR
                if (dp->mnemo == i_RTR) {
                        // RTR
-                       v = imm_special;
+                       v = imm_special++;
                        uae_u16 ccr = v & 31;
                        ccr |= rand16() & ~31;
                        put_word_test(addr, ccr);
@@ -1652,6 +1782,7 @@ static int handle_specials_stack(uae_u16 opcode, uaecptr pc, struct instr *dp, i
                } else if (dp->mnemo == i_RTE) {
                        // RTE
                        if (currprefs.cpu_model == 68000) {
+                               imm_special++;
                                v = imm_special >> 2;
                                uae_u16 sr = v & 31;
                                sr |= (v >> 5) << 12;
@@ -1659,27 +1790,15 @@ static int handle_specials_stack(uae_u16 opcode, uaecptr pc, struct instr *dp, i
                                addr += 2;
                                offset += 2;
                        } else {
-                               // TODO 68010+ RTE
+                               offset += handle_rte(opcode, pc, dp, isconstant, addr);
+                               addr += 2;
                        }
                        *isconstant = imm_special >= (1 << (4 + 5)) * 4 ? 0 : -1;
                } else if (dp->mnemo == i_RTS) {
                        // RTS
                        *isconstant = imm_special >= 256 ? 0 : -1;
                }
-               v = rand32();
-               switch (imm_special & 3)
-               {
-               case 0:
-               case 3:
-                       v = opcode_memory_start + 128;
-                       break;
-               case 1:
-                       v &= 0xffff;
-                       break;
-               case 2:
-                       v = opcode_memory_start + (uae_s16)v;
-                       break;
-               }
+               v = generate_stack_return(imm_special);
                put_long_test(addr, v);
                if (out_of_test_space) {
                        wprintf(_T("handle_specials out of bounds access!?"));
@@ -1693,8 +1812,8 @@ static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc, struct ins
 {
        uae_u16 opw1 = (opcode_memory[2] << 8) | (opcode_memory[3] << 0);
        uae_u16 opw2 = (opcode_memory[4] << 8) | (opcode_memory[5] << 0);
-       if (opc == 0x4c42
-               && opw1 == 0xcf19
+       if (opc == 0x89c2
+               //&& opw1 == 0xcf19
                //&& opw2 == 0x504e
                )
                printf("");
@@ -1713,6 +1832,7 @@ static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc, struct ins
        high_memory_accessed = 0;
        test_memory_accessed = 0;
        testing_active = 1;
+       testing_active_opcode = opc;
 
        int cnt = feature_loop_mode * 2;
 
@@ -1727,9 +1847,11 @@ static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc, struct ins
 
                (*cpufunctbl[opc])(opc);
 
-               // supervisor mode and A7 was modified: skip this test round.
+               // Supervisor mode and A7 was modified: skip this test round.
                if (s && regs.regs[15] != a7) {
-                       test_exception = -1;
+                       // but not if RTE
+                       if (!is_superstack_use_required())
+                               test_exception = -1;
                }
 
                if (!test_exception) {
@@ -1831,7 +1953,6 @@ static int isunsupported(struct instr *dp)
        switch (dp->mnemo)
        {
        case i_MOVE2C:
-       case i_MOVEC2:
        case i_FSAVE:
        case i_FRESTORE:
        case i_PFLUSH:
@@ -1846,14 +1967,21 @@ static int isunsupported(struct instr *dp)
        case i_CINVA:
        case i_CINVL:
        case i_CINVP:
+       case i_PLPAR:
+       case i_PLPAW:
                return 1;
-       case i_RTE:
-               if (cpu_lvl > 0)
-                       return 1;
-               break;
        }
        return 0;
+}
 
+static int noregistercheck(struct instr *dp)
+{
+       switch (dp->mnemo)
+       {
+       case i_MOVEC2:
+               return 1;
+       }
+       return 0;
 }
 
 static uae_u8 last_exception[256];
@@ -1922,12 +2050,14 @@ static uae_u8 *save_exception(uae_u8 *p, struct instr *dp)
        return p;
 }
 
-static uae_u16 get_ccr_ignore(struct instr *dp)
+static uae_u16 get_ccr_ignore(struct instr *dp, uae_u16 extra)
 {
        uae_u16 ccrignoremask = 0;
-       if ((cpu_lvl == 2 || cpu_lvl == 3) && test_exception == 5 && (dp->mnemo == i_DIVS || dp->mnemo == i_DIVL)) {
-               // 68020/030 DIVS.W/.L + Divide by Zero: V state is not stable.
-               ccrignoremask |= 2; // mask CCR=V
+       if ((cpu_lvl == 2 || cpu_lvl == 3) && test_exception == 5) {
+               if ((dp->mnemo == i_DIVS) || (dp->mnemo == i_DIVL && (extra & 0x0800) && !(extra & 0x0400))) {
+                       // 68020/030 DIVS.W/.L + Divide by Zero: V state is not stable.
+                       ccrignoremask |= 2; // mask CCR=V
+               }
        }
        return ccrignoremask;
 }
@@ -2010,6 +2140,8 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                }
        }
 
+       xorshiftstate ^= 0x12;
+
        int pathlen = _tcslen(path);
        _stprintf(dir, _T("%s%s"), path, mns);
        if (fpuopcode < 0) {
@@ -2187,7 +2319,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
 
                                        if (opc == 0x0156)
                                                printf("");
-                                       if (subtest_count == 1537)
+                                       if (subtest_count == 416)
                                                printf("");
 
 
@@ -2416,6 +2548,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                        out_of_test_space = 0;
                                                        test_exception = 0;
                                                        cpu_stopped = 0;
+                                                       cpu_halted = 0;
                                                        ahcnt = 0;
 
                                                        memset(&regs, 0, sizeof(regs));
@@ -2440,6 +2573,8 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                        regs.sr = ccr | sr_mask;
                                                        regs.usp = regs.regs[8 + 7];
                                                        regs.isp = test_memory_end - 0x80;
+                                                       // copy user stack to super stack, for RTE etc support
+                                                       memcpy(regs.isp - test_memory_start + test_memory, regs.usp - test_memory_start + test_memory, 0x20);
                                                        regs.msp = test_memory_end;
 
                                                        // data size optimization, only store data
@@ -2477,6 +2612,9 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                                cnt_stopped++;
                                                                // CPU stopped, skip test
                                                                skipped = 1;
+                                                       } else if (cpu_halted) {
+                                                               // CPU halted or reset, skip test
+                                                               skipped = 1;
                                                        } else if (out_of_test_space) {
                                                                exception_array[0]++;
                                                                // instruction accessed memory out of test address space bounds
@@ -2490,11 +2628,8 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                                exception_array[test_exception]++;
                                                                if (test_exception == 8 && !(sr_mask & 0x2000)) {
                                                                        // Privilege violation exception? Switch to super mode in next round.
-                                                                       // Except if reset..
-                                                                       if (lookup->mnemo != i_RESET) {
-                                                                               sr_mask_request |= 0x2000;
-                                                                               sr_allowed_mask |= 0x2000;
-                                                                       }
+                                                                       sr_mask_request |= 0x2000;
+                                                                       sr_allowed_mask |= 0x2000;
                                                                }
                                                                if (test_exception == 3) {
                                                                        if (!feature_exception3_data && !(test_exception_3_fc & 2)) {
@@ -2520,23 +2655,30 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                                // validate branch instructions
                                                                if (isbranchinst(dp)) {
                                                                        if ((regs.pc != srcaddr && regs.pc != pc - 2) || pcaddr[0] != 0x4a && pcaddr[1] != 0xfc) {
-                                                                               printf("Branch instruction target fault\n");
-                                                                               exit(0);
+                                                                               wprintf(_T("Branch instruction target fault\n"));
+                                                                               abort();
                                                                        }
                                                                }
                                                        }
                                                        MakeSR();
                                                        if (!skipped) {
+                                                               bool storeregs = true;
+                                                               if (noregistercheck(dp)) {
+                                                                       *dst++ = CT_SKIP_REGS;
+                                                                       storeregs = false;
+                                                               }
                                                                // save modified registers
                                                                for (int i = 0; i < MAX_REGISTERS; i++) {
                                                                        uae_u32 s = last_registers[i];
                                                                        uae_u32 d = regs.regs[i];
                                                                        if (s != d) {
-                                                                               dst = store_reg(dst, CT_DREG + i, s, d, -1);
+                                                                               if (storeregs) {
+                                                                                       dst = store_reg(dst, CT_DREG + i, s, d, -1);
+                                                                               }
                                                                                last_registers[i] = d;
                                                                        }
                                                                }
-                                                               uae_u32 ccrignoremask = get_ccr_ignore(dp) << 16;
+                                                               uae_u32 ccrignoremask = get_ccr_ignore(dp, ((pcaddr[2] << 8) | pcaddr[3])) << 16;
                                                                if ((regs.sr | ccrignoremask) != last_sr) {
                                                                        dst = store_reg(dst, CT_SR, last_sr, regs.sr | ccrignoremask, -1);
                                                                        last_sr = regs.sr | ccrignoremask;
@@ -2740,6 +2882,9 @@ static void test_mnemo_text(const TCHAR *path, const TCHAR *mode)
                _tcscpy(modetxt, _T("MULL"));
                extra_and = 0x0800;
                ovrname = _T("MULU");
+       } else if (!_tcsicmp(modetxt, _T("MOVEC"))) {
+               _tcscpy(modetxt, _T("MOVEC2"));
+               ovrname = _T("MOVEC");
        }
 
        for (int j = 0; lookuptab[j].name; j++) {
index dcd6a41b3274efd4f74b5649a54532de3d1a000e..c7b4dd94c224c06587fd7a0d8893279addeb176c 100644 (file)
@@ -68,7 +68,7 @@ _get_cpu_model:
        movem.l a5/a6,-(sp)
        move.l a0,a6
        lea scpucheck(pc),a5
-       jsr -0x1e(a6)
+       jsr -0x1e(a6) | Supervisor
        movem.l (sp)+,a5/a6
        bra.s .cpudone2
 .cpucheck2:    
@@ -81,7 +81,7 @@ _get_cpu_model:
        bne.s .cpudone
        dbf d0,.cpucheck
 .cpudone:
-       addq.l #1,d0
+       addq.w #1,d0
 .cpudone2:
        rts
 
index 169a496d178cba250c182e0087648922d4a32710..9f332d9034a9c403e618ee60a1c98b62d7a73a99 100644 (file)
@@ -33,4 +33,5 @@
 #define CT_END_FINISH 0xff
 #define CT_END_INIT (0x80 | 0x40)
 #define CT_END_SKIP (0x80 | 0x40 | 0x01)
+#define CT_SKIP_REGS (0x80 | 0x40 | 0x02)
 #define CT_EMPTY CT_END_INIT
index 21be525a3f335d11d502583a73b8a38ebc0eb8ce..36cdbaa52ba1aff2932bd33cffe631b0f84d69d1 100644 (file)
@@ -1,12 +1,12 @@
 
 [cputest]
 
-; CPU model (68000, 68020, 68040 or 68060).
+; CPU model (68000, 68020, 68030, 68040 or 68060).
 ; Always select 68020 when testing FPU instructions, even if test hardware CPU is 68040 or 68060.
-cpu=68020
+cpu=68000
 
 ; CPU address space. 24-bit or 32-bit. If 24-bit, tester will assume upper 8-bits of addresses gets ignored.
-cpu_address_space=32
+cpu_address_space=24
 
 ; FPU model (empty string or 0, 68881, 68882, 68040, 68060)
 ; Enable only when testing FPU. Enabled FPU mode will slow down native test execution even when not testing FPU instructions.
@@ -23,15 +23,17 @@ 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.
-;test_high_memory_start=0x00ff8000
-;test_high_memory_end=0x01000000
+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=0x780000
-test_memory_start=0x68800000
+test_memory_start=0x780000
+;test_memory_start=0x68800000
+;test_memory_start=0x07800000
+;test_memory_start=0x08800000
 test_memory_size=0x080000
 
 ; number of test rounds (registers are re-randomized after each round)
@@ -45,13 +47,13 @@ feature_exception3_data=0
 
 ; test branches to odd addresses
 ; same options as above
-feature_exception3_instruction=1
+feature_exception3_instruction=0
 
 ; SR extra mask.
 ; 0x8000 = T1
-; 0x4000 = T0 (68020)
+; 0x4000 = T0 (68020-68040)
 ; 0x2000 = S
-; 0x1000 = M (68020)
+; 0x1000 = M (68020-68060)
 ; Other bits are ignored.
 ; For example 0xa000 adds 3 extra test rounds: S=1/T1=0, S=0/T1=1 and S=1/T1=1
 ; Note: instructions that generate privilege violation exception will automatically add extra S=1 round.
index 16c3688d60248fe79cfa01e94c096f240205ecc5..05e039ffcd7b0992cff92671b64e50b73a2dfe91 100644 (file)
@@ -684,7 +684,7 @@ static uae_u8 *restore_data(uae_u8 *p)
        return p;
 }
 
-static uae_u16 test_sr, test_ccrignoremask;
+static uae_u16 test_ccrignoremask;
 static uae_u32 test_fpsr, test_fpcr;
 
 static void addinfo(void)
@@ -764,18 +764,21 @@ static void out_regs(struct registers *r, int before)
        }
        strcat(outbp, "\n");
        outbp += strlen(outbp);
-       sprintf(outbp, "SR:%c%04x   PC: %08lx ISP: %08lx MSP: %08lx\n", test_regs.sr != test_sr ? '*' : ' ', before ? test_sr : r->sr, r->pc, r->ssp, r->msp);
+       sprintf(outbp, "SR:%c%04x   PC: %08lx ISP: %08lx MSP: %08lx\n",
+               test_regs.sr != last_registers.sr ? '*' : ' ', before ? regs.sr : test_regs.sr,
+               r->pc, r->ssp, r->msp);
        outbp += strlen(outbp);
        if (before >= 0) {
-               uae_u16 s = before ? test_sr : r->sr;
-               uae_u16 s1 = test_regs.sr;
-               uae_u16 s2 = test_sr;
-               uae_u16 s3 = before ? s1 : last_registers.sr;
+               uae_u16 s = before ? regs.sr : test_regs.sr; // current value
+               uae_u16 s1 = regs.sr; // original value
+               uae_u16 s2 = test_regs.sr; // test result value
+               uae_u16 s3 = last_registers.sr; // expected result value
                for (int i = 0; srbits[i].name; i++) {
                        if (i > 0)
                                *outbp++ = ' ';
                        uae_u16 mask = 1 << srbits[i].bit;
-                       sprintf(outbp, "%s%c%d", srbits[i].name, (s3 & mask) != (s1 & mask) ? '!' : ((s1 & mask) != (s2 & mask) ? '*' : '='), (s & mask) != 0);
+                       sprintf(outbp, "%s%c%d", srbits[i].name,
+                               (s2 & mask) != (s3 & mask) ? '!' : ((s1 & mask) != (s2 & mask) ? '*' : '='), (s & mask) != 0);
                        outbp += strlen(outbp);
                }
        }
@@ -827,7 +830,7 @@ static void hexdump(uae_u8 *p, int len)
 static uae_u8 last_exception[256];
 static int last_exception_len;
 
-static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum, int sameexc)
+static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum, int sameexc, int *experr)
 {
        int exclen = 0;
        uae_u8 *exc;
@@ -931,10 +934,15 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum,
                outbp += strlen(outbp);
                hexdump(sp, exclen);
                errors = 1;
+               *experr = 1;
        }
        return p;
 }
 
+// regs: registers before execution of test code
+// test_reg: registers used during execution of test code, also modified by test code.
+// last_registers: registers after modifications from data files. Test ok if test_reg == last_registers.
+
 static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
 {
        uae_u8 regs_changed[16] = { 0 };
@@ -974,6 +982,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
        if (*p == CT_END_SKIP)
                return p + 1;
 
+       int experr = 0;
        for (;;) {
                uae_u8 v = *p;
                if (v & CT_END) {
@@ -994,7 +1003,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                        }
                        if (ignore_errors) {
                                if (exc) {
-                                       p = validate_exception(&test_regs, p, exc, exc == cpuexc);
+                                       p = validate_exception(&test_regs, p, exc, exc == cpuexc, &experr);
                                }
                                break;
                        }
@@ -1008,7 +1017,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                break;
                        }
                        if (exc) {
-                               p = validate_exception(&test_regs, p, exc, exc == cpuexc);
+                               p = validate_exception(&test_regs, p, exc, exc == cpuexc, &experr);
                        }
                        if (exc != cpuexc) {
                                addinfo();
@@ -1018,6 +1027,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                        } else {
                                                sprintf(outbp, "Exception ID: expected %d but got %d\n", exc, cpuexc);
                                        }
+                                       experr = 1;
                                }
                                outbp += strlen(outbp);
                                errors++;
@@ -1065,7 +1075,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                        if ((val & (sr_undefined_mask & test_ccrignoremask)) != (test_regs.sr & (sr_undefined_mask & test_ccrignoremask)) && !ignore_errors && !ignore_sr) {
                                addinfo();
                                if (dooutput) {
-                                       sprintf(outbp, "SR: expected %04x -> %04x but got %04x (%04x)\n", test_sr, val & 0xffff, test_regs.sr & 0xffff, test_ccrignoremask);
+                                       sprintf(outbp, "SR: expected %04x -> %04x but got %04x (%04x)\n", regs.sr & 0xffff, val & 0xffff, test_regs.sr & 0xffff, test_ccrignoremask);
                                        outbp += strlen(outbp);
                                }
                                errors++;
@@ -1245,8 +1255,10 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                }
                out_regs(&test_regs, 0);
                if (exc > 1) {
-                       sprintf(outbp, "OK: Generated exception %d\n", exc);
-                       outbp += strlen(outbp);
+                       if (!experr) {
+                               sprintf(outbp, "OK: Generated exception %d\n", exc);
+                               outbp += strlen(outbp);
+                       }
                        if (exc == 3 && cpu_lvl == 0) {
                                sprintf(outbp, "RW=%d IN=%d FC=%d\n",
                                        ((test_regs.exc >> (16 + 4)) & 1),
@@ -1326,10 +1338,11 @@ static void process_test(uae_u8 *p)
                                regs.pc = opcode_memory_addr;
                                regs.fpiar = opcode_memory_addr;
 
+                               memcpy((void*)regs.ssp, (void*)regs.regs[15], 0x20);
                                xmemcpy(&test_regs, &regs, sizeof(struct registers));
 
                                test_regs.sr = ccr | sr_mask;
-                               test_sr = test_regs.sr;
+                               uae_u32 test_sr = test_regs.sr;
                                if (fpumode) {
                                        test_regs.fpsr = (ccr & 15) << 24;
                                        test_regs.fpcr = (ccr >> 4) << 4;
@@ -1374,6 +1387,13 @@ static void process_test(uae_u8 *p)
                                        last_registers.pc = last_pc;
                                        last_registers.fpiar = last_fpiar;
 
+                                       if ((*p) == CT_SKIP_REGS) {
+                                               p++;
+                                               for (int i = 0; i < 16; i++) {
+                                                       test_regs.regs[i] = regs.regs[i];
+                                               }
+                                       }
+
                                        p = validate_test(p, ignore_errors, ignore_sr);
 
                                        last_pc = last_registers.pc;
@@ -1517,7 +1537,7 @@ static int test_mnemo(const char *path, const char *opcode)
                exit(0);
        }
 
-       printf("CPUlvl=%d, Mask=%08lx\n", cpu_lvl, addressing_mask);
+       printf("CPUlvl=%d, Mask=%08lx Code=%08lx\n", cpu_lvl, addressing_mask, opcode_memory);
        printf("%s:\n", inst_name);
 
        testcnt = 0;
diff --git a/cputest/readme.txt b/cputest/readme.txt
new file mode 100644 (file)
index 0000000..778f004
--- /dev/null
@@ -0,0 +1,100 @@
+
+UAE CPU Tester
+
+I finally wrote utility (this was my "Summer 2019" project) that can be used to verify operation of for example software emulated or FPGA 680x0 CPUs.
+It is based on UAE CPU core (gencpu generated special test core). All the CPU logic comes from UAE CPU core.
+
+Verifies:
+
+- All CPU registers (D0-D7/A0-A7, PC and SR/CCR)
+- All FPU registers (FP0-FP7, FPIAR, FPCR, FPSR)
+- Generated exception and stack frame contents (if any)
+- Memory writes, including stack modifications (if any)
+- Loop mode for JIT testing. (generates <test instruction>, dbf dn,loop)
+- Supports 68000, 68020, 68030 (only difference between 020 and 030 seems to be data cache and MMU), 68040 and 68060. (I don't currently have real 68010)
+
+Tests executed for each tested instruction:
+
+- Every CCR combination (32 tests)
+- Every FPU condition combination (4 bits) + 2 precision bits + 2 rounding bits (256 tests)
+- Every addressing mode, including optionally 68020+ addressing modes.
+- If instruction generated privilege violation exception, extra test round is run in supervisor mode (Total 64 tests).
+- Optionally can do any combination of T0, T1, S and M -bit SR register extra test rounds.
+- Every opcode value is tested. Total number of tests per opcode depends on available addressing modes etc. It can be hundreds of thousands or even millions..
+
+Test generation details:
+
+Instruction's effective address is randomized. It is accepted if it points to any of 3 test memory regions. If it points outside of test memory, it will be re-randomized few times. Test will be skipped if current EA makes it impossible to point to any of 3 test regions.
+If 68000/68010 and address error testing is enabled: 2 extra test rounds are generated, one with even and another with odd EAs to test and verify address errors.
+
+Notes and limitations:
+
+- Test generator is very brute force based, it should be more intelligent..
+- Address error testing is optional, if disabled, generated tests never cause address errors.
+- RTE test only tests stack frame types 0 and 2 (if 68020+)
+- All tests that would halt or reset the CPU are skipped (RESET in supervisor mode, STOP parameter that would stop the CPU etc)
+- Single instruction test set will take long time to run on real 68000. Few minutes to much longer...
+- Undefined flags (for example DIV and CHK) are also verified. It probably would be good idea to optionally filter them out.
+- Instruction cycle order or timing is ignored. It is not possible without extra hardware.
+- 68000 bus errors are not tested but there are some plans for future version with custom hardware. (Hatari also uses UAE CPU core)
+- FPU testing is not yet fully implemented.
+- Sometimes reported old and new condition code state does not match error report..
+
+Tester compatibility (integer instructions only):
+
+68000: Complete.
+68010: Not supported yet (Don't have real 68010, at least not yet).
+68020: Almost complete (DIVS.W/DIVS.L V-flag weirdness).
+68030: Same as 68020.
+68040: Almost complete (Weird unaligned MOVE16 behavior which may be board specific).
+68060: Same as 68040.
+
+More CPU details in WinUAE changelog.
+
+Not implemented or only partially implemented:
+
+68010+:
+
+- MOVEC: Only MOVEC to An/Dn is tested and read value is ignored. Basically only verifies if correct and only correct CPU model specific control registers exist.
+- RTE: long frames with undefined fields are skipped. Basic frame types 0 and 2 are verified, also unsupported frame types are tested, error is reported if CPU does not generate frame exception.
+- 68020+ undefined addressing mode bit combinations are not tested.
+
+All models:
+
+- Interrupts (stack frames and STOP)
+- MMU instructions (Not going to happen)
+- 68020+ cache related instructions.
+- FPU FSAVE/FRESTORE, FPU support also isn't fully implemented yet.
+
+Build instructions:
+
+- buildm68k first (already built if UAE core was previously compiled)
+- gencpu with CPU_TEST=1 define. This creates cpuemu_x_test.cpp files (x=90-94), cpustbl_test.cpp and cputbl_test.h
+- build cputestgen project.
+- build native Amiga project (cputest directory). Assembly files probably only compiles with Bebbo's GCC.
+
+
+Test generator quick instructions:
+
+Update cputestgen.ini to match your CPU model, memory settings etc...
+
+"Low memory" = memory accessible using absolute word addressing mode, positive value (0x0000 to 0x7fff). Can be larger.
+"High memory" = memory accessible using absolute word addressing mode, negative value (0xFFF8000 to 0xFFFFFFFF)
+
+If high memory is ROM space (like on 24-bit address space Amigas), memory region is used for read only tests, use "high_rom=<path to rom image>" to select ROM image. Last 32k of image is loaded.
+
+Use "test_low_memory_start"/"test_high_memory_start" and "test_low_memory_end"/"test_high_memory_end" to restrict range of memory region used for tests, for example if part of region is normally inaccessible.
+
+"test_memory_start"/"test_memory_size" is the main test memory, tested instruction and stack is located here. Must be at least 128k but larger the size, the easier it is for the generator to find effective addresses that hit test memory. This memory space must be free on target m68k hardware.
+
+All 3 memory regions (if RAM) are filled with pseudo-random pattern and saved as "lmem.dat", "hmem.dat" and "tmem.dat"
+
+Usage of Amiga m68k native test program:
+
+Copy all three dat files, test executable compiled for target platform (currently only Amiga is supported) and data file directories to target system.
+
+cputest all = run all tests, in alphabetical order. Stops when mismatch is detected.
+cputest tst.b = run tst.b tests only
+cputest all tst.b = run tst.b, then tst.w and so on in alphabetical order until end or mismatch is detected.
+
+If mismatch is detected, opcode word(s), instruction disassembly, registers before and after and reason message is shown on screen. If difference is in exception stack frame, both expected and returned stack frame is shown in hexadecimal.
index 318ca19726dde94601aee84d0a6944444fd12ed4..ecf6810c2171f35bce0a56b3e47739017269c7ce 100644 (file)
@@ -1824,6 +1824,15 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn
                        extra = get_word_debug(pc);
                        _stprintf(instrname + _tcslen(instrname), _T(",#$%04x"), extra);
                        pc += 2;
+               } else if (lookup->mnemo == i_LPSTOP) {
+                       if (extra == 0x01c0) {
+                               uae_u16 extra2 = get_word_debug(pc + 2);
+                               _stprintf(instrname, _T("LPSTOP #$%04x"), extra2);
+                               pc += 4;
+                       } else {
+                               _stprintf(instrname, _T("ILLG #$%04x"), extra);
+                               pc += 2;
+                       }
                } else if (lookup->mnemo == i_FDBcc) {
                        pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
                        pc += 2;
index d1770636ac1153c19fa851a860088ea209612f7d..74576d68fca7d953d85435d16d7a5b24ee4b7f33 100644 (file)
@@ -4201,12 +4201,12 @@ static void gen_opcode (unsigned int opcode)
                // if new SR S-bit is not set:
                // 68000 (68010?): Update SR, increase PC and then cause privilege violation exception (handled in newcpu)
                // 68000 (68010?): Traced STOP runs 4 cycles faster.
-               // 68020 68030: STOP works normally
-               // 68040 68060: Immediate privilege violation exception
+               // 68020 68030 68040: STOP works normally
+               // 68060: Immediate privilege violation exception
                if ((cpu_level == 0 || cpu_level == 1) && using_ce) {
                        printf("\t%s(regs.t1 ? 4 : 8);\n", do_cycles);
                }
-               if (cpu_level >= 4) {
+               if (cpu_level >= 5) {
                        printf("\tif (!(sr & 0x2000)) {\n");
                        incpc("%d", m68k_pc_offset);
                        printf("\t\tException(8); goto %s;\n", endlabelstr);
@@ -4221,17 +4221,27 @@ static void gen_opcode (unsigned int opcode)
                next_cpu_level = cpu_level - 1;
                break;
        case i_LPSTOP: /* 68060 */
-               printf ("\tuae_u16 sw = %s (2);\n", srcwi);
-               printf ("\tif (sw != (0x100|0x80|0x40)) { Exception (4); goto %s; }\n", endlabelstr);
+               printf ("\tuae_u16 sw = %s(2);\n", srcwi);
+               printf ("\tif (sw != 0x01c0) { Exception (11); goto %s; }\n", endlabelstr);
                printf("\tif (!(regs.sr & 0x2000)) {\n");
                printf("\t\tException(8); goto %s;\n", endlabelstr);
                printf("\t}\n");
-               printf("\tregs.sr = %s (4);\n", srcwi);
+               printf("\tuae_u16 newsr = %s(4);\n", srcwi);
+               printf("\tif (!(newsr & 0x2000)) {\n");
+               printf("\t\tException(8); goto %s;\n", endlabelstr);
+               printf("\t}\n");
+               printf("\tregs.sr = newsr;\n");
                makefromsr();
                printf ("\tm68k_setstopped();\n");
                m68k_pc_offset += 4;
                sync_m68k_pc ();
                fill_prefetch_full_ntx();
+               need_endlabel = 1;
+               break;
+       case i_HALT: /* 68060 debug */
+               printf("\tcpu_halt(CPU_HALT_68060_HALT);\n");
+               break;
+       case i_PULSE: /* 68060 debug */
                break;
        case i_RTE:
                addop_ce020 (curi, 0);
@@ -4267,9 +4277,9 @@ static void gen_opcode (unsigned int opcode)
                        printf ("\t\tint frame = format >> 12;\n");
                        printf ("\t\tint offset = 8;\n");
                        printf ("\t\tnewsr = sr; newpc = pc;\n");
-                   printf ("\t\tif (frame == 0x0) { m68k_areg (regs, 7) += offset; break; }\n");
-                   printf ("\t\telse if (frame == 0x8) { m68k_areg (regs, 7) += offset + 50; break; }\n");
-                   printf ("\t\telse { Exception_cpu(14); goto %s; }\n", endlabelstr);
+                   printf ("\t\tif (frame == 0x0) {\n\t\t\tm68k_areg (regs, 7) += offset; break; }\n");
+                   printf ("\t\telse if (frame == 0x8) {\n\t\t\tm68k_areg (regs, 7) += offset + 50; break; }\n");
+                   printf ("\t\telse {\n\t\t\tException_cpu(14); goto %s; }\n", endlabelstr);
                    printf ("\t\tregs.sr = newsr; MakeFromSR ();\n}\n");
                    pop_braces (old_brace_level);
                    printf ("\tregs.sr = newsr;\n");
@@ -4300,49 +4310,49 @@ static void gen_opcode (unsigned int opcode)
                        printf ("\t\tint offset = 8;\n");
                        printf ("\t\tnewsr = sr; newpc = pc;\n");
                        addcycles_ce020 (6);
-                   printf ("\t\tif (frame == 0x0) { m68k_areg (regs, 7) += offset; break; }\n");
+                   printf ("\t\tif (frame == 0x0) {\n\t\t\tm68k_areg (regs, 7) += offset; break; }\n");
                        if (cpu_level >= 2) {
                                // 68020+
-                               printf ("\t\telse if (frame == 0x1) { m68k_areg (regs, 7) += offset; }\n");
-                               printf ("\t\telse if (frame == 0x2) { m68k_areg (regs, 7) += offset + 4; break; }\n");
+                               printf ("\t\telse if (frame == 0x1) {\n\t\t\tm68k_areg (regs, 7) += offset; }\n");
+                               printf ("\t\telse if (frame == 0x2) {\n\t\t\tm68k_areg (regs, 7) += offset + 4; break; }\n");
                        }
                        if (cpu_level >= 4) {
                                // 68040+
-                               printf ("\t\telse if (frame == 0x3) { m68k_areg (regs, 7) += offset + 4; break; }\n");
+                               printf ("\t\telse if (frame == 0x3) {\n\t\t\tm68k_areg (regs, 7) += offset + 4; break; }\n");
                        }
                    if (using_mmu == 68060) {
-                               printf ("\t\telse if (frame == 0x4) { m68k_do_rte_mmu060 (a); m68k_areg (regs, 7) += offset + 8; break; }\n");
+                               printf ("\t\telse if (frame == 0x4) {\n\t\t\tm68k_do_rte_mmu060 (a); m68k_areg (regs, 7) += offset + 8; break; }\n");
                        } else if (cpu_level >= 4) {
                                // 68040+
-                               printf ("\t\telse if (frame == 0x4) { m68k_areg (regs, 7) += offset + 8; break; }\n");
+                               printf ("\t\telse if (frame == 0x4) {\n\t\t\tm68k_areg (regs, 7) += offset + 8; break; }\n");
                        }
                        if (cpu_level == 1) {
                                // 68010 only
-                               printf("\t\telse if (frame == 0x8) { m68k_areg (regs, 7) += offset + 50; break; }\n");
+                               printf("\t\telse if (frame == 0x8) {\n\t\t\tm68k_areg (regs, 7) += offset + 50; break; }\n");
                        }
                        if (using_mmu == 68040) {
-                       printf ("\t\telse if (frame == 0x7) { m68k_do_rte_mmu040 (a); m68k_areg (regs, 7) += offset + 52; break; }\n");
-                       } else if (cpu_level >= 4) {
-                               // 68040+
-                       printf ("\t\telse if (frame == 0x7) { m68k_areg (regs, 7) += offset + 52; break; }\n");
+                       printf ("\t\telse if (frame == 0x7) {\n\t\t\tm68k_do_rte_mmu040 (a); m68k_areg (regs, 7) += offset + 52; break; }\n");
+                       } else if (cpu_level == 4) {
+                               // 68040 only
+                       printf ("\t\telse if (frame == 0x7) {\n\t\t\tm68k_areg (regs, 7) += offset + 52; break; }\n");
                        }
                        if (cpu_level == 2 || cpu_level == 3) {
                                // 68020/68030 only
-                               printf ("\t\telse if (frame == 0x9) { m68k_areg (regs, 7) += offset + 12; break; }\n");
+                               printf ("\t\telse if (frame == 0x9) {\n\t\t\tm68k_areg (regs, 7) += offset + 12; break; }\n");
                                if (using_mmu == 68030) {
                                        if (using_prefetch_020) {
-                                               printf ("\t\telse if (frame == 0xa) { m68k_do_rte_mmu030c (a); goto %s; }\n", endlabelstr);
-                                           printf ("\t\telse if (frame == 0xb) { m68k_do_rte_mmu030c (a); goto %s; }\n", endlabelstr);
+                                               printf ("\t\telse if (frame == 0xa) {\n\t\t\tm68k_do_rte_mmu030c (a); goto %s; }\n", endlabelstr);
+                                           printf ("\t\telse if (frame == 0xb) {\n\t\t\tm68k_do_rte_mmu030c (a); goto %s; }\n", endlabelstr);
                                        } else {
-                                               printf ("\t\telse if (frame == 0xa) { m68k_do_rte_mmu030 (a); goto %s; }\n", endlabelstr);
-                                           printf ("\t\telse if (frame == 0xb) { m68k_do_rte_mmu030 (a); goto %s; }\n", endlabelstr);
+                                               printf ("\t\telse if (frame == 0xa) {\n\t\t\tm68k_do_rte_mmu030 (a); goto %s; }\n", endlabelstr);
+                                           printf ("\t\telse if (frame == 0xb) {\n\t\t\tm68k_do_rte_mmu030 (a); goto %s; }\n", endlabelstr);
                                        }
                                } else {
-                                       printf ("\t\telse if (frame == 0xa) { m68k_areg (regs, 7) += offset + 24; break; }\n");
-                                   printf ("\t\telse if (frame == 0xb) { m68k_areg (regs, 7) += offset + 84; break; }\n");
+                                       printf ("\t\telse if (frame == 0xa) {\n\t\t\tm68k_areg (regs, 7) += offset + 24; break; }\n");
+                                   printf ("\t\telse if (frame == 0xb) {\n\t\t\tm68k_areg (regs, 7) += offset + 84; break; }\n");
                                }
                        }
-                   printf ("\t\telse { Exception_cpu(14); goto %s; }\n", endlabelstr);
+                   printf ("\t\telse {\n\t\t\tException_cpu(14); goto %s; }\n", endlabelstr);
                    printf ("\t\tregs.sr = newsr;\n");
                        makefromsr_t0();
                        printf ("}\n");
@@ -4875,7 +4885,6 @@ bccl_not68020:
                printf("\t\tException_cpu(5);\n");
                printf("\t\tgoto %s;\n", endlabelstr);
                printf("\t}\n");
-               printf("\tsetdivuflags(false, (uae_u32)dst, (uae_u16)src);\n");
                printf("\tuae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;\n");
                printf("\tuae_u32 rem = (uae_u32)dst %% (uae_u32)(uae_u16)src;\n");
                if (using_ce) {
@@ -4886,7 +4895,7 @@ bccl_not68020:
                addcycles000_nonces("\t\t", "(getDivu68kCycles((uae_u32)dst, (uae_u16)src)) - 4");
                fill_prefetch_next();
                printf("\t\tif (newv > 0xffff) {\n");
-               printf("\t\t\tsetdivuflags(true, (uae_u32)dst, (uae_u16)src);\n");
+               printf("\t\t\tsetdivuflags((uae_u32)dst, (uae_u16)src);\n");
                printf("\t\t} else {\n");
                printf("\t\t");
                genflags (flag_logical, sz_word, "newv", "", "");
@@ -4912,7 +4921,6 @@ bccl_not68020:
                printf("\t\tException_cpu(5);\n");
                printf("\t\tgoto %s;\n", endlabelstr);
                printf("\t}\n");
-               printf("\tsetdivsflags(false, (uae_s32)dst, (uae_s16)src);\n");
                if (using_ce) {
                        start_brace();
                        printf("\t\tint cycles = (getDivs68kCycles((uae_s32)dst, (uae_s16)src)) - 4;\n");
@@ -4921,12 +4929,12 @@ bccl_not68020:
                addcycles000_nonces("\t\t", "(getDivs68kCycles((uae_s32)dst, (uae_s16)src)) - 4");
                fill_prefetch_next ();
                printf("\tif (dst == 0x80000000 && src == -1) {\n");
-               printf("\t\tsetdivsflags(true, (uae_s32)dst, (uae_s16)src);\n");
+               printf("\t\tsetdivsflags((uae_s32)dst, (uae_s16)src);\n");
                printf("\t} else {\n");
                printf("\t\tuae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;\n");
                printf("\t\tuae_u16 rem = (uae_s32)dst %% (uae_s32)(uae_s16)src;\n");
                printf("\t\tif ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) {\n");
-               printf("\t\t\tsetdivsflags(true, (uae_s32)dst, (uae_s16)src);\n");
+               printf("\t\t\tsetdivsflags((uae_s32)dst, (uae_s16)src);\n");
                printf("\t\t} else {\n");
                printf("\t\t\tif (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;\n");
                genflags(flag_logical, sz_word, "newv", "", "");
@@ -5488,6 +5496,7 @@ bccl_not68020:
                printf ("\tuae_u32 *regp = regs.regs + regno;\n");
                printf ("\tif (! m68k_movec2(src & 0xFFF, regp)) goto %s;\n", endlabelstr);
                trace_t0_68040_only();
+               need_endlabel = 1;
                break;
        case i_MOVE2C:
                genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
@@ -5497,6 +5506,7 @@ bccl_not68020:
                printf ("\tuae_u32 *regp = regs.regs + regno;\n");
                printf ("\tif (! m68k_move2c(src & 0xFFF, regp)) goto %s;\n", endlabelstr);
                trace_t0_68040_only();
+               need_endlabel = 1;
                break;
        case i_CAS:
                {
index 954586a3e3d752150ea295a0c1b32a90918597c2..550065f073677ad8fd5dc3761524e0d4aeacdfbf 100644 (file)
@@ -39,7 +39,7 @@ extern int movem_index2[256];
 extern int movem_next[256];
 
 uae_u16 get_word_test_prefetch(int);
-uae_u16 get_wordi_test(uaecptr);
+uae_u16 get_wordi_test(int);
 
 void put_byte_test(uaecptr, uae_u32);
 void put_word_test(uaecptr, uae_u32);
index b672e3c17a7d77a5b5126234711c7907957b8e6e..5ff7f505ad1dd9bf186e4fcbe89eaf005893700a 100644 (file)
@@ -679,8 +679,8 @@ extern void m68k_dumpcache (bool);
 extern int getDivu68kCycles (uae_u32 dividend, uae_u16 divisor);
 extern int getDivs68kCycles (uae_s32 dividend, uae_s16 divisor);
 extern void divbyzero_special(bool issigned, uae_s32 dst);
-extern void setdivuflags(bool overflow, uae_u32 dividend, uae_u16 divisor);
-extern void setdivsflags(bool overflow, uae_s32 dividend, uae_s16 divisor);
+extern void setdivuflags(uae_u32 dividend, uae_u16 divisor);
+extern void setdivsflags(uae_s32 dividend, uae_s16 divisor);
 extern void setchkundefinedflags(uae_s32 src, uae_s32 dst, int size);
 extern void setchk2undefinedflags(uae_s32 lower, uae_s32 upper, uae_s32 val, int size);
 extern void protect_roms (bool);
@@ -816,6 +816,7 @@ extern bool can_cpu_tracer (void);
 #define CPU_HALT_CPU_STUCK 9
 #define CPU_HALT_SSP_IN_NON_EXISTING_ADDRESS 10
 #define CPU_HALT_INVALID_START_ADDRESS 11
+#define CPU_HALT_68060_HALT 12
 
 uae_u32 process_cpu_indirect_memory_read(uae_u32 addr, int size);
 void process_cpu_indirect_memory_write(uae_u32 addr, uae_u32 data, int size);
index 86639dee96f21dca8218f31debc4e25cab49b049..cec523817fad49c5186ccf52a8dd48ff21b319eb 100644 (file)
@@ -35,7 +35,7 @@ ENUMDECL {
     i_CINVL, i_CINVP, i_CINVA, i_CPUSHL, i_CPUSHP, i_CPUSHA, i_MOVE16,
     i_MMUOP030, i_PFLUSHN, i_PFLUSH, i_PFLUSHAN, i_PFLUSHA,
     i_PLPAR, i_PLPAW, i_PTESTR, i_PTESTW,
-    i_LPSTOP,
+    i_LPSTOP, i_HALT, i_PULSE,
        MAX_OPCODE_FAMILY
 } ENUMNAME (instrmnem);
 
index 01fa5462a60746d5cd90f3f2583d3bd4ccc903a2..aad3f7d85820ee039dcc2db0ecb14703cc2f40a1 100644 (file)
@@ -110,10 +110,18 @@ int m68k_move2c (int regno, uae_u32 *regp)
 #if MOVEC_DEBUG > 0
        write_log (_T("move2c %04X <- %08X PC=%x\n"), regno, *regp, M68K_GETPC);
 #endif
-       if (movec_illg (regno)) {
-               op_illg (0x4E7B);
+       if (movec_illg(regno)) {
+               if (currprefs.cpu_model < 68060 && !regs.s) {
+                       Exception(8);
+                       return 0;
+               }
+               op_illg(0x4E7B);
                return 0;
        } else {
+               if (!regs.s) {
+                       Exception(8);
+                       return 0;
+               }
                switch (regno) {
                case 0: regs.sfc = *regp & 7; break;
                case 1: regs.dfc = *regp & 7; break;
@@ -185,10 +193,18 @@ int m68k_movec2 (int regno, uae_u32 *regp)
 #if MOVEC_DEBUG > 0
        write_log (_T("movec2 %04X PC=%x\n"), regno, M68K_GETPC);
 #endif
-       if (movec_illg (regno)) {
-               op_illg (0x4E7A);
+       if (movec_illg(regno)) {
+               if (currprefs.cpu_model < 68060 && !regs.s) {
+                       Exception(8);
+                       return 0;
+               }
+               op_illg(0x4E7A);
                return 0;
        } else {
+               if (!regs.s) {
+                       Exception(8);
+                       return 0;
+               }
                switch (regno) {
                case 0: *regp = regs.sfc; break;
                case 1: *regp = regs.dfc; break;
@@ -804,31 +820,27 @@ void divbyzero_special (bool issigned, uae_s32 dst)
  * 68000: V=1, C=0, Z=0, N=1
  * 68020: V=1, C=0, Z=0, N=X
  * 68040: V=1, C=0, NZ not modified.
- * 68060: V=1, C=0, N=0, Z=0
+ * 68060: V=1, C=0, NZ not modified.
  *
  * X) N is set if original 32-bit destination value is negative.
  *
  */
 
-void setdivuflags(bool overflow, uae_u32 dividend, uae_u16 divisor)
+void setdivuflags(uae_u32 dividend, uae_u16 divisor)
 {
-       if (!overflow) {
-               if (currprefs.cpu_model != 68040)
-                       CLEAR_CZNV();
-       } else {
-               if (currprefs.cpu_model == 68060) {
-                       SET_VFLG(1);
-               } else if (currprefs.cpu_model == 68040) {
-                       SET_VFLG(1);
-                       SET_CFLG(0);
-               } else if (currprefs.cpu_model >= 68020) {
-                       SET_VFLG(1);
-                       if ((uae_s32)dividend < 0)
-                               SET_NFLG(1);
-               } else {
-                       SET_VFLG(1);
+       if (currprefs.cpu_model == 68060) {
+               SET_VFLG(1);
+               SET_CFLG(0);
+       } else if (currprefs.cpu_model == 68040) {
+               SET_VFLG(1);
+               SET_CFLG(0);
+       } else if (currprefs.cpu_model >= 68020) {
+               SET_VFLG(1);
+               if ((uae_s32)dividend < 0)
                        SET_NFLG(1);
-               }
+       } else {
+               SET_VFLG(1);
+               SET_NFLG(1);
        }
 }
 
@@ -838,47 +850,46 @@ void setdivuflags(bool overflow, uae_u32 dividend, uae_u16 divisor)
  * 68000: V=1, C=0, N=1, Z=0
  * 68020: V=1, C=0, ZN = X
  * 68040: V=1, C=0. NZ not modified.
- * 68060: V=1, C=0, N=0, Z=0
+ * 68060: V=1, C=0, NZ not modified.
  *
  * X) if absolute overflow(Check getDivs68kCycles for details) : Z = 0, N = 0
  * if not absolute overflow : N is set if internal result BYTE is negative, Z is set if it is zero!
  *
  */
 
-void setdivsflags(bool overflow, uae_s32 dividend, uae_s16 divisor)
+void setdivsflags(uae_s32 dividend, uae_s16 divisor)
 {
-       if (!overflow) {
-               if (currprefs.cpu_model != 68040)
-                       CLEAR_CZNV();
-       } else {
-               if (currprefs.cpu_model == 68060) {
-                       SET_VFLG(1);
-               } else if (currprefs.cpu_model == 68040) {
-                       SET_VFLG(1);
-                       SET_CFLG(0);
-               } else if (currprefs.cpu_model >= 68020) {
-                       SET_VFLG(1);
-                       // absolute overflow?
-                       if (((uae_u32)abs(dividend) >> 16) >= (uae_u16)abs(divisor))
-                               return;
-                       uae_u32 aquot = (uae_u32)abs(dividend) / (uae_u16)abs(divisor);
-                       if ((uae_s8)aquot == 0)
-                               SET_ZFLG(1);
-                       if ((uae_s8)aquot < 0)
-                               SET_NFLG(1);
-               } else {
-                       SET_VFLG(1);
+       if (currprefs.cpu_model == 68060) {
+               SET_VFLG(1);
+               SET_CFLG(0);
+       } else if (currprefs.cpu_model == 68040) {
+               SET_VFLG(1);
+               SET_CFLG(0);
+       } else if (currprefs.cpu_model >= 68020) {
+               CLEAR_CZNV();
+               SET_VFLG(1);
+               // absolute overflow?
+               if (((uae_u32)abs(dividend) >> 16) >= (uae_u16)abs(divisor))
+                       return;
+               uae_u32 aquot = (uae_u32)abs(dividend) / (uae_u16)abs(divisor);
+               if ((uae_s8)aquot == 0)
+                       SET_ZFLG(1);
+               if ((uae_s8)aquot < 0)
                        SET_NFLG(1);
-               }
+       } else {
+               CLEAR_CZNV();
+               SET_VFLG(1);
+               SET_NFLG(1);
        }
 }
 
 /*
- * CHK.W undefined flags
+ * CHK undefined flags
  *
  * 68000: CV=0. Z: dst==0. N: dst < 0. !N: dst > src.
  * 68020: Z: dst==0. N: dst < 0. V: src-dst overflow. C: if dst < 0: (dst > src || src >= 0), if dst > src: (src >= 0).
- * 68040: N=0. If exception: N=dst < 0
+ * 68040: C=0. C=1 if exception and (dst < 0 && src >= 0) || (src >= 0 && dst >= src) || (dst < 0 && src < dst)
+ * 68060: N=0. If exception: N=dst < 0
  *
  */
 void setchkundefinedflags(uae_s32 src, uae_s32 dst, int size)
@@ -899,14 +910,14 @@ void setchkundefinedflags(uae_s32 src, uae_s32 dst, int size)
                if (dst < 0 || dst > src) {
                        if (size == sz_word) {
                                int flgs = ((uae_s16)(dst)) < 0;
-                                       int flgo = ((uae_s16)(src)) < 0;
-                                       uae_s16 val = (uae_s16)src - (uae_s16)dst;
-                                       int flgn = val < 0;
-                                       SET_VFLG((flgs ^ flgo) & (flgn ^ flgo));
+                               int flgo = ((uae_s16)(src)) < 0;
+                               uae_s16 val = (uae_s16)src - (uae_s16)dst;
+                               int flgn = val < 0;
+                               SET_VFLG((flgs ^ flgo) & (flgn ^ flgo));
                        } else {
                                int flgs = dst < 0;
-                                       int flgo = src < 0;
-                                       uae_s32 val = src - dst;
+                               int flgo = src < 0;
+                               uae_s32 val = src - dst;
                                int flgn = val < 0;
                                SET_VFLG((flgs ^ flgo) & (flgn ^ flgo));
                        }
@@ -916,7 +927,19 @@ void setchkundefinedflags(uae_s32 src, uae_s32 dst, int size)
                                SET_CFLG(src >= 0);
                        }
                }
-       } else {
+       } else if (currprefs.cpu_model == 68040) {
+               SET_CFLG(0);
+               if (dst < 0 || dst > src) {
+                       if (dst < 0 && src >= 0) {
+                               SET_CFLG(1);
+                       } else if (src >= 0 && dst >= src) {
+                               SET_CFLG(1);
+                       } else if (dst < 0 && src < dst) {
+                               SET_CFLG(1);
+                       }
+               }
+               SET_NFLG(dst < 0);
+       } else if (currprefs.cpu_model == 68060) {
                SET_NFLG(0);
                if (dst < 0 || dst > src) {
                        SET_NFLG(dst < 0);
@@ -928,7 +951,8 @@ void setchkundefinedflags(uae_s32 src, uae_s32 dst, int size)
  * CHK2/CMP2 undefined flags
  *
  * 68020-68030: See below..
- * 68040: N: val<0 V=0
+ * 68040: NV not modified.
+ * 68060: N: val<0 V=0
  *
  */
 
@@ -936,14 +960,17 @@ void setchkundefinedflags(uae_s32 src, uae_s32 dst, int size)
 // Someone else can attempt to simplify this..
 void setchk2undefinedflags(uae_s32 lower, uae_s32 upper, uae_s32 val, int size)
 {
-       SET_NFLG(0);
-       SET_VFLG(0);
-
-       if (currprefs.cpu_model >= 68040) {
+       if (currprefs.cpu_model == 68060) {
+               SET_VFLG(0);
                SET_NFLG(val < 0);
                return;
+       } else if (currprefs.cpu_model == 68040) {
+               return;
        }
 
+       SET_NFLG(0);
+       SET_VFLG(0);
+
        if (val == lower || val == upper)
                return;
 
@@ -1079,7 +1106,7 @@ static void divul_overflow(uae_u16 extra, uae_s64 a)
 
 static void divsl_divbyzero(uae_u16 extra, uae_s64 a)
 {
-       if (currprefs.cpu_model == 68060) {
+       if (currprefs.cpu_model >= 68040) {
                SET_CFLG(0);
        } else {
                SET_NFLG(0);
@@ -1091,7 +1118,7 @@ static void divsl_divbyzero(uae_u16 extra, uae_s64 a)
 
 static void divul_divbyzero(uae_u16 extra, uae_s64 a)
 {
-       if (currprefs.cpu_model == 68060) {
+       if (currprefs.cpu_model >= 68040) {
                SET_CFLG(0);
        } else {
                uae_s32 a32 = (uae_s32)a;
index eb9f1856a4e5e833fc7b25c02937655be37616e1..c7896a0c10120e4bb3b657c56db9d83a39689bfc 100644 (file)
@@ -151,6 +151,8 @@ struct mnemolookup lookuptab[] = {
        { i_PTESTW, _T("PTESTW"), NULL, 0 },
 
        { i_LPSTOP, _T("LPSTOP"), NULL, 0 },
+       { i_HALT, _T("HALT"), NULL, 0 },
+       { i_PULSE, _T("PULSE"), NULL, 0 },
        { i_ILLG, _T(""), NULL, 0 },
 };
 
index 24405726fe5baa660290f77ec42a7afc3ed6e236..57632d7044b3054fdfbda9e9a9263e880c9d97bb 100644 (file)
--- a/table68k
+++ b/table68k
 0100 1110 0111 0111:000:XNZVC:-----:00: RTR
 - 1 0 12
 
-0100 1110 0111 1010:102:?????:?????:10: MOVEC2  #1
+0100 1110 0111 1010:100:?????:?????:10: MOVEC2  #1
 - 6 0 6
-0100 1110 0111 1011:102:?????:?????:10: MOVE2C  #1
+0100 1110 0111 1011:100:?????:?????:10: MOVE2C  #1
 - 6 0 6
 0100 1110 10ss sSSS:000://///://///:80: JSR.L   s[!Dreg,Areg,Aipi,Apdi,Immd]
 - 0 0 4 jea
 1111 0110 00dd dDDD:400:-----:-----:12: MOVE16   L,d[Aipi-Aind]
 
 % 68060
-1111 1000 0000 0000:502:?????:?????:10: LPSTOP   #1
+1111 1000 0000 0000:500:?????:?????:10: LPSTOP   #1
 1111 0101 1000 1rrr:502:-----:-----:00: PLPAW    Ara
 1111 0101 1100 1rrr:502:-----:-----:00: PLPAR    Ara
-
+% "Debug Pipe Control Mode Commands"
+0100 1010 1100 1000:502:?????:?????:00: HALT
+0100 1010 1100 1100:500:?????:?????:00: PULSE