]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
68000 IPL detection timing fixes.
authorToni Wilen <twilen@winuae.net>
Sun, 17 Apr 2022 15:06:23 +0000 (18:06 +0300)
committerToni Wilen <twilen@winuae.net>
Sun, 17 Apr 2022 15:06:23 +0000 (18:06 +0300)
gencpu.cpp
newcpu.cpp

index 326180e396958aa6879b7a14c76e0de1ee5b6c58..54ca6bb0028f2863e3abb274670bd87167f630f3 100644 (file)
@@ -97,6 +97,8 @@ static int do_always_dynamic_cycles;
 #define GF_PCM2                0x100000
 // internal PC is 2 more than address being prefetched.
 #define GF_PCP2                0x200000
+// if set, long word fetch does it at the beginning (not second word)
+#define GF_NOLIPL      0x400000
 
 typedef enum
 {
@@ -248,6 +250,8 @@ static void set_last_access_ipl(void)
 
 static void set_last_access_ipl_prev(void)
 {
+       if (ipl_fetched < 0)
+               return;
        last_access_offset_ipl_prev = strlen(outbuffer);
 }
 
@@ -3716,7 +3720,9 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                                        out("uae_s32 %s = %s(%sa + 2);\n", name, srcwx, name);
                                        count_readw++;
                                        check_bus_error(name, 0, 0, 1, NULL, 1, 0);
-                                       set_last_access_ipl_prev();
+                                       if (!(flags & GF_NOLIPL)) {
+                                               set_last_access_ipl_prev();
+                                       }
                                        out("%s |= %s(%sa) << 16; \n", name, srcwx, name);
                                        count_readw++;
                                        check_bus_error(name, -2, 0, 1, NULL, 1, 0);
@@ -3724,7 +3730,9 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                                        out("uae_s32 %s = %s(%sa) << 16;\n", name, srcwx, name);
                                        count_readw++;
                                        check_bus_error(name, 0, 0, 1, NULL, 1, 0);
-                                       set_last_access_ipl_prev();
+                                       if (!(flags & GF_NOLIPL)) {
+                                               set_last_access_ipl_prev();
+                                       }
                                        out("%s |= %s(%sa + 2); \n", name, srcwx, name);
                                        count_readw++;
                                        check_bus_error(name, 2, 0, 1, NULL, 1, 0);
@@ -4030,7 +4038,9 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                                                fill_prefetch_next_after(0, NULL);
                                                insn_n_cycles += 4;
                                        }
-                                       set_last_access_ipl_prev();
+                                       if (!(flags & GF_NOLIPL)) {
+                                               set_last_access_ipl_prev();
+                                       }
                                        out("%s(%sa, %s >> 16);\n", dstwx, to, from);
                                        sprintf(tmp, "%s >> 16", from);
                                        count_writew++;
@@ -4043,7 +4053,9 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                                        if (flags & GF_SECONDWORDSETFLAGS) {
                                                genflags(flag_logical, g_instr->size, "src", "", "");
                                        }
-                                       set_last_access_ipl_prev();
+                                       if (!(flags & GF_NOLIPL)) {
+                                               set_last_access_ipl_prev();
+                                       }
                                        out("%s(%sa + 2, %s);\n", dstwx, to, from);
                                        count_writew++;
                                        check_bus_error(to, 2, 1, 1, from, 1, pcoffset);
@@ -4514,6 +4526,7 @@ static void genmovemel_ce(uae_u16 opcode)
        int size = table68k[opcode].size == sz_long ? 4 : 2;
        amodes mode = table68k[opcode].dmode;
        out("uae_u16 mask = %s;\n", gen_nextiword(mode < Ad16 ? GF_PCM2 : 0));
+       ipl_fetched = -1;
        do_instruction_buserror();
        out("uae_u32 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
        if (mode == Ad8r || mode == PC8r) {
@@ -4571,7 +4584,6 @@ static void genmovemel_ce(uae_u16 opcode)
                out("amask = movem_next[amask];\n");
                out("}\n");
        }
-       set_last_access_ipl_prev();
        out("%s(srca);\n", srcw); // and final extra word fetch that goes nowhere..
        count_readw++;
        check_bus_error("src", 0, 0, 1, NULL, 1, -1);
@@ -6121,7 +6133,7 @@ static void gen_opcode (unsigned int opcode)
                exception_pc_offset_extra_000 = 2;
                genamodedual(curi,
                        curi->smode, "srcreg", curi->size, "src", 1, GF_AA,
-                       curi->dmode, "dstreg", curi->size, "dst", 1, GF_AA);
+                       curi->dmode, "dstreg", curi->size, "dst", 1, GF_AA | GF_NOLIPL);
                genflags (flag_cmp, curi->size, "newv", "src", "dst");
                fill_prefetch_next_t();
                break;
