]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
68000 prefetch bus error updates and fixes. All prefetch bus error tests pass.
authorToni Wilen <twilen@winuae.net>
Sat, 8 Feb 2020 19:30:58 +0000 (21:30 +0200)
committerToni Wilen <twilen@winuae.net>
Sat, 8 Feb 2020 19:30:58 +0000 (21:30 +0200)
cpummu30.cpp
cputest.cpp
cputest/cputestgen.ini
cputest/main.c
custom.cpp
debug.cpp
gencpu.cpp
include/cpu_prefetch.h
include/newcpu.h
newcpu.cpp

index 6d6eaf0208b7694d47ed758db71ed920325e350f..43ed4d42f4073c5df1b0db616dab39ba642024b8 100644 (file)
@@ -3028,7 +3028,7 @@ void m68k_do_rte_mmu030 (uaecptr a7)
        regs.sr = sr;
        MakeFromSR_T0();
        if (pc & 1) {
-               exception3i(0x4E73, pc);
+               exception3_read_prefetch(0x4E73, pc);
                return;
        }
        m68k_setpci(pc);
@@ -3483,7 +3483,7 @@ void m68k_do_rte_mmu030c (uaecptr a7)
        regs.sr = sr;
        MakeFromSR_T0();
        if (pc & 1) {
-               exception3(0x4E73, pc);
+               exception3_read_prefetch(0x4E73, pc);
                return;
        }
        m68k_setpci (pc);
index e324a661e8f0d425e1975d8ce1929541a8f0f013..6a583432be6950c4dcca0ce2db622db64201bde2 100644 (file)
@@ -42,7 +42,6 @@ const int imm8_table[] = { 8, 1, 2, 3, 4, 5, 6, 7 };
 int movem_index1[256];
 int movem_index2[256];
 int movem_next[256];
-int bus_error_offset;
 int hardware_bus_error, hardware_bus_error_fake;
 
 struct mmufixup mmufixup[2];
@@ -1074,7 +1073,7 @@ void exception2_fetch(uae_u32 opcode, int offset)
        test_exception_addr = m68k_getpci() + offset;
        test_exception_opcode = opcode;
        test_exception_3_fc = 2;
