]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Cputester updates. Trace stacked on top of group 1 exception supported. Bus and addre...
authorToni Wilen <twilen@winuae.net>
Sun, 1 Dec 2019 19:33:42 +0000 (21:33 +0200)
committerToni Wilen <twilen@winuae.net>
Sun, 1 Dec 2019 19:33:42 +0000 (21:33 +0200)
.gitignore
cputest.cpp
cputest/asm.S
cputest/cputest_defines.h
cputest/main.c
gencpu.cpp
include/newcpu.h
newcpu.cpp
newcpu_common.cpp

index af888507c1353afb9ce0db937af7959d1cd6de4b..d17a92a1896fe320b2a84ba8d183f5336412f91d 100644 (file)
@@ -48,19 +48,8 @@ aros.rom.cpp
 /blitfunc.h
 /blittable.cpp
 /cpudefs.cpp
-/cpuemu_0.cpp
-/cpuemu_11.cpp
-/cpuemu_13.cpp
-/cpuemu_20.cpp
-/cpuemu_21.cpp
-/cpuemu_22.cpp
-/cpuemu_23.cpp
-/cpuemu_24.cpp
-/cpuemu_31.cpp
-/cpuemu_32.cpp
-/cpuemu_33.cpp
-/cpuemu_40.cpp
-/cpuemu_50.cpp
+/cpuemu_*.cpp
+/cpuemu_*_test.cpp
 /cpustbl.cpp
 /cpustbl_test.cpp
 /cputbl.h
index 606ba093a1ebe87f745ddadf1d715613a3be40af..b5e9fb0c83988c67466730431e8f80252bdd29eb 100644 (file)
@@ -41,7 +41,7 @@ int movem_index1[256];
 int movem_index2[256];
 int movem_next[256];
 int bus_error_offset;
-int cpu_bus_error;
+int cpu_bus_error, cpu_bus_error_fake;
 
 struct mmufixup mmufixup[2];
 cpuop_func *cpufunctbl[65536];
@@ -70,7 +70,7 @@ static TCHAR *feature_instruction_size = NULL;
 static uae_u32 feature_addressing_modes[2];
 static int ad8r[2], pc8r[2];
 static int multi_mode;
-#define MAX_TARGET_EA 8
+#define MAX_TARGET_EA 20
 static uae_u32 feature_target_ea[MAX_TARGET_EA][2];
 static int target_ea_src_cnt, target_ea_dst_cnt;
 static int target_ea_src_max, target_ea_dst_max;
@@ -113,6 +113,7 @@ static bool out_of_test_space;
 static uaecptr out_of_test_space_addr;
 static int forced_immediate_mode;
 static int test_exception;
+static int test_exception_extra;
 static int exception_stack_frame_size;
 static uaecptr test_exception_addr;
 static int test_exception_3_w;
@@ -230,7 +231,7 @@ oob:
 
 static bool is_nowrite_address(uaecptr addr, int size)
 {
-       return addr + size >= safe_memory_start && addr < safe_memory_end;
+       return addr + size > safe_memory_start && addr < safe_memory_end;
 }
 
 static void validate_addr(uaecptr addr, int size)
