]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
CPU test prefetch bus error testing (does not return correct results yet)
authorToni Wilen <twilen@winuae.net>
Sun, 8 Dec 2019 11:25:22 +0000 (13:25 +0200)
committerToni Wilen <twilen@winuae.net>
Sun, 8 Dec 2019 11:25:22 +0000 (13:25 +0200)
cputest.cpp
cputest/main.c
newcpu.cpp

index e9a8e5ee3b650f180aa559eb5b130044fefa7e03..2d17eca396ab3fa5cee87d794e3cb5fde8cc29da 100644 (file)
@@ -2479,8 +2479,9 @@ static int handle_specials_stack(uae_u16 opcode, uaecptr pc, struct instr *dp, i
        return offset;
 }
 
-static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc, struct instr *dp)
+static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp)
 {
+       uae_u16 opc = regs.ir;
        uae_u16 opw1 = (opcode_memory[2] << 8) | (opcode_memory[3] << 0);
        uae_u16 opw2 = (opcode_memory[4] << 8) | (opcode_memory[5] << 0);
        if (opc == 0x4a10
@@ -2945,9 +2946,14 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
        registers[8 + 7] = user_stack_memory_use;
 
        uae_u32 target_address = 0xffffffff;
+       uae_u32 target_opcode_address = 0xffffffff;
        target_ea[0] = 0xffffffff;
        target_ea[1] = 0xffffffff;
        target_ea[2] = 0xffffffff;
+       if (feature_target_ea[0][2] && feature_target_ea[0][2] != 0xffffffff) {
+               target_opcode_address = feature_target_ea[0][2];
+               target_ea[2] = target_opcode_address;
+       }
        if (feature_target_ea[0][0] != 0xffffffff) {
                target_address = feature_target_ea[0][0];
                target_ea[0] = target_address;
@@ -3006,7 +3012,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
 
        int sr_override = 0;
 
-       uae_u32 target_ea_bak[3], target_address_bak;
+       uae_u32 target_ea_bak[3], target_address_bak, target_opcode_address_bak;
 
        for (;;) {
 
@@ -3014,6 +3020,16 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                target_ea_bak[1] = target_ea[1];
                target_ea_bak[2] = target_ea[2];
                target_address_bak = target_address;
+               target_opcode_address_bak = target_opcode_address;
+
+               uae_u32 opcode_memory_address = opcode_memory_start;
+               uae_u8 *opcode_memory_ptr = opcode_memory;
+               if (target_opcode_address != 0xffffffff) {
+                       opcode_memory_address += target_opcode_address;
+                       opcode_memory_ptr = get_addr(opcode_memory_address, 2, 0);
+                       if (opcode_memory_address >= safe_memory_start && opcode_memory_address < safe_memory_end)
+                               break;
+               }
 
                if (quick)
                        break;
@@ -3070,6 +3086,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                        target_ea[1] = target_ea_bak[1];
                        target_ea[2] = target_ea_bak[2];
                        target_address = target_address_bak;
+                       target_opcode_address = target_opcode_address_bak;
 
                        int extra_loops = 3;
                        while (extra_loops-- > 0) {
@@ -3102,6 +3119,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                target_ea[1] = target_ea_bak[1];
                                target_ea[2] = target_ea_bak[1];
                                target_address = target_address_bak;
+                               target_opcode_address = target_opcode_address_bak;
 
                                reset_ea_state();
                                // retry few times if out of bounds access
@@ -3142,6 +3160,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        target_ea[1] = target_ea_bak[1];
                                        target_ea[2] = target_ea_bak[2];
                                        target_address = target_address_bak;
+                                       target_opcode_address = target_opcode_address_bak;
 
                                        if (opc == 0x4ed0)
                                                printf("");
@@ -3150,6 +3169,19 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
 
 
                                        uaecptr pc = opcode_memory_start + 2;
+                                       if (target_opcode_address != 0xffffffff) {
+                                               pc -= 2;
+                                               int cnt = 0;
+                                               while (pc - 2 != opcode_memory_address) {
+                                                       put_word_test(pc, 0x4e71);
+                                                       pc += 2;
+                                                       cnt++;
+                                                       if (cnt >= 16) {
+                                                               wprintf(_T("opcode target is too far from opcode address\n"));
+                                                               abort();
+                                                       }
+                                               }
+                                       }
 
                                        if (dp->mnemo != i_ILLG) {
 
@@ -3170,7 +3202,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                        pc += o;
                                                }
 
-                                               uae_u8 *ao = opcode_memory + 2;
+                                               uae_u8 *ao = opcode_memory_ptr + 2;
                                                uae_u16 apw1 = (ao[0] << 8) | (ao[1] << 0);
                                                uae_u16 apw2 = (ao[2] << 8) | (ao[3] << 0);
                                                if (opc == 0x4eb1
@@ -3182,7 +3214,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                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];
+                                                       uae_u16 mask = (opcode_memory_ptr[2] << 8) | opcode_memory_ptr[3];
                                                        int count = 0;
                                                        for (int i = 0; i < 16; i++) {
                                                                if (mask & (1 << i))
@@ -3231,7 +3263,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                // if destination EA modified opcode
                                                dp = table68k + opc;
 
-                                               uae_u8 *bo = opcode_memory + 2;
+                                               uae_u8 *bo = opcode_memory_ptr + 2;
                                                uae_u16 bopw1 = (bo[0] << 8) | (bo[1] << 0);
                                                uae_u16 bopw2 = (bo[2] << 8) | (bo[3] << 0);
                                                if (opc == 0x0662
@@ -3247,20 +3279,20 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
 
                                        }
 
-                                       put_word_test(opcode_memory_start, opc);
+                                       put_word_test(opcode_memory_address, opc);
 
                                        if (extra_or || extra_and) {
-                                               uae_u16 ew = get_word_test(opcode_memory_start + 2);
+                                               uae_u16 ew = get_word_test(opcode_memory_address + 2);
                                                uae_u16 ew2 = (ew | extra_or) & ~extra_and;
                                                if (ew2 != ew) {
-                                                       put_word_test(opcode_memory_start + 2, ew2);
+                                                       put_word_test(opcode_memory_address + 2, ew2);
                                                }
                                        }
 
                                        // loop mode
                                        if (feature_loop_mode) {
                                                // dbf dn, opcode_memory_start
-                                               put_long_test(pc, ((0x51c8 | feature_loop_mode_register) << 16) | ((opcode_memory_start - pc - 2) & 0xffff));
+                                               put_long_test(pc, ((0x51c8 | feature_loop_mode_register) << 16) | ((opcode_memory_address - pc - 2) & 0xffff));
                                                pc += 4;
                                        }
 
@@ -3268,7 +3300,14 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        // running on real hardware.
                                        uae_u32 originalendopcode = 0x4afc4e71;
                                        uae_u32 endopcode = originalendopcode;
-                                       put_long_test(pc, endopcode); // illegal instruction + nop
+                                       uae_u32 actualendpc = pc;
+                                       if (!is_nowrite_address(pc, 4)) {
+                                               put_long_test(pc, endopcode); // illegal instruction + nop
+                                               actualendpc += 4;
+                                       } else if (!is_nowrite_address(pc, 2)) {
+                                               put_word_test(pc, endopcode >> 16);
+                                               actualendpc += 2;
+                                       }
                                        pc += 4;
 
                                        if (isconstant_src < 0 || isconstant_dst < 0) {
@@ -3289,7 +3328,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                abort();
                                        }
 
-                                       dst = store_mem_bytes(dst, opcode_memory_start, pc - opcode_memory_start, subtest_count > 0 ? oldbytes : NULL);
+                                       dst = store_mem_bytes(dst, opcode_memory_start, actualendpc - opcode_memory_start, subtest_count > 0 ? oldbytes : NULL);
                                        ahcnt = 0;
 
 
@@ -3305,7 +3344,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        uaecptr nextpc;
                                        srcaddr = 0xffffffff;
                                        dstaddr = 0xffffffff;
-                                       uae_u32 dflags = m68k_disasm_2(out, sizeof(out) / sizeof(TCHAR), opcode_memory_start, &nextpc, 1, &srcaddr, &dstaddr, 0xffffffff, 0);
+                                       uae_u32 dflags = m68k_disasm_2(out, sizeof(out) / sizeof(TCHAR), opcode_memory_address, &nextpc, 1, &srcaddr, &dstaddr, 0xffffffff, 0);
                                        if (verbose) {
                                                my_trim(out);
                                                wprintf(_T("%08u %s"), subtest_count, out);
@@ -3474,9 +3513,16 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                        // swap end opcode illegal/nop
                                                        endopcode = (endopcode >> 16) | (endopcode << 16);
                                                        noaccesshistory++;
-                                                       put_long_test(pc - 4, endopcode);
+                                                       int endopcodesize = 0;
+                                                       if (!is_nowrite_address(pc - 4, 4)) {
+                                                               put_long_test(pc - 4, endopcode);
+                                                               endopcodesize = (endopcode >> 16) == 0x4e71 ? 2 : 4;
+                                                       } else if (!is_nowrite_address(pc - 4, 2)) {
+                                                               put_word_test(pc - 4, endopcode >> 16);
+                                                               endopcodesize = 2;
+                                                       }
                                                        noaccesshistory--;
-                                                       int endopcodesize = (endopcode >> 16) == 0x4e71 ? 2 : 4;
+                                                       
 
                                                        // swap branch target illegal/nop
                                                        if (branch_target_swap_mode) {
@@ -3560,7 +3606,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                        if (subtest_count == 2052)
                                                                printf("");
 
-                                                       execute_ins(opc, pc - endopcodesize, branch_target_pc, dp);
+                                                       execute_ins(pc - endopcodesize, branch_target_pc, dp);
 
                                                        if (regs.s)
                                                                s_cnt++;
@@ -3797,7 +3843,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                }
                dst = storage_buffer;
 
-               if (opcodecnt == 1 && target_address == 0xffffffff)
+               if (opcodecnt == 1 && target_address == 0xffffffff && target_opcode_address == 0xffffffff)
                        break;
                if (lookup->mnemo == i_ILLG)
                        break;
@@ -3834,6 +3880,18 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                        nextround = true;
                }
 
+               if (target_opcode_address != 0xffffffff) {
+                       nextround = false;
+                       target_ea_opcode_cnt++;
+                       if (target_ea_opcode_cnt >= target_ea_opcode_max) {
+                               target_ea_opcode_cnt = 0;
+                               if (target_ea_opcode_max > 0)
+                                       nextround = true;
+                       }
+                       target_opcode_address = feature_target_ea[target_ea_opcode_cnt][2];
+                       target_ea[2] = opcode_memory_address + target_opcode_address;
+               }
+
                if (nextround) {
                        rounds--;
                        if (rounds < 0)
@@ -4067,7 +4125,7 @@ int __cdecl main(int argc, char *argv[])
                feature_target_ea[i][2] = 0xffffffff;
        }
        for (int i = 0; i < 3; i++) {
-               if (ini_getstring(ini, INISECTION, i == 2 ? _T("feature_target_opcode") : (i ? _T("feature_target_dst_ea") : _T("feature_target_src_ea")), &vs)) {
+               if (ini_getstring(ini, INISECTION, i == 2 ? _T("feature_target_opcode_offset") : (i ? _T("feature_target_dst_ea") : _T("feature_target_src_ea")), &vs)) {
                        int cnt = 0;
                        TCHAR *p = vs;
                        while (p && *p) {
index 78660d0d50cc614243d136ba99d1a871e77482c9..204794ffba83ff213fa468eab3cb0eb3838d494b 100644 (file)
@@ -219,6 +219,16 @@ static int is_valid_test_addr_read(uae_u32 a)
                (a >= test_memory_addr && a < test_memory_end);
 }
 
+static int is_valid_test_addr_readwrite(uae_u32 a)
+{
+       if ((uae_u8 *)a >= safe_memory_start && (uae_u8 *)a < safe_memory_end)
+               return 0;
+       return (a >= test_low_memory_start && a < test_low_memory_end && test_low_memory_start != 0xffffffff) ||
+               (a >= test_high_memory_start && a < test_high_memory_end && test_high_memory_start != 0xffffffff) ||
+               (a >= test_memory_addr && a < test_memory_end);
+}
+
+
 static void endinfo(void)
 {
        printf("Last test: %lu\n", testcnt);
@@ -951,8 +961,11 @@ static void out_disasm(uae_u8 *mem)
        int lines = 0;
        while (lines++ < 5) {
                int v = 0;
-               if (!is_valid_test_addr_read((uae_u32)p) || !is_valid_test_addr_read((uae_u32)p + 1))
+               if (!is_valid_test_addr_read((uae_u32)p) || !is_valid_test_addr_read((uae_u32)p + 1)) {
+                       sprintf(outbp, "%08lx -- INACCESSIBLE --\n", p);
+                       outbp += strlen(outbp);
                        break;
+               }
                tmpbuffer[0] = 0;
                if (!(((uae_u32)code) & 1)) {
                        v = disasm_instr(code + offset, tmpbuffer);
@@ -962,6 +975,8 @@ static void out_disasm(uae_u8 *mem)
                                uae_u16 v = (p[i * 2 + 0] << 8) | (p[i * 2 + 1]);
                                sprintf(outbp, "%04x ", v);
                                outbp += strlen(outbp);
+                               if (v == 0x4e71)
+                                       lines--;
                        }
                        sprintf(outbp, " %s\n", tmpbuffer);
                        outbp += strlen(outbp);
@@ -1764,7 +1779,7 @@ static void process_test(uae_u8 *p)
                uae_u32 originalopcodeend = 0x4afc4e71;
                uae_u8 *opcode_memory_end = (uae_u8*)pc;
                for (;;) {
-                       if (gl(opcode_memory_end) == originalopcodeend)
+                       if (opcode_memory_end == safe_memory_start || gw(opcode_memory_end) == 0x4afc)
                                break;
                        opcode_memory_end += 2;
                        if (opcode_memory_end > (uae_u8*)pc + 32) {
@@ -1776,6 +1791,12 @@ static void process_test(uae_u8 *p)
                }
                uae_u32 opcodeend = originalopcodeend;
                int extraccr = 0;
+               int validendsize = 0;
+               if (is_valid_test_addr_readwrite((uae_u32)opcode_memory_end + 2)) {
+                       validendsize = 2;
+               } else if (is_valid_test_addr_readwrite((uae_u32)opcode_memory_end)) {
+                       validendsize = 1;
+               }
 
                uae_u32 last_pc = opcode_memory_addr;
                uae_u32 last_fpiar = opcode_memory_addr;
@@ -1797,7 +1818,11 @@ static void process_test(uae_u8 *p)
                        for (int ccr = 0;  ccr < maxccr; ccr++) {
 
                                opcodeend = (opcodeend >> 16) | (opcodeend << 16);
-                               pl(opcode_memory_end, opcodeend);
+                               if (validendsize == 2) {
+                                       pl(opcode_memory_end, opcodeend);
+                               } else if (validendsize == 1) {
+                                       pw(opcode_memory_end, opcodeend >> 16);
+                               }
 
                                if (regs.branchtarget != 0xffffffff) {
                                        if (regs.branchtarget_mode == 1) {
@@ -1932,7 +1957,11 @@ static void process_test(uae_u8 *p)
 
                }
 
-               pl(opcode_memory_end, originalopcodeend);
+               if (validendsize == 2) {
+                       pl(opcode_memory_end, originalopcodeend);
+               } else if (validendsize == 1) {
+                       pw(opcode_memory_end, originalopcodeend >> 16);
+               }
 
                restoreahist();
 
index 5f9a32cc0f7c60fed53b6d2c3095b19b66800854..6bb92166dd090b89350bd87a4a9ba46042768eb1 100644 (file)
@@ -6906,6 +6906,7 @@ void exception3b (uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc)
 
 void exception2_setup(uaecptr addr, bool read, int size, uae_u32 fc)
 {
+       uae_u32 opcode = last_op_for_exception_3;
        last_addr_for_exception_3 = m68k_getpc() + bus_error_offset;
        last_fault_for_exception_3 = addr;
        last_writeaccess_for_exception_3 = read == 0;
@@ -6917,11 +6918,14 @@ void exception2_setup(uaecptr addr, bool read, int size, uae_u32 fc)
        cpu_bus_error = 0;
 
        if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible) {
-               if (generates_group1_exception(regs.ir)) {
+               if (generates_group1_exception(regs.ir) && !(opcode & 0x20000)) {
                        last_notinstruction_for_exception_3 = true;
                        fc = -1;
                }
-               last_op_for_exception_3 = regs.ir;
+               if (opcode & 0x10000)
+                       last_notinstruction_for_exception_3 = true;
+               if (!(opcode & 0x20000))
+                       last_op_for_exception_3 = regs.ir;
        }
 }
 
@@ -6942,30 +6946,24 @@ void exception2(uaecptr addr, bool read, int size, uae_u32 fc)
 
 void exception2_read(uae_u32 opcode, uaecptr addr, int size, int fc)
 {
-       exception2_setup(addr, true, size, fc);
        last_op_for_exception_3 = opcode;
-       if (opcode & 0x10000)
-               last_notinstruction_for_exception_3 = true;
+       exception2_setup(addr, true, size, fc);
        Exception(2);
 }
 
 void exception2_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc)
 {
-       exception2_setup(addr, false, size, fc);
        last_op_for_exception_3 = opcode;
-       if (opcode & 0x10000)
-               last_notinstruction_for_exception_3 = true;
+       exception2_setup(addr, false, size, fc);
        regs.write_buffer = val;
        Exception(2);
 }
 
 void exception2_fetch(uae_u32 opcode, uaecptr addr)
 {
-       exception2_setup(addr, true, 1, 2);
        last_op_for_exception_3 = opcode;
+       exception2_setup(addr, true, 1, 2);
        last_di_for_exception_3 = 0;
-       if (opcode & 0x10000)
-               last_notinstruction_for_exception_3 = true;
        Exception(2);
 }