]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
68010 bus error/address error stack frame partial tester support.
authorToni Wilen <twilen@winuae.net>
Sat, 19 Oct 2019 09:53:57 +0000 (12:53 +0300)
committerToni Wilen <twilen@winuae.net>
Sat, 19 Oct 2019 09:53:57 +0000 (12:53 +0300)
cputest.cpp
cputest/asm.S
cputest/main.c
gencpu.cpp
include/newcpu.h
jit/exception_handler.cpp
newcpu.cpp
newcpu_common.cpp

index 96d46479a47541f9b8f0bc98d0a2ef974a08f136..3878f63663c6d8293a2c2be05e5672a6b3769751 100644 (file)
@@ -113,6 +113,9 @@ static int exception_stack_frame_size;
 static uaecptr test_exception_addr;
 static int test_exception_3_w;
 static int test_exception_3_fc;
+static int test_exception_3_size;
+static int test_exception_3_value;
+static int test_exception_3_di;
 static int test_exception_opcode;
 
 static uae_u8 imm8_cnt;
@@ -135,6 +138,7 @@ static int high_memory_accessed;
 static int test_memory_accessed;
 static uae_u16 extra_or, extra_and;
 static uae_u32 cur_registers[MAX_REGISTERS];
+static uae_u32 test_last_read, test_last_write;
 
 struct uae_prefs currprefs;
 
@@ -279,11 +283,18 @@ static void check_bus_error(uaecptr addr, int write, int fc)
        }
 }
 
+static uae_u8 get_ibyte_test(uaecptr addr)
+{
+       check_bus_error(addr, 0, regs.s ? 5 : 1);
+       uae_u8 *p = get_addr(addr, 1, 0);
+       return *p;
+}
+
 static uae_u16 get_iword_test(uaecptr addr)
 {
        check_bus_error(addr, 0, regs.s ? 6 : 2);
        if (addr & 1) {
-               return (get_byte_test(addr + 0) << 8) | (get_byte_test(addr + 1) << 0);
+               return (get_ibyte_test(addr + 0) << 8) | (get_ibyte_test(addr + 1) << 0);
        } else {
                uae_u8 *p = get_addr(addr, 2, 0);
                return (p[0] << 8) | (p[1]);
@@ -296,6 +307,7 @@ uae_u16 get_word_test_prefetch(int o)
        if (cpu_lvl < 2)
                o -= 2;
        regs.irc = get_iword_test(m68k_getpci() + o + 2);
+       test_last_read = regs.irc;
        return get_iword_test(m68k_getpci() + o);
 }
 
@@ -327,6 +339,7 @@ void put_byte_test(uaecptr addr, uae_u32 v)
                ah->oldval = *p;
                ah->size = sz_byte;
        }
+       test_last_write = v;
        *p = v;
 }
 void put_word_test(uaecptr addr, uae_u32 v)
@@ -352,6 +365,7 @@ void put_word_test(uaecptr addr, uae_u32 v)
                p[0] = v >> 8;
                p[1] = v & 0xff;
        }
+       test_last_write = v;
 }
 void put_long_test(uaecptr addr, uae_u32 v)
 {
@@ -382,9 +396,9 @@ void put_long_test(uaecptr addr, uae_u32 v)
                p[2] = v >> 8;
                p[3] = v >> 0;
        }
+       test_last_write = v;
 }
 
-
 static void undo_memory(struct accesshistory *ahp, int  *cntp)
 {
        out_of_test_space = 0;
@@ -412,39 +426,45 @@ static void undo_memory(struct accesshistory *ahp, int  *cntp)
        }
 }
 
-
 uae_u32 get_byte_test(uaecptr addr)
 {
        check_bus_error(addr, 0, regs.s ? 5 : 1);
        uae_u8 *p = get_addr(addr, 1, 0);
+       test_last_read = *p;
        return *p;
 }
 uae_u32 get_word_test(uaecptr addr)
 {
+       uae_u16 v;
        check_bus_error(addr, 0, regs.s ? 5 : 1);
        if (addr & 1) {
-               return (get_byte_test(addr + 0) << 8) | (get_byte_test(addr + 1) << 0);
+               v = (get_byte_test(addr + 0) << 8) | (get_byte_test(addr + 1) << 0);
        } else {
                uae_u8 *p = get_addr(addr, 2, 0);
-               return (p[0] << 8) | (p[1]);
+               v = (p[0] << 8) | (p[1]);
        }
+       test_last_read = v;
+       return v;
 }
 uae_u32 get_long_test(uaecptr addr)
 {
+       uae_u32 v;
        check_bus_error(addr, 0, regs.s ? 5 : 1);
        if (addr & 1) {
                uae_u8 v0 = get_byte_test(addr + 0);
                uae_u16 v1 = get_word_test(addr + 1);
                uae_u8 v3 = get_byte_test(addr + 3);
-               return (v0 << 24) | (v1 << 8) | (v3 << 0);
+               v = (v0 << 24) | (v1 << 8) | (v3 << 0);
        } else if (addr & 2) {
                uae_u16 v0 = get_word_test(addr + 0);
                uae_u16 v1 = get_word_test(addr + 2);
-               return (v0 << 16) | (v1 << 0);
+               v = (v0 << 16) | (v1 << 0);
        } else {
                uae_u8 *p = get_addr(addr, 4, 0);
-               return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]);
+               v = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]);
        }
+       test_last_read = v;
+       return v;
 }
 
 uae_u32 get_byte_debug(uaecptr addr)