-       test_exception_3_size = 1;
+       test_exception_3_size = sz_word;
        test_exception_3_di = 0;
 
        if (currprefs.cpu_model == 68000) {
@@ -1184,6 +1183,21 @@ void exception3_write(uae_u32 opcode, uae_u32 addr, int size, uae_u32 val, int f
        doexcstack();
 }
 
+void exception3_read_prefetch(uae_u32 opcode, uae_u32 addr)
+{
+       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_opcode(uae_u32 opcode, uae_u32 addr, int size, int fc)
 {
        add_memory_cycles(1);
@@ -4103,6 +4117,15 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                                if (feature_exception_vectors) {
                                                                        skipped = 1;
                                                                }
+                                                       } else {
+                                                               // wanted read address error but got write
+                                                               if (target_ea[0] != 0xffffffff && (target_ea[0] & 1) && target_ea[1] == 0xffffffff && test_exception_3_w) {
+                                                                       skipped = 1;
+                                                               }
+                                                               // wanted write address error but got read
+                                                               if (target_ea[1] != 0xffffffff && (target_ea[1] & 1) && target_ea[0] == 0xffffffff && !test_exception_3_w) {
+                                                                       skipped = 1;
+                                                               }
                                                        }
 
                                                        if (feature_usp == 2) {
index 29d29d9117b34592991e1e46ea3908c84e9949dc..b7137416416b58c429d55e1e36dbacda1051ad05 100644 (file)
@@ -75,7 +75,7 @@ feature_target_dst_ea=
 
 ; addresses where test instruction is located, use for bus error prefetch testing
 ; automatically enables RP bus error mode, data read bus errors are skipped.
-;feature_target_opcode_offset=90,92,94,96,98,100,102,104
+feature_target_opcode_offset=
 
 ; Memory region that generates bus error (both read and write).
 ; Must be inside any test memory region.
@@ -99,7 +99,8 @@ feature_usp=0
 ; exception vector bus error/address error test
 ; 0: normal
 ; non-zero: replace exception vectors with this value (except vectors 2 and 3)
-;feature_exception_vectors=0x0007321
+; skips all tests that didn't generate address error
+feature_exception_vectors=
 
 ; CCR/FPU status flags mode
 ; 0 = all combinations (32 CCR loops, 256 FPU loops)
@@ -184,7 +185,7 @@ feature_target_src_ea=0x87fff1,0x7111
 feature_target_dst_ea=
 mode=all
 
-; destination EA address error
+; destination EA address error (MOVE, MOVEM)
 [test=AE_DST]
 enabled=0
 feature_target_src_ea=
@@ -195,7 +196,7 @@ mode=all
 [test=ODD_STK]
 enabled=0
 feature_usp=2
-mode=branchs
+mode=rts,rtd,rtr,jsr,bsr,link,unlk,pea
 
 ; exception vector address error
 [test=ODD_EXC]
@@ -205,7 +206,7 @@ mode=chk,trap,trapv,divu,divs,orsr
 
 ; interrupt exception with odd interrupt vectors
 [test=ODD_IRQ]
-enabled=1
+enabled=0
 mode=nop,ext,swap
 feature_interrupts=1
 feature_exception_vectors=0x000123
@@ -216,8 +217,9 @@ enabled=0
 feature_safe_memory_start=0x880000
 feature_safe_memory_size=0x80000
 feature_safe_memory_mode=P
-feature_target_opcode_offset=90,92,94,96,98,100,102,104
-opcode_memory_start=0x87ff98
+feature_target_opcode_offset=2,4,6,8,10,12,14,16
+opcode_memory_start=0x87ffee
+test_memory_size=0xa0000
 mode=all
 
 ; source EA read bus error (requires extra hardware)
index 7317501e6bfb7b5493ddda3c101cd908ff7a00db..b36af1769217766f7b6ec5875cbd722eba3d18a6 100644 (file)
@@ -139,7 +139,7 @@ static short gotcycles;
 static short interrupttest;
 static short randomizetest;
 static uae_u32 cyclecounter_addr;
-static short uae;
+static short uaemode;
 #ifdef AMIGA
 static short interrupt_count;
 static uae_u16 main_intena;
@@ -527,11 +527,11 @@ extern void uae_command(char*);
 static int set_berr(int mask, int ask)
 {
 #ifdef AMIGA
-       if (uae) {
+       if (uaemode) {
                if (!mask) {
                        sprintf(tmpbuffer, "dbg \"w 0\"");
                } else {
-                       sprintf(tmpbuffer, "dbg \"w 0 %08x %08x BE%s%s%s\"", (uae_u32)safe_memory_start, safe_memory_end - safe_memory_start, (mask & 1) ? "R" : "", (mask & 2) ? "W" : "", (mask & 4) ? "P" : "");
+                       sprintf(tmpbuffer, "dbg \"w 0 %08x %08x B%s%s%s\"", (uae_u32)safe_memory_start, safe_memory_end - safe_memory_start, (mask & 1) ? "R" : "", (mask & 2) ? "W" : "", (mask & 4) ? "P" : "");
                }
                uae_command(tmpbuffer);
                return 0;
@@ -1715,7 +1715,7 @@ static int getexceptioncycles(int exc)
                {
                case 2:
                case 3:
-                       return 60;
+                       return 56;
                case 4:
                case 5:
                case 6:
@@ -2738,7 +2738,7 @@ static int test_mnemo(const char *opcode)
        interrupttest = (lvl_mask >> 26) & 1;
        randomizetest = (lvl_mask >> 28) & 1;
        sr_undefined_mask = lvl_mask & 0xffff;
-       safe_memory_mode = (lvl_mask >> 23) & 3;
+       safe_memory_mode = (lvl_mask >> 23) & 7;
        fpu_model = read_u32(headerfile, &headoffset);
        test_low_memory_start = read_u32(headerfile, &headoffset);
        test_low_memory_end = read_u32(headerfile, &headoffset);
@@ -2987,6 +2987,9 @@ int main(int argc, char *argv[])
                printf("-exit n = exit after n tests.\n");
                printf("-cycles [range adjust] = check cycle counts.\n");
                printf("-cyclecnt <address>. Use custom hardware cycle counter.\n");
+#ifdef AMIGA
+               printf("-uae = running in UAE, automatic bus error enable/disable.\n");
+#endif
                return 0;
        }
 
@@ -3068,7 +3071,7 @@ int main(int argc, char *argv[])
                                cycles = 1;
                        }
                } else if (!_stricmp(s, "-uae")) {
-                       uae = 1;
+                       uaemode = 1;
                }
        }
 
index cad7516ec8fa5db4c7e34447c7c557eff18b347a..00431de9191c3c47e5c09c4711c75e5f249f39c1 100644 (file)
@@ -11845,8 +11845,9 @@ void do_cycles_ce020 (unsigned long cycles)
 
 bool is_cycle_ce(uaecptr addr)
 {
+       addr &= currprefs.address_space_24 ? 0x00ffffff : 0xffffffff;
        addrbank *ab = get_mem_bank_real(addr);
-       if ((ab->flags & ABFLAG_CHIPRAM) || ab == &custom_bank) {
+       if (!ab || (ab->flags & ABFLAG_CHIPRAM) || ab == &custom_bank) {
                int hpos = current_hpos();
                return (cycle_line[hpos] & CYCLE_MASK) != 0;
        }
index 7c61607d66cd8740496c4b90d35376d3716b87fb..4f60cbd926cde6efa8d0c6da20445f9cf8d9ce6f 100644 (file)
--- a/debug.cpp
+++ b/debug.cpp
@@ -50,6 +50,7 @@
 #include "ini.h"
 #include "readcpu.h"
 #include "cputbl.h"
+#include "keybuf.h"
 
 #define TRACE_SKIP_INS 1
 #define TRACE_MATCH_PC 2
@@ -114,6 +115,7 @@ void deactivate_debugger (void)
        processname = NULL;
        debugmem_enable();
        debug_pc = 0xffffffff;
+       keybuf_ignore_next_release();
 }
 
 void activate_debugger (void)
@@ -3598,12 +3600,11 @@ void memwatch_dump2 (TCHAR *buf, int bufsize, int num)
                                buf = buf_out(buf, &bufsize, _T(" L"));
                        if (mwn->nobreak)
                                buf = buf_out(buf, &bufsize, _T(" N"));
-                       if ((mwn->bus_error & (1 | 4)) && (mwn->bus_error & 2)) {
-                               buf = buf_out(buf, &bufsize, _T(" BER"));
-                       } else if (mwn->bus_error & (1 | 4)) {
-                               buf = buf_out(buf, &bufsize, _T(" BERR"));
-                       } else if (mwn->bus_error & 2) {
-                               buf = buf_out(buf, &bufsize, _T(" BERW"));
+                       if (mwn->bus_error) {
+                               buf = buf_out(buf, &bufsize, _T(" BER%s%s%s"),
+                                       (mwn->bus_error & 1) ? _T("R") : _T(""),
+                                       (mwn->bus_error & 2) ? _T("W") : _T(""),
+                                       (mwn->bus_error & 4) ? _T("P") : _T(""));
                        }
                        for (int j = 0; memwatch_access_masks[j].mask; j++) {
                                uae_u32 mask = memwatch_access_masks[j].mask;
@@ -3738,7 +3739,7 @@ static void memwatch (TCHAR **c)
                        if (more_params(c)) {
                                for (;;) {
                                        TCHAR ncc = _totupper(peek_next_char(c));
-                                       TCHAR nc = _totupper (next_char (c));
+                                       TCHAR nc = _totupper(next_char(c));
                                        if (mwn->rwi == 7)
                                                mwn->rwi = 0;
                                        if (nc == 'F')
@@ -3750,21 +3751,30 @@ static void memwatch (TCHAR **c)
                                        if (nc == 'R')
                                                mwn->rwi |= 1;
                                        if (nc == 'B') {
-                                               mwn->bus_error = 7;
-                                               if (ncc == 'R') {
-                                                       mwn->bus_error = 1 | 4;
-                                                       mwn->rwi |= 1 | 4;
-                                                       next_char(c);
-                                               }
-                                               if (ncc == 'W') {
-                                                       mwn->bus_error = 2;
-                                                       mwn->rwi |= 2;
-                                                       next_char(c);
+                                               mwn->bus_error = 0;
+                                               for (;;) {
+                                                       ncc = next_char2(c);
+                                                       if (ncc == ' ' || ncc == 0)
+                                                               break;
+                                                       if (ncc == 'R') {
+                                                               mwn->bus_error |= 1;
+                                                               mwn->rwi |= 1;
+                                                       } else if (ncc == 'W') {
+                                                               mwn->bus_error |= 2;
+                                                               mwn->rwi |= 2;
+                                                       } else if (ncc == 'P') {
+                                                               mwn->bus_error |= 4;
+                                                               mwn->rwi |= 4;
+                                                       } else {
+                                                               break;
+                                                       }
                                                }
                                                if (!mwn->rwi)
                                                        mwn->rwi = 7;
+                                               if (!mwn->bus_error)
+                                                       mwn->bus_error = 7;
                                        }
-                                       if (ncc == ' ')
+                                       if (ncc == ' ' || ncc == 0)
                                                break;
                                        if (nc == 'P' && ncc == 'C') {
                                                next_char(c);
index 600694b57a07ddb51c1deecdf8116b48cdaad558..3bafb2e7667f2fe9929ed8bb0574ad8ff19aadc1 100644 (file)
@@ -78,6 +78,7 @@ static int optimized_flags;
 #define GF_SECONDEA    0x08000
 #define GF_NOFETCH     0x10000 // 68010
 #define GF_CLR68010    0x20000 // 68010
+#define GF_NOEXC       0x40000
 
 typedef enum
 {
@@ -761,6 +762,11 @@ static void gen_nextilong2 (const char *type, const char *name, int flags, int m
                        out("%s = %s(%d) << 16;\n", name, prefetch_word, r + 2);
                        count_read++;
                        out("%s |= regs.irc;\n", name);
+                       check_bus_error_ins(r + 2);
+                       do_instruction_buserror();
+                       strcpy(bus_error_code, bus_error_code2);
+                       bus_error_code2[0] = 0;
+                       bus_error_text[0] = 0;
                } else {
                        out("%s = %s(%d) << 16;\n", name, prefetch_word, r + 2);
                        count_read++;
@@ -778,8 +784,12 @@ static void gen_nextilong2 (const char *type, const char *name, int flags, int m
                                out("%s = %s(%d) << 16;\n", name, prefetch_word, r + 2);
                                count_read++;
                                insn_n_cycles += 4;
-                               check_bus_error_ins(r + 2);
                                out("%s |= regs.irc;\n", name);
+                               check_bus_error_ins(r + 2);
+                               do_instruction_buserror();
+                               strcpy(bus_error_code, bus_error_code2);
+                               bus_error_code2[0] = 0;
+                               bus_error_text[0] = 0;
                        } else {
                                out("%s = %s(%d) << 16;\n", name, prefetch_word, r + 2);
                                count_read++;
@@ -969,6 +979,7 @@ static void fill_prefetch_bcc(void)
                if (cpu_level == 0) {
                        out("if(regs.t1) opcode |= 0x10000;\n");
                }
+               next_level_000();
        }
 
        out("%s(%d);\n", prefetch_word, m68k_pc_offset + 2);
@@ -1039,6 +1050,7 @@ static void fill_prefetch_full_ntx(int beopcode)
                                if (beopcode == 3)
                                        out("if(t1) opcode |= 0x10000;\n");
                        }
+                       next_level_000();
                        fill_prefetch_1(2);
                } else {
                        fill_prefetch_1_empty(2);
@@ -1083,6 +1095,7 @@ static void fill_prefetch_full(int beopcode)
                        if (beopcode > 1 && cpu_level == 0) {
                                out("if(regs.t1) opcode |= 0x10000;\n");
                        }
+                       next_level_000();
                        fill_prefetch_1(2);
                } else {
                        fill_prefetch_1_empty(2);
@@ -1100,7 +1113,7 @@ static void fill_prefetch_full(int beopcode)
        }
 }
 
-static void fill_prefetch_full_000_special(void)
+static void fill_prefetch_full_000_special(const char *format, ...)
 {
        if (!using_prefetch)
                return;
@@ -1119,6 +1132,15 @@ static void fill_prefetch_full_000_special(void)
                                out("if(regs.t1) opcode |= 0x10000;\n");
                        }
                }
+               next_level_000();
+       }
+       if (format) {
+               char outbuf[256];
+               va_list parms;
+               va_start(parms, format);
+               _vsnprintf(outbuf, sizeof(outbuf) - 1, format, parms);
+               va_end(parms);
+               out(outbuf);
        }
        out("%s(%d);\n", prefetch_word, 2);
        count_read++;
@@ -1285,6 +1307,7 @@ static void fill_prefetch_next_noopcodecopy(const char *format, ...)
                        if (cpu_level == 0) {
                                out("opcode |= 0x20000;\n");
                        }
+                       next_level_000();
                }
                fill_prefetch_1(m68k_pc_offset + 2);
                if (using_bus_error) {
@@ -1317,6 +1340,7 @@ static void fill_prefetch_next_t(void)
                        if (cpu_level == 0) {
                                strcat(bus_error_code, "if (regs.t1) opcode |= 0x10000;\n");
                        }
+                       next_level_000();
                }
                fill_prefetch_1(m68k_pc_offset + 2);
                loopmode_end();
@@ -1346,7 +1370,6 @@ static void fill_prefetch_next_extra(const char *cond, const char *format, ...)
        }
 }
 
-
 static void fill_prefetch_next_after(int copy, const char *format, ...)
 {
        if (using_prefetch) {
@@ -1355,6 +1378,7 @@ static void fill_prefetch_next_after(int copy, const char *format, ...)
                if (cpu_level == 0) {
                        out("opcode |= 0x20000;\n");
                }
+               next_level_000();
                bus_error_code[0] = 0;
                if (format) {
                        va_list parms;
@@ -1375,7 +1399,6 @@ static void fill_prefetch_next_after(int copy, const char *format, ...)
        }
 }
 
-
 static void fill_prefetch_next_skipopcode(void)
 {
        if (using_prefetch) {
@@ -2544,6 +2567,11 @@ static void move_68000_address_error(int size, int *setapdi, int *fcmodeflags)
        int smode = g_instr->smode;
        int dmode = g_instr->dmode;
 
+       if (dmode == Apdi) {
+               addcycles000_onlyce(2);
+               addcycles000_nonce(2);
+       }
+
        if (size == sz_word) {
                // Word MOVE is relatively simply
                int set_ccr = 0;
@@ -3144,7 +3172,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 && getv != 3 && size != sz_byte && !movem) {
+       if ((using_prefetch || using_ce) && using_exception_3 && getv != 0 && getv != 3 && size != sz_byte && !movem && !(flags & GF_NOEXC)) {
                int setapdiback = 0;
                int fcmodeflags = 0;
                int exp3rw = getv == 2;
@@ -3613,6 +3641,7 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                                        if (flags & GF_SECONDWORDSETFLAGS) {
                                                genflags(flag_logical, g_instr->size, "src", "", "");
                                        }
+                                       // ADDX.L/SUBX.L -(an),-(an) only
                                        if (store_dir > 1) {
                                                fill_prefetch_next_after(0, NULL);
                                        }
@@ -3664,6 +3693,7 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                                        if (flags & GF_SECONDWORDSETFLAGS) {
                                                genflags(flag_logical, g_instr->size, "src", "", "");
                                        }
+                                       // ADDX.L/SUBX.L -(an),-(an) only
                                        if (store_dir > 1) {
                                                fill_prefetch_next_after(0, NULL);
                                        }
@@ -5018,6 +5048,8 @@ static void gen_opcode (unsigned int opcode)
                        if (curi->size != sz_long) {
                                genflags(flag_subx, curi->size, "newv", "src", "dst");
                                genflags(flag_zn, curi->size, "newv", "", "");
+                       } else {
+                               out("int oldz = GET_ZFLG();\n");
                        }
                        if (isreg(curi->smode) && curi->size != sz_long) {
                                genastore("newv", curi->dmode, "dstreg", curi->size, "dst");
@@ -5036,6 +5068,7 @@ static void gen_opcode (unsigned int opcode)
                                                "SET_VFLG((bflgs ^ bflgo) & (bflgo ^ bflgn));\n"
                                                "SET_CFLG(bflgs ^ ((bflgs ^ bflgn) & (bflgo ^ bflgn)));\n"
                                                "SET_XFLG(GET_CFLG());\n"
+                                               "SET_ZFLG(oldz);\n"
                                                "if (newv & 0xffff) SET_ZFLG(0);\n"
                                                "SET_NFLG(newv & 0x8000); \n"
                                                "dreg_68000_long_replace_low(dstreg, newv);\n");
@@ -5208,6 +5241,8 @@ static void gen_opcode (unsigned int opcode)
                        if (curi->size != sz_long) {
                                genflags(flag_addx, curi->size, "newv", "src", "dst");
                                genflags(flag_zn, curi->size, "newv", "", "");
+                       } else {
+                               out("int oldz = GET_ZFLG();\n");
                        }
                        if (isreg(curi->smode) && curi->size != sz_long) {
                                genastore("newv", curi->dmode, "dstreg", curi->size, "dst");
@@ -5226,6 +5261,7 @@ static void gen_opcode (unsigned int opcode)
                                                "SET_VFLG((bflgs ^ bflgn) & (bflgo ^ bflgn));\n"
                                                "SET_CFLG(bflgs ^ ((bflgs ^ bflgo) & (bflgo ^ bflgn)));\n"
                                                "SET_XFLG(GET_CFLG());\n"
+                                               "SET_ZFLG(oldz);\n"
                                                "if (newv & 0xffff) SET_ZFLG(0);\n"
                                                "SET_NFLG(newv & 0x8000); \n"
                                                "dreg_68000_long_replace_low(dstreg, newv);\n");
@@ -5299,17 +5335,7 @@ static void gen_opcode (unsigned int opcode)
                if (curi->smode == Dreg) {
                        if (curi->size == sz_long) {
                                // prefetch bus error and long register: only low word is updated
-                               // N flag from high word. Z both.
-                               fill_prefetch_next_after(1,
-                                       "dreg_68000_long_replace_low(srcreg, dst);\n"
-                                       "int bflgs = ((uae_s16)(src)) < 0;\n"
-                                       "int bflgo = ((uae_s16)(0)) < 0;\n"
-                                       "int bflgn = ((uae_s16)(dst)) < 0;\n"
-                                       "SET_ZFLG(((uae_s16)(dst)) == 0);\n"
-                                       "SET_VFLG((bflgs ^ bflgo) & (bflgn ^ bflgo));\n"
-                                       "SET_CFLG(((uae_u16)(src)) > ((uae_u16)(0)));\n"
-                                       "SET_NFLG(dst & 0x80000000);\n"
-                                       "SET_XFLG(GET_CFLG());\n");
+                               fill_prefetch_next_after(1, "dreg_68000_long_replace_low(srcreg, dst);\n");
                                genastore_rev("dst", curi->smode, "srcreg", curi->size, "src");
                        } else {
                                genastore_rev("dst", curi->smode, "srcreg", curi->size, "src");
@@ -5343,17 +5369,7 @@ static void gen_opcode (unsigned int opcode)
                if (curi->smode == Dreg) {
                        if (curi->size == sz_long) {
                                // prefetch bus error and long register: only low word is updated
-                               // N flag from high word. Z both.
-                               fill_prefetch_next_after(1,
-                                       "dreg_68000_long_replace_low(srcreg, newv);\n"
-                                       "int bflgs = ((uae_s16)(src)) < 0;\n"
-                                       "int bflgo = ((uae_s16)(0)) < 0;\n"
-                                       "int bflgn = ((uae_s16)(newv)) < 0;\n"
-                                       "SET_VFLG((bflgs ^ bflgo) & (bflgo ^ bflgn));\n"
-                                       "SET_CFLG(bflgs ^ ((bflgs ^ bflgn) & (bflgo ^ bflgn)));\n"
-                                       "SET_ZFLG(GET_ZFLG() & (((uae_s16)(newv)) == 0));\n"
-                                       "SET_NFLG(((uae_s32)(newv)) < 0);\n"
-                                       "SET_XFLG(GET_CFLG());\n");
+                               fill_prefetch_next_after(1, "dreg_68000_long_replace_low(srcreg, newv);\n");
                                genastore_rev("newv", curi->smode, "srcreg", curi->size, "src");
                        } else {
                                genastore_rev("newv", curi->smode, "srcreg", curi->size, "src");
@@ -6131,7 +6147,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, m68k_areg(regs, 7), 1, 1);\n");
+                       out("exception3_read_opcode(opcode, m68k_areg(regs, 7), 1, 1);\n");
                        write_return_cycles_noadd(0);
                        out("}\n");
                }
@@ -6157,7 +6173,7 @@ static void gen_opcode (unsigned int opcode)
                        out("regs.sr = sr;\n");
                        makefromsr();
                        out("if (pc & 1) {\n");
-                       out("exception3_read(opcode | 0x20000, pc, 1, 2);\n");
+                       out("exception3_read_opcode(opcode | 0x20000, pc, 1, 2);\n");
                        write_return_cycles(0);
                        out("}\n");
                        setpc ("pc");
@@ -6205,7 +6221,7 @@ static void gen_opcode (unsigned int opcode)
                        makefromsr();
                        out("if (pc & 1) {\n");
                        dummy_prefetch("pc", "oldpc");
-                       out("exception3i(opcode, pc);\n");
+                       out("exception3_read_prefetch(opcode, pc);\n");
                        write_return_cycles(0);
                        out("}\n");
                        out("newsr = sr; newpc = pc;\n");
@@ -6302,7 +6318,7 @@ static void gen_opcode (unsigned int opcode)
                        addcycles_ce020 (4);
                        makefromsr_t0();
                    out("if (newpc & 1) {\n");
-                   out("exception3i(opcode, newpc);\n");
+                   out("exception3_read_prefetch(opcode, newpc);\n");
                        write_return_cycles(0);
                        out("}\n");
                    setpc ("newpc");
@@ -6315,7 +6331,7 @@ static void gen_opcode (unsigned int opcode)
                clear_m68k_offset();
                tail_ce020_done = true;
                if (using_ce || using_prefetch) {
-                       fill_prefetch_full_000_special();
+                       fill_prefetch_full_000_special(NULL);
                } else {
                        fill_prefetch_full_ntx(0);
                }
@@ -6337,7 +6353,7 @@ static void gen_opcode (unsigned int opcode)
                if (cpu_level >= 4) {
                        out("m68k_areg(regs, 7) -= 4 + offs;\n");
                }
-               out("exception3i(0x%04X, pc);\n", opcode);
+               out("exception3_read_prefetch(opcode, pc);\n");
                write_return_cycles(0);
                out("}\n");
                setpc ("pc");
@@ -6345,7 +6361,7 @@ static void gen_opcode (unsigned int opcode)
                clear_m68k_offset();
                tail_ce020_done = true;
                if (using_prefetch || using_ce) {
-                       fill_prefetch_full_000_special();
+                       fill_prefetch_full_000_special(NULL);
                } else {
                        fill_prefetch_full(0);
                }
@@ -6373,14 +6389,22 @@ static void gen_opcode (unsigned int opcode)
                        addop_ce020(curi, 0, 0);
                        // smode must be first in case it is A7. Except if 68040!
                        if (cpu_level == 4) {
-                               genamode(NULL, Apdi, "7", sz_long, "old", 2, 0, GF_AA);
+                               genamode(NULL, Apdi, "7", sz_long, "old", 2, 0, GF_AA | GF_NOEXC);
                                genamode(NULL, curi->smode, "srcreg", sz_long, "src", 1, 0, GF_AA);
                        } else {
                                genamode(NULL, curi->smode, "srcreg", sz_long, "src", 1, 0, GF_AA);
-                               genamode(NULL, Apdi, "7", sz_long, "old", 2, 0, GF_AA);
+                               genamode(NULL, Apdi, "7", sz_long, "old", 2, 0, GF_AA | GF_NOEXC);
                        }
                        strcpy(bus_error_code, "m68k_areg(regs, 7) += 4;\n");
                        genamode(NULL, curi->dmode, "dstreg", curi->size, "offs", 1, 0, 0);
+                       if (cpu_level <= 1 && using_exception_3) {
+                               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");
+                               write_return_cycles(0);
+                               out("}\n");
+                       }
                        genastore("src", Apdi, "7", sz_long, "old");
                        genastore("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src");
                        out("m68k_areg(regs, 7) += offs;\n");
@@ -6411,7 +6435,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, m68k_areg(regs, 7), 1, 1);\n");
+                       out("exception3_read_opcode(opcode, m68k_areg(regs, 7), 1, 1);\n");
                        write_return_cycles(0);
                        out("}\n");
                }
@@ -6460,12 +6484,12 @@ static void gen_opcode (unsigned int opcode)
                if (cpu_level >= 4) {
                        out("m68k_areg(regs, 7) -= 4;\n");
                }
-               out("exception3i(0x%04X, faultpc);\n", opcode);
+               out("exception3_read_prefetch(opcode, faultpc);\n");
                write_return_cycles(0);
                out("}\n");
                clear_m68k_offset();
                if (using_prefetch || using_ce) {
-                       fill_prefetch_full_000_special();
+                       fill_prefetch_full_000_special(NULL);
                } else {
                        fill_prefetch_full(0);
                }
@@ -6520,9 +6544,8 @@ static void gen_opcode (unsigned int opcode)
                break;
        case i_RTR:
                if (cpu_level <= 1 && using_exception_3) {
-                       // RTR (and RTS) exception3 does not have normal 4 cycle delay
                        out("if (m68k_areg(regs, 7) & 1) {\n");
-                       out("exception3_read(opcode, m68k_areg(regs, 7), 1, 1);\n");
+                       out("exception3_read_opcode(opcode, m68k_areg(regs, 7), 1, 1);\n");
                        write_return_cycles(0);
                        out("}\n");
                }
@@ -6533,7 +6556,7 @@ static void gen_opcode (unsigned int opcode)
                if (cpu_level >= 4) {
                        out("if (pc & 1) {\n");
                        out("m68k_areg(regs, 7) -= 6;\n");
-                       out("exception3i(0x%04X, pc);\n", opcode);
+                       out("exception3_read_prefetch(opcode, pc);\n");
                        write_return_cycles(0);
                        out("}\n");
                }
@@ -6548,13 +6571,13 @@ static void gen_opcode (unsigned int opcode)
                                dummy_prefetch(NULL, NULL);
                        }
                        setpc("oldpc");
-                       out("exception3i(0x%04X, faultpc);\n", opcode);
+                       out("exception3_read_prefetch(opcode, faultpc);\n");
                        write_return_cycles(0);
                        out("}\n");
                }
                clear_m68k_offset();
                if (using_prefetch || using_ce) {
-                       fill_prefetch_full_000_special();
+                       fill_prefetch_full_000_special(NULL);
                } else {
                        fill_prefetch_full(0);
                }
@@ -6572,9 +6595,6 @@ static void gen_opcode (unsigned int opcode)
                        if (using_exception_3 && cpu_level <= 1) {
                                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);
@@ -6583,7 +6603,7 @@ static void gen_opcode (unsigned int opcode)
                                        addcycles000_onlyce(6);
                                        addcycles000_nonce(6);
                                }
-                               out("exception3i(opcode, srca);\n");
+                               out("exception3_read_prefetch(opcode, srca);\n");
                                write_return_cycles_noadd(0);
                                out("}\n");
                                pop_ins_cnt();
@@ -6607,7 +6627,7 @@ static void gen_opcode (unsigned int opcode)
                                        out("m68k_areg(regs, 7) -= 4;\n");
                                if (using_exception_3 && cpu_level >= 2) {
                                        out("if (%s & 1) {\n", getpc);
-                                       out("exception3i(opcode, %s);\n", getpc);
+                                       out("exception3_read_prefetch(opcode, %s);\n", getpc);
                                        write_return_cycles(0);
                                        out("}\n");
                                }
@@ -6616,7 +6636,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, m68k_areg(regs, 7), 1, m68k_areg(regs, 7) >> 16, 1);\n");
+                                       out("exception3_write_opcode(opcode, m68k_areg(regs, 7), 1, m68k_areg(regs, 7) >> 16, 1);\n");
                                        write_return_cycles(0);
                                        out("}\n");
                                }
@@ -6681,7 +6701,7 @@ static void gen_opcode (unsigned int opcode)
                                addcycles000_onlyce(6);
                                addcycles000_nonce(6);
                        }
-                       out("exception3i(opcode, srca);\n");
+                       out("exception3_read_prefetch(opcode, srca);\n");
                        write_return_cycles_noadd(0);
                        out("}\n");
                        pop_ins_cnt();
@@ -6728,28 +6748,28 @@ static void gen_opcode (unsigned int opcode)
                        genamode(curi, curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA|GF_NOREFILL);
                }
                out("s = (uae_s32)src + 2;\n");
+               addcycles000(2);
+               out("uaecptr oldpc = %s;\n", getpc);
+               out("uaecptr nextpc = oldpc + %d;\n", m68k_pc_offset);
                if (using_exception_3) {
                        if (cpu_level == 0) {
                                out("if (m68k_areg(regs, 7) & 1) {\n");
                                out("m68k_areg(regs, 7) -= 4;\n");
-                               out("exception3b(opcode, m68k_areg(regs, 7), true, false, %s + 2);\n", getpc);
+                               incpc("2");
+                               out("exception3_write_opcode(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("exception3b(opcode, m68k_areg(regs, 7), true, true, %s);\n", getpc);
+                               out("exception3_write_opcode(opcode, m68k_areg(regs, 7), sz_word, oldpc, 1);\n");
                                write_return_cycles(0);
                                out("}\n");
                        }
                }
-               addcycles000(2);
-               out("uaecptr oldpc = %s;\n", getpc);
-               out("uaecptr nextpc = oldpc + %d;\n", m68k_pc_offset);
                if (using_exception_3 && cpu_level == 1) {
                        // 68010 TODO: looks like prefetches are done first and stack writes last
                        out("if (s & 1) {\n");
-                       dummy_prefetch("(oldpc + s) & ~1", "oldpc");
-                       out("exception3b(opcode, oldpc + s, false, true, %s);\n", getpc);
+                       out("exception3_read_prefetch(opcode, s);\n");
                        write_return_cycles(0);
                        out("}\n");
                }
@@ -6757,7 +6777,7 @@ static void gen_opcode (unsigned int opcode)
                        out("if (s & 1) {\n");
                        if (cpu_level < 4)
                                out("m68k_areg(regs, 7) -= 4;\n");
-                       out("exception3b(opcode, %s + s, 0, 1, %s + s);\n", getpc, getpc);
+                       out("exception3_read_prefetch(opcode, s);\n");
                        write_return_cycles(0);
                        out("}\n");
                }
@@ -6769,9 +6789,7 @@ static void gen_opcode (unsigned int opcode)
                        out("m68k_do_bsr_ce020(nextpc, s);\n");
                } else if (using_ce020 == 2) {
                        out("m68k_do_bsr_ce030(nextpc, s);\n");
-               } else if (using_ce) {
-                       out("m68k_do_bsr_ce(nextpc, s);\n");
-               } else if (using_prefetch || (using_test && cpu_level <= 1)) {
+               } else if (using_ce || using_prefetch || (using_test && cpu_level <= 1)) {
                        out("m68k_areg(regs, 7) -= 4;\n");
                        out("uaecptr dsta = m68k_areg(regs, 7);\n");
                        out("%s(dsta, nextpc >> 16);\n", dstw);
@@ -6780,14 +6798,14 @@ static void gen_opcode (unsigned int opcode)
                        check_bus_error("dst", 2, 1, 1, "nextpc", 1);
                        incpc("s");
                } else if (using_prefetch_020 || (using_test && cpu_level >= 2)) {
-                       out("m68k_do_bsri (nextpc, s);\n");
+                       out("m68k_do_bsri(nextpc, s);\n");
                } else {
-                       out("m68k_do_bsr (nextpc, s);\n");
+                       out("m68k_do_bsr(nextpc, s);\n");
                }
                count_write += 2;
                if (using_exception_3 && cpu_level == 0) {
                        out("if (%s & 1) {\n", getpc);
-                       out("exception3b(opcode, %s, false, true, %s);\n", getpc, getpc);
+                       out("exception3_read_prefetch(opcode, %s);\n", getpc);
                        write_return_cycles(0);
                        out("}\n");
                }
@@ -6798,7 +6816,7 @@ static void gen_opcode (unsigned int opcode)
                }
                clear_m68k_offset();
                if (using_prefetch || using_ce) {
-                       fill_prefetch_full_000_special();
+                       fill_prefetch_full_000_special(NULL);
                } else {
                        fill_prefetch_full(0);
                }
