]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Remaining 68010 address error tester errors fixed.
authorToni Wilen <twilen@winuae.net>
Wed, 19 Feb 2020 20:09:08 +0000 (22:09 +0200)
committerToni Wilen <twilen@winuae.net>
Wed, 19 Feb 2020 20:09:08 +0000 (22:09 +0200)
cputest.cpp
gencpu.cpp
include/newcpu.h
newcpu.cpp
newcpu_common.cpp

index 0846d9eb1a76677c860aeb05901a1e3276255c41..e7da017b1facfe0f755cafc3d9ead9d8d3c9be11 100644 (file)
@@ -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;
index c4b3e1b9cb20df3de1930176a8b03438a397375c..9a2b8f8148bf12ea94abf22168e06643fa6dcb01 100644 (file)
@@ -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");
                }
index 9875066a6ce166a3a3e6e0ae0d5dacd6970c187d..14c037269f1e660c2d365dba3a5bf8b3c0c8c04a 100644 (file)
@@ -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);
index 086c2aadf331554da1864019e6d95e4668285d7e..fde7f7e1b395654e28976d4d9c0c814ee821b86a 100644 (file)
@@ -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)
index 42e7da936bb19215897203147bce7f49bca130b1..628d9fea107f457516b17f2dc1cd6521d88e76da 100644 (file)
@@ -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;