]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
68010 bus error updates. Read data bus errors fully supported. Write and prefetch...
authorToni Wilen <twilen@winuae.net>
Sat, 22 Feb 2020 12:52:58 +0000 (14:52 +0200)
committerToni Wilen <twilen@winuae.net>
Sat, 22 Feb 2020 12:52:58 +0000 (14:52 +0200)
cputest.cpp
cputest/main.c
disasm.cpp
gencpu.cpp
include/newcpu.h
newcpu.cpp

index e7da017b1facfe0f755cafc3d9ead9d8d3c9be11..bddf2d6450b5a250a76ebf650ac62886c9faba97 100644 (file)
@@ -410,7 +410,8 @@ void put_byte_test(uaecptr addr, uae_u32 v)
                ah->size = sz_byte;
                ah->donotsave = false;
        }
-       regs.write_buffer = v;
+       regs.write_buffer &= 0xff00;
+       regs.write_buffer |= v & 0xff;
        *p = v;
        add_memory_cycles(1);
 }
@@ -511,7 +512,8 @@ uae_u32 get_byte_test(uaecptr addr)
        check_bus_error(addr, 0, regs.s ? 5 : 1);
        uae_u8 *p = get_addr(addr, 1, 0);
        read_buffer_prev = regs.read_buffer;
-       regs.read_buffer = *p;
+       regs.read_buffer &= 0xff00;
+       regs.read_buffer |= *p;
        add_memory_cycles(1);
        return *p;
 }