@@ -6811,7 +6829,7 @@ static void gen_opcode (unsigned int opcode)
                        if (cpu_level < 2) {
                                addcycles000(2);
                                out("if (cctrue(%d)) {\n", curi->cc);
-                               out("exception3i(opcode, %s + 1);\n", getpc);
+                               out("exception3_read_prefetch(opcode, %s + 1);\n", getpc);
                                write_return_cycles(0);
                                out("}\n");
                                sync_m68k_pc();
@@ -6828,7 +6846,7 @@ static void gen_opcode (unsigned int opcode)
                addcycles000(2);
                if (using_exception_3 && cpu_level >= 4) {
                        out("if (src & 1) {\n");
-                       out("exception3i(opcode, %s + 2 + (uae_s32)src);\n", getpc);
+                       out("exception3_read_prefetch(opcode, %s + 2 + (uae_s32)src);\n", getpc);
                        write_return_cycles(0);
                        out("}\n");
                }
@@ -6840,14 +6858,14 @@ static void gen_opcode (unsigned int opcode)
                                incpc("((uae_s32)src + 2) & ~1");
                                dummy_prefetch(NULL, "oldpc");
                        }
-                       out("exception3i(opcode, %s + 2 + (uae_s32)src);\n", getpc);
+                       out("exception3_read_prefetch(opcode, %s + 2 + (uae_s32)src);\n", getpc);
                        write_return_cycles(0);
                        out("}\n");
                }
                push_ins_cnt();
                if (using_prefetch) {
                        incpc ("(uae_s32)src + 2");
-                       fill_prefetch_full_000_special();
+                       fill_prefetch_full_000_special(NULL);
                        if (using_ce)
                                out("return;\n");
                        else
@@ -6874,10 +6892,10 @@ static void gen_opcode (unsigned int opcode)
                        fill_prefetch_bcc();
                } else if (curi->size == sz_word) {
                        add_head_cycs (6);
-                       fill_prefetch_full_000_special();
+                       fill_prefetch_full_000_special(NULL);
                } else {
                        add_head_cycs (6);
-                       fill_prefetch_full_000_special();
+                       fill_prefetch_full_000_special(NULL);
                }
                insn_n_cycles = curi->size == sz_byte ? 8 : 12;
                branch_inst = 1;
