From ed66dac15ca4d6135a3ef88f3a9c513d2857e670 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 22 Feb 2020 14:52:58 +0200 Subject: [PATCH] 68010 bus error updates. Read data bus errors fully supported. Write and prefetch to do. --- cputest.cpp | 87 +++++++++++++++++++++++++++++++++++++++--------- cputest/main.c | 4 +-- disasm.cpp | 2 +- gencpu.cpp | 74 ++++++++++++++++++++++++++++++++++------ include/newcpu.h | 1 + newcpu.cpp | 19 +++++++++-- 6 files changed, 156 insertions(+), 31 deletions(-) diff --git a/cputest.cpp b/cputest.cpp index e7da017b..bddf2d64 100644 --- a/cputest.cpp +++ b/cputest.cpp @@ -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; diff --git a/cputest/main.c b/cputest/main.c index 15615d8c..2d058702 100644 --- a/cputest/main.c +++ b/cputest/main.c @@ -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) diff --git a/disasm.cpp b/disasm.cpp index 77b994ec..2606af00 100644 --- a/disasm.cpp +++ b/disasm.cpp @@ -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 { diff --git a/gencpu.cpp b/gencpu.cpp index 9a2b8f81..571de5ae 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -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)) { diff --git a/include/newcpu.h b/include/newcpu.h index 14c03726..1849ce75 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -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); diff --git a/newcpu.cpp b/newcpu.cpp index fde7f7e1..6b1ec345 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -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); } -- 2.47.3