]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
68010 bus/address error support updates.
authorToni Wilen <twilen@winuae.net>
Sat, 19 Oct 2019 17:04:12 +0000 (20:04 +0300)
committerToni Wilen <twilen@winuae.net>
Sat, 19 Oct 2019 17:04:12 +0000 (20:04 +0300)
cputest.cpp
gencpu.cpp
include/newcpu.h
newcpu.cpp
newcpu_common.cpp

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