@@ -6905,12 +6923,22 @@ bccl_not68020:
        case i_PEA:
                if (curi->smode == Ad8r || curi->smode == PC8r)
                        addcycles000(2);
+               if (cpu_level <= 1 && using_exception_3) {
+                       out("uae_u16 old_opcode = opcode;\n");
+               }
                genamode(curi, curi->smode, "srcreg", curi->size, "src", 0, 0, GF_AA);
-               genamode(NULL, Apdi, "7", sz_long, "dst", 2, 0, GF_AA);
-               if (!(curi->smode == absw || curi->smode == absl))
-                       fill_prefetch_next_after(0, "m68k_areg(regs, 7) += 4;\n");
+               genamode(NULL, Apdi, "7", sz_long, "dst", 2, 0, GF_AA | GF_NOEXC);
                if (curi->smode == Ad8r || curi->smode == PC8r)
                        addcycles000(2);
+               if (!(curi->smode == absw || curi->smode == absl))
+                       fill_prefetch_next_after(0, "m68k_areg(regs, 7) += 4;\n");
+               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");
+                       write_return_cycles(0);
+                       out("}\n");
+               }
                genastore("srca", Apdi, "7", sz_long, "dst");
                if ((curi->smode == absw || curi->smode == absl))
                        fill_prefetch_next_t();