@@ -283,6 +284,7 @@ static void check_bus_error(uaecptr addr, int write, int fc)
        if (safe_memory_start == 0xffffffff && safe_memory_end == 0xffffffff)
                return;
        if (addr >= safe_memory_start && addr < safe_memory_end) {
+               cpu_bus_error_fake = 1;
                if ((safe_memory_mode & 1) && !write)
                        cpu_bus_error = 1;
                if ((safe_memory_mode & 2) && write)
@@ -334,7 +336,7 @@ void put_byte_test(uaecptr addr, uae_u32 v)
 {
        check_bus_error(addr, 1, regs.s ? 5 : 1);
        uae_u8 *p = get_addr(addr, 1, 1);
-       if (!out_of_test_space && !noaccesshistory && !cpu_bus_error) {
+       if (!out_of_test_space && !noaccesshistory && !cpu_bus_error_fake) {
                previoussame(addr, sz_byte);
                if (ahcnt >= MAX_ACCESSHIST) {
                        wprintf(_T("ahist overflow!"));
@@ -357,7 +359,7 @@ void put_word_test(uaecptr addr, uae_u32 v)
                put_byte_test(addr + 1, v >> 0);
        } else {
                uae_u8 *p = get_addr(addr, 2, 1);
-               if (!out_of_test_space && !noaccesshistory && !cpu_bus_error) {
+               if (!out_of_test_space && !noaccesshistory && !cpu_bus_error_fake) {
                        previoussame(addr, sz_word);
                        if (ahcnt >= MAX_ACCESSHIST) {
                                wprintf(_T("ahist overflow!"));
@@ -386,7 +388,7 @@ void put_long_test(uaecptr addr, uae_u32 v)
                put_word_test(addr + 2, v >> 0);
        } else {
                uae_u8 *p = get_addr(addr, 4, 1);
-               if (!out_of_test_space && !noaccesshistory && !cpu_bus_error) {
+               if (!out_of_test_space && !noaccesshistory && !cpu_bus_error_fake) {
                        previoussame(addr, sz_long);
                        if (ahcnt >= MAX_ACCESSHIST) {
                                wprintf(_T("ahist overflow!"));
@@ -808,8 +810,12 @@ static void doexcstack(void)
        testing_active = -1;
 
        int opcode = (opcode_memory[0] << 8) | (opcode_memory[1]);
-       if (test_exception_opcode >= 0)
+       if (test_exception_opcode >= 0) {
                opcode = test_exception_opcode;
+       }
+       if (SPCFLAG_DOTRACE && test_exception == 9) {
+               SPCFLAG_DOTRACE = 0;
+       }
 
        int sv = regs.s;
        uaecptr tmp = m68k_areg(regs, 7);
@@ -819,6 +825,7 @@ static void doexcstack(void)
                        uae_u16 mode = (sv ? 4 : 0) | test_exception_3_fc;
                        mode |= test_exception_3_w ? 0 : 16;
                        Exception_build_68000_address_error_stack_frame(mode, opcode, test_exception_addr, regs.pc);
+                       SPCFLAG_DOTRACE = 0;
                }
        } else if (cpu_lvl == 1) {
                if (test_exception == 2 || test_exception == 3) {
@@ -832,6 +839,7 @@ static void doexcstack(void)
                                ssw &= 0x00ff;
                        regs.mmu_fault_addr = test_exception_addr;
                        Exception_build_stack_frame(regs.instruction_pc, regs.pc, ssw, 3, 0x08);
+                       SPCFLAG_DOTRACE = 0;
                } else {
                        Exception_build_stack_frame_common(regs.instruction_pc, regs.pc, 0, test_exception);
                }
@@ -905,12 +913,19 @@ uae_u32 REGPARAM2 op_illg(uae_u32 opcode)
 void exception2_fetch(uae_u32 opcode, uaecptr addr)
 {
        test_exception = 2;
-       test_exception_3_w = 1;
+       test_exception_3_w = 0;
        test_exception_addr = addr;
        test_exception_opcode = opcode;
        test_exception_3_fc = 2;
        test_exception_3_size = 1;
        test_exception_3_di = 0;
+
+       if (currprefs.cpu_model == 68000) {
+               if (generates_group1_exception(regs.ir)) {
+                       test_exception_3_fc |= 8;  // set N/I
+               }
+       }
+
        doexcstack();
 }
 
@@ -923,6 +938,14 @@ void exception2_read(uae_u32 opcode, uaecptr addr, int size, int fc)
        test_exception_3_fc = fc;
        test_exception_3_size = size;
        test_exception_3_di = 1;
+
+       if (currprefs.cpu_model == 68000) {
+               if (generates_group1_exception(regs.ir)) {
+                       test_exception_3_fc |= 8;  // set N/I
+               }
+               test_exception_opcode = regs.ir;
+       }
+
        doexcstack();
 }
 
@@ -936,6 +959,14 @@ void exception2_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int f
        test_exception_3_size = size;
        regs.write_buffer = val;
        test_exception_3_di = 1;
+
+       if (currprefs.cpu_model == 68000) {
+               if (generates_group1_exception(regs.ir)) {
+                       test_exception_3_fc |= 8;  // set N/I
+               }
+               test_exception_opcode = regs.ir;
+       }
+
        doexcstack();
 }
 
@@ -948,6 +979,16 @@ void exception3_read(uae_u32 opcode, uae_u32 addr, int size, int fc)
        test_exception_3_fc = fc;
        test_exception_3_size = size;
        test_exception_3_di = 1;
+
+       if (currprefs.cpu_model == 68000) {
+               if (generates_group1_exception(regs.ir)) {
+                       test_exception_3_fc |= 8; // set N/I
+               }
+               if (opcode & 0x10000)
+                       test_exception_3_fc |= 8;
+               test_exception_opcode = regs.ir;
+       }
+
        doexcstack();
 }
 void exception3_write(uae_u32 opcode, uae_u32 addr, int size, uae_u32 val, int fc)
@@ -960,6 +1001,16 @@ void exception3_write(uae_u32 opcode, uae_u32 addr, int size, uae_u32 val, int f
        test_exception_3_size = size;
        regs.write_buffer = val;
        test_exception_3_di = 1;
+
+       if (currprefs.cpu_model == 68000) {
+               if (generates_group1_exception(regs.ir)) {
+                       test_exception_3_fc |= 8; // set N/I
+               }
+               if (opcode & 0x10000)
+                       test_exception_3_fc |= 8;
+               test_exception_opcode = regs.ir;
+       }
+
        doexcstack();
 }
 
@@ -1464,6 +1515,19 @@ static void reset_ea_state(void)
        ea_state_found[2] = 0;
 }
 
+// if other EA is target EA, don't point this EA
+// to same address space.
+static bool other_targetea_same(int srcdst, uae_u32 v)
+{
+       if (target_ea[srcdst ^ 1] == 0xffffffff)
+               return false;
+       if (!is_nowrite_address(target_ea[srcdst ^ 1], 1))
+               return false;
+       if (!is_nowrite_address(v, 1))
+               return false;
+       return true;
+}
+
 // attempt to find at least one zero, positive and negative source value
 static int analyze_address(struct instr *dp, int srcdst, uae_u32 addr)
 {
@@ -1613,6 +1677,8 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str
                                        add <<= (v >> 9) & 3; // SCALE
                                }
                                addr += (uae_s8)(v & 0xff); // DISPLACEMENT
+                               if (other_targetea_same(srcdst, addr))
+                                       continue;
                                if (analyze_address(dp, srcdst, addr))
                                        break;
                                maxcnt--;
@@ -1662,8 +1728,10 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str
                uae_u16 v;
                for (;;) {
                        v = rand16();
+                       if (other_targetea_same(srcdst, (uae_s32)(uae_s16)v))
+                               continue;
                        if (analyze_address(dp, srcdst, v))
-                               break;
+                               break;  
                }
                put_word_test(pc, v);
                *isconstant = 16;
@@ -1691,6 +1759,8 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str
                                v = opcode_memory_start + offset;
                        }
                        immabsl_cnt++;
+                       if (other_targetea_same(srcdst, v))
+                               continue;
                        if (analyze_address(dp, srcdst, v))
                                break;
                }
@@ -2345,9 +2415,9 @@ 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 == 0x2191
-               && opw1 == 0xdd12
-               && opw2 == 0xf78c
+       if (opc == 0x4ea9
+               && opw1 == 0xffff
+               //&& opw2 == 0xf78c
                )
                printf("");
        if (regs.sr & 0x2000)
@@ -2367,15 +2437,21 @@ static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc, struct ins
        testing_active = 1;
        testing_active_opcode = opc;
        cpu_bus_error = 0;
+       cpu_bus_error_fake = 0;
        regs.read_buffer = regs.irc;
        regs.write_buffer = 0xf00d;
 
-       int cnt = feature_loop_mode * 2;
+       int cnt = (feature_loop_mode + 1) * 2;
        if (multi_mode)
                cnt = 100;
 
        for (;;) {
 
+               if (cnt <= 0) {
+                       wprintf(_T(" Loop mode didn't end!?\n"));
+                       abort();
+               }
+
                if (SPCFLAG_TRACE)
                        do_trace();
 
@@ -2404,18 +2480,19 @@ static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc, struct ins
                        break;
                }
 
-               if (!test_exception) {
-                       if (SPCFLAG_DOTRACE)
-                               Exception(9);
-
-                       if (cpu_stopped && regs.s == 0 && currprefs.cpu_model <= 68010) {
-                               // 68000/68010 undocumented special case:
-                               // if STOP clears S-bit and T was not set:
-                               // cause privilege violation exception, PC pointing to following instruction.
-                               // If T was set before STOP: STOP works as documented.
-                               cpu_stopped = 0;
-                               Exception(8);
-                       }
+               if (!SPCFLAG_DOTRACE && cpu_stopped && regs.s == 0 && currprefs.cpu_model <= 68010) {
+                       // 68000/68010 undocumented special case:
+                       // if STOP clears S-bit and T was not set:
+                       // cause privilege violation exception, PC pointing to following instruction.
+                       // If T was set before STOP: STOP works as documented.
+                       cpu_stopped = 0;
+                       Exception(8);
+               }
+
+               // Trace is only added as an exception if there was no other exceptions
+               // Trace stacked with other exception is handled later
+               if (SPCFLAG_DOTRACE && !test_exception) {
+                       Exception(9);
                }
 
                // Amiga Chip ram does not support TAS or MOVE16
@@ -2427,15 +2504,15 @@ static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc, struct ins
                if (regs.pc == endpc || regs.pc == targetpc)
                        break;
 
-               if (test_exception)
+               if (test_exception || SPCFLAG_DOTRACE)
                        break;
 
                if (!valid_address(regs.pc, 2, 0))
                        break;
 
-               if (!feature_loop_mode && !multi_mode) {
-                       wprintf(_T(" Test instruction didn't finish in single step in non-loop mode!?\n"));
-                       abort();
+               if (regs.pc + 2 == targetpc) {
+                       opc = regs.ir;
+                       continue;
                }
 
                if (cpu_lvl < 2) {
@@ -2445,10 +2522,12 @@ static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc, struct ins
                }
 
                cnt--;
-               if (cnt <= 0) {
-                       wprintf(_T(" Loop mode didn't end!?\n"));
+
+               if (!feature_loop_mode && !multi_mode && opc != 0x4e71) {
+                       wprintf(_T(" Test instruction didn't finish in single step in non-loop mode!?\n"));
                        abort();
                }
+
        }
 
        testing_active = 0;
@@ -2531,11 +2610,13 @@ static int noregistercheck(struct instr *dp)
 
 static uae_u8 last_exception[256];
 static int last_exception_len;
+static int last_exception_extra;
 
 static uae_u8 *save_exception(uae_u8 *p, struct instr *dp)
 {
        uae_u8 *op = p;
        p++;
+       *p++ = test_exception_extra;
        uae_u8 *sf = test_memory + test_memory_size + EXTRA_RESERVED_SPACE - exception_stack_frame_size;
        // parse exception and store fields that are unique
        // SR and PC was already saved with non-exception data
@@ -2598,13 +2679,14 @@ static uae_u8 *save_exception(uae_u8 *p, struct instr *dp)
                        abort();
                }
        }
-       if (last_exception_len > 0 && last_exception_len == exception_stack_frame_size && !memcmp(sf, last_exception, exception_stack_frame_size)) {
+       if (last_exception_len > 0 && last_exception_len == exception_stack_frame_size && test_exception_extra == last_exception_extra && !memcmp(sf, last_exception, exception_stack_frame_size)) {
                // stack frame was identical to previous
                p = op;
                *p++ = 0xff;
        } else {
                int datalen = (p - op) - 1;
                last_exception_len = exception_stack_frame_size;
+               last_exception_extra = test_exception_extra;
                *op = (uae_u8)datalen;
                memcpy(last_exception, sf, exception_stack_frame_size);
        }
@@ -2829,12 +2911,13 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
        int sr_override = 0;
 
        uae_u32 target_ea_bak[2], target_address_bak;
-       target_ea_bak[0] = target_ea[0];
-       target_ea_bak[1] = target_ea[1];
-       target_address_bak = target_address;
 
        for (;;) {
 
+               target_ea_bak[0] = target_ea[0];
+               target_ea_bak[1] = target_ea[1];
+               target_address_bak = target_address;
+
                if (quick)
                        break;
 
@@ -2858,6 +2941,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                uae_u32 dstaddr_old = 0xffffffff;
                uae_u32 srcaddr = 0xffffffff;
                uae_u32 dstaddr = 0xffffffff;
+               uae_u32 branchtarget_old = 0xffffffff;
 
                for (int opcode = 0; opcode < 65536; opcode++) {
 
@@ -2916,6 +3000,9 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                // if instruction has immediate(s), repeat instruction test multiple times
                                // each round generates new random immediate(s)
                                int constant_loops = 32;
+                               if (dp->mnemo == i_ILLG) {
+                                       constant_loops = 1;
+                               }
 
                                while (constant_loops-- > 0) {
                                        uae_u8 oldbytes[OPCODE_AREA];
@@ -2927,114 +3014,127 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        int did_out_of_bounds = 0;
                                        uae_u8 *prev_dst2 = dst;
 
+                                       uae_u32 branch_target_swap_address = 0;
+                                       int branch_target_swap_mode = 0;
+                                       uae_u32 branch_target_data_original = 0x4afc4e71;
+                                       uae_u32 branch_target_data = branch_target_data_original;
+
                                        out_of_test_space = 0;
+                                       noaccesshistory = 0;
+                                       cpu_bus_error_fake = 0;
+                                       cpu_bus_error = 0;
                                        ahcnt = 0;
+                                       ahcnt2 = 0;
                                        multi_mode = 0;
 
                                        target_ea[0] = target_ea_bak[0];
                                        target_ea[1] = target_ea_bak[1];
                                        target_address = target_address_bak;
 
-                                       if (opc == 0x0156)
+                                       if (opc == 0x4ed0)
                                                printf("");
-                                       if (subtest_count == 416)
+                                       if (subtest_count == 2568)
                                                printf("");
 
 
                                        uaecptr pc = opcode_memory_start + 2;
 
-                                       pc += handle_specials_preea(opc, pc, dp);
-
+                                       if (dp->mnemo != i_ILLG) {
 
-                                       uae_u32 srcea = 0xffffffff;
-                                       uae_u32 dstea = 0xffffffff;
+                                               pc += handle_specials_preea(opc, pc, dp);
 
-                                       // create source addressing mode
-                                       if (dp->suse) {
-                                               int o = create_ea(&opc, pc, dp->smode, dp->sreg, dp, &isconstant_src, 0, fpuopcode, opcodesize, &srcea);
-                                               if (o < 0) {
-                                                       memcpy(opcode_memory, oldbytes, sizeof(oldbytes));
-                                                       if (o == -1)
-                                                               goto nextopcode;
-                                                       continue;
-                                               }
-                                               pc += o;
-                                       }
 
-                                       uae_u8 *ao = opcode_memory + 2;
-                                       uae_u16 apw1 = (ao[0] << 8) | (ao[1] << 0);
-                                       uae_u16 apw2 = (ao[2] << 8) | (ao[3] << 0);
-                                       if (opc == 0x4eb1
-                                               && apw1 == 0xee38
-                                               //&& apw2 == 0x7479
-                                               )
-                                               printf("");
+                                               uae_u32 srcea = 0xffffffff;
+                                               uae_u32 dstea = 0xffffffff;
 
-                                       if (target_address != 0xffffffff && (dp->mnemo == i_MVMEL || dp->mnemo == i_MVMLE)) {
-                                               // if MOVEM and more than 1 register: randomize address so that any MOVEM
-                                               // access can hit target address
-                                               uae_u16 mask = (opcode_memory[2] << 8) | opcode_memory[3];
-                                               int count = 0;
-                                               for (int i = 0; i < 16; i++) {
-                                                       if (mask & (1 << i))
-                                                               count++;
-                                               }
-                                               if (count > 0) {
-                                                       int diff = (rand8() % count);
-                                                       if (dp->dmode == Apdi) {
-                                                               diff = -diff;
+                                               // create source addressing mode
+                                               if (dp->suse) {
+                                                       int o = create_ea(&opc, pc, dp->smode, dp->sreg, dp, &isconstant_src, 0, fpuopcode, opcodesize, &srcea);
+                                                       if (o < 0) {
+                                                               memcpy(opcode_memory, oldbytes, sizeof(oldbytes));
+                                                               if (o == -1)
+                                                                       goto nextopcode;
+                                                               continue;
                                                        }
-                                                       uae_u32 ta = target_address;
-                                                       target_address -= diff * (1 << dp->size);
-                                                       if (target_ea[0] == ta)
-                                                               target_ea[0] = target_address;
-                                                       if (target_ea[1] == ta)
-                                                               target_ea[1] = target_address;
+                                                       pc += o;
                                                }
-                                       }
 
-                                       // if source EA modified opcode
-                                       dp = table68k + opc;
+                                               uae_u8 *ao = opcode_memory + 2;
+                                               uae_u16 apw1 = (ao[0] << 8) | (ao[1] << 0);
+                                               uae_u16 apw2 = (ao[2] << 8) | (ao[3] << 0);
+                                               if (opc == 0x4eb1
+                                                       && apw1 == 0xee38
+                                                       //&& apw2 == 0x7479
+                                                       )
+                                                       printf("");
+
+                                               if (target_address != 0xffffffff && (dp->mnemo == i_MVMEL || dp->mnemo == i_MVMLE)) {
+                                                       // if MOVEM and more than 1 register: randomize address so that any MOVEM
+                                                       // access can hit target address
+                                                       uae_u16 mask = (opcode_memory[2] << 8) | opcode_memory[3];
+                                                       int count = 0;
+                                                       for (int i = 0; i < 16; i++) {
+                                                               if (mask & (1 << i))
+                                                                       count++;
+                                                       }
+                                                       if (count > 0) {
+                                                               int diff = (rand8() % count);
+                                                               if (dp->dmode == Apdi) {
+                                                                       diff = -diff;
+                                                               }
+                                                               uae_u32 ta = target_address;
+                                                               target_address -= diff * (1 << dp->size);
+                                                               if (target_ea[0] == ta)
+                                                                       target_ea[0] = target_address;
+                                                               if (target_ea[1] == ta)
+                                                                       target_ea[1] = target_address;
+                                                       }
+                                               }
 
-                                       // create destination addressing mode
-                                       if (dp->duse) {
-                                               int o = create_ea(&opc, pc, dp->dmode, dp->dreg, dp, &isconstant_dst, 1, fpuopcode, opcodesize, &dstea);
-                                               if (o < 0) {
-                                                       memcpy(opcode_memory, oldbytes, sizeof(oldbytes));
-                                                       if (o == -1)
-                                                               goto nextopcode;
-                                                       continue;
+                                               // if source EA modified opcode
+                                               dp = table68k + opc;
+
+                                               // create destination addressing mode
+                                               if (dp->duse) {
+                                                       int o = create_ea(&opc, pc, dp->dmode, dp->dreg, dp, &isconstant_dst, 1, fpuopcode, opcodesize, &dstea);
+                                                       if (o < 0) {
+                                                               memcpy(opcode_memory, oldbytes, sizeof(oldbytes));
+                                                               if (o == -1)
+                                                                       goto nextopcode;
+                                                               continue;
+                                                       }
+                                                       pc += o;
                                                }
-                                               pc += o;
-                                       }
 
-                                       // requested target address but no EA? skip
-                                       if (target_address != 0xffffffff) {
-                                               if (srcea != target_address && dstea != target_address) {
-                                                       memcpy(opcode_memory, oldbytes, sizeof(oldbytes));
-                                                       continue;
+                                               // requested target address but no EA? skip
+                                               if (target_address != 0xffffffff) {
+                                                       if (srcea != target_address && dstea != target_address) {
+                                                               memcpy(opcode_memory, oldbytes, sizeof(oldbytes));
+                                                               continue;
+                                                       }
                                                }
-                                       }
 
 
-                                       pc = handle_specials_extra(opc, pc, dp);
+                                               pc = handle_specials_extra(opc, pc, dp);
 
-                                       // if destination EA modified opcode
-                                       dp = table68k + opc;
+                                               // if destination EA modified opcode
+                                               dp = table68k + opc;
 
-                                       uae_u8 *bo = opcode_memory + 2;
-                                       uae_u16 bopw1 = (bo[0] << 8) | (bo[1] << 0);
-                                       uae_u16 bopw2 = (bo[2] << 8) | (bo[3] << 0);
-                                       if (opc == 0xf228
-                                               && bopw1 == 0x003a
-                                               //&& bopw2 == 0x2770
-                                               )
-                                               printf("");
+                                               uae_u8 *bo = opcode_memory + 2;
+                                               uae_u16 bopw1 = (bo[0] << 8) | (bo[1] << 0);
+                                               uae_u16 bopw2 = (bo[2] << 8) | (bo[3] << 0);
+                                               if (opc == 0xf228
+                                                       && bopw1 == 0x003a
+                                                       //&& bopw2 == 0x2770
+                                                       )
+                                                       printf("");
+
+                                               // bcc.x
+                                               pc += handle_specials_branch(opc, pc, dp, &isconstant_src);
+                                               // misc
+                                               pc += handle_specials_misc(opc, pc, dp, &isconstant_src);
 
-                                       // bcc.x
-                                       pc += handle_specials_branch(opc, pc, dp, &isconstant_src);
-                                       // misc
-                                       pc += handle_specials_misc(opc, pc, dp, &isconstant_src);
+                                       }
 
                                        put_word_test(opcode_memory_start, opc);
 
@@ -3055,8 +3155,10 @@ 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.
-                                       put_word_test(pc, 0x4afc); // illegal instruction
-                                       pc += 2;
+                                       uae_u32 originalendopcode = 0x4afc4e71;
+                                       uae_u32 endopcode = originalendopcode;
+                                       put_long_test(pc, endopcode); // illegal instruction + nop
+                                       pc += 4;
 
                                        if (isconstant_src < 0 || isconstant_dst < 0) {
                                                constant_loops++;
@@ -3124,6 +3226,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        }
 #endif
                                        uaecptr branch_target = 0xffffffff;
+                                       uaecptr branch_target_pc = 0xffffffff;
                                        int bc = isbranchinst(dp);
                                        if (bc) {
                                                if (bc < 0) {
@@ -3160,12 +3263,20 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                        continue;
                                                } else {
                                                        // branch target = generate exception
-                                                       if (!is_nowrite_address(srcaddr, 2)) {
-                                                               put_word_test(srcaddr, 0x4afc);
+                                                       if (!is_nowrite_address(srcaddr, 4)) {
+                                                               branch_target_swap_address = srcaddr;
+                                                               branch_target_swap_mode = 1;
+                                                               put_long_test(srcaddr, branch_target_data);
+                                                       } else {
+                                                               if (!is_nowrite_address(srcaddr, 2)) {
+                                                                       put_word_test(srcaddr, branch_target_data >> 16);
+                                                                       branch_target_swap_address = srcaddr;
+                                                                       branch_target_swap_mode = 2;
+                                                               }
                                                        }
                                                        branch_target = srcaddr;
                                                        dst = store_mem(dst, 1);
-                                                       memcpy(&ahist2, &ahist, sizeof(struct accesshistory) *MAX_ACCESSHIST);
+                                                       memcpy(&ahist2, &ahist, sizeof(struct accesshistory) * MAX_ACCESSHIST);
                                                        ahcnt2 = ahcnt;
                                                }
                                                testing_active = 0;
@@ -3179,6 +3290,11 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                dst = store_reg(dst, CT_DSTADDR, dstaddr_old, dstaddr, -1);
                                                dstaddr_old = dstaddr;
                                        }
+                                       if (branch_target != branchtarget_old) {
+                                               dst = store_reg(dst, CT_BRANCHTARGET, branchtarget_old, branch_target, -1);
+                                               branchtarget_old = branch_target;
+                                               *dst++ = branch_target_swap_mode;
+                                       }
 
                                        *dst++ = CT_END_INIT;
 
@@ -3210,7 +3326,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
 
                                                int maxflag = fpumode ? 256 : 32;
                                                // if cc-instruction: always do full test
-                                               if (feature_flag_mode == 1 && !dp->ccuse) {
+                                               if (feature_flag_mode == 1 && (dp->mnemo == i_ILLG || !dp->ccuse)) {
                                                        maxflag = fpumode ? 256 / 8 : 2;
                                                }
 
@@ -3238,13 +3354,39 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
 
                                                        out_of_test_space = 0;
                                                        test_exception = 0;
+                                                       test_exception_extra = 0;
                                                        cpu_stopped = 0;
                                                        cpu_halted = 0;
                                                        ahcnt = 0;
 
                                                        memset(&regs, 0, sizeof(regs));
 
+                                                       // swap end opcode illegal/nop
+                                                       endopcode = (endopcode >> 16) | (endopcode << 16);
+                                                       noaccesshistory++;
+                                                       put_long_test(pc - 4, endopcode);
+                                                       noaccesshistory--;
+                                                       int endopcodesize = (endopcode >> 16) == 0x4e71 ? 2 : 4;
+
+                                                       // swap branch target illegal/nop
+                                                       if (branch_target_swap_mode) {
+                                                               noaccesshistory++;
+                                                               branch_target_data = (branch_target_data >> 16) | (branch_target_data << 16);
+                                                               branch_target_pc = branch_target;
+                                                               if (branch_target_swap_mode == 1) {
+                                                                       put_long_test(branch_target_swap_address, branch_target_data);
+                                                                       if ((branch_target_data >> 16) == 0x4e71)
+                                                                               branch_target_pc = branch_target + 2;
+                                                                       else
+                                                                               branch_target_pc = branch_target;
+                                                               } else if (branch_target_swap_mode == 2) {
+                                                                       put_word_test(branch_target_swap_address, branch_target_data >> 16);
+                                                               }
+                                                               noaccesshistory--;
+                                                       }
+
                                                        regs.pc = opcode_memory_start;
+                                                       regs.ir = get_word_test(regs.pc + 0);
                                                        regs.irc = get_word_test(regs.pc + 2);
 
                                                        // set up registers
@@ -3298,10 +3440,10 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                        if (regs.sr & 0x2000)
                                                                prev_s_cnt++;
 
-                                                       if (subtest_count == 23360)
+                                                       if (subtest_count == 220)
                                                                printf("");
 
-                                                       execute_ins(opc, pc - 2, branch_target, dp);
+                                                       execute_ins(opc, pc - endopcodesize, branch_target_pc, dp);
 
                                                        if (regs.s)
                                                                s_cnt++;
@@ -3348,7 +3490,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                                                skipped = 1;
                                                                        }
                                                                }
-                                                               if (test_exception == 9) {
+                                                               if (SPCFLAG_DOTRACE || test_exception == 9) {
                                                                        t_cnt++;
                                                                }
                                                        } else {
@@ -3356,13 +3498,38 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                                ok++;
                                                                // validate branch instructions
                                                                if (isbranchinst(dp)) {
-                                                                       if ((regs.pc != srcaddr && regs.pc != pc - 2) || pcaddr[0] != 0x4a && pcaddr[1] != 0xfc) {
+                                                                       if ((regs.pc != branch_target_pc && regs.pc != pc - endopcodesize) || ((pcaddr[0] != 0x4a && pcaddr[1] != 0xfc) && (pcaddr[0] != 0x4e && pcaddr[1] != 0x71))) {
                                                                                wprintf(_T("Branch instruction target fault\n"));
                                                                                abort();
                                                                        }
                                                                }
                                                        }
+
+                                                       noaccesshistory++;
+                                                       put_long_test(pc - 4, originalendopcode);
+                                                       if (branch_target_data != 0xffffff) {
+                                                               if (branch_target_swap_address == 1) {
+                                                                       put_long_test(branch_target_swap_address, branch_target_data_original);
+                                                               } else if (branch_target_swap_mode == 2) {
+                                                                       put_word_test(branch_target_swap_address, branch_target_data_original >> 16);
+                                                               }
+                                                       }
+                                                       noaccesshistory--;
+
                                                        MakeSR();
+
+                                                       // did we have trace also active?
+                                                       if (SPCFLAG_DOTRACE) {
+                                                               if (regs.t1 && (test_exception == 5 || test_exception == 6 || test_exception == 7 || (test_exception >= 32 && test_exception <= 47))) {
+                                                                       test_exception_extra = 9;
+                                                               } else {
+                                                                       test_exception_extra = 0;
+                                                               }
+                                                               // clear trace
+                                                               regs.t0 = 0;
+                                                               regs.t1 = 0;
+                                                       }
+
                                                        if (!skipped) {
                                                                bool storeregs = true;
                                                                if (noregistercheck(dp)) {
index 164d8c442137b1313c67d0ab362243c874aa379e..e697c9214f940f36e152c8879d782da82bf8d25a 100644 (file)
@@ -32,6 +32,9 @@ S_FPU = S_EXCFRAME+4
 S_FPIAR = S_FPU+8*12
 S_FPCR = S_FPIAR+4
 S_FPSR = S_FPCR+4
+S_TRACECNT = S_FPSR+4
+S_TRACESTACK = S_TRACECNT+4
+S_NEXT = S_TRACESTACK+12
 
        | set CPU special registers
 _setcpu:
@@ -212,6 +215,17 @@ _msp_address2:
        movem.l (a0),d0-d7/a0-a6
        rte
 
+exception_trace000:
+       move.l a0,-(sp)
+       move.l datapointer(pc),a0
+       tst.l S_TRACECNT(a0)
+       bne.s .nexttrace000
+       move.l 4(sp),S_TRACESTACK(a0)
+       move.l 8(sp),S_TRACESTACK+4(a0)
+.nexttrace000:
+       addq.l #1,S_TRACECNT(a0)
+       move.l (sp)+,a0
+       rte
 
 _exceptiontable000:
        bsr.s exception | 2
@@ -221,7 +235,7 @@ _exceptiontable000:
        bsr.s exception | 6
        bsr.s exception | 7
        bsr.s exception | 8
-       bsr.s exception | 9
+       bra.s exception_trace000 | 9
        bsr.s exception | 10
        bsr.s exception | 11
        bsr.s exception | 12
@@ -295,6 +309,19 @@ exception:
        movem.l (sp)+,d1-d7/a0-a6
        rts
 
+exception_trace010:
+       move.l a0,-(sp)
+       move.l datapointer(pc),a0
+       tst.l S_TRACECNT(a0)
+       bne.s .nexttrace010
+       move.l 4(sp),S_TRACESTACK(a0)
+       move.l 8(sp),S_TRACESTACK+4(a0)
+       move.l 12(sp),S_TRACESTACK+8(a0)
+.nexttrace010:
+       addq.l #1,S_TRACECNT(a0)
+       move.l (sp)+,a0
+       rte
+
 _exceptiontable010:
        bsr.s exception010      | 2
        bsr.s exception010      | 3
@@ -303,7 +330,7 @@ _exceptiontable010:
        bsr.s exception010 | 6
        bsr.s exception010 | 7
        bsr.s exception010 | 8
-       bsr.s exception010 | 9
+       bra.s exception_trace010 | 9
        bsr.s exception010 | 10
        bsr.s exception010 | 11
        bsr.s exception010 | 12
@@ -374,6 +401,9 @@ exception010:
        movem.l (sp)+,d1-d7/a0-a6
        rts
 
+exception_trace010t1:
+       bra exception_trace010
+
 _exceptiontable020:
        bsr.s exception020      | 2
        bsr.s exception020      | 3
@@ -382,7 +412,7 @@ _exceptiontable020:
        bsr.s exception020 | 6
        bsr.s exception020 | 7
        bsr.s exception020 | 8
-       bsr.s exception020 | 9
+       bra.s exception_trace010t1 | 9
        bsr.s exception020 | 10
        bsr.s exception020 | 11
        bsr.s exception020 | 12
@@ -460,6 +490,9 @@ _msp_address3:
        movem.l (sp)+,d1-d7/a0-a6
        rts
 
+exception_trace010t2:
+       bra exception_trace010
+
 _exceptiontablefpu:
        bsr.s exceptionfpu      | 2
        bsr.s exceptionfpu      | 3
@@ -468,7 +501,7 @@ _exceptiontablefpu:
        bsr.s exceptionfpu | 6
        bsr.s exceptionfpu | 7
        bsr.s exceptionfpu | 8
-       bsr.s exceptionfpu | 9
+       bsr.s exception_trace010t2 | 9
        bsr.s exceptionfpu | 10
        bsr.s exceptionfpu | 11
        bsr.s exceptionfpu | 12
index 327c0b9dc7f99f4d3e347d23fd2b1c8a28c97d90..3a7c8361f06417d49346b12a6f3f7e35a6105287 100644 (file)
@@ -1,5 +1,5 @@
 
-#define DATA_VERSION 6
+#define DATA_VERSION 7
 
 #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_BRANCHTARGET 27
 #define CT_SRCADDR 28
 #define CT_DSTADDR 29
 #define CT_MEMWRITE 30
index 1136208da7f30ce860303ebbfe34f96053467d04..b5a0211d4d59c739f919850603e5cf8f41a35a77 100644 (file)
@@ -45,7 +45,10 @@ struct registers
        uae_u32 excframe;
        struct fpureg fpuregs[8];
        uae_u32 fpiar, fpcr, fpsr;
-       uae_u32 srcaddr, dstaddr;
+       uae_u32 tracecnt;
+       uae_u16 tracedata[6];
+       uae_u32 srcaddr, dstaddr, branchtarget;
+       uae_u8 branchtarget_mode;
 };
 
 static struct registers test_regs;
@@ -90,6 +93,8 @@ static int low_memory_offset;
 static int high_memory_offset;
 
 static uae_u32 vbr[256];
+static int exceptioncount[256];
+static int supercnt;
 
 static char inst_name[16+1];
 #ifndef M68K
@@ -112,6 +117,7 @@ static uae_u32 interrupt_mask;
 #define SIZE_STORED_ADDRESS 16
 static uae_u8 srcaddr[SIZE_STORED_ADDRESS];
 static uae_u8 dstaddr[SIZE_STORED_ADDRESS];
+static uae_u8 branchtarget[SIZE_STORED_ADDRESS];
 static uae_u8 stackaddr[SIZE_STORED_ADDRESS];
 static uae_u32 stackaddr_ptr;
 
@@ -189,6 +195,7 @@ extern void flushcache(uae_u32);
 extern void *error_vector;
 
 #endif
+static uae_u32 exceptiontableinuse;
 
 struct accesshistory
 {
@@ -208,9 +215,9 @@ static void endinfo(void)
        uae_u8 *p = opcode_memory;
        for (int i = 0; i < 32 * 2; i += 2) {
                uae_u16 v = (p[i] << 8) | (p[i + 1]);
+               printf(" %04x", v);
                if (v == 0x4afc && i > 0)
                        break;
-               printf(" %04x", v);
        }
        printf("\n");
 }
@@ -331,15 +338,19 @@ static void start_test(void)
                for (int i = 32; i < 48; i++) {
                        p[i] = (uae_u32)(((uae_u32)&exceptiontable000) + (i - 2) * 2);
                }
+               exceptiontableinuse = (uae_u32)&exceptiontable000;
        } else {
                oldvbr = setvbr((uae_u32)vbr);
                for (int i = 2; i < 48; i++) {
                        if (fpu_model) {
                                vbr[i] = (uae_u32)(((uae_u32)&exceptiontablefpu) + (i - 2) * 2);
+                               exceptiontableinuse = (uae_u32)&exceptiontablefpu;
                        } else if (cpu_lvl == 1) {
                                vbr[i] = (uae_u32)(((uae_u32)&exceptiontable010) + (i - 2) * 2);
+                               exceptiontableinuse = (uae_u32)&exceptiontable010;
                        } else {
                                vbr[i] = (uae_u32)(((uae_u32)&exceptiontable020) + (i - 2) * 2);
+                               exceptiontableinuse = (uae_u32)&exceptiontable020;
                        }
                        if (i >= 2 && i < 12) {
                                error_vectors[i - 2] = vbr[i];
@@ -736,7 +747,9 @@ static uae_u8 *restore_memory(uae_u8 *p, int storedata)
                                v &= 31;
                                if (v == 0)
                                        v = 32;
+#ifndef _MSC_VER
                                xmemcpy(addr, p, v);
+#endif
                                p += v;
                                break;
                        }
@@ -788,6 +801,10 @@ static uae_u8 *restore_data(uae_u8 *p)
        } else if (mode == CT_DSTADDR) {
                int size;
                p = restore_value(p, &regs.dstaddr, &size);
+       } else if (mode == CT_BRANCHTARGET) {
+               int size;
+               p = restore_value(p, &regs.branchtarget, &size);
+               regs.branchtarget_mode = *p++;
        } else if (mode < CT_AREG + 8) {
                int size;
                if ((v & CT_SIZE_MASK) == CT_SIZE_FPU) {
@@ -874,54 +891,64 @@ static void addinfo_bytes(char *name, uae_u8 *src, uae_u32 address, int offset,
 
 extern uae_u16 disasm_instr(uae_u16 *, char *);
 
-static void addinfo(void)
+static void out_disasm(uae_u8 *mem)
 {
-       if (infoadded)
-               return;
-       infoadded = 1;
-       if (!dooutput)
-               return;
-       sprintf(outbp, "%lu:", testcnt);
-       outbp += strlen(outbp);
-
        uae_u16 *code;
 #ifndef M68K
        uae_u16 swapped[16];
        for (int i = 0; i < 16; i++) {
-               swapped[i] = (opcode_memory[i * 2 + 0] << 8) | (opcode_memory[i * 2 + 1] << 0);
+               swapped[i] = (mem[i * 2 + 0] << 8) | (mem[i * 2 + 1] << 0);
        }
        code = swapped;
 #else
-       code = (uae_u16*)opcode_memory;
+       code = (uae_u16*)mem;
 #endif
-       uae_u8 *p = opcode_memory;
+       uae_u8 *p = mem;
        int offset = 0;
        int lines = 0;
        while (lines++ < 10) {
+               if (!is_valid_test_addr((uae_u32)p) || !is_valid_test_addr((uae_u32)p + 1))
+                       break;
                tmpbuffer[0] = 0;
                int v = disasm_instr(code + offset, tmpbuffer);
                for (int i = 0; i < v; i++) {
                        uae_u16 v = (p[i * 2 + 0] << 8) | (p[i * 2 + 1]);
-                       sprintf(outbp, "%s%04x", i ? " " : (lines == 0 ? "\t\t" : "\t"), v);
+                       sprintf(outbp, "%s %08lx %04x", i ? " " : (lines == 0 ? "\t\t" : "\t"), &p[i * 2], v);
                        outbp += strlen(outbp);
                }
                sprintf(outbp, " %s\n", tmpbuffer);
                outbp += strlen(outbp);
-               if (v <= 0)
+               if (v <= 0 || code[offset] == 0x4afc)
                        break;
                while (v > 0) {
                        offset++;
                        p += 2;
-                       if (code[offset] == 0x4afc) {
-                               v = -1;
-                               break;
-                       }
                        v--;
                }
                if (v < 0)
                        break;
        }
        *outbp = 0;
+}
+
+static void addinfo(void)
+{
+       if (infoadded)
+               return;
+       infoadded = 1;
+       if (!dooutput)
+               return;
+       sprintf(outbp, "%lu:", testcnt);
+       outbp += strlen(outbp);
+
+       out_disasm(opcode_memory);
+
+       if (regs.branchtarget != 0xffffffff) {
+               out_disasm((uae_u8*)regs.branchtarget);
+
+       }
+
+       uae_u16 *code = (uae_u16*)opcode_memory;
        if (code[0] == 0x4e73 || code[0] == 0x4e74 || code[0] == 0x4e75) {
                addinfo_bytes("P", stackaddr, stackaddr_ptr, -SIZE_STORED_ADDRESS_OFFSET, SIZE_STORED_ADDRESS);
                addinfo_bytes(" ", (uae_u8 *)stackaddr_ptr - SIZE_STORED_ADDRESS_OFFSET, stackaddr_ptr, -SIZE_STORED_ADDRESS_OFFSET, SIZE_STORED_ADDRESS);
@@ -1063,10 +1090,10 @@ static void hexdump(uae_u8 *p, int len)
        *outbp++ = '\n';
 }
 
-static uae_u8 last_exception[256];
+static uae_u8 last_exception[256], last_exception_extra;
 static int last_exception_len;
 
-static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum, int sameexc, int *experr)
+static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum, int *gotexcnum, int *experr)
 {
        int exclen = 0;
        uae_u8 *exc;
@@ -1076,8 +1103,59 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum,
        uae_u8 excdatalen = *p++;
        int size;
 
-       if (!excdatalen)
+       if (!excdatalen) {
                return p;
+       }
+
+       if (excdatalen != 0xff) {
+               // check possible extra trace
+               last_exception_extra = *p++;
+               // some other exception + trace
+               if (last_exception_extra == 9) {
+                       exceptioncount[last_exception_extra]++;
+                       if (regs->tracecnt == 0) {
+                               sprintf(outbp, "Expected trace exception but got none\n", regs->tracecnt);
+                               outbp += strlen(outbp);
+                               errors = 1;
+                               *experr = 1;
+                       } else {
+                               uae_u16 sr = regs->tracedata[0];
+                               if (!(sr & 0x2000) || (sr | 0x2000 | 0xc000) != (regs->sr | 0x2000 | 0xc000)) {
+                                       sprintf(outbp, "Trace exception stack frame SR mismatch: %04x != %04x\n", sr, regs->sr);
+                                       outbp += strlen(outbp);
+                                       errors = 1;
+                                       *experr = 1;
+                               }
+                               uae_u32 ret = (regs->tracedata[1] << 16) | regs->tracedata[2];
+                               uae_u32 retv = exceptiontableinuse + (excnum - 2) * 2;
+                               if (ret != retv) {
+                                       sprintf(outbp, "Trace exception stacked PC mismatch: %08lx != %08lx (%ld)\n", ret, retv, excnum);
+                                       outbp += strlen(outbp);
+                                       errors = 1;
+                                       *experr = 1;
+                               }
+                       }
+               } else if (!last_exception_extra && excnum != 9) {
+                       if (regs->tracecnt > 0) {
+                               sprintf(outbp, "Got unexpected trace exception\n");
+                               outbp += strlen(outbp);
+                               errors = 1;
+                               *experr = 1;
+                       }
+               } else if (last_exception_extra) {
+                       end_test();
+                       printf("Unsupported exception extra %d\n", last_exception_extra);
+                       exit(0);
+               }
+               // trace only
+               if (excnum == 9 && *gotexcnum == 4) {
+                       sp = (uae_u8 *)regs->tracedata;
+                       *gotexcnum = 9;
+               }
+       }
+
+       exceptioncount[*gotexcnum]++;
+
        exc = last_exception;
        if (excdatalen != 0xff) {
                if (cpu_lvl == 0) {
@@ -1184,7 +1262,7 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum,
        } else {
                exclen = last_exception_len;
        }
-       if (exclen == 0 || !sameexc)
+       if (exclen == 0 || *gotexcnum != excnum)
                return p;
        if (memcmp(exc, sp, exclen)) {
                sprintf(outbp, "Exception %ld stack frame mismatch:\n", excnum);
@@ -1277,7 +1355,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, &experr);
+                                       p = validate_exception(&test_regs, p, exc, &cpuexc, &experr);
                                }
                                break;
                        }
@@ -1291,7 +1369,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, &experr);
+                               p = validate_exception(&test_regs, p, exc, &cpuexc, &experr);
                        }
                        if (exc != cpuexc) {
                                addinfo();
@@ -1359,6 +1437,8 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                        sr_changed = 0;
                        last_registers.sr = val;
                } else if (mode == CT_PC) {
+                       volatile uae_u16 *c = (volatile uae_u16 *)0x100;
+                       *c = 0x1234;
                        uae_u32 val = last_registers.pc;
                        p = restore_rel(p, &val, 0);
                        pc_changed = 0;
@@ -1575,6 +1655,7 @@ static void process_test(uae_u8 *p)
        regs.sr = interrupt_mask << 8;
        regs.srcaddr = 0xffffffff;
        regs.dstaddr = 0xffffffff;
+       regs.branchtarget = 0xffffffff;
 
        start_test();
 
@@ -1599,6 +1680,7 @@ static void process_test(uae_u8 *p)
 
                store_addr(regs.srcaddr, srcaddr);
                store_addr(regs.dstaddr, dstaddr);
+               store_addr(regs.branchtarget, branchtarget);
 
                xmemcpy(&last_registers, &regs, sizeof(struct registers));
 
@@ -1608,6 +1690,19 @@ static void process_test(uae_u8 *p)
                        flushcache(cpu_lvl);
 
                uae_u32 pc = opcode_memory_addr;
+               uae_u32 originalopcodeend = 0x4afc4e71;
+               uae_u8 *opcode_memory_end = (uae_u8*)pc;
+               for (;;) {
+                       if (gl(opcode_memory_end) == originalopcodeend)
+                               break;
+                       opcode_memory_end += 2;
+                       if (opcode_memory_end > (uae_u8*)pc + 32) {
+                               end_test();
+                               printf("Corrupted opcode memory\n");
+                               exit(0);
+                       }
+               }
+               uae_u32 opcodeend = originalopcodeend;
 
                int extraccr = 0;
 
@@ -1630,6 +1725,24 @@ static void process_test(uae_u8 *p)
                        int maxccr = *p++;
                        for (int ccr = 0;  ccr < maxccr; ccr++) {
 
+                               opcodeend = (opcodeend >> 16) | (opcodeend << 16);
+                               pl(opcode_memory_end, opcodeend);
+
+                               if (regs.branchtarget != 0xffffffff) {
+                                       if (regs.branchtarget_mode == 1) {
+                                               uae_u32 bv = gl((uae_u8*)regs.branchtarget);
+                                               bv = (bv >> 16) | (bv << 16);
+                                               pl((uae_u8*)regs.branchtarget, bv);
+                                       } else if (regs.branchtarget_mode == 2) {
+                                               uae_u16 bv = gw((uae_u8 *)regs.branchtarget);
+                                               if (bv == 0x4e71)
+                                                       bv = 0x4afc;
+                                               else
+                                                       bv = 0x4e71;
+                                               pw((uae_u8 *)regs.branchtarget, bv);
+                                       }
+                               }
+
                                regs.ssp = super_stack_memory - 0x80;
                                regs.msp = super_stack_memory;
                                regs.pc = opcode_memory_addr;
@@ -1714,6 +1827,8 @@ static void process_test(uae_u8 *p)
                                        }
 
                                        p = validate_test(p, ignore_errors, ignore_sr);
+                                       if (regs.sr & 0x2000)
+                                               supercnt++;
 
                                        last_pc = last_registers.pc;
                                        last_fpiar = last_registers.fpiar;
@@ -1743,6 +1858,8 @@ static void process_test(uae_u8 *p)
 
                }
 
+               pl(opcode_memory_end, originalopcodeend);
+
                restoreahist();
 
        }
@@ -1754,7 +1871,6 @@ end:
                printf("\n");
                printf(outbuffer);
        }
-
 }
 
 static void freestuff(void)
@@ -1888,6 +2004,8 @@ static int test_mnemo(const char *path, const char *opcode)
        printf("%s:\n", inst_name);
 
        testcnt = 0;
+       memset(exceptioncount, 0, sizeof(exceptioncount));
+       supercnt = 0;
 
        for (;;) {
                printf("%s. %lu...\n", tfname, testcnt);
@@ -1940,6 +2058,14 @@ static int test_mnemo(const char *path, const char *opcode)
                filecnt++;
        }
 
+       printf("S=%ld", supercnt);
+       for (int i = 0; i < 256; i++) {
+               if (exceptioncount[i]) {
+                       printf(" E%02d=%ld", i, exceptioncount[i]);
+               }
+       }
+       printf("\n");
+
        if (!errors && !quit) {
                printf("All tests complete (total %lu).\n", testcnt);
        }
index 2b25e5b3b1dc72b8d2e9a29cc0b23eac53d85a90..e301630f953b5dec2f5e72d2d214fdff3eda3665 100644 (file)
@@ -76,6 +76,7 @@ static int optimized_flags;
 #define GF_REVERSE 4096
 #define GF_REVERSE2 8192
 #define GF_SECONDWORDSETFLAGS 16384
+#define GF_SECONDEA 32768
 
 typedef enum
 {
@@ -197,6 +198,22 @@ static instr *curi_ce020;
 static bool no_prefetch_ce020;
 static bool got_ea_ce020;
 
+// 68020-30 needs different implementation than 68040/060
+static void next_level_040_to_030(void)
+{
+       if (cpu_level >= 4) {
+               if (next_cpu_level < 4)
+                       next_cpu_level = 4 - 1;
+       }
+}
+
+// 68000 <> 68010
+static void next_level_000(void)
+{
+       if (next_cpu_level < 0)
+               next_cpu_level = 0;
+}
+
 static void fpulimit (void)
 {
        if (limit_braces)
@@ -520,7 +537,7 @@ static void check_bus_error_ins(int offset)
        sprintf(bus_error_text, "\t\texception2_fetch(%s, m68k_getpci() + %d);\n", opcode, offset);
 }
 
-static void check_prefetch_bus_error(int offset)
+static void check_prefetch_bus_error(int offset, int secondprefetchmode)
 {
        if (!using_bus_error)
                return;
@@ -530,7 +547,7 @@ static void check_prefetch_bus_error(int offset)
                else
                        offset = 2;
                // full prefetch: opcode field is zero
-               if (offset == 2) {
+               if ((offset == 2 && !secondprefetchmode) || secondprefetchmode > 0) {
                        bus_error_specials = 1;
                }
        }
@@ -739,7 +756,7 @@ static void fill_prefetch_2 (void)
        if (!using_prefetch)
                return;
        printf ("\t%s (%d);\n", prefetch_word, m68k_pc_offset + 2);
-       check_prefetch_bus_error(m68k_pc_offset + 2);
+       check_prefetch_bus_error(m68k_pc_offset + 2, 0);
        did_prefetch = 1;
        ir2irc = 0;
        count_read++;
@@ -750,7 +767,7 @@ static void fill_prefetch_1 (int o)
 {
        if (using_prefetch) {
                printf ("\t%s (%d);\n", prefetch_word, o);
-               check_prefetch_bus_error(o);
+               check_prefetch_bus_error(o, 0);
                did_prefetch = 1;
                ir2irc = 0;
                count_read++;
@@ -763,7 +780,7 @@ static void fill_prefetch_1_empty(int o)
 {
        if (using_prefetch) {
                printf("\t%s (%d);\n", prefetch_word, o);
-               check_prefetch_bus_error(o ? -2 : -1);
+               check_prefetch_bus_error(o ? -2 : -1, 0);
                did_prefetch = 1;
                ir2irc = 0;
                count_read++;
@@ -866,7 +883,7 @@ static void fill_prefetch_0 (void)
        if (!using_prefetch)
                return;
        printf ("\t%s (0);\n", prefetch_word);
-       check_prefetch_bus_error(0);
+       check_prefetch_bus_error(0, 0);
        did_prefetch = 1;
        ir2irc = 0;
        count_read++;
@@ -879,7 +896,7 @@ static void dummy_prefetch (void)
        if (!using_prefetch)
                return;
        printf ("\t%s (%d);\n", srcwi, o);
-       check_prefetch_bus_error(o);
+       check_prefetch_bus_error(o, 0);
        count_read++;
        insn_n_cycles += 4;
 }
@@ -888,6 +905,9 @@ static void fill_prefetch_next (void)
 {
        if (using_prefetch) {
                irc2ir();
+               if (using_bus_error) {
+                       printf("\topcode = regs.ir;\n");
+               }
                fill_prefetch_1(m68k_pc_offset + 2);
        }
 //     if (using_prefetch_020) {
@@ -1273,6 +1293,11 @@ static void move_68000_bus_error(int offset, int size, int *setapdi, int *fcmode
                        // instruction opcode and Instruction/Not field is one!
                        printf("\t\topcode = regs.ir;\n");
                        *fcmodeflags |= 0x08; // "Not instruction" = 1
+       
+               } else if (dmode == Aipi) {
+
+                       // move.w x,(an)+: an is not increased
+                       printf("\t\tm68k_areg(regs, dstreg) -= 2;\n");
                }
 
        } else if (size == sz_long && ((offset == 0 && dmode != Apdi) || (offset == 2 && dmode == Apdi))) {
@@ -1395,36 +1420,39 @@ static void move_68000_bus_error(int offset, int size, int *setapdi, int *fcmode
 static char const *bus_error_reg;
 static int bus_error_reg_add;
 
-static void do_bus_error_fixes(const char *name, int offset, int write)
+static int do_bus_error_fixes(const char *name, int offset, int write)
 {
        switch (bus_error_reg_add)
        {
        case 1:
-               if (g_instr->mnemo == i_CMPM && write) {
-                       ;
-               } else {
+       case -1:
+               if (g_instr->mnemo == i_CMPM && bus_error_reg_add > 0) {
+                       // CMPM.B (an)+,(an)+: first increased normally, second not increased
                        printf("\t\tm68k_areg(regs, %s) += areg_byteinc[%s] + %d;\n", bus_error_reg, bus_error_reg, offset);
                }
                break;
        case 2:
+       case -2:
                printf("\t\tm68k_areg(regs, %s) += 2 + %d;\n", bus_error_reg, offset);
                break;
        case 3:
-               if (g_instr->mnemo == i_CMPM) {
-                       // CMPM.L (an)+,(an)+: increased by 2
+       case -3:
+               if (g_instr->mnemo == i_CMPM && bus_error_reg_add > 0) {
+                       // CMPM.L (an)+,(an)+: first increased normally, second not increased
                        printf("\t\tm68k_areg(regs, %s) += 2 + %d;\n", bus_error_reg, offset);
                }
                break;
        case 4:
+       case -4:
                if ((g_instr->mnemo == i_ADDX || g_instr->mnemo == i_SUBX) && g_instr->size == sz_long) {
                        // ADDX.L/SUBX.L -(an),-(an) source: stack frame decreased by 2, not 4.
-                       offset = 2;
+                       offset += 2;
                } else {
                        printf("\t\tm68k_areg (regs, %s) = %sa;\n", bus_error_reg, name);
                }
                break;
        }
-
+       return offset;
 }
 
 static void check_bus_error(const char *name, int offset, int write, int size, const char *writevar, int fc)
@@ -1435,6 +1463,8 @@ static void check_bus_error(const char *name, int offset, int write, int size, c
        if (!using_prefetch && !using_ce)
                return;
 
+       next_level_000();
+
        uae_u32 extra = fc & 0xffff0000;
        fc &= 0xffff;
 
@@ -1456,7 +1486,7 @@ static void check_bus_error(const char *name, int offset, int write, int size, c
                        move_68000_bus_error(offset, g_instr->size, &setapdiback, &fc);
                }
 
-               do_bus_error_fixes(name, offset, write);
+               offset = do_bus_error_fixes(name, offset, write);
 
                if (g_instr->mnemo == i_BTST && (g_instr->dmode == PC16 || g_instr->dmode == PC8r)) {
                        // BTST special case where destination is read access
@@ -1476,9 +1506,9 @@ static void check_bus_error(const char *name, int offset, int write, int size, c
                        printf("\t\topcode |= 0x%x;\n", extra);
                }
 
-               if (cpu_level == 0 && write) {
-                       printf("\t\topcode = regs.irc;\n");
-               }
+               //if (cpu_level == 0 && write) {
+               //      printf("\t\topcode = regs.irc;\n");
+               //}
 
                if (write) {
                        printf("\t\texception2_write(opcode, %sa + %d, %d, %s, %d);\n",
@@ -1944,21 +1974,6 @@ static int gence020cycles_jea (instr *curi, amodes mode)
        return oph;
 }
 
-// 68020-30 needs different implementation than 68040/060
-static void next_level_040_to_030(void)
-{
-       if (cpu_level >= 4) {
-               if (next_cpu_level < 4)
-                       next_cpu_level = 4 - 1;
-       }
-}
-
-static void next_level_000 (void)
-{
-       if (next_cpu_level < 0)
-               next_cpu_level = 0;
-}
-
 static void maybeaddop_ce020 (int flags)
 {
        if (flags & GF_OPCE020)
@@ -1996,10 +2011,11 @@ static void move_68000_address_error(int size, int *setapdi, int *fcmodeflags)
                        break;
                }
                if (dmode == Apdi) {
-                       // this is buggy, address error stack frame opcode field contains next
-                       // instruction opcode and Instruction/Not field is one!
-                       printf("\t\topcode = regs.irc;\n");
-                       *fcmodeflags |= 0x08; // "Not instruction" = 1
+                       // partial prefetch already done
+                       printf("\t\tregs.ir = regs.irc;\n");
+                       // if trace, I/N is also set
+                       printf("\t\tif(regs.t1) opcode |= 0x10000;\n");
+
                }
                if (set_ccr) {
                        printf("\t\tccr_68000_word_move_ae_normal((uae_s16)(src));\n");
@@ -2399,6 +2415,9 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                } else if (mode == Apdi) {
                        bus_error_reg_add = 4;
                }
+               if (flags & GF_SECONDEA) {
+                       bus_error_reg_add = -bus_error_reg_add;
+               }
        }
 
        exception_pc_offset = 0;
@@ -2418,10 +2437,12 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                int fcmodeflags = 0;
                int exp3rw = getv == 2;
 
+               next_level_000();
+
                printf("\tif (%sa & 1) {\n", name);
 
                if (cpu_level == 1) {
-                       if (bus_error_reg_add == 4)
+                       if (abs(bus_error_reg_add) == 4)
                                bus_error_reg_add = 0;
                        // 68010 CLR <memory>: pre and post are not added yet
                        if (g_instr->mnemo == i_CLR) {
@@ -2686,7 +2707,7 @@ static void genamodedual (instr *curi, amodes smode, const char *sreg, wordsizes
        subhead_ce020 = subhead;
        curi_ce020 = curi;
        genamode3 (curi, smode, sreg, ssize, sname, sgetv, 0, sflags);
-       genamode3 (NULL, dmode, dreg, dsize, dname, dgetv, 0, dflags | (eadmode == true ? GF_OPCE020 : 0));
+       genamode3 (NULL, dmode, dreg, dsize, dname, dgetv, 0, dflags | (eadmode == true ? GF_OPCE020 : 0) | GF_SECONDEA);
        if (eadmode == false)
                maybeaddop_ce020 (GF_OPCE020);
 }
@@ -3246,21 +3267,25 @@ static void genmovemel_ce (uae_u16 opcode)
        start_brace();
        if (table68k[opcode].size == sz_long) {
                printf("\twhile (dmask) {\n");
-               printf("\t\tuae_u32 v = %s (srca) << 16;\n", srcw);
+               printf("\t\tuae_u32 v = (%s(srca) << 16) | (m68k_dreg(regs, movem_index1[dmask]) & 0xffff);\n", srcw);
                check_bus_error("src", 0, 0, 1, NULL, 1);
-               printf("\t\tv |= %s (srca + 2);\n", srcw);
+               printf("\t\tm68k_dreg(regs, movem_index1[dmask]) = v;\n");
+               printf("\t\tv &= 0xffff0000;\n");
+               printf("\t\tv |= % s(srca + 2); \n", srcw);
                check_bus_error("src", 2, 0, 1, NULL, 1);
-               printf("\t\tm68k_dreg (regs, movem_index1[dmask]) = v;\n");
+               printf("\t\tm68k_dreg(regs, movem_index1[dmask]) = v;\n");
                printf("\t\tsrca += %d;\n", size);
                printf("\t\tdmask = movem_next[dmask];\n");
                addcycles000_nonce("\t\t", 8);
                printf("\t}\n");
                printf("\twhile (amask) {\n");
-               printf("\t\tuae_u32 v = %s (srca) << 16;\n", srcw);
+               printf("\t\tuae_u32 v = (%s(srca) << 16) | (m68k_areg(regs, movem_index1[amask]) & 0xffff);\n", srcw);
                check_bus_error("src", 0, 0, 1, NULL, 1);
-               printf("\t\tv |= %s (srca + 2);\n", srcw);
+               printf("\t\tm68k_areg(regs, movem_index1[amask]) = v;\n");
+               printf("\t\tv &= 0xffff0000;\n");
+               printf("\t\tv |= %s(srca + 2);\n", srcw);
                check_bus_error("src", 2, 0, 1, NULL, 1);
-               printf("\t\tm68k_areg (regs, movem_index1[amask]) = v;\n");
+               printf("\t\tm68k_areg(regs, movem_index1[amask]) = v;\n");
                printf("\t\tsrca += %d;\n", size);
                printf("\t\tamask = movem_next[amask];\n");
                addcycles000_nonce("\t\t", 8);
@@ -4062,7 +4087,7 @@ static void gen_opcode (unsigned int opcode)
                if (!isreg (curi->smode))
                        addcycles000 (2);
                genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA | GF_REVERSE);
-               genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_AA | GF_REVERSE | GF_RMW);
+               genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_AA | GF_REVERSE | GF_RMW | GF_SECONDEA);
                fill_prefetch_next ();
                if (curi->size == sz_long && isreg (curi->smode))
                        addcycles000 (4);
@@ -4160,7 +4185,7 @@ static void gen_opcode (unsigned int opcode)
                if (!isreg (curi->smode))
                        addcycles000 (2);
                genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA | GF_REVERSE);
-               genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_AA | GF_REVERSE | GF_RMW);
+               genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_AA | GF_REVERSE | GF_RMW | GF_SECONDEA);
                fill_prefetch_next ();
                if (curi->size == sz_long && isreg (curi->smode))
                        addcycles000 (4);
@@ -5089,75 +5114,89 @@ static void gen_opcode (unsigned int opcode)
                next_level_040_to_030();
                break;
        case i_JSR:
-               // possible idle cycle, prefetch from new address, stack high return addr, stack low, prefetch
-               no_prefetch_ce020 = true;
-               genamode (curi, curi->smode, "srcreg", curi->size, "src", 0, 0, GF_AA|GF_NOREFILL);
-               start_brace ();
-               printf("\tuaecptr oldpc = %s;\n", getpc);
-               printf("\tuaecptr nextpc = oldpc + %d;\n", m68k_pc_offset);
-               if (using_exception_3 && cpu_level <= 1) {
-                       printf("\tif (srca & 1) {\n");
-                       printf("\t\texception3i (opcode, srca);\n");
-                       printf("\t\tgoto %s;\n", endlabelstr);
-                       printf("\t}\n");
-                       need_endlabel = 1;
-               }
-               if (using_mmu) {
-                       printf ("\t%s (m68k_areg (regs, 7) - 4, nextpc);\n", dstl);
-                       printf ("\tm68k_areg (regs, 7) -= 4;\n");
-                       setpc ("srca");
-                       clear_m68k_offset();
-               } else {
-                       if (curi->smode == Ad16 || curi->smode == absw || curi->smode == PC16)
-                               addcycles000 (2);
-                       if (curi->smode == Ad8r || curi->smode == PC8r) {
-                               addcycles000 (6);
-                               if (cpu_level <= 1 && using_prefetch)
-                                       printf ("\tnextpc += 2;\n");
-                       }
-                       setpc ("srca");
-                       clear_m68k_offset();
-                       if (using_exception_3 && cpu_level >= 2) {
-                               printf("\tif (%s & 1) {\n", getpc);
-                               printf("\t\texception3i (opcode, %s);\n", getpc);
-                               printf("\t\tgoto %s;\n", endlabelstr);
-                               printf("\t}\n");
-                               need_endlabel = 1;
-                       }
-                       fill_prefetch_1(0);
-                       if (cpu_level < 4)
-                               printf("\tm68k_areg (regs, 7) -= 4;\n");
+               {
+                       // possible idle cycle, prefetch from new address, stack high return addr, stack low, prefetch
+                       no_prefetch_ce020 = true;
+                       genamode(curi, curi->smode, "srcreg", curi->size, "src", 0, 0, GF_AA | GF_NOREFILL);
+                       start_brace();
+                       printf("\tuaecptr oldpc = %s;\n", getpc);
+                       printf("\tuaecptr nextpc = oldpc + %d;\n", m68k_pc_offset);
                        if (using_exception_3 && cpu_level <= 1) {
-                               printf("\tif (m68k_areg(regs, 7) & 1) {\n");
-                               printf("\t\texception3_write(opcode, m68k_areg(regs, 7), 1, m68k_areg(regs, 7) >> 16, 1);\n");
+                               printf("\tif (srca & 1) {\n");
+                               printf("\t\texception3i (opcode, srca);\n");
                                printf("\t\tgoto %s;\n", endlabelstr);
                                printf("\t}\n");
                                need_endlabel = 1;
                        }
-                       if (using_ce || using_prefetch) {
-                               printf("\tuaecptr dsta = m68k_areg(regs, 7);\n");
-                               printf("\t%s(dsta, nextpc >> 16);\n", dstw);
-                               check_bus_error("dst", 0, 1, 1, "nextpc >> 16", 1);
-                               printf("\t%s(dsta + 2, nextpc);\n", dstw);
-                               check_bus_error("dst", 2, 1, 1, "nextpc", 1);
+                       if (using_mmu) {
+                               printf("\t%s (m68k_areg (regs, 7) - 4, nextpc);\n", dstl);
+                               printf("\tm68k_areg (regs, 7) -= 4;\n");
+                               setpc("srca");
+                               clear_m68k_offset();
                        } else {
+                               if (curi->smode == Ad16 || curi->smode == absw || curi->smode == PC16)
+                                       addcycles000(2);
+                               if (curi->smode == Ad8r || curi->smode == PC8r) {
+                                       addcycles000(6);
+                                       if (cpu_level <= 1 && using_prefetch)
+                                               printf("\tnextpc += 2;\n");
+                               }
+                               setpc("srca");
+                               clear_m68k_offset();
+                               if (using_exception_3 && cpu_level >= 2) {
+                                       printf("\tif (%s & 1) {\n", getpc);
+                                       printf("\t\texception3i (opcode, %s);\n", getpc);
+                                       printf("\t\tgoto %s;\n", endlabelstr);
+                                       printf("\t}\n");
+                                       need_endlabel = 1;
+                               }
+                               fill_prefetch_1(0);
                                if (cpu_level < 4)
-                                       printf("\t%s(m68k_areg(regs, 7), nextpc);\n", dstl);
-                               else
-                                       printf("\t%s(m68k_areg(regs, 7) - 4, nextpc);\n", dstl);
+                                       printf("\tm68k_areg (regs, 7) -= 4;\n");
+                               if (using_exception_3 && cpu_level <= 1) {
+                                       printf("\tif (m68k_areg(regs, 7) & 1) {\n");
+                                       printf("\t\texception3_write(opcode, m68k_areg(regs, 7), 1, m68k_areg(regs, 7) >> 16, 1);\n");
+                                       printf("\t\tgoto %s;\n", endlabelstr);
+                                       printf("\t}\n");
+                                       need_endlabel = 1;
+                               }
+                               if (using_ce || using_prefetch) {
+                                       printf("\tuaecptr dsta = m68k_areg(regs, 7);\n");
+                                       printf("\t%s(dsta, nextpc >> 16);\n", dstw);
+                                       check_bus_error("dst", 0, 1, 1, "nextpc >> 16", 1);
+                                       printf("\t%s(dsta + 2, nextpc);\n", dstw);
+                                       check_bus_error("dst", 2, 1, 1, "nextpc", 1);
+                               } else {
+                                       if (cpu_level < 4)
+                                               printf("\t%s(m68k_areg(regs, 7), nextpc);\n", dstl);
+                                       else
+                                               printf("\t%s(m68k_areg(regs, 7) - 4, nextpc);\n", dstl);
+                               }
+                               if (cpu_level >= 4)
+                                       printf("\tm68k_areg (regs, 7) -= 4;\n");
+                               if (using_debugmem) {
+                                       printf("\tif (debugmem_trace)\n");
+                                       printf("\t\tbranch_stack_push(oldpc, nextpc);\n");
+                               }
                        }
-                       if (cpu_level >= 4)
-                               printf("\tm68k_areg (regs, 7) -= 4;\n");
-                       if (using_debugmem) {
-                               printf("\tif (debugmem_trace)\n");
-                               printf("\t\tbranch_stack_push(oldpc, nextpc);\n");
+                       count_write += 2;
+                       fill_prefetch_full_020();
+                       if (using_prefetch || using_ce) {
+                               int sp = (curi->smode == Ad16 || curi->smode == absw || curi->smode == absl || curi->smode == PC16 || curi->smode == Ad8r || curi->smode == PC8r) ? -1 : 0;
+                               irc2ir();
+                               printf("\topcode = regs.ir;\n");
+                               printf("\t%s (%d);\n", prefetch_word, 2);
+                               check_prefetch_bus_error(-2, sp);
+                               did_prefetch = 1;
+                               ir2irc = 0;
+                               count_read++;
+                               insn_n_cycles += 4;
+                       } else {
+                               fill_prefetch_next_empty();
                        }
+                       branch_inst = 1;
+                       next_level_040_to_030();
                }
-               count_write += 2;
-               fill_prefetch_full_020 ();
-               fill_prefetch_next_empty();
-               branch_inst = 1;
-               next_level_040_to_030();
                break;
        case i_JMP:
                no_prefetch_ce020 = true;
@@ -5175,7 +5214,21 @@ static void gen_opcode (unsigned int opcode)
                        addcycles000 (6);
                setpc ("srca");
                clear_m68k_offset();
-               fill_prefetch_full ();
+               if (using_prefetch || using_ce) {
+                       printf("\t%s (%d);\n", prefetch_word, 0);
+                       check_prefetch_bus_error(-1, 0);
+                       irc2ir();
+                       printf("\t%s (%d);\n", prefetch_word, 2);
+                       int sp = (curi->smode == Ad16 || curi->smode == absw || curi->smode == absl || curi->smode == PC16 || curi->smode == Ad8r || curi->smode == PC8r) ? -1 : 0;
+                       printf("\topcode = regs.ir;\n");
+                       check_prefetch_bus_error(-2, sp);
+                       did_prefetch = 1;
+                       ir2irc = 0;
+                       count_read++;
+                       insn_n_cycles += 4;
+               } else {
+                       fill_prefetch_full();
+               }
                branch_inst = 1;
                break;
        case i_BSR:
index 4c8a950f5c0940ecbb0d248f8b10218fc3923c09..8b624501af0007ad73fe8ff4e5a0cb5e841b31d3 100644 (file)
@@ -695,6 +695,7 @@ extern void Exception_build_68000_address_error_stack_frame(uae_u16 mode, uae_u1
 extern uae_u32 exception_pc(int nr);
 extern void cpu_restore_fixup(void);
 extern bool privileged_copro_instruction(uae_u16 opcode);
+extern bool generates_group1_exception(uae_u16 opcode);
 
 void ccr_68000_long_move_ae_LZN(uae_s32 src);
 void ccr_68000_long_move_ae_LN(uae_s32 src);
index 9da12a180d2e7b59393e75ca4741b9622175d71d..65e486a22f8172980c06dacf1eb40cb4738d44a3 100644 (file)
@@ -80,6 +80,8 @@ static bool last_notinstruction_for_exception_3;
 /* set when writing exception stack frame */
 static int exception_in_exception;
 
+static void exception3_read_special(uae_u32 opcode, uaecptr addr, int size, int fc);
+
 int mmu_enabled, mmu_triggered;
 int cpu_cycles;
 int bus_error_offset;
@@ -2651,7 +2653,7 @@ static void Exception_mmu030 (int nr, uaecptr oldpc)
                if (nr == 2 || nr == 3)
                        cpu_halt (CPU_HALT_DOUBLE_FAULT);
                else
-                       exception3_read(regs.ir, newpc, 1, 1);
+                       exception3_read_special(regs.ir, newpc, 1, 1);
                return;
        }
        if (interrupt)
@@ -2717,7 +2719,7 @@ static void Exception_mmu (int nr, uaecptr oldpc)
                if (nr == 2 || nr == 3)
                        cpu_halt (CPU_HALT_DOUBLE_FAULT);
                else
-                       exception3_read(regs.ir, newpc, 2, 1);
+                       exception3_read_special(regs.ir, newpc, 2, 1);
                return;
        }
 
@@ -2861,7 +2863,7 @@ static void Exception_normal (int nr)
                                                        if (nr == 2 || nr == 3)
                                                                cpu_halt (CPU_HALT_DOUBLE_FAULT);
                                                        else
-                                                               exception3_read(regs.ir, newpc, 2, 1);
+                                                               exception3_read_special(regs.ir, newpc, 2, 1);
                                                        return;
                                                }
                                                m68k_setpc (newpc);
@@ -6860,13 +6862,37 @@ void exception3_notinstruction(uae_u32 opcode, uaecptr addr)
 {
        exception3f (opcode, addr, true, false, true, 0xffffffff, 1, false, -1);
 }
+static void exception3_read_special(uae_u32 opcode, uaecptr addr, int size, int fc)
+{
+       exception3f(opcode, addr, false, 0, false, 0xffffffff, size, false, fc);
+}
 void exception3_read(uae_u32 opcode, uaecptr addr, int size, int fc)
 {
-       exception3f (opcode, addr, false, 0, false, 0xffffffff, size, false, fc);
+       bool ni = false;
+       if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible) {
+               if (generates_group1_exception(regs.ir)) {
+                       ni = true;
+                       fc = -1;
+               }
+               if (opcode & 0x100000)
+                       ni = true;
+               opcode = regs.ir;
+       }
+       exception3f (opcode, addr, false, 0, ni, 0xffffffff, size, false, fc);
 }
 void exception3_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc)
 {
-       exception3f (opcode, addr, true, 0, false, 0xffffffff, size, false, fc);
+       bool ni = false;
+       if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible) {
+               if (generates_group1_exception(regs.ir)) {
+                       ni = true;
+                       fc = -1;
+               }
+               if (opcode & 0x100000)
+                       ni = true;
+               opcode = regs.ir;
+       }
+       exception3f (opcode, addr, true, 0, ni, 0xffffffff, size, false, fc);
        regs.write_buffer = val;
 }
 void exception3i (uae_u32 opcode, uaecptr addr)
@@ -6889,6 +6915,14 @@ void exception2_setup(uaecptr addr, bool read, int size, uae_u32 fc)
        last_size_for_exception_3 = size;
        last_di_for_exception_3 = 1;
        cpu_bus_error = 0;
+
+       if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible) {
+               if (generates_group1_exception(regs.ir)) {
+                       last_notinstruction_for_exception_3 = true;
+                       fc = -1;
+               }
+               last_op_for_exception_3 = regs.ir;
+       }
 }
 
 void exception2(uaecptr addr, bool read, int size, uae_u32 fc)
index 74499e3d8897e557dda06fc6582340fb2235bfab..56f18f36c4fd3cb3c8cbb89790fa81cd351f6a6e 100644 (file)
@@ -1642,3 +1642,21 @@ bool privileged_copro_instruction(uae_u16 opcode)
        }
        return false;
 }
+
+bool generates_group1_exception(uae_u16 opcode)
+{
+       struct instr *table = &table68k[opcode];
+       // illegal/a-line/f-line?
+       if (table->mnemo == i_ILLG)
+               return true;
+       // privilege violation?
+       if (!regs.s) {
+               if (table->plev == 1 && currprefs.cpu_model > 68000)
+                       return true;
+               if (table->plev == 2)
+                       return true;
+               if (table->plev == 3 && table->size == sz_word)
+                       return true;
+       }
+       return false;
+}