@@ -6184,6 +6196,7 @@ static void gen_opcode (unsigned int opcode)
        case i_MVPMR: // MOVEP M->R
                out("uaecptr mempa = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword(0));
                check_prefetch_buserror(m68k_pc_offset, -2);
+               ipl_fetched = 1;
                genamode(curi, curi->dmode, "dstreg", curi->size, "dst", 2, 0, cpu_level == 1 ? GF_NOFETCH : 0);
                if (curi->size == sz_word) {
                        out("uae_u16 val  = (%s(mempa) & 0xff) << 8;\n", srcb);
@@ -6988,7 +7001,9 @@ static void gen_opcode (unsigned int opcode)
                                write_return_cycles(0);
                                out("}\n");
                        }
-                       genastore("src", Apdi, "7", sz_long, "old");
+                       set_last_access_ipl();
+                       ipl_fetched = 1;
+                       genastore_2("src", Apdi, "7", sz_long, "old", 0, GF_NOLIPL);
                        genastore("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src");
                        out("m68k_areg(regs, 7) += offs;\n");
                        fill_prefetch_next_t();
@@ -7952,6 +7967,8 @@ bccl_not68020:
                genamode(curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
                genamode(curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0);
                sync_m68k_pc();
+               set_last_access_ipl();
+               ipl_fetched = 1;
                addcycles000(4);
                out("if (dst > src) {\n");
                out("setchkundefinedflags(src, dst, %d);\n", curi->size);
index ab30081a9313ebd5fd79570b9acb88c4073eead5..d846a4c3462721c870976fa7a7ebb331bbf0c2fe 100644 (file)
@@ -4475,7 +4475,7 @@ static int do_specialties (int cycles)
        }
 
        bool first = true;
-       while ((regs.spcflags & SPCFLAG_STOP) && !(regs.spcflags & SPCFLAG_BRK)) {
+       while (regs.spcflags & SPCFLAG_STOP) {
        isstopped:
                check_uae_int_request();
                {
@@ -4496,9 +4496,13 @@ static int do_specialties (int cycles)
 
                if (m68k_interrupt_delay) {
                        unset_special(SPCFLAG_INT);
-                       ipl_fetch ();
-                       if (time_for_interrupt ()) {
-                               do_interrupt (regs.ipl);
+                       if (first) {
+                               ipl_fetch();
+                       }
+                       if (time_for_interrupt()) {
+                               x_do_cycles(4 * cpucycleunit);
+                               do_interrupt(regs.ipl);
+                               break;
                        }
                } else {
                        if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {
@@ -4511,17 +4515,28 @@ static int do_specialties (int cycles)
                                }
                                if (m68kint) {
 #endif
-                                       if (intr > 0 && intr > regs.intmask)
-                                               do_interrupt (intr);
+                                       if (intr > 0 && intr > regs.intmask) {
+                                               do_interrupt(intr);
+                                               break;
+                                       }
 #ifdef WITH_PPC
                                }
 #endif
                        }
                }
 
-               if (!first)
-                       x_do_cycles(currprefs.cpu_cycle_exact ? 2 * CYCLE_UNIT : 4 * CYCLE_UNIT);
+               if (!first) {
+                       if (currprefs.cpu_compatible) {
+                               x_do_cycles(2 * cpucycleunit);
+                               ipl_fetch();
+                               x_do_cycles(2 * cpucycleunit);
+                       } else {
+                               x_do_cycles(4 * cpucycleunit);
+                               ipl_fetch();
+                       }
+               }
                first = false;
+
                if (regs.spcflags & SPCFLAG_COPPER)
                        do_copper();
 
@@ -4530,6 +4545,11 @@ static int do_specialties (int cycles)
                        return 1;
                }
 
+               if (regs.spcflags & SPCFLAG_BRK) {
+                       stopped_debug = false;
+                       goto dodebug;
+               }
+
 #ifdef WITH_PPC
                if (ppc_state) {
                        uae_ppc_execute_check();
@@ -4567,6 +4587,7 @@ static int do_specialties (int cycles)
        }
 
        if ((regs.spcflags & SPCFLAG_BRK) || stopped_debug) {
+dodebug:
                unset_special(SPCFLAG_BRK);
 #ifdef DEBUGGER
                if (stopped_debug && !regs.stopped) {