@@ -6932,7 +6960,7 @@ bccl_not68020:
                addcycles000_nonce(2);
                if (using_exception_3 && cpu_level >= 4) {
                        out("if (offs & 1) {\n");
-                       out("exception3i(opcode, oldpc + (uae_s32)offs + 2);\n");
+                       out("exception3_read_prefetch(opcode, oldpc + (uae_s32)offs + 2);\n");
                        write_return_cycles(0);
                        out("}\n");
                }
@@ -6947,7 +6975,7 @@ bccl_not68020:
                        if (cpu_level == 1) {
                                out("%s(%d);\n", prefetch_word, -1);
                        }
-                       out("exception3i(opcode, %s);\n", getpc);
+                       out("exception3_read_prefetch(opcode, %s);\n", getpc);
                        write_return_cycles(0);
                        out("}\n");
                        
@@ -6991,7 +7019,7 @@ bccl_not68020:
                        int old_m68k_pc_total = m68k_pc_total;
                        clear_m68k_offset();
                        get_prefetch_020_continue();
-                       fill_prefetch_full_000_special();
+                       fill_prefetch_full_000_special(NULL);
                        returncycles(8);
                        m68k_pc_offset = old_m68k_pc_offset;
                        m68k_pc_total = old_m68k_pc_total;
