From 8e67ce134b6c5f284520b18bf97fe0f9ecf8ddde Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Wed, 19 Feb 2020 22:09:08 +0200 Subject: [PATCH] Remaining 68010 address error tester errors fixed. --- cputest.cpp | 48 ++++++++++++++++-- gencpu.cpp | 123 +++++++++++++++++++++++++++++--------------- include/newcpu.h | 6 ++- newcpu.cpp | 127 +++++++++++++++++++++++++++++++++++----------- newcpu_common.cpp | 12 +++-- 5 files changed, 233 insertions(+), 83 deletions(-) diff --git a/cputest.cpp b/cputest.cpp index 0846d9eb..e7da017b 100644 --- a/cputest.cpp +++ b/cputest.cpp @@ -1191,9 +1191,36 @@ void exception3_write(uae_u32 opcode, uae_u32 addr, int size, uae_u32 val, int f doexcstack(); } +// load to irc only +void exception3_read_prefetch_only(uae_u32 opcode, uae_u32 addr) +{ + if (cpu_lvl == 1) { + uae_u16 prev = regs.read_buffer; + get_word_test(addr & ~1); + regs.irc = regs.read_buffer; + regs.read_buffer = prev; + } else { + add_memory_cycles(1); + } + + test_exception = 3; + test_exception_3_w = 0; + test_exception_addr = addr; + test_exception_opcode = opcode; + test_exception_3_fc = 2; + test_exception_3_size = sz_word; + test_exception_3_di = 0; + + doexcstack(); +} + void exception3_read_prefetch(uae_u32 opcode, uae_u32 addr) { - add_memory_cycles(1); + if (cpu_lvl == 1) { + get_word_test(addr & ~1); + } else { + add_memory_cycles(1); + } test_exception = 3; test_exception_3_w = 0; @@ -1206,13 +1233,24 @@ void exception3_read_prefetch(uae_u32 opcode, uae_u32 addr) doexcstack(); } -void exception3_read_opcode(uae_u32 opcode, uae_u32 addr, int size, int fc) +void exception3_read_access2(uae_u32 opcode, uae_u32 addr, int size, int fc) { - add_memory_cycles(1); + get_word_test(addr & ~1); + get_word_test(addr & ~1); + exception3_read(opcode, addr, size, fc); +} + +void exception3_read_access(uae_u32 opcode, uae_u32 addr, int size, int fc) +{ + if (cpu_lvl == 1) { + get_word_test(addr & ~1); + } else { + add_memory_cycles(1); + } exception3_read(opcode, addr, size, fc); } -void exception3_write_opcode(uae_u32 opcode, uae_u32 addr, int size, uae_u32 val, int fc) +void exception3_write_access(uae_u32 opcode, uae_u32 addr, int size, uae_u32 val, int fc) { add_memory_cycles(1); exception3_write(opcode, addr, size, val, fc); @@ -2819,7 +2857,7 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp) testing_active_opcode = opc; hardware_bus_error = 0; hardware_bus_error_fake = 0; - read_buffer_prev = regs.ir; + read_buffer_prev = regs.irc; regs.read_buffer = regs.irc; regs.write_buffer = 0xf00d; exception_extra_frame_size = 0; diff --git a/gencpu.cpp b/gencpu.cpp index c4b3e1b9..9a2b8f81 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -2761,6 +2761,8 @@ static void move_68010_address_error(int size, int *setapdi, int *fcmodeflags) if (size == sz_word) { // Word MOVE is relatively simple int set_ccr = 0; + int reset_ccr = 0; + *setapdi = 1; switch (smode) { case Dreg: @@ -2768,6 +2770,8 @@ static void move_68010_address_error(int size, int *setapdi, int *fcmodeflags) case imm: if (dmode == Apdi || dmode == Ad16 || dmode == Ad8r || dmode == absw || dmode == absl) set_ccr = 1; + else + reset_ccr = 1; break; case Aind: case Aipi: @@ -2787,6 +2791,9 @@ static void move_68010_address_error(int size, int *setapdi, int *fcmodeflags) } else if (dmode == absl && smode >= Aind && smode < imm) { out("regs.irc = dsta >> 16;\n"); } + if (reset_ccr) { + out("regflags.cznv = oldflags;\n"); + } if (set_ccr) { out("ccr_68000_word_move_ae_normal((uae_s16)(src));\n"); } @@ -2795,6 +2802,11 @@ static void move_68010_address_error(int size, int *setapdi, int *fcmodeflags) int set_ccr = 0; int set_high_word = 0; int set_low_word = 0; + if (dmode == Apdi) { + *setapdi = -4; + } else { + *setapdi = 1; + } switch (smode) { case Dreg: @@ -2833,10 +2845,7 @@ static void move_68010_address_error(int size, int *setapdi, int *fcmodeflags) break; } - if (dmode == Apdi) { - dummy_prefetch(NULL, NULL); - *setapdi = 0; - } else if (dmode == absl && smode >= Aind && smode < imm) { + if (dmode == absl && smode >= Aind && smode < imm) { out("regs.irc = dsta >> 16;\n"); } @@ -2886,6 +2895,28 @@ static void check_address_error(const char *name, int mode, const char *reg, in } else { do_bus_error_fixes(name, 0, getv == 2); } + if (g_instr->mnemo == i_MOVES) { + // MOVES has strange behavior + out("regs.irc = extra;\n"); + if (!exp3rw) { + out("regs.write_buffer = extra;\n"); + } else { + // moves.w an,-(an)/(an)+ (same registers): write buffer contains modified value. + if (mode == Aipi || mode == Apdi) { + out("if (dstreg + 8 == ((extra >> 12) & 15)) {\n"); + out("src += %d;\n", mode == Aipi ? 2 : -2); + out("}\n"); + } + } + if (size == sz_long) { + if (mode == Aipi) { + out("m68k_areg(regs, dstreg) += 4;\n"); + } else if (mode == Apdi) { + setapdiback = 1; + } + } + } + // x,-(an): an is modified (MOVE to CCR counts as word sized) if (mode == Apdi && (g_instr->size == sz_word || g_instr->size == i_MV2SR) && g_instr->mnemo != i_CLR) { out("m68k_areg(regs, %s) = %sa;\n", reg, name); @@ -2917,6 +2948,9 @@ static void check_address_error(const char *name, int mode, const char *reg, in } else { move_68010_address_error(size, &setapdiback, &fcmodeflags); } + if (mode != Apdi && mode != Aipi) { + setapdiback = 0; + } } } else if (g_instr->mnemo == i_MVSR2) { // If MOVE from SR generates address error exception, @@ -2931,8 +2965,13 @@ static void check_address_error(const char *name, int mode, const char *reg, in setapdiback = 0; } + // can be used for both Apdi and Aipi if (setapdiback) { - out("m68k_areg(regs, %s) = %sa;\n", reg, name); + if (setapdiback > 0) { + out("m68k_areg(regs, %s) = %sa;\n", reg, name); + } else { + out("m68k_areg(regs, %s) = %sa + %d;\n", reg, name, -setapdiback); + } } // MOVE.L EA,-(An) causing address error: stacked value is original An - 2, not An - 4. @@ -2941,16 +2980,24 @@ static void check_address_error(const char *name, int mode, const char *reg, in if (exp3rw) { const char *shift = (size == sz_long && !(flags & GF_REVERSE)) ? " >> 16" : ""; - out("exception3_write_opcode(opcode, %sa, %d, %s%s, %d);\n", + out("exception3_write_access(opcode, %sa, %d, %s%s, %d);\n", name, size, g_srcname, shift, // PC-relative: FC=2 (getv == 1 && (g_instr->smode == PC16 || g_instr->smode == PC8r) ? 2 : 1) | fcmodeflags); } else { - out("exception3_read_opcode(opcode, %sa, %d, %d);\n", - name, size, - // PC-relative: FC=2 - (getv == 1 && (g_instr->smode == PC16 || g_instr->smode == PC8r) ? 2 : 1) | fcmodeflags); + // 68010 address error: if addressing mode is (An), (An)+ or -(An) and byte or word: CPU does extra read access! + if (cpu_level == 1 && (g_instr->smode == Aind || g_instr->smode == Aipi || g_instr->smode == Apdi) && g_instr->size < sz_long) { + out("exception3_read_access2(opcode, %sa, %d, %d);\n", + name, size, + // PC-relative: FC=2 + (getv == 1 && (g_instr->smode == PC16 || g_instr->smode == PC8r) ? 2 : 1) | fcmodeflags); + } else { + out("exception3_read_access(opcode, %sa, %d, %d);\n", + name, size, + // PC-relative: FC=2 + (getv == 1 && (g_instr->smode == PC16 || g_instr->smode == PC8r) ? 2 : 1) | fcmodeflags); + } } write_return_cycles_noadd(0); @@ -4120,11 +4167,11 @@ static void movem_ex3(int write) out("uaecptr srcav = srca;\n"); } if (write) { - out("exception3_write_opcode(opcode, srca, %d, srcav, %d);\n", + out("exception3_write_access(opcode, srca, %d, srcav, %d);\n", g_instr->size, (g_instr->dmode == PC16 || g_instr->dmode == PC8r) ? 2 : 1); } else { - out("exception3_read_opcode(opcode, srca, %d, %d);\n", + out("exception3_read_access(opcode, srca, %d, %d);\n", g_instr->size, (g_instr->dmode == PC16 || g_instr->dmode == PC8r) ? 2 : 1); } @@ -5976,8 +6023,9 @@ static void gen_opcode (unsigned int opcode) genamode(curi, curi->dmode, "dstreg", curi->size, "dst", 2, 0, flags | GF_NOEXC3); - if (curi->mnemo == i_MOVEA && curi->size == sz_word) + if (curi->mnemo == i_MOVEA && curi->size == sz_word) { out("src = (uae_s32)(uae_s16)src;\n"); + } if (curi->dmode == Apdi) { // -(an) decrease is not done if bus error @@ -6012,7 +6060,10 @@ static void gen_opcode (unsigned int opcode) int storeflags = flags & (GF_REVERSE | GF_APDI); if (curi->mnemo == i_MOVE) { - if (curi->size == sz_long && cpu_level <= 1 && (using_prefetch || using_ce) && curi->dmode >= Aind) { + if (cpu_level == 1 && (isreg(curi->smode) || curi->smode == imm)) { + out("uae_u16 oldflags = regflags.cznv;\n"); + } + if (curi->size == sz_long && (using_prefetch || using_ce) && curi->dmode >= Aind) { // to support bus error exception correct flags, flags needs to be set // after first word has been written. storeflags |= GF_SECONDWORDSETFLAGS; @@ -6270,7 +6321,7 @@ static void gen_opcode (unsigned int opcode) next_level_000(); if (cpu_level <= 1 && using_exception_3) { out("if (m68k_areg(regs, 7) & 1) {\n"); - out("exception3_read_opcode(opcode, m68k_areg(regs, 7), 1, 1);\n"); + out("exception3_read_access(opcode, m68k_areg(regs, 7), 1, 1);\n"); write_return_cycles_noadd(0); out("}\n"); } @@ -6296,7 +6347,7 @@ static void gen_opcode (unsigned int opcode) out("regs.sr = sr;\n"); makefromsr(); out("if (pc & 1) {\n"); - out("exception3_read_opcode(opcode | 0x20000, pc, 1, 2);\n"); + out("exception3_read_access(opcode | 0x20000, pc, 1, 2);\n"); write_return_cycles(0); out("}\n"); setpc ("pc"); @@ -6345,8 +6396,7 @@ static void gen_opcode (unsigned int opcode) out("regs.sr = sr;\n"); makefromsr(); out("if (pc & 1) {\n"); - dummy_prefetch("pc", "oldpc"); - out("exception3_read_prefetch(opcode, pc);\n"); + out("exception3_read_prefetch_only(opcode, pc);\n"); write_return_cycles(0); out("}\n"); out("newsr = sr; newpc = pc;\n"); @@ -6476,7 +6526,7 @@ static void gen_opcode (unsigned int opcode) if (cpu_level >= 4) { out("m68k_areg(regs, 7) -= 4 + offs;\n"); } - out("exception3_read_prefetch(opcode, pc);\n"); + out("exception3_read_prefetch_only(opcode, pc);\n"); write_return_cycles(0); out("}\n"); setpc ("pc"); @@ -6524,7 +6574,7 @@ static void gen_opcode (unsigned int opcode) out("if (olda & 1) {\n"); out("m68k_areg(regs, 7) += 4;\n"); out("m68k_areg(regs, srcreg) = olda;\n"); - out("exception3_write_opcode(opcode, olda, sz_word, src >> 16, 1);\n"); + out("exception3_write_access(opcode, olda, sz_word, src >> 16, 1);\n"); write_return_cycles(0); out("}\n"); } @@ -6556,7 +6606,7 @@ static void gen_opcode (unsigned int opcode) out("uaecptr pc = %s;\n", getpc); if (cpu_level <= 1 && using_exception_3) { out("if (m68k_areg(regs, 7) & 1) {\n"); - out("exception3_read_opcode(opcode, m68k_areg(regs, 7), 1, 1);\n"); + out("exception3_read_access(opcode, m68k_areg(regs, 7), 1, 1);\n"); write_return_cycles(0); out("}\n"); } @@ -6598,14 +6648,11 @@ static void gen_opcode (unsigned int opcode) } out("if (%s & 1) {\n", getpc); out("uaecptr faultpc = %s;\n", getpc); - if (cpu_level == 1) { - dummy_prefetch(NULL, NULL); - } setpc("pc"); if (cpu_level >= 4) { out("m68k_areg(regs, 7) -= 4;\n"); } - out("exception3_read_prefetch(opcode, faultpc);\n"); + out("exception3_read_prefetch_only(opcode, faultpc);\n"); write_return_cycles(0); out("}\n"); clear_m68k_offset(); @@ -6666,7 +6713,7 @@ static void gen_opcode (unsigned int opcode) case i_RTR: if (cpu_level <= 1 && using_exception_3) { out("if (m68k_areg(regs, 7) & 1) {\n"); - out("exception3_read_opcode(opcode, m68k_areg(regs, 7), 1, 1);\n"); + out("exception3_read_access(opcode, m68k_areg(regs, 7), 1, 1);\n"); write_return_cycles(0); out("}\n"); } @@ -6688,11 +6735,8 @@ static void gen_opcode (unsigned int opcode) if (cpu_level < 4) { out("if (%s & 1) {\n", getpc); out("uaecptr faultpc = %s;\n", getpc); - if (cpu_level == 1) { - dummy_prefetch(NULL, NULL); - } setpc("oldpc"); - out("exception3_read_prefetch(opcode, faultpc);\n"); + out("exception3_read_prefetch_only(opcode, faultpc);\n"); write_return_cycles(0); out("}\n"); } @@ -6724,7 +6768,7 @@ static void gen_opcode (unsigned int opcode) addcycles000_onlyce(6); addcycles000_nonce(6); } - out("exception3_read_prefetch(opcode, srca);\n"); + out("exception3_read_prefetch_only(opcode, srca);\n"); write_return_cycles_noadd(0); out("}\n"); pop_ins_cnt(); @@ -6757,7 +6801,7 @@ static void gen_opcode (unsigned int opcode) out("m68k_areg(regs, 7) -= 4;\n"); if (using_exception_3 && cpu_level <= 1) { out("if (m68k_areg(regs, 7) & 1) {\n"); - out("exception3_write_opcode(opcode, m68k_areg(regs, 7), 1, m68k_areg(regs, 7) >> 16, 1);\n"); + out("exception3_write_access(opcode, m68k_areg(regs, 7), 1, m68k_areg(regs, 7) >> 16, 1);\n"); write_return_cycles(0); out("}\n"); } @@ -6810,9 +6854,6 @@ static void gen_opcode (unsigned int opcode) if (using_exception_3) { push_ins_cnt(); out("if (srca & 1) {\n"); - if (curi->smode >= Ad16 && cpu_level == 1 && using_prefetch) { - dummy_prefetch("srca", NULL); - } if (curi->smode == Ad16 || curi->smode == absw || curi->smode == PC16) { addcycles000_onlyce(2); addcycles000_nonce(2); @@ -6821,7 +6862,7 @@ static void gen_opcode (unsigned int opcode) addcycles000_onlyce(6); addcycles000_nonce(6); } - out("exception3_read_prefetch(opcode, srca);\n"); + out("exception3_read_prefetch_only(opcode, srca);\n"); write_return_cycles_noadd(0); out("}\n"); pop_ins_cnt(); @@ -6876,12 +6917,12 @@ static void gen_opcode (unsigned int opcode) out("if (m68k_areg(regs, 7) & 1) {\n"); out("m68k_areg(regs, 7) -= 4;\n"); incpc("2"); - out("exception3_write_opcode(opcode, m68k_areg(regs, 7), sz_word, oldpc, 1);\n"); + out("exception3_write_access(opcode, m68k_areg(regs, 7), sz_word, oldpc, 1);\n"); write_return_cycles(0); out("}\n"); } else if (cpu_level == 1) { out("if (m68k_areg(regs, 7) & 1) {\n"); - out("exception3_write_opcode(opcode, m68k_areg(regs, 7), sz_word, oldpc, 1);\n"); + out("exception3_write_access(opcode, m68k_areg(regs, 7), sz_word, oldpc, 1);\n"); write_return_cycles(0); out("}\n"); } @@ -6889,7 +6930,7 @@ static void gen_opcode (unsigned int opcode) if (using_exception_3 && cpu_level == 1) { // 68010 TODO: looks like prefetches are done first and stack writes last out("if (s & 1) {\n"); - out("exception3_read_prefetch(opcode, s);\n"); + out("exception3_read_prefetch_only(opcode, s + oldpc);\n"); write_return_cycles(0); out("}\n"); } @@ -6982,8 +7023,10 @@ static void gen_opcode (unsigned int opcode) out("if (src & 1) {\n"); if (cpu_level == 1) { out("uaecptr oldpc = %s;\n", getpc); + out("uae_u16 rb = regs.irc;\n"); incpc("((uae_s32)src + 2) & ~1"); dummy_prefetch(NULL, "oldpc"); + out("regs.read_buffer = rb;\n"); } out("exception3_read_prefetch(opcode, %s + 2 + (uae_s32)src);\n", getpc); write_return_cycles(0); @@ -7062,7 +7105,7 @@ bccl_not68020: if (cpu_level <= 1 && using_exception_3) { out("if (dsta & 1) {\n"); out("regs.ir = old_opcode;\n"); - out("exception3_write_opcode(old_opcode, dsta, sz_word, srca >> 16, 1);\n"); + out("exception3_write_access(old_opcode, dsta, sz_word, srca >> 16, 1);\n"); write_return_cycles(0); out("}\n"); } diff --git a/include/newcpu.h b/include/newcpu.h index 9875066a..14c03726 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -730,9 +730,11 @@ extern int fpp_cond(int condition); extern void exception3_read(uae_u32 opcode, uaecptr addr, int size, int fc); extern void exception3_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc); -extern void exception3_read_opcode(uae_u32 opcode, uaecptr addr, int size, int fc); -extern void exception3_write_opcode(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc); +extern void exception3_read_access(uae_u32 opcode, uaecptr addr, int size, int fc); +extern void exception3_read_access2(uae_u32 opcode, uaecptr addr, int size, int fc); +extern void exception3_write_access(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc); extern void exception3_read_prefetch(uae_u32 opcode, uaecptr addr); +extern void exception3_read_prefetch_only(uae_u32 opcode, uaecptr addr); extern void exception3_notinstruction(uae_u32 opcode, uaecptr addr); 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); diff --git a/newcpu.cpp b/newcpu.cpp index 086c2aad..fde7f7e1 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -2367,7 +2367,7 @@ static void exception_debug (int nr) /* -Address/Bus Error: +68000 Address/Bus Error: - [memory access causing bus/address error] - 8 idle cycles (+4 if bus error) @@ -2384,6 +2384,46 @@ Address/Bus Error: - 2 idle cycles - prefetch +68010 Address/Bus Error: + +- [memory access causing bus/address error] +- 8 idle cycles (+4 if bus error) +- write word 28 +- write word 26 +- write word 27 +- write word 25 +- write word 23 +- write word 24 +- write word 22 +- write word 21 +- write word 20 +- write word 19 +- write word 18 +- write word 17 +- write word 16 +- write word 15 +- write word 13 +- write word 14 +- write instruction buffer +- (skipped) +- write data input buffer +- (skipped) +- write data output buffer +- (skipped) +- write fault address low word +- write fault address high word +- write special status word +- write PC low word +- write SR +- write PC high word +- write frame format +- read exception address high word +- read exception address low word +- prefetch +- 2 idle cycles +- prefetch + + Division by Zero: - 4 idle cycles (EA + 4 cycles in cpuemu) @@ -2503,12 +2543,19 @@ static void Exception_ce000 (int nr) interrupt = nr >= 24 && nr < 24 + 8; if (!interrupt) { start = 4; - if (nr == 7) // TRAPV + if (nr == 7) { // TRAPV start = 0; - else if (nr == 3) - start = 8; - else if (nr == 2) - start = 12; + } else if (nr == 3) { + if (currprefs.cpu_model == 68000) + start = 8; + else + start = 4; + } else if (nr == 2) { + if (currprefs.cpu_model == 68000) + start = 12; + else + start = 8; + } } if (start) @@ -2537,7 +2584,7 @@ static void Exception_ce000 (int nr) mode |= last_notinstruction_for_exception_3 ? 8 : 0; // undocumented bits contain opcode mode |= last_op_for_exception_3 & ~31; - m68k_areg(regs, 7) -= 14; + m68k_areg(regs, 7) -= 7 * 2; exception_in_exception = -1; x_put_word(m68k_areg(regs, 7) + 12, last_addr_for_exception_3); x_put_word(m68k_areg(regs, 7) + 8, regs.sr); @@ -2559,26 +2606,24 @@ static void Exception_ce000 (int nr) ssw |= last_writeaccess_for_exception_3 ? 0 : 0x0100; // RW if (last_op_for_exception_3 & 0x20000) ssw &= 0x00ff; - m68k_areg(regs, 7) -= 50; + m68k_areg(regs, 7) -= (29 - 4) * 2; 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_fault_for_exception_3); // fault addr - x_put_word(m68k_areg(regs, 7) + 6, 0); // unused - x_put_word(m68k_areg(regs, 7) + 8, out); // data output buffer - x_put_word(m68k_areg(regs, 7) + 10, 0); // unused - x_put_word(m68k_areg(regs, 7) + 12, in); // data input buffer - x_put_word(m68k_areg(regs, 7) + 14, 0); // unused - x_put_word(m68k_areg(regs, 7) + 16, regs.irc); // instruction input buffer - x_put_word(m68k_areg(regs, 7) + 18, 0); // version for (int i = 0; i < 15; i++) { - x_put_word(m68k_areg(regs, 7) + 20 + i * 2, 0); + x_put_word(m68k_areg(regs, 7) + 20 + i * 2, ((i + 1) << 8) | ((i + 2) << 0)); } + x_put_word(m68k_areg(regs, 7) + 18, 0); // version + x_put_word(m68k_areg(regs, 7) + 16, regs.irc); // instruction input buffer + x_put_word(m68k_areg(regs, 7) + 12, in); // data input buffer + x_put_word(m68k_areg(regs, 7) + 8, out); // data output buffer + x_put_word(m68k_areg(regs, 7) + 4, last_fault_for_exception_3); // fault addr + x_put_word(m68k_areg(regs, 7) + 2, last_fault_for_exception_3 >> 16); + x_put_word(m68k_areg(regs, 7) + 0, ssw); // ssw } } if (currprefs.cpu_model == 68010) { // 68010 creates only format 0 and 8 stack frames - m68k_areg (regs, 7) -= 8; + m68k_areg (regs, 7) -= 4 * 2; if (m68k_areg(regs, 7) & 1) { exception3_notinstruction(regs.ir, m68k_areg(regs, 7) + 4); return; @@ -2591,7 +2636,7 @@ static void Exception_ce000 (int nr) x_put_word (m68k_areg (regs, 7) + 2, currpc >> 16); // write high address x_put_word (m68k_areg (regs, 7) + 6, (frame_id << 12) | (vector_nr * 4)); } else { - m68k_areg (regs, 7) -= 6; + m68k_areg (regs, 7) -= 3 * 2; if (m68k_areg(regs, 7) & 1) { exception3_notinstruction(regs.ir, m68k_areg(regs, 7) + 4); return; @@ -2627,9 +2672,9 @@ kludge_me_do: m68k_setpc(regs.vbr + 4 * vector_nr); if (interrupt) { regs.ir = nr; - exception3_read_opcode(regs.ir | 0x20000 | 0x10000, newpc, sz_word, 2); + exception3_read_access(regs.ir | 0x20000 | 0x10000, newpc, sz_word, 2); } else { - exception3_read_opcode(regs.ir | 0x40000 | 0x20000 | (g1 ? 0x10000 : 0), newpc, sz_word, 2); + exception3_read_access(regs.ir | 0x40000 | 0x20000 | (g1 ? 0x10000 : 0), newpc, sz_word, 2); } } else if (currprefs.cpu_model == 68010) { // offset, not vbr + offset @@ -2638,7 +2683,7 @@ kludge_me_do: regs.write_buffer = 4 * vector_nr; regs.read_buffer = newpc; regs.irc = regs.read_buffer; - exception3_read_opcode(regs.opcode, newpc, sz_word, 2); + exception3_read_access(regs.opcode, newpc, sz_word, 2); } else { exception3_notinstruction(regs.ir, newpc); } @@ -2854,8 +2899,8 @@ static void add_approximate_exception_cycles(int nr) } else { switch (nr) { - case 2: cycles = 134; break; /* Bus error */ - case 3: cycles = 130; break; /* Address error */ + case 2: cycles = 140; break; /* Bus error */ + case 3: cycles = 136; break; /* Address error */ case 4: cycles = 38; break; /* Illegal instruction */ case 5: cycles = 38; break; /* Division by zero */ case 6: cycles = 38; break; /* CHK */ @@ -3110,9 +3155,9 @@ kludge_me_do: m68k_setpc(regs.vbr + 4 * vector_nr); if (interrupt) { regs.ir = nr; - exception3_read_opcode(regs.ir | 0x20000 | 0x10000, newpc, sz_word, 2); + exception3_read_access(regs.ir | 0x20000 | 0x10000, newpc, sz_word, 2); } else { - exception3_read_opcode(regs.ir | 0x40000 | 0x20000 | (g1 ? 0x10000 : 0), newpc, sz_word, 2); + exception3_read_access(regs.ir | 0x40000 | 0x20000 | (g1 ? 0x10000 : 0), newpc, sz_word, 2); } } else if (currprefs.cpu_model == 68010) { regs.t1 = 0; @@ -3120,7 +3165,7 @@ kludge_me_do: regs.write_buffer = 4 * vector_nr; regs.read_buffer = newpc; regs.irc = regs.read_buffer; - exception3_read_opcode(regs.ir, newpc, sz_word, 2); + exception3_read_access(regs.ir, newpc, sz_word, 2); } else { exception3_notinstruction(regs.ir, newpc); } @@ -7095,6 +7140,20 @@ static void exception3_read_special(uae_u32 opcode, uaecptr addr, int size, int exception3f(opcode, addr, false, 0, false, 0xffffffff, size, fc); } +// 68010 special prefetch handling +void exception3_read_prefetch_only(uae_u32 opcode, uae_u32 addr) +{ + if (currprefs.cpu_model == 68010) { + uae_u16 prev = regs.read_buffer; + x_get_word(addr & ~1); + regs.irc = regs.read_buffer; + } else { + x_do_cycles(4 * cpucycleunit); + } + last_di_for_exception_3 = 0; + exception3f(opcode, addr, false, true, false, m68k_getpc(), sz_word, -1); +} + // Some hardware accepts address error aborted reads or writes as normal reads/writes. void exception3_read_prefetch(uae_u32 opcode, uaecptr addr) { @@ -7102,12 +7161,18 @@ void exception3_read_prefetch(uae_u32 opcode, uaecptr addr) last_di_for_exception_3 = 0; exception3f(opcode, addr, false, true, false, m68k_getpc(), sz_word, -1); } -void exception3_read_opcode(uae_u32 opcode, uaecptr addr, int size, int fc) +void exception3_read_access(uae_u32 opcode, uaecptr addr, int size, int fc) { x_do_cycles(4 * cpucycleunit); exception3_read(opcode, addr, size, fc); } -void exception3_write_opcode(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc) +void exception3_read_access2(uae_u32 opcode, uaecptr addr, int size, int fc) +{ + // (An), -(An) and (An)+ and 68010: read happens twice! + x_do_cycles(8 * cpucycleunit); + exception3_read(opcode, addr, size, fc); +} +void exception3_write_access(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc) { x_do_cycles(4 * cpucycleunit); exception3_write(opcode, addr, size, val, fc); @@ -7147,8 +7212,8 @@ void exception3_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int f opcode = regs.ir; } last_di_for_exception_3 = 1; - exception3f(opcode, addr, true, ia, ni, 0xffffffff, size, fc); regs.write_buffer = val; + exception3f(opcode, addr, true, ia, ni, 0xffffffff, size, fc); } void exception2_setup(uae_u32 opcode, uaecptr addr, bool read, int size, uae_u32 fc) diff --git a/newcpu_common.cpp b/newcpu_common.cpp index 42e7da93..628d9fea 100644 --- a/newcpu_common.cpp +++ b/newcpu_common.cpp @@ -1434,17 +1434,19 @@ 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), regs.irc); // instruction input buffer m68k_areg(regs, 7) -= 2; - x_put_word(m68k_areg(regs, 7), 0); // unused + // unused not written m68k_areg(regs, 7) -= 2; 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 + // unused not written m68k_areg(regs, 7) -= 2; 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; - x_put_long(m68k_areg(regs, 7), regs.mmu_fault_addr); // fault addr + // unused not written + m68k_areg(regs, 7) -= 2; + x_put_word(m68k_areg(regs, 7), regs.mmu_fault_addr); // fault addr + m68k_areg(regs, 7) -= 2; + x_put_word(m68k_areg(regs, 7), regs.mmu_fault_addr >> 16); // fault addr m68k_areg(regs, 7) -= 2; x_put_word(m68k_areg(regs, 7), ssw); // ssw break; -- 2.47.3