From 318bf2d9c581df43289d59fd209e260d961fcb41 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 19 Oct 2019 20:04:12 +0300 Subject: [PATCH] 68010 bus/address error support updates. --- cputest.cpp | 30 ++++++++++---------- gencpu.cpp | 71 +++++++++++++++++++++++++++++++++++++++-------- include/newcpu.h | 1 + newcpu.cpp | 13 +++++---- newcpu_common.cpp | 8 ++++-- 5 files changed, 88 insertions(+), 35 deletions(-) diff --git a/cputest.cpp b/cputest.cpp index 3878f636..fb27b6d2 100644 --- a/cputest.cpp +++ b/cputest.cpp @@ -114,7 +114,6 @@ static uaecptr test_exception_addr; static int test_exception_3_w; static int test_exception_3_fc; static int test_exception_3_size; -static int test_exception_3_value; static int test_exception_3_di; static int test_exception_opcode; @@ -138,7 +137,6 @@ static int high_memory_accessed; static int test_memory_accessed; static uae_u16 extra_or, extra_and; static uae_u32 cur_registers[MAX_REGISTERS]; -static uae_u32 test_last_read, test_last_write; struct uae_prefs currprefs; @@ -307,7 +305,7 @@ uae_u16 get_word_test_prefetch(int o) if (cpu_lvl < 2) o -= 2; regs.irc = get_iword_test(m68k_getpci() + o + 2); - test_last_read = regs.irc; + regs.read_buffer = regs.irc; return get_iword_test(m68k_getpci() + o); } @@ -339,7 +337,7 @@ void put_byte_test(uaecptr addr, uae_u32 v) ah->oldval = *p; ah->size = sz_byte; } - test_last_write = v; + regs.write_buffer = v; *p = v; } void put_word_test(uaecptr addr, uae_u32 v) @@ -365,7 +363,7 @@ void put_word_test(uaecptr addr, uae_u32 v) p[0] = v >> 8; p[1] = v & 0xff; } - test_last_write = v; + regs.write_buffer = v; } void put_long_test(uaecptr addr, uae_u32 v) { @@ -396,7 +394,7 @@ void put_long_test(uaecptr addr, uae_u32 v) p[2] = v >> 8; p[3] = v >> 0; } - test_last_write = v; + regs.write_buffer = v; } static void undo_memory(struct accesshistory *ahp, int *cntp) @@ -430,7 +428,7 @@ uae_u32 get_byte_test(uaecptr addr) { check_bus_error(addr, 0, regs.s ? 5 : 1); uae_u8 *p = get_addr(addr, 1, 0); - test_last_read = *p; + regs.read_buffer = *p; return *p; } uae_u32 get_word_test(uaecptr addr) @@ -443,7 +441,7 @@ uae_u32 get_word_test(uaecptr addr) uae_u8 *p = get_addr(addr, 2, 0); v = (p[0] << 8) | (p[1]); } - test_last_read = v; + regs.read_buffer = v; return v; } uae_u32 get_long_test(uaecptr addr) @@ -463,7 +461,7 @@ uae_u32 get_long_test(uaecptr addr) uae_u8 *p = get_addr(addr, 4, 0); v = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]); } - test_last_read = v; + regs.read_buffer = v; return v; } @@ -821,9 +819,9 @@ static void doexcstack(void) 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 + if (test_exception_opcode & 0x20000) + ssw &= 0x00ff; regs.mmu_fault_addr = test_exception_addr; - regs.mmu_effective_addr = test_exception_3_value; - regs.mmu_effective_addr = (test_last_read & 0xffff) | ((test_last_write & 0xffff) << 16); Exception_build_stack_frame(regs.instruction_pc, regs.pc, ssw, 3, 0x08); } else { Exception_build_stack_frame_common(regs.instruction_pc, regs.pc, 0, test_exception); @@ -885,7 +883,7 @@ uae_u32 REGPARAM2 op_illg(uae_u32 opcode) void exception2_fetch(uae_u32 opcode, uaecptr addr) { test_exception = 2; - test_exception_3_w = 0; + test_exception_3_w = 1; test_exception_addr = addr; test_exception_opcode = opcode; test_exception_3_fc = 2; @@ -914,7 +912,7 @@ 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; - test_exception_3_value = val; + regs.write_buffer = val; test_exception_3_di = 1; doexcstack(); } @@ -938,7 +936,7 @@ void exception3_write(uae_u32 opcode, uae_u32 addr, int size, uae_u32 val, int f test_exception_opcode = opcode; test_exception_3_fc = fc; test_exception_3_size = size; - test_exception_3_value = val; + regs.write_buffer = val; test_exception_3_di = 1; doexcstack(); } @@ -2201,8 +2199,8 @@ static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc, struct ins testing_active = 1; testing_active_opcode = opc; cpu_bus_error = 0; - test_last_read = regs.irc; - test_last_write = 0xf00d; + regs.read_buffer = regs.irc; + regs.write_buffer = 0xf00d; int cnt = feature_loop_mode * 2; if (multi_mode) diff --git a/gencpu.cpp b/gencpu.cpp index fc47470c..8a6706ec 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -1467,6 +1467,10 @@ static void check_bus_error(const char *name, int offset, int write, int size, c fc = 2; } + if (cpu_level == 1 && g_instr->mnemo == i_MVSR2 && !write) { + printf("\t\topcode |= 0x20000;\n"); // upper byte of SSW is zero -flag. + } + // 68010 bus/address error HB bit if (extra && cpu_level == 1) printf("\t\topcode |= 0x%x;\n", extra); @@ -2404,7 +2408,7 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char } // check possible address error (if 68000/010 and enabled) - if ((using_prefetch || using_ce) && using_exception_3 && getv != 0 && size != sz_byte && !movem) { + if ((using_prefetch || using_ce) && using_exception_3 && getv != 0 && getv != 3 && size != sz_byte && !movem) { int setapdiback = 0; int fcmodeflags = 0; int exp3rw = getv == 2; @@ -2414,9 +2418,16 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char if (cpu_level == 1) { if (bus_error_reg_add == 4) bus_error_reg_add = 0; + // 68010 CLR : pre and post are not added yet + if (g_instr->mnemo == i_CLR) { + if (mode == Aipi) + bus_error_reg_add = 0; + if (mode == Apdi) + bus_error_reg_add = 0; + } do_bus_error_fixes(name, 0); // x,-(an): an is modified - if (mode == Apdi && g_instr->size == sz_word) { + if (mode == Apdi && g_instr->size == sz_word && g_instr->mnemo != i_CLR) { printf("\t\tm68k_areg (regs, %s) = %sa;\n", reg, name); } } @@ -2444,6 +2455,9 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char // If MOVE from SR generates address error exception, // Change it to read because it does dummy read first. exp3rw = 0; + if (cpu_level == 1) { + printf("\t\topcode |= 0x20000;\n"); // upper byte of SSW is zero -flag. + } } if (setapdiback) { @@ -4246,12 +4260,35 @@ static void gen_opcode (unsigned int opcode) break; case i_CLR: next_level_000 (); - genamode (curi, curi->smode, "srcreg", curi->size, "src", cpu_level == 0 ? 1 : 2, 0, 0); - fill_prefetch_next (); - if (isreg (curi->smode) && curi->size == sz_long) - addcycles000 (2); - genflags (flag_logical, curi->size, "0", "", ""); - genastore_rev ("0", curi->smode, "srcreg", curi->size, "src"); + if (cpu_level == 0) { + genamode(curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0); + fill_prefetch_next(); + if (isreg(curi->smode) && curi->size == sz_long) + addcycles000(2); + genflags(flag_logical, curi->size, "0", "", ""); + genastore_rev("0", curi->smode, "srcreg", curi->size, "src"); + } else if (cpu_level == 1) { + genamode(curi, curi->smode, "srcreg", curi->size, "src", 3, 0, 0); + if (isreg(curi->smode) && curi->size == sz_long) + addcycles000(2); + if (!isreg(curi->smode) && using_exception_3 && (using_prefetch || using_ce)) { + printf("\tif(srca & 1) {\n"); + printf("\t\texception3_write(opcode, srca, 1, 0, 1);\n"); + printf("\t\tgoto %s;\n", endlabelstr); + printf("\t}\n"); + need_endlabel = 1; + } + genflags(flag_logical, curi->size, "0", "", ""); + genastore_rev("0", curi->smode, "srcreg", curi->size, "src"); + fill_prefetch_next(); + } else { + genamode(curi, curi->smode, "srcreg", curi->size, "src", 2, 0, 0); + fill_prefetch_next(); + if (isreg(curi->smode) && curi->size == sz_long) + addcycles000(2); + genflags(flag_logical, curi->size, "0", "", ""); + genastore_rev("0", curi->smode, "srcreg", curi->size, "src"); + } break; case i_NOT: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, GF_RMW); @@ -4539,13 +4576,13 @@ static void gen_opcode (unsigned int opcode) } break; case i_MVSR2: // MOVE FROM SR - genamode (curi, curi->smode, "srcreg", sz_word, "src", 2, 0, 0); + genamode (curi, curi->smode, "srcreg", sz_word, "src", cpu_level == 0 ? 2 : 3, 0, 0); if (isreg (curi->smode)) { fill_prefetch_next (); addcycles000 (2); } else { - // read first and ignore result - if (cpu_level <= 1 && curi->size == sz_word) { + // 68000: read first and ignore result + if (cpu_level == 0 && curi->size == sz_word) { printf("\t%s (srca);\n", srcw); check_bus_error("src", 0, 0, 1, NULL, 1); count_write++; @@ -4553,6 +4590,13 @@ static void gen_opcode (unsigned int opcode) fill_prefetch_next (); } printf ("\tMakeSR ();\n"); + if (!isreg(curi->smode) && cpu_level == 1 && using_exception_3 && (using_prefetch || using_ce)) { + printf("\tif(srca & 1) {\n"); + printf("\t\texception3_write(opcode, srca, 1, regs.sr, 1);\n"); + printf("\t\tgoto %s;\n", endlabelstr); + printf("\t}\n"); + need_endlabel = 1; + } // real write if (curi->size == sz_byte) genastore ("regs.sr & 0xff", curi->smode, "srcreg", sz_word, "src"); @@ -5092,7 +5136,10 @@ static void gen_opcode (unsigned int opcode) printf("\t%s(dsta + 2, nextpc);\n", dstw); check_bus_error("dst", 2, 1, 1, "nextpc", 1); } else { - printf("\t%s(m68k_areg(regs, 7), nextpc);\n", dstl); + 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"); diff --git a/include/newcpu.h b/include/newcpu.h index fac8105c..915e8def 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -182,6 +182,7 @@ struct regstruct uae_u32 chipset_latch_rw; uae_u32 chipset_latch_read; uae_u32 chipset_latch_write; + uae_u16 write_buffer, read_buffer; uaecptr usp, isp, msp; uae_u16 sr; diff --git a/newcpu.cpp b/newcpu.cpp index 5778764e..1cb56e24 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -75,8 +75,6 @@ static bool last_size_for_exception_3; static int last_fc_for_exception_3; /* Data (1) or instruction fetch (0) */ static int last_di_for_exception_3; -/* Value */ -static int last_value_for_exception_3; /* not instruction */ static bool last_notinstruction_for_exception_3; /* set when writing exception stack frame */ @@ -2523,15 +2521,17 @@ static void Exception_ce000 (int nr) ssw |= (last_op_for_exception_3 & 0x10000) ? 0x0400 : 0x0000; // HB ssw |= last_size_for_exception_3 == 0 ? 0x0200 : 0x0000; // BY ssw |= last_writeaccess_for_exception_3 ? 0 : 0x0100; // RW + if (last_op_for_exception_3 & 0x20000) + ssw &= 0x00ff; m68k_areg(regs, 7) -= 50; exception_in_exception = -1; frame_id = 8; x_put_word(m68k_areg(regs, 7) + 0, ssw); // ssw x_put_long(m68k_areg(regs, 7) + 2, last_addr_for_exception_3); // fault addr x_put_word(m68k_areg(regs, 7) + 6, 0); // unused - x_put_word(m68k_areg(regs, 7) + 8, last_value_for_exception_3); // data output buffer + x_put_word(m68k_areg(regs, 7) + 8, regs.write_buffer); // data output buffer x_put_word(m68k_areg(regs, 7) + 10, 0); // unused - x_put_word(m68k_areg(regs, 7) + 12, 0); // data input buffer + x_put_word(m68k_areg(regs, 7) + 12, regs.read_buffer); // data input buffer x_put_word(m68k_areg(regs, 7) + 14, 0); // unused x_put_word(m68k_areg(regs, 7) + 16, last_op_for_exception_3); // instruction input buffer x_put_word(m68k_areg(regs, 7) + 18, 0); // version @@ -2923,8 +2923,9 @@ static void Exception_normal (int nr) ssw |= (last_op_for_exception_3 & 0x10000) ? 0x0400 : 0x0000; // HB ssw |= last_size_for_exception_3 == 0 ? 0x0200 : 0x0000; // BY ssw |= last_writeaccess_for_exception_3 ? 0x0000 : 0x0100; // RW + if (last_op_for_exception_3 & 0x20000) + ssw &= 0x00ff; regs.mmu_fault_addr = last_addr_for_exception_3; - regs.mmu_effective_addr = last_value_for_exception_3; Exception_build_stack_frame(oldpc, currpc, ssw, nr, 0x08); used_exception_build_stack_frame = true; } @@ -6858,6 +6859,7 @@ void exception3_read(uae_u32 opcode, uaecptr addr, int size, int 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); + regs.write_buffer = val; } void exception3i (uae_u32 opcode, uaecptr addr) { @@ -6907,6 +6909,7 @@ void exception2_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int f { exception2_setup(addr, false, size, fc); last_op_for_exception_3 = opcode; + regs.write_buffer = val; Exception(2); } diff --git a/newcpu_common.cpp b/newcpu_common.cpp index b801929f..7f528433 100644 --- a/newcpu_common.cpp +++ b/newcpu_common.cpp @@ -1365,6 +1365,9 @@ void Exception_build_stack_frame(uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int x_put_long(m68k_areg(regs, 7), regs.mmu_effective_addr); break; case 0x8: // address error (68010) + { + uae_u16 in = regs.read_buffer; + uae_u16 out = regs.write_buffer; for (i = 0; i < 15; i++) { m68k_areg(regs, 7) -= 2; x_put_word(m68k_areg(regs, 7), 0); @@ -1376,11 +1379,11 @@ void Exception_build_stack_frame(uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int m68k_areg(regs, 7) -= 2; x_put_word(m68k_areg(regs, 7), 0); // unused m68k_areg(regs, 7) -= 2; - x_put_word(m68k_areg(regs, 7), regs.mmu_effective_addr); // data input buffer + x_put_word(m68k_areg(regs, 7), in); // data input buffer m68k_areg(regs, 7) -= 2; x_put_word(m68k_areg(regs, 7), 0); // unused m68k_areg(regs, 7) -= 2; - x_put_word(m68k_areg(regs, 7), regs.mmu_effective_addr >> 16); // data output buffer + x_put_word(m68k_areg(regs, 7), out); // data output buffer m68k_areg(regs, 7) -= 2; x_put_word(m68k_areg(regs, 7), 0); // unused m68k_areg(regs, 7) -= 4; @@ -1388,6 +1391,7 @@ void Exception_build_stack_frame(uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int m68k_areg(regs, 7) -= 2; x_put_word(m68k_areg(regs, 7), ssw); // ssw break; + } case 0x9: // coprocessor mid-instruction stack frame (68020, 68030) m68k_areg(regs, 7) -= 4; x_put_long(m68k_areg(regs, 7), regs.fp_ea); -- 2.47.3