@@ -794,11 +814,16 @@ static void doexcstack(void)
                        Exception_build_68000_address_error_stack_frame(mode, opcode, test_exception_addr, regs.pc);
                }
        } else if (cpu_lvl == 1) {
-               if (test_exception == 3) {
+               if (test_exception == 2 || test_exception == 3) {
                        uae_u16 ssw = (sv ? 4 : 0) | test_exception_3_fc;
-                       ssw |= test_exception_3_w ? 0 : 0x100;
-                       ssw |= (test_exception_3_fc & 2) ? 0 : 0x2000;
+                       ssw |= test_exception_3_di ? 0x0000 : 0x2000; // IF
+                       ssw |= (!test_exception_3_w && test_exception_3_di) ? 0x1000 : 0x000; // DF
+                       ssw |= (test_exception_opcode & 0x10000) ? 0x0400 : 0x0000; // HB
+                       ssw |= test_exception_3_size == 0 ? 0x0200 : 0x0000; // BY
+                       ssw |= test_exception_3_w ? 0x0000 : 0x0100; // RW
                        regs.mmu_fault_addr = test_exception_addr;
+                       regs.mmu_effective_addr = test_exception_3_value;
+                       regs.mmu_effective_addr = (test_last_read & 0xffff) | ((test_last_write & 0xffff) << 16);
                        Exception_build_stack_frame(regs.instruction_pc, regs.pc, ssw, 3, 0x08);
                } else {
                        Exception_build_stack_frame_common(regs.instruction_pc, regs.pc, 0, test_exception);
@@ -857,45 +882,67 @@ uae_u32 REGPARAM2 op_illg(uae_u32 opcode)
        return op_illg_1(opcode);
 }
 
-void exception2_read(uae_u32 opcode, uaecptr addr, int fc)
+void exception2_fetch(uae_u32 opcode, uaecptr addr)
+{
+       test_exception = 2;
+       test_exception_3_w = 0;
+       test_exception_addr = addr;
+       test_exception_opcode = opcode;
+       test_exception_3_fc = 2;
+       test_exception_3_size = 1;
+       test_exception_3_di = 0;
+       doexcstack();
+}
+
+void exception2_read(uae_u32 opcode, uaecptr addr, int size, int fc)
 {
        test_exception = 2;
        test_exception_3_w = 0;
        test_exception_addr = addr;
        test_exception_opcode = opcode;
        test_exception_3_fc = fc;
+       test_exception_3_size = size;
+       test_exception_3_di = 1;
        doexcstack();
 }
 
-void exception2_write(uae_u32 opcode, uaecptr addr, int fc)
+void exception2_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc)
 {
        test_exception = 2;
        test_exception_3_w = 1;
        test_exception_addr = addr;
        test_exception_opcode = opcode;
        test_exception_3_fc = fc;
+       test_exception_3_size = size;
+       test_exception_3_value = val;
+       test_exception_3_di = 1;
        doexcstack();
 }
 
-
-void exception3_read(uae_u32 opcode, uae_u32 addr, int fc)
+void exception3_read(uae_u32 opcode, uae_u32 addr, int size, int fc)
 {
        test_exception = 3;
        test_exception_3_w = 0;
        test_exception_addr = addr;
        test_exception_opcode = opcode;
        test_exception_3_fc = fc;
+       test_exception_3_size = size;
+       test_exception_3_di = 1;
        doexcstack();
 }
-void exception3_write(uae_u32 opcode, uae_u32 addr, int fc)
+void exception3_write(uae_u32 opcode, uae_u32 addr, int size, uae_u32 val, int fc)
 {
        test_exception = 3;
        test_exception_3_w = 1;
        test_exception_addr = addr;
        test_exception_opcode = opcode;
        test_exception_3_fc = fc;
+       test_exception_3_size = size;
+       test_exception_3_value = val;
+       test_exception_3_di = 1;
        doexcstack();
 }
+
 void REGPARAM2 Exception(int n)
 {
        test_exception = n;
@@ -2154,6 +2201,8 @@ static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc, struct ins
        testing_active = 1;
        testing_active_opcode = opc;
        cpu_bus_error = 0;
+       test_last_read = regs.irc;
+       test_last_write = 0xf00d;
 
        int cnt = feature_loop_mode * 2;
        if (multi_mode)
@@ -2352,6 +2401,22 @@ static uae_u8 *save_exception(uae_u8 *p, struct instr *dp)
                        // FSLW or PC of faulted instruction
                        p = store_rel(p, 0, opcode_memory_start, gl(sf + 12), 1);
                        break;
+               case 8: // 68010 address/bus error
+                       // SSW
+                       *p++ = sf[8];
+                       *p++ = sf[9];
+                       // fault address
+                       p = store_rel(p, 0, opcode_memory_start, gl(sf + 10), 1);
+                       // data output
+                       *p++ = sf[16];
+                       *p++ = sf[17];
+                       // data input
+                       *p++ = sf[20];
+                       *p++ = sf[21];
+                       // instruction
+                       *p++ = sf[24];
+                       *p++ = sf[25];
+                       break;
                case 0x0a: // 68020/030 address error.
                case 0x0b: // Don't save anything extra, too many undefined fields and bits..
                        exception_stack_frame_size = 0x08;
@@ -2744,8 +2809,12 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                        if (dp->dmode == Apdi) {
                                                                diff = -diff;
                                                        }
+                                                       uae_u32 ta = target_address;
                                                        target_address -= diff * (1 << dp->size);
-                                                       target_ea[1] = target_address;
+                                                       if (target_ea[0] == ta)
+                                                               target_ea[0] = target_address;
+                                                       if (target_ea[1] == ta)
+                                                               target_ea[1] = target_address;
                                                }
                                        }
 
index 85ee63e57f5fa6abb98e4d3e5b9a412da3567bdd..d1833eb6a72a21b85b4e71adab4b4b14d35850e9 100644 (file)
@@ -147,6 +147,9 @@ _execute_test010:
        move.l S_AREG+7*4(a0),a1
        move.l a1,USP
        movem.l (a0),d0-d7/a0-a6
+       | clear data output buffer.
+       | we don't want random DOB contents in bus/address error frame
+       move.w #0xf00d,dummy
        rte
 
        | 68020+ test entrypoint
@@ -392,3 +395,5 @@ datapointer:
        dc.l 0
 superstack:
        dc.l 0
+dummy:
+       dc.l 0
index ab1de0876d6c04c430f44a0cdf8682430e27b0bf..77dfb08a605197cda46e5745e9d848d4057afaf7 100644 (file)
@@ -1134,6 +1134,30 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum,
                                pl(exc + 12, v);
                                exclen = 16;
                                break;
+                       case 8:
+                               exc[8] = *p++;
+                               exc[9] = *p++;
+                               v = opcode_memory_addr;
+                               p = restore_rel_ordered(p, &v);
+                               pl(exc + 10, v);
+                               // data out
+                               exc[16] = *p++;
+                               exc[17] = *p++;
+                               // data in
+                               exc[20] = *p++;
+                               exc[21] = *p++;
+                               // inst
+                               exc[24] = *p++;
+                               exc[25] = *p++;
+                               exc[14] = exc[15] = 0;
+                               sp[14] = sp[15] = 0;
+                               exc[18] = exc[19] = 0;
+                               sp[18] = sp[19] = 0;
+                               exc[22] = exc[23] = 0;
+                               sp[22] = sp[23] = 0;
+                               // ignore undocumented data
+                               exclen = 26;
+                               break;
                        case 0x0a:
                        case 0x0b:
                                exclen = 8;
index 14a51e12b01c8438a9cee995eaafe9cdf1c1bf91..bab5f1399060167254aa2bba39d462d7bf257928 100644 (file)
@@ -515,7 +515,7 @@ static void check_bus_error_ins(int offset)
        } else {
                opcode = "opcode";
        }
-       sprintf(bus_error_text, "\t\texception2_read(%s, m68k_getpci() + %d, 2);\n", opcode, offset);
+       sprintf(bus_error_text, "\t\texception2_fetch(%s, m68k_getpci() + %d);\n", opcode, offset);
 }
 
 static void check_prefetch_bus_error(int offset)