@@ -7011,16 +7039,19 @@ bccl_not68020:
                        out("}\n");
                        out("regs.loop_mode = 0;\n");
                        setpc("oldpc + %d", m68k_pc_offset);
-                       fill_prefetch_full_000_special();
+                       fill_prefetch_full_000_special(NULL);
                        returncycles(8);
                        out("}\n");
                }
 
                fill_prefetch_1(0);
-               if (cpu_level < 2 || cpu_level >= 4) {
+               if (cpu_level >= 4) {
                        genastore("(src - 1)", curi->smode, "srcreg", curi->size, "src");
                }
                out("if (src) {\n");
+               if (cpu_level < 2) {
+                       genastore("(src - 1)", curi->smode, "srcreg", curi->size, "src");
+               }
                irc2ir();
                add_head_cycs (6);
 
@@ -7058,7 +7089,7 @@ bccl_not68020:
                setpc ("oldpc + %d", m68k_pc_offset);
                clear_m68k_offset();
                get_prefetch_020_continue();
-               fill_prefetch_full_000_special();
+               fill_prefetch_full_000_special("if (!cctrue(%d)) {\nm68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | (((src - 1)) & 0xffff);\n}\n", curi->cc);
                insn_n_cycles = 12;
                branch_inst = 1;
                next_level_040_to_030();
index 8bb6be7e9dab9c6e156dc4e1aa8a0dd8a8220069..f30b95fef8374e6b782a6bb78170828de976b884 100644 (file)
@@ -427,31 +427,6 @@ STATIC_INLINE void put_byte_ce000 (uaecptr addr, uae_u32 v)
        mem_access_delay_byte_write (addr, v);
 }
 