@@ -935,11 +937,12 @@ static void doexcstack2(void)
        } else if (cpu_lvl == 1) {
                if (test_exception == 2 || test_exception == 3) {
                        uae_u16 ssw = (sv ? 4 : 0) | test_exception_3_fc;
-                       ssw |= test_exception_3_di ? 0x0000 : 0x2000; // IF
+                       ssw |= test_exception_3_di > 0 ? 0x0000 : (test_exception_3_di < 0 ? (0x2000 | 0x1000) : 0x2000);
                        ssw |= (!test_exception_3_w && test_exception_3_di) ? 0x1000 : 0x000; // DF
                        ssw |= (test_exception_opcode & 0x10000) ? 0x0400 : 0x0000; // HB
                        ssw |= test_exception_3_size == 0 ? 0x0200 : 0x0000; // BY
                        ssw |= test_exception_3_w ? 0x0000 : 0x0100; // RW
+                       ssw |= (test_exception_opcode & 0x80000) ? 0x0800 : 0x0000; // RM
                        regs.mmu_fault_addr = test_exception_addr;
                        Exception_build_stack_frame(regs.instruction_pc, regs.pc, ssw, test_exception, 0x08);
                        SPCFLAG_DOTRACE = 0;
@@ -1020,12 +1023,16 @@ static void doexcstack(void)
        if (interrupt) {
                regs.intmask = original_exception - 24;
                regs.ir = original_exception;
-               flags |= 0x10000 | 0x20000;
+               if (cpu_lvl == 0) {
+                       flags |= 0x10000 | 0x20000;
+               } else {
+                       flags |= 0x20000;
+               }
        }
 
        // set I/N if original exception was group 1 exception.
        flags |= 0x20000;
-       if (g1) {
+       if (g1 && cpu_lvl == 0) {
                flags |= 0x10000;
        }
 
@@ -1074,7 +1081,7 @@ uae_u32 REGPARAM2 op_illg(uae_u32 opcode)
        return op_illg_1(opcode);
 }
 
-void exception2_fetch(uae_u32 opcode, int offset)
+static void exception2_fetch_common(uae_u32 opcode, int offset)
 {
        test_exception = 2;
        test_exception_3_w = 0;
@@ -1091,7 +1098,20 @@ void exception2_fetch(uae_u32 opcode, int offset)
                if (opcode & 0x10000)
                        test_exception_3_fc |= 8;
        }
+}
+
+void exception2_fetch(uae_u32 opcode, int offset)
+{
+       exception2_fetch_common(opcode, offset);
+       doexcstack();
+}
 
+void exception2_fetch_opcode(uae_u32 opcode, int offset)
+{
+       exception2_fetch_common(opcode, offset);
+       if (currprefs.cpu_model == 68010) {
+               test_exception_3_di = -1;
+       }
        doexcstack();
 }
 
@@ -1126,7 +1146,12 @@ void exception2_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int f
        test_exception_opcode = opcode;
        test_exception_3_fc = fc;
        test_exception_3_size = size;
-       regs.write_buffer = val;
+       if (size == sz_byte) {
+               regs.write_buffer &= 0xff00;
+               regs.write_buffer |= val & 0xff;
+       } else {
+               regs.write_buffer = val;
+       }
        test_exception_3_di = 1;
 
        if (currprefs.cpu_model == 68000) {
@@ -2465,8 +2490,18 @@ static int create_ea_exact(uae_u16 *opcodep, uaecptr pc, int mode, int reg, stru
        {
                bool vgot = false;
                uae_u16 v;
-               if (srcdst && dp->mnemo != i_DBcc)
-                       return -2;
+               if (dp->mnemo == i_MOVES) {
+                       v = imm16_cnt << 11;
+                       v |= rand16() & 0x07ff;
+                       imm16_cnt++;
+                       *isconstant = 32;
+                       put_word_test(pc, v);
+                       return 2;
+               }
+               if (srcdst) {
+                       if (dp->mnemo != i_DBcc)
+                               return -2;
+               }
                if (dp->mnemo == i_DBcc || dp->mnemo == i_BSR || dp->mnemo == i_Bcc) {
                        uae_u32 pct = pc + 2 - 2;
                        if (target <= pct + 0x7ffe && target >= pct - 0x8000) {
@@ -2829,8 +2864,8 @@ 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 == 0xd196 
-               //&& opw1 == 0x64fc
+       if (opc == 0x199c 
+               && opw1 == 0x2808
                //&& opw2 == 0x4afc
                )
                printf("");
@@ -3602,7 +3637,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                regs.regs[15] = target_usp_address;
                                        }
 
-                                       if (opc == 0x4a53)
+                                       if (opc == 0x0e51)
                                                printf("");
                                        if (subtest_count >= 700)
                                                printf("");
@@ -3698,6 +3733,15 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                        pc += o;
                                                }
 
+                                               if (dp->mnemo == i_MOVES) {
+                                                       // MOVES is stupid
+                                                       if (!(get_word_test(pc - 2) & 0x0800)) {
+                                                               uae_u32 vv = dstea;
+                                                               dstea = srcea;
+                                                               srcea = vv;
+                                                       }
+                                               }
+
                                                // requested target address but no EA? skip
                                                if (target_address != 0xffffffff && isbranchinst(dp) != 2 && (feature_usp < 3 || !stackinst(dp))) {
                                                        if (srcea != target_address && dstea != target_address) {
@@ -3821,12 +3865,16 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        out_of_test_space = false;
 
                                        if ((dflags & 1) && target_ea[0] != 0xffffffff && srcaddr != 0xffffffff && srcaddr != target_ea[0]) {
-                                               wprintf(_T(" Source address mismatch %08x <> %08x\n"), target_ea[0], srcaddr);
+                                               if (verbose) {
+                                                       wprintf(_T(" Source address mismatch %08x <> %08x\n"), target_ea[0], srcaddr);
+                                               }
                                                memcpy(opcode_memory, oldcodebytes, sizeof(oldcodebytes));
                                                continue;
                                        }
                                        if ((dflags & 2) && target_ea[1] != 0xffffffff && dstaddr != target_ea[1]) {
-                                               wprintf(_T(" Destination address mismatch %08x <> %08x\n"), target_ea[1], dstaddr);
+                                               if (verbose) {
+                                                       wprintf(_T(" Destination address mismatch %08x <> %08x\n"), target_ea[1], dstaddr);
+                                               }
                                                memcpy(opcode_memory, oldcodebytes, sizeof(oldcodebytes));
                                                continue;
                                        }
@@ -3834,11 +3882,17 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        if ((dflags & 1) && target_ea[0] == 0xffffffff && (srcaddr & addressing_mask) >= safe_memory_start - 4 && (srcaddr & addressing_mask) < safe_memory_end + 4) {
                                                // random generated EA must never be inside safe memory
                                                memcpy(opcode_memory, oldcodebytes, sizeof(oldcodebytes));
+                                               if (verbose) {
+                                                       wprintf(_T("\n"));
+                                               }
                                                continue;
                                        }
                                        if ((dflags & 2) && target_ea[1] == 0xffffffff && (dstaddr & addressing_mask) >= safe_memory_start - 4 && (dstaddr & addressing_mask) < safe_memory_end + 4) {
                                                // random generated EA must never be inside safe memory
                                                memcpy(opcode_memory, oldcodebytes, sizeof(oldcodebytes));
+                                               if (verbose) {
+                                                       wprintf(_T("\n"));
+                                               }
                                                continue;
                                        }
 
@@ -4179,6 +4233,9 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                                if (target_ea[1] != 0xffffffff && (target_ea[1] & 1) && target_ea[0] == 0xffffffff && !test_exception_3_w) {
                                                                        skipped = 1;
                                                                }
+                                                               if (safe_memory_mode) {
+                                                                       skipped = 1;
+                                                               }                                       
                                                        }
 
                                                        if (feature_usp == 2) {
@@ -4850,7 +4907,7 @@ static int test(struct ini_data *ini, const TCHAR *sections, const TCHAR *testna
                        if (i == 2) {
                                target_ea_opcode_max = cnt;
                                if (cnt > 0) {
-                                       safe_memory_mode = 7;
+                                       safe_memory_mode = 1 | 4;
                                }
                        } else if (i) {
                                target_ea_dst_max = cnt;
index 15615d8c6d477f7fae0e9a8091c3fd660f0c446d..2d058702076551e1ccf50442d2ba99b75cdf20f5 100644 (file)
@@ -648,8 +648,8 @@ static uae_u8 *load_file(const char *path, const char *file, uae_u8 *p, int *siz
                        p += size2;
                        size -= size2;
                }
-               if ((safe_memory_mode & 1)) {
-                       // if reading cause bus error: skip it
+               if ((safe_memory_mode & 2) && (safe_memory_mode & (1 | 4))) {
+                       // if writing causes bus error and other bit(s) are also active: skip it
                        if (size > 0 && p >= safe_memory_start && p < safe_memory_end) {
                                int size2 = safe_memory_end - p;
                                if (size2 > size)
index 77b994ec3e3f72ea4c0b49e1fc3f989056e8e1bb..2606af009929d37159e80a0fecdb6fd69a6c06d4 100644 (file)
@@ -1777,7 +1777,7 @@ uae_u32 m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int
                        TCHAR *p;
                        pc += 2;
                        if (!(extra & 0x0800)) {
-                               pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, &actualea_src, safemode);
+                               pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &deaddr2, &actualea_dst, safemode);
                                p = instrname + _tcslen(instrname);
                                _stprintf(p, _T(",%c%d"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
                        } else {
index 9a2b8f8148bf12ea94abf22168e06643fa6dcb01..571de5aeab6832e447e690207bc0f384b60e123a 100644 (file)
@@ -776,6 +776,17 @@ static void check_bus_error_ins(int offset)
        sprintf(bus_error_text, "exception2_fetch(%s, %d);\n", opcode, offset);
 }
 
+static void check_bus_error_ins_opcode(int offset)
+{
+       const char *opcode;
+       if (bus_error_specials) {
+               opcode = "0";
+       } else {
+               opcode = "opcode";
+       }
+       sprintf(bus_error_text, "exception2_fetch_opcode(%s, %d);\n", opcode, offset);
+}
+
 static void check_prefetch_bus_error(int offset, int secondprefetchmode)
 {
        if (!using_bus_error || using_mmu)
@@ -791,7 +802,7 @@ static void check_prefetch_bus_error(int offset, int secondprefetchmode)
                        bus_error_specials = 1;
                }
        }
-       check_bus_error_ins(offset);
+       check_bus_error_ins_opcode(offset);
        do_instruction_buserror();
 }
 
@@ -2161,7 +2172,45 @@ static void check_bus_error(const char *name, int offset, int write, int size, c
 
                                //out("m68k_areg(regs, %s) = %sa;\n", bus_error_reg, name);
                        }
-
+                       if (g_instr->mnemo == i_MOVES) {
+                               out("regs.irc = extra;\n");
+                               if (!write) {
+                                       out("regs.write_buffer = extra;\n");
+                               }
+                               if (g_instr->size == sz_long) {
+                                       // moves.l an,-(an)/(an)+ (same registers): write buffer contains modified value.
+                                       if (g_instr->dmode == Aipi || g_instr->dmode == Apdi) {
+                                               out("if (dstreg + 8 == ((extra >> 12) & 15)) {\n");
+                                               out("src += %d;\n", g_instr->dmode == Aipi ? 2 : -2);
+                                               out("}\n");
+                                       }
+                                       if (g_instr->dmode == Apdi) {
+                                               if (!write) {
+                                                       out("m68k_areg(regs, dstreg) = srca;\n");
+                                               }
+                                       } else if (g_instr->dmode == Aipi) {
+                                               out("m68k_areg(regs, dstreg) += 4;\n");
+                                       }
+                               }
+                       } else if (g_instr->mnemo == i_TAS) {
+                               if (!write) {
+                                       out("regs.read_buffer = regs.irc & 0xff00;\n");
+                                       out("regs.read_buffer |= 0x80;\n");
+                               }
+                               out("opcode |= 0x80000;\n");
+                       } else if (g_instr->mnemo == i_CLR) {
+                               if (g_instr->smode < Ad16) {
+                                       out("regflags.cznv = oldflags;\n");
+                               }
+                               // (an)+ and -(an) is done later
+                               if (g_instr->smode == Aipi || g_instr->smode == Apdi) {
+                                       if (g_instr->size == sz_byte) {
+                                               out("m68k_areg(regs, srcreg) %c= areg_byteinc[srcreg];\n", g_instr->smode == Aipi ? '-' : '+');
+                                       } else {
+                                               out("m68k_areg(regs, srcreg) %c= %d;\n", g_instr->smode == Aipi ? '-' : '+', 1 << g_instr->size);
+                                       }
+                               }
+                       }
                }
 
                // write causing bus error and trace: set I/N
@@ -2174,10 +2223,6 @@ static void check_bus_error(const char *name, int offset, int write, int size, c
                        out("if (regs.t1) opcode |= 0x10000;\n"); // I/N set
                }
 
-               //if (cpu_level == 0 && write) {
-               //      out("opcode = regs.irc;\n");
-               //}
-
                if (write) {
                        out("exception2_write(opcode, %sa + %d, %d, %s, %d);\n",
                                name, offset, size, writevar,
@@ -3916,7 +3961,7 @@ static void genastore_rev_prefetch(const char *from, amodes mode, const char *re
 }
 static void genastore_fc (const char *from, amodes mode, const char *reg, wordsizes size, const char *to)
 {
-       genastore_2 (from, mode, reg, size, to, 1, GF_FC);
+       genastore_2(from, mode, reg, size, to, 0, GF_FC);
 }
 
 static void movem_mmu060 (const char *code, int size, bool put, bool aipi, bool apdi)
@@ -4259,7 +4304,10 @@ static void genmovemel_ce(uae_u16 opcode)
                out("uae_u32 v = (%s(srca) << 16) | (m68k_dreg(regs, movem_index1[dmask]) & 0xffff);\n", srcw);
                addcycles000_nonce(4);
                check_bus_error("src", 0, 0, 1, NULL, 1);
-               out("m68k_dreg(regs, movem_index1[dmask]) = v;\n");
+               if (cpu_level == 0) {
+                       // 68010 does not do partial updates
+                       out("m68k_dreg(regs, movem_index1[dmask]) = v;\n");
+               }
                out("v &= 0xffff0000;\n");
                out("v |= %s(srca + 2); \n", srcw);
                addcycles000_nonce(4);
@@ -4272,7 +4320,9 @@ static void genmovemel_ce(uae_u16 opcode)
                out("uae_u32 v = (%s(srca) << 16) | (m68k_areg(regs, movem_index1[amask]) & 0xffff);\n", srcw);
                addcycles000_nonce(4);
                check_bus_error("src", 0, 0, 1, NULL, 1);
-               out("m68k_areg(regs, movem_index1[amask]) = v;\n");
+               if (cpu_level == 0) {
+                       out("m68k_areg(regs, movem_index1[amask]) = v;\n");
+               }
                out("v &= 0xffff0000;\n");
                out("v |= %s(srca + 2);\n", srcw);
                addcycles000_nonce(4);
@@ -5634,6 +5684,7 @@ static void gen_opcode (unsigned int opcode)
                                genastore_rev("0", curi->smode, "srcreg", curi->size, "src");
                        }
                } else if (cpu_level == 1) {
+                       out("uae_u16 oldflags = regflags.cznv;\n");
                        genamode(curi, curi->smode, "srcreg", curi->size, "src", 3, 0, GF_CLR68010);
                        if (isreg(curi->smode) && curi->size == sz_long) {
                                addcycles000(2);
@@ -5665,7 +5716,7 @@ static void gen_opcode (unsigned int opcode)
                                write_return_cycles(0);
                                out("}\n");
                        }
-                       fill_prefetch_next();
+                       fill_prefetch_next_after(0, "CLEAR_CZNV();\nSET_ZFLG(1);\n");
                        genflags(flag_logical, curi->size, "0", "", "");
                        genastore_rev("0", curi->smode, "srcreg", curi->size, "src");
                } else {
@@ -8055,6 +8106,7 @@ bccl_not68020:
                        addcycles000(4);
                        out("if (extra & 0x800) {\n");
                        {
+                               // reg -> memory
                                int old_m68k_pc_offset = m68k_pc_offset;
                                int old_m68k_pc_total = m68k_pc_total;
                                push_ins_cnt();
@@ -8076,6 +8128,7 @@ bccl_not68020:
                        }
                        out("} else {\n");
                        {
+                               // memory -> reg
                                genamode(curi, curi->dmode, "dstreg", curi->size, "src", 1, 0, GF_FC | (cpu_level == 1 ? GF_NOFETCH : 0));
                                out("if (extra & 0x8000) {\n");
                                switch (curi->size) {
@@ -8292,6 +8345,7 @@ bccl_not68020:
                        } else {
                                genamode(curi, curi->smode, "srcreg", curi->size, "src", 2, 0, GF_LRMW | GF_NOFETCH);
                                out("uae_u8 src = %s(srca);\n", srcb);
+                               check_bus_error("src", 0, 0, 0, "src", 1);
                        }
                        genflags(flag_logical, curi->size, "src", "", "");
                        if (!isreg(curi->smode)) {
index 14c037269f1e660c2d365dba3a5bf8b3c0c8c04a..1849ce750a49fa069d308546efe6adf1c84d5632 100644 (file)
@@ -740,6 +740,7 @@ extern void exception2 (uaecptr addr, bool read, int size, uae_u32 fc);
 extern void exception2_setup(uae_u32 opcode, uaecptr addr, bool read, int size, uae_u32 fc);
 extern void exception2_read(uae_u32 opcode, uaecptr addr, int size, int fc);
 extern void exception2_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc);
+extern void exception2_fetch_opcode(uae_u32 opcode, int offset);
 extern void exception2_fetch(uae_u32 opcode, int offset);
 extern void m68k_reset (void);
 extern void cpureset (void);
index fde7f7e1b395654e28976d4d9c0c814ee821b86a..6b1ec3453f3ba066f32f21678900d05fc57a56af 100644 (file)
@@ -2599,7 +2599,7 @@ static void Exception_ce000 (int nr)
                        uae_u16 in = regs.read_buffer;
                        uae_u16 out = regs.write_buffer;
                        uae_u16 ssw = (sv ? 4 : 0) | last_fc_for_exception_3;
-                       ssw |= last_di_for_exception_3 ? 0x0000 : 0x2000; // IF
+                       ssw |= last_di_for_exception_3 > 0 ? 0x0000 : (last_di_for_exception_3 < 0 ? (0x2000 | 0x1000) : 0x2000);
                        ssw |= (!last_writeaccess_for_exception_3 && last_di_for_exception_3) ? 0x1000 : 0x000; // DF
                        ssw |= (last_op_for_exception_3 & 0x10000) ? 0x0400 : 0x0000; // HB
                        ssw |= last_size_for_exception_3 == 0 ? 0x0200 : 0x0000; // BY
@@ -3080,7 +3080,7 @@ static void Exception_normal (int nr)
                        } else {
                                // 68010 bus/address error (partially implemented only)
                                uae_u16 ssw = (sv ? 4 : 0) | last_fc_for_exception_3;
-                               ssw |= last_di_for_exception_3 ? 0x0000 : 0x2000; // IF
+                               ssw |= last_di_for_exception_3 > 0 ? 0x0000 : (last_di_for_exception_3 < 0 ? (0x2000 | 0x1000) : 0x2000);
                                ssw |= (!last_writeaccess_for_exception_3 && last_di_for_exception_3) ? 0x1000 : 0x000; // DF
                                ssw |= (last_op_for_exception_3 & 0x10000) ? 0x0400 : 0x0000; // HB
                                ssw |= last_size_for_exception_3 == 0 ? 0x0200 : 0x0000; // BY
@@ -7268,7 +7268,7 @@ void exception2_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int f
        Exception(2);
 }
 
-void exception2_fetch(uae_u32 opcode, int offset)
+static void exception2_fetch_common(uae_u32 opcode, int offset)
 {
        last_fault_for_exception_3 = m68k_getpc() + offset;
        last_writeaccess_for_exception_3 = 0;
@@ -7286,7 +7286,20 @@ void exception2_fetch(uae_u32 opcode, int offset)
                if (opcode & 0x10000)
                        last_fc_for_exception_3 |= 8;
        }
+}
+
+void exception2_fetch_opcode(uae_u32 opcode, int offset)
+{
+       exception2_fetch_common(opcode, offset);
+       if (currprefs.cpu_model == 68010) {
+               last_di_for_exception_3 = -1;
+       }
+       Exception(2);
+}
 
+void exception2_fetch(uae_u32 opcode, int offset)
+{
+       exception2_fetch_common(opcode, offset);
        Exception(2);
 }