@@ -1393,20 +1393,56 @@ static void move_68000_bus_error(int offset, int size, int *setapdi, int *fcmode
 static char const *bus_error_reg;
 static int bus_error_reg_add;
 
-static void check_bus_error(const char *name, int offset, int write, int fc)
+static void do_bus_error_fixes(const char *name, int offset)
+{
+       switch (bus_error_reg_add)
+       {
+       case 1:
+               if (g_instr->mnemo == i_CMPM && write) {
+                       ;
+               } else {
+                       printf("\t\tm68k_areg(regs, %s) += areg_byteinc[%s] + %d;\n", bus_error_reg, bus_error_reg, offset);
+               }
+               break;
+       case 2:
+               printf("\t\tm68k_areg(regs, %s) += 2 + %d;\n", bus_error_reg, offset);
+               break;
+       case 3:
+               if (g_instr->mnemo == i_CMPM) {
+                       // CMPM.L (an)+,(an)+: increased by 2
+                       printf("\t\tm68k_areg(regs, %s) += 2 + %d;\n", bus_error_reg, offset);
+               }
+               break;
+       case 4:
+               if ((g_instr->mnemo == i_ADDX || g_instr->mnemo == i_SUBX) && g_instr->size == sz_long) {
+                       // ADDX.L/SUBX.L -(an),-(an) source: stack frame decreased by 2, not 4.
+                       offset = 2;
+               } else {
+                       printf("\t\tm68k_areg (regs, %s) = %sa;\n", bus_error_reg, name);
+               }
+               break;
+       }
+
+}
+
+static void check_bus_error(const char *name, int offset, int write, int size, const char *writevar, int fc)
 {
        // check possible bus error (if 68000/010 and enabled)
        if (!using_bus_error)
                return;
        if (!using_prefetch && !using_ce)
                return;
+
+       uae_u32 extra = fc & 0xffff0000;
+       fc &= 0xffff;
+
        printf("\tif(cpu_bus_error) {\n");
 
        int setapdiback = 0;
 
        if (fc == 2) {
 
-               printf("\t\texception2_read(opcode, m68k_getpci() + %d, 2);\n", offset);
+               printf("\t\texception2_fetch(opcode, m68k_getpci() + %d);\n", offset);
 
        } else {
 
@@ -1418,33 +1454,7 @@ static void check_bus_error(const char *name, int offset, int write, int fc)
                        move_68000_bus_error(offset, g_instr->size, &setapdiback, &fc);
                }
 
-               switch (bus_error_reg_add)
-               {
-               case 1:
-                       if (g_instr->mnemo == i_CMPM && write) {
-                               ;
-                       } else {
-                               printf("\t\tm68k_areg(regs, %s) += areg_byteinc[%s] + %d;\n", bus_error_reg, bus_error_reg, offset);
-                       }
-                       break;
-               case 2:
-                       printf("\t\tm68k_areg(regs, %s) += 2 + %d;\n", bus_error_reg, offset);
-                       break;
-               case 3:
-                       if (g_instr->mnemo == i_CMPM) {
-                               // CMPM.L (an)+,(an)+: increased by 2
-                               printf("\t\tm68k_areg(regs, %s) += 2 + %d;\n", bus_error_reg, offset);
-                       }
-                       break;
-               case 4:
-                       if ((g_instr->mnemo == i_ADDX || g_instr->mnemo == i_SUBX) && g_instr->size == sz_long) {
-                               // ADDX.L/SUBX.L -(an),-(an) source: stack frame decreased by 2, not 4.
-                               offset = 2;
-                       } else {
-                               printf("\t\tm68k_areg (regs, %s) = %sa;\n", bus_error_reg, name);
-                       }
-                       break;
-               }
+               do_bus_error_fixes(name, offset);
 
                if (g_instr->mnemo == i_BTST && (g_instr->dmode == PC16 || g_instr->dmode == PC8r)) {
                        // BTST special case where destination is read access
@@ -1455,10 +1465,21 @@ static void check_bus_error(const char *name, int offset, int write, int fc)
                        fc = 2;
                }
 
-               printf("\t\texception2_%s(opcode, %sa + %d, %d);\n",
-                       write ? "write" : "read", name, offset,
-                       (!write && (g_instr->smode == PC16 || g_instr->smode == PC8r)) ||
-                       (write && (g_instr->dmode == PC16 || g_instr->dmode == PC8r)) ? 2 : fc);
+               // 68010 bus/address error HB bit
+               if (extra && cpu_level == 1)
+                       printf("\t\topcode |= 0x%x;\n", extra);
+
+               if (write) {
+                       printf("\t\texception2_write(opcode, %sa + %d, %d, %s, %d);\n",
+                               name, offset, size, writevar,
+                               (!write && (g_instr->smode == PC16 || g_instr->smode == PC8r)) ||
+                               (write && (g_instr->dmode == PC16 || g_instr->dmode == PC8r)) ? 2 : fc);
+               } else {
+                       printf("\t\texception2_read(opcode, %sa + %d, %d, %d);\n",
+                               name, offset, size,
+                               (!write && (g_instr->smode == PC16 || g_instr->smode == PC8r)) ||
+                               (write && (g_instr->dmode == PC16 || g_instr->dmode == PC8r)) ? 2 : fc);
+               }
        }
 
        printf("\t\tgoto %s;\n", endlabelstr);
@@ -2345,6 +2366,28 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
        /* We get here for all non-reg non-immediate addressing modes to
        * actually fetch the value. */
 
+       bus_error_reg_add = 0;
+       bus_error_reg = reg;
+       if (!movem) {
+               if (mode == Aipi) {
+                       switch (size)
+                       {
+                       case sz_byte:
+                               bus_error_reg_add = 1;
+                               break;
+                       case sz_word:
+                               bus_error_reg_add = 2;
+                               break;
+                       case sz_long:
+                               bus_error_reg_add = 3;
+                               break;
+                       default: term();
+                       }
+               } else if (mode == Apdi) {
+                       bus_error_reg_add = 4;
+               }
+       }
+
        exception_pc_offset = 0;
        if (getv == 2) {
                // store
@@ -2364,6 +2407,16 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
 
                printf("\tif (%sa & 1) {\n", name);
 
+               if (cpu_level == 1) {
+                       if (bus_error_reg_add == 4)
+                               bus_error_reg_add = 0;
+                       do_bus_error_fixes(name, 0);
+                       // x,-(an): an is modified
+                       if (mode == Apdi && g_instr->size == sz_word) {
+                               printf("\t\tm68k_areg (regs, %s) = %sa;\n", reg, name);
+                       }
+               }
+
                if (g_instr->mnemo == i_ADDX || g_instr->mnemo == i_SUBX) {
                        // ADDX/SUBX special case
                        if (g_instr->size == sz_word) {
@@ -2371,7 +2424,9 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                        }
                } else if (mode == Apdi) {
                        // 68000 decrements register first, then checks for address error
-                       setapdiback = 1;
+                       // 68010 does not
+                       if (cpu_level == 0)
+                               setapdiback = 1;
                }
 
                if (exception_pc_offset)
@@ -2395,10 +2450,18 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                if ((flags & (GF_REVERSE | GF_REVERSE2)) && size == sz_long && mode == Apdi)
                        printf("\t\t%sa += %d;\n", name, flags & GF_REVERSE2 ? -2 : 2);
 
-               printf("\t\texception3_%s(opcode, %sa, %d);\n",
-                       exp3rw ? "write" : "read", name,
-                       // PC-relative: FC=2
-                       (getv == 1 && (g_instr->smode == PC16 || g_instr->smode == PC8r) ? 2 : 1) | fcmodeflags);
+               if (exp3rw) {
+                       printf("\t\texception3_write(opcode, %sa, %d, %s, %d);\n",
+                               name, size, "0",
+                               // PC-relative: FC=2
+                               (getv == 1 && (g_instr->smode == PC16 || g_instr->smode == PC8r) ? 2 : 1) | fcmodeflags);
+
+               } else {
+                       printf("\t\texception3_read(opcode, %sa, %d, %d);\n",
+                               name, size,
+                               // PC-relative: FC=2
+                               (getv == 1 && (g_instr->smode == PC16 || g_instr->smode == PC8r) ? 2 : 1) | fcmodeflags);
+               }
 
                printf ("\t\tgoto %s;\n", endlabelstr);
                printf ("\t}\n");
@@ -2411,28 +2474,6 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
        else if (flags & GF_IR2IRC)
                irc2ir (true);
 
-       bus_error_reg_add = 0;
-       bus_error_reg = reg;
-       if (!movem) {
-               if (mode == Aipi) {
-                       switch (size)
-                       {
-                       case sz_byte:
-                               bus_error_reg_add = 1;
-                               break;
-                       case sz_word:
-                               bus_error_reg_add = 2;
-                               break;
-                       case sz_long:
-                               bus_error_reg_add = 3;
-                               break;
-                       default: term();
-                       }
-               } else if (mode == Apdi) {
-                       bus_error_reg_add = 4;
-               }
-       }
-
        if (getv == 1) {
                const char *srcbx = !(flags & GF_FC) ? srcb : "sfc_nommu_get_byte";
                const char *srcwx = !(flags & GF_FC) ? srcw : "sfc_nommu_get_word";
@@ -2467,14 +2508,14 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                        {
                                insn_n_cycles += 4; printf("\tuae_s8 %s = %s (%sa);\n", name, srcbx, name);
                                count_read++;
-                               check_bus_error(name, 0, 0, 1);
+                               check_bus_error(name, 0, 0, 0, NULL, 1);
                                break;
                        }
                        case sz_word:
                        {
                                insn_n_cycles += 4; printf("\tuae_s16 %s = %s (%sa);\n", name, srcwx, name);
                                count_read++;
-                               check_bus_error(name, 0, 0, 1);
+                               check_bus_error(name, 0, 0, 1, NULL, 1);
                                break;
                        }
                        case sz_long:
@@ -2482,14 +2523,14 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                                insn_n_cycles += 8;
                                if ((flags & GF_REVERSE) && mode == Apdi) {
                                        printf("\tuae_s32 %s = %s(%sa + 2);\n", name, srcwx, name);
-                                       check_bus_error(name, 0, 0, 1);
+                                       check_bus_error(name, 0, 0, 1, NULL, 1);
                                        printf("\t%s |= %s(%sa) << 16; \n", name, srcw, name);
-                                       check_bus_error(name, -2, 0, 1);
+                                       check_bus_error(name, -2, 0, 1, NULL, 1);
                                } else {
                                        printf("\tuae_s32 %s = %s(%sa) << 16;\n", name, srcwx, name);
-                                       check_bus_error(name, 0, 0, 1);
+                                       check_bus_error(name, 0, 0, 1, NULL, 1);
                                        printf("\t%s |= %s(%sa + 2); \n", name, srcw, name);
-                                       check_bus_error(name, 2, 0, 1);
+                                       check_bus_error(name, 2, 0, 1, NULL, 1);
                                }
                                count_read += 2;
                                break;
@@ -2629,6 +2670,8 @@ static void genamodedual (instr *curi, amodes smode, const char *sreg, wordsizes
 
 static void genastore_2 (const char *from, amodes mode, const char *reg, wordsizes size, const char *to, int store_dir, int flags)
 {
+       char tmp[100];
+
        if (candormw) {
                if (strcmp (rmw_varname, to) != 0)
                        candormw = false;
@@ -2738,7 +2781,7 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                                check_ipl_again();
                                printf ("\tx_put_byte (%sa, %s);\n", to, from);
                                count_write++;
-                               check_bus_error(to, 0, 1, 1);
+                               check_bus_error(to, 0, 1, 0, from, 1);
                                break;
                        case sz_word:
                                if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
@@ -2746,29 +2789,31 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                                check_ipl_again();
                                printf ("\tx_put_word (%sa, %s);\n", to, from);
                                count_write++;
-                               check_bus_error(to, 0, 1, 1);
+                               check_bus_error(to, 0, 1, 1, from, 1);
                                break;
                        case sz_long:
                                if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
                                        term ();
                                if (store_dir) {
                                        printf ("\t%s (%sa + 2, %s);\n", dstwx, to, from);
-                                       check_bus_error(to, 2, 1, 1);
+                                       check_bus_error(to, 2, 1, 1, from, 1);
                                        check_ipl_again();
                                        if (flags & GF_SECONDWORDSETFLAGS) {
                                                genflags(flag_logical, g_instr->size, "src", "", "");
                                        }
                                        printf ("%s (%sa, %s >> 16);\n", dstwx, to, from);
-                                       check_bus_error(to, 0, 1, 1);
+                                       sprintf(tmp, "%s >> 16", from);
+                                       check_bus_error(to, 0, 1, 1, tmp, 1);
                                } else {
                                        printf ("\t%s (%sa, %s >> 16);\n", dstwx, to, from);
-                                       check_bus_error(to, 0, 1, 1);
+                                       sprintf(tmp, "%s >> 16", from);
+                                       check_bus_error(to, 0, 1, 1, tmp, 1);
                                        check_ipl_again();
                                        if (flags & GF_SECONDWORDSETFLAGS) {
                                                genflags(flag_logical, g_instr->size, "src", "", "");
                                        }
                                        printf ("\t%s (%sa + 2, %s);\n", dstwx, to, from);
-                                       check_bus_error(to, 2, 1, 1);
+                                       check_bus_error(to, 2, 1, 1, "from", 1);
                                }
                                count_write += 2;
                                break;
@@ -2781,14 +2826,14 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                                insn_n_cycles += 4;
                                printf ("\t%s (%sa, %s);\n", dstbx, to, from);
                                count_write++;
-                               check_bus_error(to, 0, 1, 1);
+                               check_bus_error(to, 0, 1, 0, from, 1);
                                break;
                        case sz_word:
                                insn_n_cycles += 4;
                                if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
                                        term ();
                                printf ("\t%s (%sa, %s);\n", dstwx, to, from);
-                               check_bus_error(to, 0, 1, 1);
+                               check_bus_error(to, 0, 1, 1, from, 1);
                                count_write++;
                                break;
                        case sz_long:
@@ -2797,20 +2842,22 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                                        term ();
                                if (store_dir) {
                                        printf("\t%s(%sa + 2, %s);\n", dstwx, to, from);
-                                       check_bus_error(to, 2, 1, 1);
+                                       check_bus_error(to, 2, 1, 1, from, 1);
                                        if (flags & GF_SECONDWORDSETFLAGS) {
                                                genflags(flag_logical, g_instr->size, "src", "", "");
                                        }
                                        printf("\t%s(%sa, %s >> 16); \n", dstwx, to, from);
-                                       check_bus_error(to, 0, 1, 1);
+                                       sprintf(tmp, "%s >> 16", from);
+                                       check_bus_error(to, 0, 1, 1, tmp, 1);
                                } else {
                                        printf("\t%s (%sa, %s >> 16);\n", dstwx, to, from);
-                                       check_bus_error(to, 0, 1, 1);
+                                       sprintf(tmp, "%s >> 16", from);
+                                       check_bus_error(to, 0, 1, 1, tmp, 1);
                                        if (flags & GF_SECONDWORDSETFLAGS) {
                                                genflags(flag_logical, g_instr->size, "src", "", "");
                                        }
                                        printf("\t%s(%sa + 2, %s); \n", dstwx, to, from);
-                                       check_bus_error(to, 2, 1, 1);
+                                       check_bus_error(to, 2, 1, 1, from, 1);
                                }
                                count_write += 2;
                                break;
@@ -3106,8 +3153,15 @@ static void movem_ex3(int write)
                                printf("\t\topcode |= 0x01020000;\n");
                        }
                }
-               printf("\t\texception3_%s(opcode, srca, %d);\n",
-                       write ? "write" : "read", (g_instr->dmode == PC16 || g_instr->dmode == PC8r) ? 2 : 1);
+               if (write) {
+                       printf("\t\texception3_write(opcode, srca, %d, srca, %d);\n",
+                               g_instr->size,
+                               (g_instr->dmode == PC16 || g_instr->dmode == PC8r) ? 2 : 1);
+               } else {
+                       printf("\t\texception3_read(opcode, srca, %d, %d);\n",
+                               g_instr->size,
+                               (g_instr->dmode == PC16 || g_instr->dmode == PC8r) ? 2 : 1);
+               }
                printf("\t\tgoto %s;\n", endlabelstr);
                printf("\t}\n");
                need_endlabel = 1;
@@ -3170,9 +3224,9 @@ static void genmovemel_ce (uae_u16 opcode)
        if (table68k[opcode].size == sz_long) {
                printf("\twhile (dmask) {\n");
                printf("\t\tuae_u32 v = %s (srca) << 16;\n", srcw);
-               check_bus_error("src", 0, 0, 1);
+               check_bus_error("src", 0, 0, 1, NULL, 1);
                printf("\t\tv |= %s (srca + 2);\n", srcw);
-               check_bus_error("src", 2, 0, 1);
+               check_bus_error("src", 2, 0, 1, NULL, 1);
                printf("\t\tm68k_dreg (regs, movem_index1[dmask]) = v;\n");
                printf("\t\tsrca += %d;\n", size);
                printf("\t\tdmask = movem_next[dmask];\n");
@@ -3180,9 +3234,9 @@ static void genmovemel_ce (uae_u16 opcode)
                printf("\t}\n");
                printf("\twhile (amask) {\n");
                printf("\t\tuae_u32 v = %s (srca) << 16;\n", srcw);
-               check_bus_error("src", 0, 0, 1);
+               check_bus_error("src", 0, 0, 1, NULL, 1);
                printf("\t\tv |= %s (srca + 2);\n", srcw);
-               check_bus_error("src", 2, 0, 1);
+               check_bus_error("src", 2, 0, 1, NULL, 1);
                printf("\t\tm68k_areg (regs, movem_index1[amask]) = v;\n");
                printf("\t\tsrca += %d;\n", size);
                printf("\t\tamask = movem_next[amask];\n");
@@ -3191,7 +3245,7 @@ static void genmovemel_ce (uae_u16 opcode)
        } else {
                printf("\twhile (dmask) {\n");
                printf("\t\tuae_u32 v = (uae_s32)(uae_s16)%s (srca);\n", srcw);
-               check_bus_error("src", 0, 0, 1);
+               check_bus_error("src", 0, 0, 1, NULL, 1);
                printf("\t\tm68k_dreg (regs, movem_index1[dmask]) = v;\n");
                printf("\t\tsrca += %d;\n", size);
                printf("\t\tdmask = movem_next[dmask];\n");
@@ -3199,7 +3253,7 @@ static void genmovemel_ce (uae_u16 opcode)
                printf("\t}\n");
                printf("\twhile (amask) {\n");
                printf("\t\tuae_u32 v = (uae_s32)(uae_s16)%s (srca);\n", srcw);
-               check_bus_error("src", 0, 0, 1);
+               check_bus_error("src", 0, 0, 1, NULL, 1);
                printf("\t\tm68k_areg (regs, movem_index1[amask]) = v;\n");
                printf("\t\tsrca += %d;\n", size);
                printf("\t\tamask = movem_next[amask];\n");
@@ -3207,7 +3261,7 @@ static void genmovemel_ce (uae_u16 opcode)
                printf("\t}\n");
        }
        printf("\t%s (srca);\n", srcw); // and final extra word fetch that goes nowhere..
-       check_bus_error("src", 0, 0, 1);
+       check_bus_error("src", 0, 0, 1, NULL, 1);
        count_read++;
        if (table68k[opcode].dmode == Aipi)
                printf("\tm68k_areg (regs, dstreg) = srca;\n");
@@ -3292,18 +3346,18 @@ static void genmovemle_ce (uae_u16 opcode)
                        movem_ex3(1);
                        printf ("\twhile (amask) {\n");
                        printf ("\t\t%s (srca - 2, m68k_areg (regs, movem_index2[amask]));\n", dstw);
-                       check_bus_error("src", -2, 1, 1);
-                       printf ("\t\t%s (srca - 4, m68k_areg (regs, movem_index2[amask]) >> 16);\n", dstw);
-                       check_bus_error("src", -4, 1, 1);
+                       check_bus_error("src", -2, 1, 1, "m68k_areg(regs, movem_index2[amask])", 1);
+                       printf ("\t\t%s (srca - 4, m68k_areg(regs, movem_index2[amask]) >> 16);\n", dstw);
+                       check_bus_error("src", -4, 1, 1, "m68k_areg(regs, movem_index2[amask]) >> 16", 1);
                        printf("\t\tsrca -= %d;\n", size);
                        printf ("\t\tamask = movem_next[amask];\n");
                        addcycles000_nonce("\t\t", 8);
                        printf ("\t}\n");
                        printf ("\twhile (dmask) {\n");
-                       printf ("\t\t%s (srca - 2, m68k_dreg (regs, movem_index2[dmask]));\n", dstw);
-                       check_bus_error("src", -2, 1, 1);
-                       printf ("\t\t%s (srca - 4, m68k_dreg (regs, movem_index2[dmask]) >> 16);\n", dstw);
-                       check_bus_error("src", -4, 1, 1);
+                       printf ("\t\t%s (srca - 2, m68k_dreg(regs, movem_index2[dmask]));\n", dstw);
+                       check_bus_error("src", -2, 1, 1, "m68k_dreg(regs, movem_index2[dmask])", 1);
+                       printf ("\t\t%s (srca - 4, m68k_dreg(regs, movem_index2[dmask]) >> 16);\n", dstw);
+                       check_bus_error("src", -4, 1, 1, "m68k_dreg(regs, movem_index2[dmask]) >> 16", 1);
                        printf("\t\tsrca -= %d;\n", size);
                        printf ("\t\tdmask = movem_next[dmask];\n");
                        addcycles000_nonce("\t\t", 8);
@@ -3313,19 +3367,19 @@ static void genmovemle_ce (uae_u16 opcode)
                        printf ("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
                        movem_ex3(1);
                        printf ("\twhile (dmask) {\n");
-                       printf ("\t\t%s (srca, m68k_dreg (regs, movem_index1[dmask]) >> 16);\n", dstw);
-                       check_bus_error("src", 0, 1, 1);
-                       printf ("\t\t%s (srca + 2, m68k_dreg (regs, movem_index1[dmask]));\n", dstw);
-                       check_bus_error("src", 2, 1, 1);
+                       printf ("\t\t%s (srca, m68k_dreg(regs, movem_index1[dmask]) >> 16);\n", dstw);
+                       check_bus_error("src", 0, 1, 1, "m68k_dreg(regs, movem_index1[dmask]) >> 16", 1);
+                       printf ("\t\t%s (srca + 2, m68k_dreg(regs, movem_index1[dmask]));\n", dstw);
+                       check_bus_error("src", 2, 1, 1, "m68k_dreg(regs, movem_index1[dmask])", 1);
                        printf ("\t\tsrca += %d;\n", size);
                        printf ("\t\tdmask = movem_next[dmask];\n");
                        addcycles000_nonce("\t\t", 8);
                        printf ("\t}\n");
                        printf ("\twhile (amask) {\n");
-                       printf ("\t\t%s (srca, m68k_areg (regs, movem_index1[amask]) >> 16);\n", dstw);
-                       check_bus_error("src", 0, 1, 1);
-                       printf ("\t\t%s (srca + 2, m68k_areg (regs, movem_index1[amask]));\n", dstw);
-                       check_bus_error("src", 2, 1, 1);
+                       printf ("\t\t%s (srca, m68k_areg(regs, movem_index1[amask]) >> 16);\n", dstw);
+                       check_bus_error("src", 0, 1, 1, "m68k_areg(regs, movem_index1[amask]) >> 16", 1);
+                       printf ("\t\t%s (srca + 2, m68k_areg(regs, movem_index1[amask]));\n", dstw);
+                       check_bus_error("src", 2, 1, 1, "m68k_areg(regs, movem_index1[amask])", 1);
                        printf ("\t\tsrca += %d;\n", size);
                        printf ("\t\tamask = movem_next[amask];\n");
                        addcycles000_nonce("\t\t", 8);
@@ -3337,15 +3391,15 @@ static void genmovemle_ce (uae_u16 opcode)
                        movem_ex3(1);
                        printf ("\twhile (amask) {\n");
                        printf ("\t\tsrca -= %d;\n", size);
-                       printf ("\t\t%s (srca, m68k_areg (regs, movem_index2[amask]));\n", dstw);
-                       check_bus_error("src", 0, 1, 1);
+                       printf ("\t\t%s (srca, m68k_areg(regs, movem_index2[amask]));\n", dstw);
+                       check_bus_error("src", 0, 1, 1, "m68k_areg(regs, movem_index2[amask])", 1);
                        printf ("\tamask = movem_next[amask];\n");
                        addcycles000_nonce("\t\t", 4);
                        printf ("\t}\n");
                        printf ("\twhile (dmask) {\n");
                        printf ("\t\tsrca -= %d;\n", size);
-                       printf ("\t\t%s (srca, m68k_dreg (regs, movem_index2[dmask]));\n", dstw);
-                       check_bus_error("src", 0, 1, 1);
+                       printf ("\t\t%s (srca, m68k_dreg(regs, movem_index2[dmask]));\n", dstw);
+                       check_bus_error("src", 0, 1, 1, "m68k_dreg(regs, movem_index2[dmask])", 1);
                        printf ("\t\tdmask = movem_next[dmask];\n");
                        addcycles000_nonce("\t\t", 4);
                        printf ("\t}\n");
@@ -3354,15 +3408,15 @@ static void genmovemle_ce (uae_u16 opcode)
                        printf ("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
                        movem_ex3(1);
                        printf ("\twhile (dmask) {\n");
-                       printf ("\t\t%s (srca, m68k_dreg (regs, movem_index1[dmask]));\n", dstw);
-                       check_bus_error("src", 0, 1, 1);
+                       printf ("\t\t%s (srca, m68k_dreg(regs, movem_index1[dmask]));\n", dstw);
+                       check_bus_error("src", 0, 1, 1, "m68k_dreg(regs, movem_index1[dmask])", 1);
                        printf ("\t\tsrca += %d;\n", size);
                        printf ("\t\tdmask = movem_next[dmask];\n");
                        addcycles000_nonce("\t\t", 4);
                        printf ("\t}\n");
                        printf ("\twhile (amask) {\n");
-                       printf ("\t\t%s (srca, m68k_areg (regs, movem_index1[amask]));\n", dstw);
-                       check_bus_error("src", 0, 1, 1);
+                       printf ("\t\t%s (srca, m68k_areg(regs, movem_index1[amask]));\n", dstw);
+                       check_bus_error("src", 0, 1, 1, "m68k_areg(regs, movem_index1[amask])", 1);
                        printf ("\t\tsrca += %d;\n", size);
                        printf ("\t\tamask = movem_next[amask];\n");
                        addcycles000_nonce("\t\t", 4);
@@ -4291,19 +4345,19 @@ static void gen_opcode (unsigned int opcode)
                printf ("\tuaecptr mempa = m68k_areg (regs, dstreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword (0));
                if (curi->size == sz_word) {
                        printf("\t%s(mempa, src >> 8);\n", dstb);
-                       check_bus_error("memp", 0, 1, 1);
+                       check_bus_error("memp", 0, 1, 0, "src >> 8", 1 | 0x10000);
                        printf("\t%s(mempa + 2, src); \n", dstb);
-                       check_bus_error("memp", 2, 1, 1);
+                       check_bus_error("memp", 2, 1, 0, "src", 1);
                        count_write += 2;
                } else {
                        printf("\t%s(mempa, src >> 24);\n", dstb);
-                       check_bus_error("memp", 0, 1, 1);
+                       check_bus_error("memp", 0, 1, 0, "src >> 24", 1 | 0x10000);
                        printf("\t%s(mempa + 2, src >> 16);\n", dstb);
-                       check_bus_error("memp", 2, 1, 1);
+                       check_bus_error("memp", 2, 1, 0, "src >> 16", 1);
                        printf("\t%s(mempa + 4, src >> 8);\n", dstb);
-                       check_bus_error("memp", 4, 1, 1);
+                       check_bus_error("memp", 4, 1, 0, "src >> 8", 1 | 0x10000);
                        printf("\t%s(mempa + 6, src); \n", dstb);
-                       check_bus_error("memp", 6, 1, 1);
+                       check_bus_error("memp", 6, 1, 0, "src", 1);
                        count_write += 4;
                }
                fill_prefetch_next ();
@@ -4313,23 +4367,23 @@ static void gen_opcode (unsigned int opcode)
                genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 2, 0, 0);
                if (curi->size == sz_word) {
                        printf ("\tuae_u16 val  = (%s (mempa) & 0xff) << 8;\n", srcb);
-                       check_bus_error("memp", 0, 0, 1);
+                       check_bus_error("memp", 0, 0, 0, NULL, 1 | 0x10000);
                        printf ("\tval |= (%s (mempa + 2) & 0xff);\n", srcb);
-                       check_bus_error("memp", 2, 0, 1);
+                       check_bus_error("memp", 2, 0, 0, NULL, 1);
                        count_read += 2;
                } else {
                        printf ("\tuae_u32 val  = (%s (mempa) & 0xff) << 24;\n", srcb);
-                       check_bus_error("memp", 0, 0, 1);
+                       check_bus_error("memp", 0, 0, 0, NULL, 1 | 0x10000);
                        printf ("\tval |= (%s (mempa + 2) & 0xff) << 16;\n", srcb);
-                       check_bus_error("memp", 2, 0, 1);
+                       check_bus_error("memp", 2, 0, 0, NULL, 1);
 
                        // upper word gets updated after two bytes (makes only difference if bus error is possible)
                        printf("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0x0000ffff) | (val & 0xffff0000);\n");
 
                        printf("\tval |= (%s (mempa + 4) & 0xff) << 8;\n", srcb);
-                       check_bus_error("memp", 4, 0, 1);
+                       check_bus_error("memp", 4, 0, 0, NULL, 1 | 0x10000);
                        printf ("\tval |= (%s (mempa + 6) & 0xff);\n", srcb);
-                       check_bus_error("memp", 6, 0, 1);
+                       check_bus_error("memp", 6, 0, 0, NULL, 1);
                        count_read += 4;
                }
                fill_prefetch_next ();
@@ -4489,7 +4543,7 @@ static void gen_opcode (unsigned int opcode)
                        // read first and ignore result
                        if (cpu_level <= 1 && curi->size == sz_word) {
                                printf("\t%s (srca);\n", srcw);
-                               check_bus_error("src", 0, 0, 1);
+                               check_bus_error("src", 0, 0, 1, NULL, 1);
                                count_write++;
                        }
                        fill_prefetch_next ();
@@ -4894,7 +4948,7 @@ static void gen_opcode (unsigned int opcode)
                printf ("\tuaecptr pc = %s;\n", getpc);
                if (cpu_level <= 1 && using_exception_3) {
                        printf("\tif (m68k_areg(regs, 7) & 1) {\n");
-                       printf("\t\texception3_read(opcode, m68k_areg(regs, 7), 1);\n");
+                       printf("\t\texception3_read(opcode, m68k_areg(regs, 7), 1, 1);\n");
                        printf("\t\tgoto %s;\n", endlabelstr);
                        printf("\t}\n");
                }
@@ -4911,9 +4965,9 @@ static void gen_opcode (unsigned int opcode)
                } else if (using_ce || using_prefetch || (using_test && cpu_level <= 1)) {
                        printf("\tuaecptr newpc, dsta = m68k_areg(regs, 7);\n");
                        printf("\tnewpc = %s(dsta) << 16;\n", srcw);
-                       check_bus_error("dst", 0, 0, 1);
+                       check_bus_error("dst", 0, 0, 1, NULL, 1);
                        printf("\tnewpc |= %s(dsta + 2);\n", srcw);
-                       check_bus_error("dst", 2, 0, 1);
+                       check_bus_error("dst", 2, 0, 1, NULL, 1);
                        printf("\tm68k_areg(regs, 7) += 4;\n");
                        setpc("newpc");
                } else if (using_prefetch_020 || (using_test && cpu_level >= 2)) {
@@ -5022,7 +5076,7 @@ static void gen_opcode (unsigned int opcode)
                                printf("\tm68k_areg (regs, 7) -= 4;\n");
                        if (using_exception_3 && cpu_level <= 1) {
                                printf("\tif (m68k_areg(regs, 7) & 1) {\n");
-                               printf("\t\texception3_write(opcode, m68k_areg(regs, 7), 1);\n");
+                               printf("\t\texception3_write(opcode, m68k_areg(regs, 7), 1, m68k_areg(regs, 7) >> 16, 1);\n");
                                printf("\t\tgoto %s;\n", endlabelstr);
                                printf("\t}\n");
                                need_endlabel = 1;
@@ -5030,9 +5084,9 @@ static void gen_opcode (unsigned int opcode)
                        if (using_ce || using_prefetch) {
                                printf("\tuaecptr dsta = m68k_areg(regs, 7);\n");
                                printf("\t%s(dsta, nextpc >> 16);\n", dstw);
-                               check_bus_error("dst", 0, 1, 1);
+                               check_bus_error("dst", 0, 1, 1, "nextpc >> 16", 1);
                                printf("\t%s(dsta + 2, nextpc);\n", dstw);
-                               check_bus_error("dst", 2, 1, 1);
+                               check_bus_error("dst", 2, 1, 1, "nextpc", 1);
                        } else {
                                printf("\t%s(m68k_areg(regs, 7), nextpc);\n", dstl);
                        }
@@ -5124,9 +5178,9 @@ static void gen_opcode (unsigned int opcode)
                        printf("\tm68k_areg(regs, 7) -= 4;\n");
                        printf("\tuaecptr dsta = m68k_areg(regs, 7);\n");
                        printf("\t%s(dsta, nextpc >> 16);\n", dstw);
-                       check_bus_error("dst", 0, 1, 1);
+                       check_bus_error("dst", 0, 1, 1, "nextpc >> 16", 1);
                        printf("\t%s(dsta + 2, nextpc);\n", dstw);
-                       check_bus_error("dst", 2, 1, 1);
+                       check_bus_error("dst", 2, 1, 1, "nextpc", 1);
                        incpc("s");
                } else if (using_prefetch_020 || (using_test && cpu_level >= 2)) {
                        printf ("\tm68k_do_bsri (nextpc, s);\n");
index 1f69cf5443f964a04fa3e1f34528c64f6d768a38..fac8105cd3bddd43f15be3761f3e27b2210bbad2 100644 (file)
@@ -717,15 +717,16 @@ extern void fpux_restore (int*);
 extern bool fpu_get_constant(fpdata *fp, int cr);
 extern int fpp_cond(int condition);
 
-extern void exception3_read(uae_u32 opcode, uaecptr addr, int fc);
-extern void exception3_write(uae_u32 opcode, uaecptr addr, int fc);
+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_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(uaecptr addr, bool read, uae_u32 fc);
-extern void exception2_read(uae_u32 opcode, uaecptr addr, int fc);
-extern void exception2_write(uae_u32 opcode, uaecptr addr, int fc);
+extern void exception2_setup(uaecptr addr, bool read, int size, uae_u32 fc);
+extern void exception2_read(uae_u32 opcode, uaecptr addr, int size, int fc);
+extern void exception2_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc);
+extern void exception2_fetch(uae_u32 opcode, uaecptr addr);
 extern void m68k_reset (void);
 extern void cpureset (void);
 extern void cpu_halt (int id);
index efc4e04a1e0efe0eb43b02d83bf9527b96fe6c8f..9f4698b0f6d29ffa922c523d67551227891416d3 100644 (file)
@@ -507,7 +507,7 @@ LONG WINAPI EvalException(LPEXCEPTION_POINTERS info)
        }
        if (currprefs.comp_catchfault) {
                // setup fake exception
-               exception2_setup(uae_p32(address) - uae_p32(NATMEM_OFFSET), info->ExceptionRecord->ExceptionInformation[0] == 0, regs.s ? 4 : 0);
+               exception2_setup(uae_p32(address) - uae_p32(NATMEM_OFFSET), info->ExceptionRecord->ExceptionInformation[0] == 0, 1, regs.s ? 4 : 0);
                return EXCEPTION_EXECUTE_HANDLER;
        }
        return EXCEPTION_CONTINUE_SEARCH;
index e89fe279c3d9a227aaf6475550f849ff628f4945..5778764e7b334a87bfdca4c27109501fc42f4565 100644 (file)
@@ -69,8 +69,14 @@ static uaecptr last_addr_for_exception_3;
 static uaecptr last_fault_for_exception_3;
 /* read (0) or write (1) access */
 static bool last_writeaccess_for_exception_3;
+/* size */
+static bool last_size_for_exception_3;
 /* FC */
 static int last_fc_for_exception_3;
+/* Data (1) or instruction fetch (0) */
+static int last_di_for_exception_3;
+/* Value */
+static int last_value_for_exception_3;
 /* not instruction */
 static bool last_notinstruction_for_exception_3;
 /* set when writing exception stack frame */
@@ -2492,6 +2498,7 @@ static void Exception_ce000 (int nr)
                write_log(_T("Exception %d (%08x %x) at %x -> %x!\n"),
                        nr, last_op_for_exception_3, last_addr_for_exception_3, currpc, get_long_debug(4 * nr));
                if (currprefs.cpu_model == 68000) {
+                       // 68000 bus/address error
                        uae_u16 mode = (sv ? 4 : 0) | last_fc_for_exception_3;
                        mode |= last_writeaccess_for_exception_3 ? 0 : 16;
                        mode |= last_notinstruction_for_exception_3 ? 8 : 0;
@@ -2509,17 +2516,20 @@ static void Exception_ce000 (int nr)
                        x_do_cycles(2 * cpucycleunit);
                        goto kludge_me_do;
                } else {
-                       // 68010 address error (partially implemented only)
+                       // 68010 bus/address error (partially implemented only)
                        uae_u16 ssw = (sv ? 4 : 0) | last_fc_for_exception_3;
-                       ssw |= last_writeaccess_for_exception_3 ? 0 : 0x100;
-                       ssw |= (last_fc_for_exception_3 & 2) ? 0 : 0x2000;
+                       ssw |= last_di_for_exception_3 ? 0x0000 : 0x2000; // IF
+                       ssw |= (!last_writeaccess_for_exception_3 && last_di_for_exception_3) ? 0x1000 : 0x000; // DF
+                       ssw |= (last_op_for_exception_3 & 0x10000) ? 0x0400 : 0x0000; // HB
+                       ssw |= last_size_for_exception_3 == 0 ? 0x0200 : 0x0000; // BY
+                       ssw |= last_writeaccess_for_exception_3 ? 0 : 0x0100; // RW
                        m68k_areg(regs, 7) -= 50;
                        exception_in_exception = -1;
                        frame_id = 8;
                        x_put_word(m68k_areg(regs, 7) + 0, ssw); // ssw
                        x_put_long(m68k_areg(regs, 7) + 2, last_addr_for_exception_3); // fault addr
                        x_put_word(m68k_areg(regs, 7) + 6, 0); // unused
-                       x_put_word(m68k_areg(regs, 7) + 8, 0); // data output buffer
+                       x_put_word(m68k_areg(regs, 7) + 8, last_value_for_exception_3); // data output buffer
                        x_put_word(m68k_areg(regs, 7) + 10, 0); // unused
                        x_put_word(m68k_areg(regs, 7) + 12, 0); // data input buffer
                        x_put_word(m68k_areg(regs, 7) + 14, 0); // unused
@@ -2641,7 +2651,7 @@ static void Exception_mmu030 (int nr, uaecptr oldpc)
                if (nr == 2 || nr == 3)
                        cpu_halt (CPU_HALT_DOUBLE_FAULT);
                else
-                       exception3_read(regs.ir, newpc, 1);
+                       exception3_read(regs.ir, newpc, 1, 1);
                return;
        }
        if (interrupt)
@@ -2707,7 +2717,7 @@ static void Exception_mmu (int nr, uaecptr oldpc)
                if (nr == 2 || nr == 3)
                        cpu_halt (CPU_HALT_DOUBLE_FAULT);
                else
-                       exception3_read(regs.ir, newpc, 1);
+                       exception3_read(regs.ir, newpc, 2, 1);
                return;
        }
 
@@ -2851,7 +2861,7 @@ static void Exception_normal (int nr)
                                                        if (nr == 2 || nr == 3)
                                                                cpu_halt (CPU_HALT_DOUBLE_FAULT);
                                                        else
-                                                               exception3_read(regs.ir, newpc, 1);
+                                                               exception3_read(regs.ir, newpc, 2, 1);
                                                        return;
                                                }
                                                m68k_setpc (newpc);
@@ -2906,11 +2916,15 @@ static void Exception_normal (int nr)
                                Exception_build_stack_frame(last_fault_for_exception_3, currpc, ssw, nr, 0x0b);
                                used_exception_build_stack_frame = true;
                        } else {
-                               // 68010 address error (partially implemented only)
+                               // 68010 bus/address error (partially implemented only)
                                uae_u16 ssw = (sv ? 4 : 0) | last_fc_for_exception_3;
-                               ssw |= last_writeaccess_for_exception_3 ? 0 : 0x100;
-                               ssw |= (last_fc_for_exception_3 & 2) ? 0 : 0x2000;
+                               ssw |= last_di_for_exception_3 ? 0x0000 : 0x2000; // IF
+                               ssw |= (!last_writeaccess_for_exception_3 && last_di_for_exception_3) ? 0x1000 : 0x000; // DF
+                               ssw |= (last_op_for_exception_3 & 0x10000) ? 0x0400 : 0x0000; // HB
+                               ssw |= last_size_for_exception_3 == 0 ? 0x0200 : 0x0000; // BY
+                               ssw |= last_writeaccess_for_exception_3 ? 0x0000 : 0x0100; // RW
                                regs.mmu_fault_addr = last_addr_for_exception_3;
+                               regs.mmu_effective_addr = last_value_for_exception_3;
                                Exception_build_stack_frame(oldpc, currpc, ssw, nr, 0x08);
                                used_exception_build_stack_frame = true;
                        }
@@ -2938,7 +2952,7 @@ static void Exception_normal (int nr)
                add_approximate_exception_cycles(nr);
                nextpc = m68k_getpc ();
                if (nr == 2 || nr == 3) {
-                       // 68000 bus error/address error
+                       // 68000 bus/address error
                        uae_u16 mode = (sv ? 4 : 0) | last_fc_for_exception_3;
                        mode |= last_writeaccess_for_exception_3 ? 0 : 16;
                        mode |= last_notinstruction_for_exception_3 ? 8 : 0;
@@ -6805,7 +6819,7 @@ uae_u8 *restore_mmu (uae_u8 *src)
 
 #endif /* SAVESTATE */
 
-static void exception3f (uae_u32 opcode, uaecptr addr, bool writeaccess, bool instructionaccess, bool notinstruction, uaecptr pc, bool plus2, int fc)
+static void exception3f (uae_u32 opcode, uaecptr addr, bool writeaccess, bool instructionaccess, bool notinstruction, uaecptr pc, int size, bool plus2, int fc)
 {
        if (currprefs.cpu_model >= 68040)
                addr &= ~1;
@@ -6826,6 +6840,7 @@ static void exception3f (uae_u32 opcode, uaecptr addr, bool writeaccess, bool in
        last_writeaccess_for_exception_3 = writeaccess;
        last_fc_for_exception_3 = fc >= 0 ? fc : (instructionaccess ? 2 : 1);
        last_notinstruction_for_exception_3 = notinstruction;
+       last_size_for_exception_3 = size;
        Exception (3);
 #if EXCEPTION3_DEBUGGER
        activate_debugger();
@@ -6834,26 +6849,26 @@ static void exception3f (uae_u32 opcode, uaecptr addr, bool writeaccess, bool in
 
 void exception3_notinstruction(uae_u32 opcode, uaecptr addr)
 {
-       exception3f (opcode, addr, true, false, true, 0xffffffff, false, -1);
+       exception3f (opcode, addr, true, false, true, 0xffffffff, 1, false, -1);
 }
-void exception3_read(uae_u32 opcode, uaecptr addr, int fc)
+void exception3_read(uae_u32 opcode, uaecptr addr, int size, int fc)
 {
-       exception3f (opcode, addr, false, 0, false, 0xffffffff, false, fc);
+       exception3f (opcode, addr, false, 0, false, 0xffffffff, size, false, fc);
 }
-void exception3_write(uae_u32 opcode, uaecptr addr, int fc)
+void exception3_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc)
 {
-       exception3f (opcode, addr, true, 0, false, 0xffffffff, false, fc);
+       exception3f (opcode, addr, true, 0, false, 0xffffffff, size, false, fc);
 }
 void exception3i (uae_u32 opcode, uaecptr addr)
 {
-       exception3f (opcode, addr, 0, 1, false, 0xffffffff, true, -1);
+       exception3f (opcode, addr, 0, 1, false, 0xffffffff, 1, true, -1);
 }
 void exception3b (uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc)
 {
-       exception3f (opcode, addr, w, i, false, pc, true, -1);
+       exception3f (opcode, addr, w, i, false, pc, 1, true, -1);
 }
 
-void exception2_setup(uaecptr addr, bool read, uae_u32 fc)
+void exception2_setup(uaecptr addr, bool read, int size, uae_u32 fc)
 {
        last_addr_for_exception_3 = m68k_getpc() + bus_error_offset;
        last_fault_for_exception_3 = addr;
@@ -6861,6 +6876,8 @@ void exception2_setup(uaecptr addr, bool read, uae_u32 fc)
        last_fc_for_exception_3 = fc;
        last_op_for_exception_3 = regs.opcode;
        last_notinstruction_for_exception_3 = exception_in_exception != 0;
+       last_size_for_exception_3 = size;
+       last_di_for_exception_3 = 1;
        cpu_bus_error = 0;
 }
 
@@ -6874,24 +6891,34 @@ void exception2(uaecptr addr, bool read, int size, uae_u32 fc)
                        mmu_bus_error (addr, 0, fc, read == false, size, 0, true);
                }
        } else {
-               exception2_setup(addr, read, fc);
+               exception2_setup(addr, read, size == 1 ? 0 : (size == 2 ? 1 : 2), fc);
                THROW(2);
-               activate_debugger();
        }
 }
 
-void exception2_read(uae_u32 opcode, uaecptr addr, int fc)
+void exception2_read(uae_u32 opcode, uaecptr addr, int size, int fc)
 {
-       exception2_setup(addr, true, fc);
+       exception2_setup(addr, true, size, fc);
+       last_op_for_exception_3 = opcode;
+       Exception(2);
+}
+
+void exception2_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc)
+{
+       exception2_setup(addr, false, size, fc);
+       last_op_for_exception_3 = opcode;
        Exception(2);
 }
 
-void exception2_write(uae_u32 opcode, uaecptr addr, int fc)
+void exception2_fetch(uae_u32 opcode, uaecptr addr)
 {
-       exception2_setup(addr, false, fc);
+       exception2_setup(addr, true, 1, 2);
+       last_op_for_exception_3 = opcode;
+       last_di_for_exception_3 = 0;
        Exception(2);
 }
 
+
 void cpureset (void)
 {
     /* RESET hasn't increased PC yet, 1 word offset */
index ecb4f97f5d6900ac82f03779d6115845dde1b1a3..b801929fbefd6ff1e9713da6f53759aff369a8e5 100644 (file)
@@ -818,7 +818,7 @@ void divbyzero_special (bool issigned, uae_s32 dst)
 /* DIVU overflow
  *
  * 68000: V=1, N=1, C=0, Z=0
- * 68010: V=1, N=1, C=0, Z=0
+ * 68010: V=1, N=divisor<0x8000, C=0, Z=divided upper word == 0xffff and divisor == 0xffff
  * 68020: V=1, C=0, Z=0, N=X
  * 68040: V=1, C=0, NZ not modified.
  * 68060: V=1, C=0, NZ not modified.
@@ -841,8 +841,9 @@ void setdivuflags(uae_u32 dividend, uae_u16 divisor)
                        SET_NFLG(1);
        } else if (currprefs.cpu_model == 68010) {
                SET_VFLG(1);
-               SET_NFLG(1);
-               SET_ZFLG(0);
+               SET_NFLG(divisor < 0x8000);
+               // can anyone explain this?
+               SET_ZFLG((dividend >> 16) == 0xffff && divisor == 0xffff);
                SET_CFLG(0);
        } else {
                // 68000
@@ -1369,17 +1370,17 @@ void Exception_build_stack_frame(uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int
                        x_put_word(m68k_areg(regs, 7), 0);
                }
                m68k_areg(regs, 7) -= 2;
-               x_put_word(m68k_areg(regs, 7), 0); // version
+               x_put_word(m68k_areg(regs, 7), 0x0000); // version (probably bits 12 to 15 only because other bits change)
                m68k_areg(regs, 7) -= 2;
-               x_put_word(m68k_areg(regs, 7), regs.opcode); // instruction input buffer
+               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
                m68k_areg(regs, 7) -= 2;
-               x_put_word(m68k_areg(regs, 7), 0); // data input buffer
+               x_put_word(m68k_areg(regs, 7), regs.mmu_effective_addr); // data input buffer
                m68k_areg(regs, 7) -= 2;
                x_put_word(m68k_areg(regs, 7), 0); // unused
                m68k_areg(regs, 7) -= 2;
-               x_put_word(m68k_areg(regs, 7), 0); // data output buffer
+               x_put_word(m68k_areg(regs, 7), regs.mmu_effective_addr >> 16); // data output buffer
                m68k_areg(regs, 7) -= 2;
                x_put_word(m68k_areg(regs, 7), 0); // unused
                m68k_areg(regs, 7) -= 4;