-STATIC_INLINE void m68k_do_rts_ce (void)
-{
-       uaecptr pc;
-       pc = x_get_word (m68k_areg (regs, 7)) << 16;
-       pc |= x_get_word (m68k_areg (regs, 7) + 2);
-       m68k_areg (regs, 7) += 4;
-       m68k_setpci (pc);
-}
-
-STATIC_INLINE void m68k_do_bsr_ce (uaecptr oldpc, uae_s32 offset)
-{
-       m68k_areg (regs, 7) -= 4;
-       x_put_word (m68k_areg (regs, 7), oldpc >> 16);
-       x_put_word (m68k_areg (regs, 7) + 2, oldpc);
-       m68k_incpci (offset);
-}
-
-STATIC_INLINE void m68k_do_jsr_ce (uaecptr oldpc, uaecptr dest)
-{
-       m68k_areg (regs, 7) -= 4;
-       x_put_word (m68k_areg (regs, 7), oldpc >> 16);
-       x_put_word (m68k_areg (regs, 7) + 2, oldpc);
-       m68k_setpci (dest);
-}
-
 #endif
 
 STATIC_INLINE uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp)
index 74f2d9b76b8d52c52dc2e5e42cfb13c019b46258..ca5823eb7db3af0707e6b627dbd703381ed8e578 100644 (file)
@@ -52,7 +52,6 @@ extern int fpp_movem_index2[256];
 extern int fpp_movem_next[256];
 #endif
 
-extern int bus_error_offset;
 extern int hardware_bus_error;
 
 typedef uae_u32 REGPARAM3 cpuop_func (uae_u32) REGPARAM;
@@ -732,9 +731,8 @@ 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_prefetch(uae_u32 opcode, uaecptr addr);
 extern void exception3_notinstruction(uae_u32 opcode, uaecptr addr);
-extern void exception3i (uae_u32 opcode, uaecptr addr);
-extern void exception3b (uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc);
 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);
index 20dabbab65a2558cc216793453f1eabce87ce734..3a64de3a5d20076dd1fbf02d58d94cc339b858bd 100644 (file)
@@ -84,7 +84,6 @@ static void exception3_read_special(uae_u32 opcode, uaecptr addr, int size, int
 
 int mmu_enabled, mmu_triggered;
 int cpu_cycles;
-int bus_error_offset;
 int hardware_bus_error;
 static int baseclock;
 int m68k_pc_indirect;
@@ -2615,9 +2614,9 @@ kludge_me_do:
                        m68k_setpc(regs.vbr + 4 * vector_nr);
                        if (interrupt) {
                                regs.ir = nr;
-                               exception3_read(regs.ir | 0x20000 | 0x10000, newpc, 1, 2);
+                               exception3_read(regs.ir | 0x20000 | 0x10000, newpc, sz_word, 2);
                        } else {
-                               exception3_read(regs.ir | 0x40000, newpc, 1, 2);
+                               exception3_read(regs.ir | 0x40000, newpc, sz_word, 2);
                        }
                } else if (currprefs.cpu_model == 68010) {
                        // offset, not vbr + offset
@@ -2626,7 +2625,7 @@ kludge_me_do:
                        regs.write_buffer = 4 * vector_nr;
                        regs.read_buffer = newpc;
                        regs.irc = regs.read_buffer;
-                       exception3b(regs.opcode, newpc, false, true, newpc);
+                       exception3_read(regs.opcode, newpc, sz_word, 2);
                } else {
                        exception3_notinstruction(regs.ir, newpc);
                }
@@ -3093,9 +3092,9 @@ kludge_me_do:
                        m68k_setpc(regs.vbr + 4 * vector_nr);
                        if (interrupt) {
                                regs.ir = nr;
-                               exception3_read(regs.ir | 0x20000 | 0x10000, newpc, 1, 2);
+                               exception3_read(regs.ir | 0x20000 | 0x10000, newpc, sz_word, 2);
                        } else {
-                               exception3_read(regs.ir | 0x40000, newpc, 1, 2);
+                               exception3_read(regs.ir | 0x40000, newpc, sz_word, 2);
                        }
                } else if (currprefs.cpu_model == 68010) {
                        regs.t1 = 0;
@@ -3103,7 +3102,7 @@ kludge_me_do:
                        regs.write_buffer = 4 * vector_nr;
                        regs.read_buffer = newpc;
                        regs.irc = regs.read_buffer;
-                       exception3b(regs.ir, newpc, false, true, newpc);
+                       exception3_read(regs.ir, newpc, sz_word, 2);
                } else {
                        exception3_notinstruction(regs.ir, newpc);
                }
@@ -7030,6 +7029,12 @@ static void exception3_read_special(uae_u32 opcode, uaecptr addr, int size, int
 }
 
 // Some hardware accepts address error aborted reads or writes as normal reads/writes.
+void exception3_read_prefetch(uae_u32 opcode, uaecptr addr)
+{
+       x_do_cycles(4 * cpucycleunit);
+       last_di_for_exception_3 = 0;
+       exception3f(opcode, addr, false, true, false, m68k_getpc(), sz_word, false, -1);
+}
 void exception3_read_opcode(uae_u32 opcode, uaecptr addr, int size, int fc)
 {
        x_do_cycles(4 * cpucycleunit);
@@ -7078,20 +7083,10 @@ void exception3_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int f
        exception3f(opcode, addr, true, ia, ni, 0xffffffff, size, false, fc);
        regs.write_buffer = val;
 }
-void exception3i(uae_u32 opcode, uaecptr addr)
-{
-       last_di_for_exception_3 = 0;
-       exception3f (opcode, addr, 0, 1, false, 0xffffffff, 1, true, -1);
-}
-void exception3b(uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc)
-{
-       last_di_for_exception_3 = 0;
-       exception3f (opcode, addr, w, i, false, pc, 1, true, -1);
-}
 
 void exception2_setup(uae_u32 opcode, uaecptr addr, bool read, int size, uae_u32 fc)
 {
-       last_addr_for_exception_3 = m68k_getpc() + bus_error_offset;
+       last_addr_for_exception_3 = m68k_getpc();
        last_fault_for_exception_3 = addr;
        last_writeaccess_for_exception_3 = read == 0;
        last_op_for_exception_3 = opcode;
@@ -7143,9 +7138,23 @@ void exception2_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int f
 
 void exception2_fetch(uae_u32 opcode, int offset)
 {
-       uaecptr addr = m68k_getpc() + offset;
-       exception2_setup(opcode, addr, true, 1, 2);
+       last_fault_for_exception_3 = m68k_getpc() + offset;
+       last_writeaccess_for_exception_3 = 0;
+       last_op_for_exception_3 = opcode;
+       last_fc_for_exception_3 = 2;
+       last_notinstruction_for_exception_3 = exception_in_exception != 0;
+       last_size_for_exception_3 = sz_word;
        last_di_for_exception_3 = 0;
+       hardware_bus_error = 0;
+
+       if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible) {
+               if (generates_group1_exception(regs.ir) && !(opcode & 0x20000)) {
+                       last_fc_for_exception_3 |= 8;  // set N/I
+               }
+               if (opcode & 0x10000)
+                       last_fc_for_exception_3 |= 8;
+       }
+
        Exception(2);
 }